/** * Built-in persistent datastore. * - Datastore is capable of serving NoSQL object data and Key-Value data. */ export type Datastore = { /** * - Connect to Datastore */ open: () => Promise; }; /** * @type {Datastore} */ export const Datastore: Datastore; /** * @type {Datastore} */ export const datastore: Datastore; export const aggregation: typeof agg; export const crudlify: typeof crud; /** * Express style API * @type {Codehooks} */ export const coho: Codehooks; export const app: Codehooks; export const coderunner: any; /** * Scheduled background worker functions */ export namespace schedule { function runAt(date: any, payload: any, worker: string): Promise; function run(payload: any, worker: string): Promise; function cron( cronExpression: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ): void; } /** * Real time publish subscribe events */ export namespace realtime { type SSEListener = { _id: string; [key: string]: any; }; /** * Create a real time channel for clients for listen to and server to publish to * @param path string - e.g. '/goals' * @example * realtime.createChannel('/goals') */ function createChannel(path: string, ...hook: any): void; /** * * @param channel string - e.g. '/goals' * @param data object - Event object to publish * @param query object - optional matching criteria for listeners to get the event * @example * realtime.publishEvent('/goals', {player: "Rod", score: 2}) */ function publishEvent( channel: string, data: object, query?: object ): Promise; /** * Create a listener to use to connect to an EventSource later * @param path string - Channel * @param data object - Listener topics of interest * @returns Promise with SSEListener */ function createListener(path: string, data: object): Promise; /** * Get a listener topics * @param path string - Channel * @param listenerID - A valid _id for a listener */ function getListener(path: string, listenerID: string): Promise; /** * Get all listeners on channel * @param path string - Channel */ function getListeners(path: string): Promise; /** * Delete a listenerID * @param path string - Channel * @param listenerID - A valid listenerID */ function removeListener( path: string, listenerID: string ): Promise; } /** * Virtual filesystem */ export namespace filestore { /** * Raad file content as stream * @see {@link https://codehooks.io/docs/fileapi#filestoregetreadstreampath API docs} * @param path Absolute path to file * @param options Not in use * @returns Promise EventEmitter with chunks on data * @example * app.get('/image', async (req: httpRequest, res: httpResponse) => { * const bufStream = await filestore.getReadStream('/img/logo.png'); * res.set('content-type', 'image/png') * bufStream.on('data', (buf) => { * res.write(buf, 'buffer') * }) * .on('end', () => { * res.end() * }) * }) */ function getReadStream(path: string, options?: any): Promise; /** * Read file content as string * @see {@link https://codehooks.io/docs/fileapi#filestorereadfilepath API docs} * @param path Absolute path to file * @param options * @returns Promise File content as string */ function readFile(path: string, options?: any): Promise; /** * Save file binary buffer * @see {@link https://codehooks.io/docs/fileapi#filestoresavefilepath-filestream API docs} * @param path Abolute path to file, e.g. /static/home.html * @param buffer Stream data * @param options Not in use * @returns Promise with save result * @example * import {PassThrough} from 'stream'; * app.post('/file', async (req, res) => { * try { * const stream = new PassThrough(); * req.pipe(stream); * const result = await filestore.saveFile('/static.html', stream); * res.end(result) * } catch (error) { * console.error(error) * res.status(404).end('Bad upload') * } * }) */ function saveFile(path: string, buffer: any, options?: any): Promise; /** * Delete file * @see {@link https://codehooks.io/docs/fileapi#filestoredeletefilepath API docs} * @param path * @param options */ function deleteFile(path: string, options?: any): Promise; /** * List file directories and files * @see {@link https://codehooks.io/docs/fileapi#filestorelistpath API docs} * @param path * @param options */ function list(path: string, options?: any): Promise>; /** * Read binary buffer from file * @param path Path to file * @returns Promise with Buffer * @example * const myBuf = await filestore.getFileAsBuffer('/images/logo.png'); */ function readFileAsBuffer(path: any): Promise; } export default _coho; /** * keyvalOptions */ export type keyvalOptions = { /** * - Time to live in milliseconds */ ttl: number; /** * - Name of isolated keyspace */ keyspace: string; }; /** * NoSQL API */ export type NoSQLAPI = { /** * - Get object by ID (objectID) or query (NoSQL query {...}), returns a Promise with the object * @throws {Error} Rejects if the object is not found */ getOne: (query: string | object) => Promise; /** * - Get object by ID (objectID) or query (NoSQL query {...}), returns a Promise with the object - alias for getOne * @throws {Error} Rejects if the object is not found */ findOne: (query: string | object) => Promise; /** * - Get object by ID (objectID) or query (NoSQL query {...}), returns a Promise with the object or null if not found */ findOneOrNull: (query: string | object) => Promise; /** * - Get stream of objects by query * https://codehooks.io/docs/nosql-database-api#getmanycollection-query-options */ getMany: (query: object, options?: object) => DataStream; /** * - Get stream of objects by query, alias for getMany */ find: (query: object, options?: object) => DataStream; /** * - Insert a new data object into a collection in the current Datastore */ insertOne: (document: object) => Promise; /** * - Update one data object by ID in a datastore collection. * - Input document is patched with the matched database object * @param query string | object * @param document object * @param updateoperators object * @param options object - {upsert: true} * @returns Promise */ updateOne: ( query: string | object, document: object, updateoperators?: object, options?: object ) => Promise; /** * - Update multiple data objects in a datastore collection. * - Input document is patched with the matched database objects */ updateMany: ( query: object, document: object, options?: object ) => Promise; /** * - Replace one data object by ID in a datastore collection. * - Input document overwrites the matched database object, the _id value is not overwritten. */ replaceOne: ( query: string | object, document: object, options?: object ) => Promise; /** * - Replace multiple data objects in a datastore collection. * - Input document overwrites the matched database objects. The _id value is not overwritten */ replaceMany: ( query: object, document: object, options?: object ) => Promise; /** * - Remove one data object by ID in a collection in the current Datastore */ removeOne: (query: string | object) => Promise; /** * - Remove multiple data objects in a collection in the current Datastore */ removeMany: (query: object) => Promise; /** * Validate database colletion data agains JSON-Schema * @param schema JSON-schema * @returns Promise with result */ createSchema: (schema: object) => Promise; /** * Validate database colletion data agains JSON-Schema * @param schema JSON-schema * @returns Promise with result */ setSchema: (schema: object) => Promise; /** * Remove JSON-schema for database collection * @param collection string * @returns Promise with result */ removeSchema: () => Promise; /** * Get JSON-schema for database collection * @returns Promise with result */ getSchema: () => Promise; /** * Count database collection items * @returns Promise result */ count: () => Promise; }; /** * Database API */ export type DatastoreAPI = { /** * - Get database collection by string name, returns an NoSQL API object */ collection: (collection: string) => NoSQLAPI; /** * - Get object by ID (objectID) or query (NoSQL query {...}), returns a Promise with the object * @throws {Error} Rejects if the object is not found */ getOne: (collection: string, query: string | object) => Promise; /** * - Get stream of objects by query * * https://codehooks.io/docs/nosql-database-api#getmanycollection-query-options */ getMany: (collection: string, query?: object, options?: object) => DataStream; /** * - Get object by ID (objectID) or query (NoSQL query {...}), returns a Promise with the object (alias for getOne) * @throws {Error} Rejects if the object is not found */ findOne: (collection: string, query: string | object) => Promise; /** * - Get object by ID (objectID) or query (NoSQL query {...}), returns a Promise with the object or null if not found */ findOneOrNull: (collection: string, query: string | object) => Promise; /** * - Alias for getMany * https://codehooks.io/docs/nosql-database-api#getmanycollection-query-options */ find: (collection: string, query?: object, options?: object) => DataStream; /** * - Insert a new data object into a collection in the current Datastore */ insertOne: (collection: string, document: object) => Promise; /** * - Update one data object by ID in a datastore collection. * - Input document is patched with the matched database object * @param collection string * @param query string | object * @param updateoperators object * @param options object - {upsert: true} * @returns Promise */ updateOne: ( collection: string, query: string | object, updateoperators?: object, options?: object ) => Promise; /** * - Update multiple data objects in a datastore collection. * - Input document is patched with the matched database objects */ updateMany: ( collection: string, query: object, document: object, updateoperators?: object ) => Promise; /** * - Replace one data object by ID in a datastore collection. * - Input document overwrites the matched database object, the _id value is not overwritten. */ replaceOne: ( collection: string, query: string | object, document: object, options?: object ) => Promise; /** * - Replace multiple data objects in a datastore collection. * - Input document overwrites the matched database objects. The _id value is not overwritten */ replaceMany: ( collection: string, query: object, document: object, options?: object ) => Promise; /** * - Remove one data object by ID in a collection in the current Datastore */ removeOne: (collection: string, query: string | object) => Promise; /** * - Remove multiple data objects in a collection in the current Datastore */ removeMany: (collection: string, query: object) => Promise; /** * - Set a key-value pair in the current Datastore */ set: (key: string, value: string | object, options?: object) => Promise; /** * - Get a key-value pair in the current Datastore */ get: (key: string, options?: object) => Promise; /** * - Get all key-value pair that matches keypattern in the current Datastore */ getAll: (keypattern: string, options?: object) => DataStream; /** * - Increment a key-value pair in the current Datastore */ incr: (key: string, value: number, options?: object) => Promise; /** * - Decrement a key-value pair in the current Datastore */ decr: (key: string, value: number, options?: object) => Promise; /** * - Delete a key-value pair in the current Datastore */ del: (key: string, options?: object) => Promise; /** * - Delete a range of key-value pairs in the current Datastore */ delAll: (keypattern: string, options?: object) => Promise; /** * - Add a queued job in a datastore. * - Jobs in the queue are processed by your worker function. */ enqueue: (topic: string, document: object, options?: object) => Promise; /** * Queue each item from the result of a database query to a worker function * @see {@link https://codehooks.io/docs/queueapi#enqueuefromquerycollection-query-topic-options Codehooks docs} * @param collection Collection name * @param query Database Query * @param topic Worker function topic string * @param options Query options * @returns Promise * @example * async function someFunction() { * const query = {"Market Category": "G"}; * const topic = 'stockWorker'; * const qres = await conn.enqueueFromQuery('stocks', query, topic); * } * * app.worker('stockWorker', (req: httpRequest, res: httpResponse) => { * const { body } = req; * console.log('Working on', body.payload) * // do stuff with body.payload * res.end() * }) */ enqueueFromQuery: ( collection: string, query: object, topic: string, options?: object ) => Promise; /** * Validate database colletion data agains JSON-Schema * @param collection string * @param schema JSON-schema * @returns Promise with result */ createSchema: (collection: string, schema: object) => Promise; /** * Validate database colletion data agains JSON-Schema * @param collection string * @param schema JSON-schema * @returns Promise with result */ setSchema: (collection: string, schema: object) => Promise; /** * Remove JSON-schema for database collection * @param collection string * @returns Promise with result */ removeSchema: (collection: string) => Promise; /** * Get JSON-schema for database collection * @param collection string * @returns Promise with result */ getSchema: (collection: string) => Promise; /** * Count database collection items * @returns Promise result */ count: (collection: string) => Promise; }; /** * Persistent NoSql and Kev-Value datastore */ export type DataStream = { /** * - Emits data, stream.on('data', (data) => //console.debug(data)) */ on: (event: string, callback: (data: any) => any) => void; /** * - Pipe datastream to JSON output */ json: (response: httpResponse) => void; /** * - Return an array of objects */ toArray: () => Promise; /** * Return an iterator * @param data * @returns Promise with iterator */ forEach: (data: object) => Promise; }; export type httpRequest = { /** * - HTTP header key value pairs, e.g. req.headers['content-type'] */ headers: any; /** * - Get the URL query parameters as key-value pairs */ query: any; /** * - Get the URL route variables as key-value pairs */ params: any; /** * - Get the request body * - JSON payload */ body: any; /** * - Get the raw unparsed request body as a string */ rawBody: string; /** * - Get the URL full path, e.g. /dev/myroute */ path: string; /** * - Get the URL api path, e.g. /myroute */ apiPath: string; /** * - Get the URL full path and query parameter string */ originalUrl: string; /** * - Get the HTTP request verb */ method: string; /** * - Get the project URL domain name */ hostname: string; /** * Pipe data to stream * @param data * @returns */ pipe: (data: any) => void; }; export type httpResponse = { /** * - End request (optional: send text|JSON data to client) */ end: (data: string | object | void) => void; /** * - Send text|JSON data to client and end request * @example * res.end() * res.status(404).end() */ send: (data: string | object) => void; /** * - End request and send JSON data to client * @example * res.json({ user: 'tobi' }) * res.status(500).json({ error: 'message' }) */ json: (document: object) => any; /** * - Write stream data to the client response. * - Content-type must be set before any write operations * - set optional type to 'buffer' for binary write operations * @example * res.set('content-type', 'text/plain') * res.write('line one') * res.write('\n') * res.write('line two') * res.end() */ write: (data: any, type?: string) => any; /** * - Set a response header value, * @example * res.set('Content-Type', 'text/html; charset=UTF-8'); */ set: (header: string, value: string) => any; /** * - Set multiple response header values, * @example * res.headers({'Content-Type': 'text/html; charset=UTF-8','X-myheader': '123456890'}); */ headers: (headers: object) => any; /** * Set a response header value * @param header string * @param value string * @returns */ setHeader: (header: string, value: string | string[]) => any; /** * Remove any default headers from a response * @param header string * @returns */ removeHeader: (header: string) => any; /** * - Return a HTTP response status code for a client request, * @example * res.status(401).end(); */ status: (code: number) => any; /** * - Render template with object data * @example * res.render('services', {title: "Services page"}) */ render: (template: string, context: object) => void; /** * - Sets the response header to redirect client request * @param statusCode - optional, set to 302 by default * @param url * @returns * @example * res.redirect('/assets/login.html'); // default status 302, Temporary * res.redirect(301, '/home/correct.html'); // status code 301, Permanently */ redirect: (statusCode: number | string, url?: string) => void; }; export type nextFunction = (error?: string) => void; // Aliases for developers familiar with Express.js conventions export type Request = httpRequest; export type Response = httpResponse; export type NextFunction = nextFunction; export type Filesystem = { /** * - Get binary file input stream. Takes a path (string) to file (e.g. /static/logo.png) and an options object (Object) for future use. Returns a Promise resolving to a binary data stream emitter. */ getReadStream: (filePath: string, options?: any) => Promise; /** * - Get file as text. Takes an absolute path (string) to file (e.g. /static/home.html) and an options object (Object) for future use. Returns a Promise resolving to the file content (string). */ readFile: (filePath: string, options?: any) => Promise; /** * - Save file binary buffer. Takes an absolute path (string) to file (e.g. /static/home.html), a buffer (Buffer) to save, and file meta data (Object). Returns a Promise resolving to the save result. */ saveFile: (filePath: string, buf: any, options?: any) => Promise; /** * - Delete a file. Takes an absolute path (string) to file and an options object (Object) for future use. Returns a Promise resolving to the result. */ deleteFile: (filePath: string, options?: any) => Promise; /** * - List content of a file directory. Takes an absolute path (string) to file and an options object (Object) for future use. Returns a Promise resolving to the result. */ list: (filePath: string, options?: any) => Promise; /** * - Read file into a Buffer. Takes an absolute path (*) to file. Returns a Promise resolving to a Buffer. */ readFileAsBuffer: (filePath: any) => Promise; }; import { agg } from './aggregation/index.mjs'; import * as crud from './crudlify/index.mjs'; export class Codehooks { static getInstance(): Codehooks; /** * Express style api */ settings: {}; routes: {}; queues: {}; jobs: {}; auths: {}; appmiddleware: any[]; datastore: any; listeners: any[]; workers: {}; /** * POST requests - e.g. app.post('/foo', callbackFunction) * @example * app.post('/myroute', (req, res) => { * //console.debug('Body', req.body) * res.json({"message": "thanks!"}) * }) * @param {string} path - API route, e.g. '/foo' * @param {...function(httpRequest, httpResponse, function(string):void)} hook - callback function(s) with parameters (req, res, [next]) */ post: ( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ) => void; /** * GET requests - e.g. app.get('/foo/:ID', callbackFunction) * @example * app.get('/myroute', (req, res) => { * //console.debug('Params', req.params) * res.json({"message": "thanks!"}) * }) * @param {string} path - API route, e.g. '/foo/:ID' * @param {...function(httpRequest, httpResponse, function(string):void)} hook - callback function(s) with parameters (req, res, [next]) */ get: ( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ) => void; /** * PUT requests * @example * app.put('/myroute', (req, res) => { * //console.debug('Body', req.body) * res.json({"message": "thanks!"}) * }) * @param {string} path - API route, e.g. '/foo/:ID' * @param {...function(httpRequest, httpResponse, function(string):void):void} hook - callback function(s) with parameters (req, res, [next]) */ put: ( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => void)[] ) => void; /** * PATCH requests * @example * app.patch('/myroute', (req, res) => { * //console.debug('Body', req.body) * res.json({"message": "thanks!"}) * }) * @param {string} path - API route, e.g. '/foo/:ID' * @param {...function(httpRequest, httpResponse, function(string):void)} hook - callback function(s) with parameters (req, res, [next]) */ patch: ( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ) => void; /** * DELETE requests - app.delete('/foo', callbackFunction) * @example * app.delete('/myroute', (req, res) => { * res.json({"message": "thanks!"}) * }) * @param {string} path - API route, e.g. '/foo/:ID' * @param {...function(httpRequest, httpResponse, function(string):void)} hook - callback function(s) with parameters (req, res, [next]) */ delete: ( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ) => void; /** * All HTTP methods - app.all('/pets/cat', (req, res) => res.end('Mjau')) * @example * app.all('/myroute', (req, res) => { * //console.debug('Body', req.body || 'no body') * res.json({"message": "thanks!"}) * }) * @param {string} path - API route, e.g. '- API endpoint route, e.g. '/pets' * @param {...function(httpRequest, httpResponse, function(string)):void} hook - callback function(s) with parameters (req, res, [next]) */ all: ( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: (error?: string) => any ) => void)[] ) => void; /** * Allow custom authentication * @example * app.auth('/*', (req, res, next) => { * if (1 === 1) { * next() * } else { * res.status(403).end('No soup!') * } * }) * @param {string|RegExp} path - API route, e.g. '/foo/*' * @param {...function(httpRequest, httpResponse, function(string):void):void} hook - callback function(s) with parameters (req, res, [next]) */ auth: ( path: string | RegExp, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => void)[] ) => void; /** * Global middleware * @example * // global middleware * app.use((req, res, next) => { * //console.debug("Global middleware was here!"); * next(); // proceed * }) * @param {...function(httpRequest, httpResponse, function(string):void):void} hook - callback function(s) with parameters (req, res, next) */ use( ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => void)[] ): void; /** * Global middleware * @example * // middleware on a route defined by a regular expression * app.use(/^\/(foo|bar)/, (req, res, next) => { * //console.debug("RegExp route middleware was here!"); * next(); // proceed * }) * @param {RegExp} regex * @param {...function(httpRequest, httpResponse, function(string):void):void} hook - callback function(s) with parameters (req, res, next) */ use( regex: RegExp, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => void)[] ): void; /** * Global middleware * @example * // middleware on a specific route * app.use('/myroute', (req, res, next) => { * //console.debug("Route middleware was here!"); * next(); // proceed * }) * @param {string} path * @param {...function(httpRequest, httpResponse, function(string):void):void} hook - callback function(s) with parameters (req, res, next) */ use( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => void)[] ): void; /** * Global route middleware * @example * // Global middleware on a specific route * app.use('/myroute', (req, res, next) => { * //console.debug("Route middleware was here!"); * next(); // proceed * }) * @param {string|RegExp} path - Optional API route or RegExp, e.g. '/myroute/*' * @param {...function(httpRequest, httpResponse, function(string):void):void} hook - callback function(s) with parameters (req, res, next) */ useRoute: ( path: string | RegExp, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => void)[] ) => void; /** * Process queue job items for topic * @param {string} topic * @param {...function(httpRequest, httpResponse, function(string):void)} hook - callback function(s) with parameters (req, res, [next]) */ queue: ( topic: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ) => void; /** * Add application worker function * @param {string} name - Unique worker name * @param {function} hook - Worker callback function with parameters (req, res, [next]) * @param {Record} options - Optional configuration stored in key-value store under `worker:${name}` key in keyspace '_codehooks_worker_settings' * * @example * // Simple worker * await app.worker('myworker', (req, res) => { * const {body:{payload}} = req * console.log('worker payload data', payload) * res.end() *}) * * @example * // Worker with configuration stored in KV store * await app.worker('myworker', (req, res) => { * const {body:{payload}} = req * console.log('Processing:', payload) * res.end() * }, { * workers: 2, * timeout: 30000 * }) */ worker: ( name: string, hook: ( request: httpRequest, response: httpResponse, next?: nextFunction ) => any, options?: Record ) => Promise; /** * Create cron background jobs * @example * // call function each minute * app.job('* * * * *', (req, res) => { * //console.debug('tick each minute') * res.end() * }) * @param {string} cronExpression - cron expression * @param {...function(httpRequest, httpResponse, function(string):void)} hook - callback function(s) with parameters (req, res, [next]) */ job: ( cronExpression: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ) => void; /** * Set up a server-sent events channel endpoint (SSE). * This method registers a set of middleware (hooks) for the channel and defines an SSE endpoint. * * @param {string} path - The channel on which to establish a real-time connection. This acts as the base path for the SSE endpoint. * @param {...function(httpRequest, httpResponse, function(string):void)} hook - Optional middleware functions to be applied to the channel (access check for example). These functions are executed in the order they are provided. */ realtime( path: string, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[] ): void; /** * Serve static file content from a source code diretory * @param {Object} options - * - options.route - API route to serve assets * - options.directory - path to directory with assets/files * - options.default - default file name if root is / @param {...function(httpRequest, httpResponse, function(string):void)} hook - Optional middleware functions to be applied before resource is served * @example * app.static({route:'/static', directory: '/assets'}, (req, res, next) => { * console.log("Serving a static resource", req.path); * next(); * }) * @returns void */ static: (options: any, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[]) => void; /** * Serve file content from a blob storage diretory * @param {Object} options - {route: "/documents", directory: "/docs"} * @returns void */ storage: (options: any, ...hook: (( request: httpRequest, response: httpResponse, next: nextFunction ) => any)[]) => void; /** * Configuration settings * @param {string} key * @param {*} val * @example * app.set('views', '/views') * app.set('view engine', {"hbs": handlebars}) */ set: (key: string, val: any) => void; /** * * @param {string} view * @param {object} data * @param {function(string):void)} cb */ render: (view: string, data: object, cb: any) => Promise; /** * Create CRUD REST API for database * @see {@link https://codehooks.io/docs/database-rest-api} * @see {@link https://codehooks.io/docs/database-rest-api#data-validation-with-yup Data validation with Yup, Zod, JSON.schema} * @param {object} schema * @param {object} options - Optional {prefix: "/crud"} serve all crud routes under sub route /crud/* * @returns Promise - Eventhooks */ crudlify: ( schema?: object, options?: object ) => Promise; /** * Returns the Codehooks serverless definitions used by a serverless runtime engine * @example * export default app.init(); * @returns {Object} App instance */ init: (cb?: any) => any; /** * Alias for app.init() * @example * export default app.start(); * @returns {Object} App instance */ start: (cb?: any) => any; /** * Use Node Express app to run standalone * All Codehooks routes will be applied as Express Routes * @param {Object} express app instance * @param {Object} options for Datastore and routing space */ useExpress: (express: any, options: any) => Promise; /** * Set Datastore interface * @param {*} ds */ setDatastore: (ds: any) => void; getDatastore: () => { open: () => Promise; }; addListener: (observer: any) => void; /** * Create a new workflow * @param name - Unique identifier for the workflow * @param description - Human-readable description of the workflow * @param steps - Object containing step definitions * @param options - Optional configuration options * @returns Workflow instance for managing the workflow */ createWorkflow: (name: string, description: string, steps: WorkflowDefinition, options?: WorkflowConfig) => Workflow; /** * Register a workflow with the application * @param name - Unique identifier for the workflow * @param description - Human-readable description * @param steps - Step definitions * @returns Promise with the registered workflow name */ registerWorkflow: (name: string, description: string, steps: WorkflowDefinition) => Promise; /** * Fetch data from another Codehooks API * @param url - URL to fetch from, e.g. http://myapi-ffee.codehooks.io/dev/api/myroute * @param options - Fetch options * @returns Promise with the fetched data */ internalFetch: (url: string, options?: any) => Promise; /** * Enable OpenAPI documentation * @param config - OpenAPI configuration * @param uiPath - Path to serve Swagger UI (default: '/docs') * @returns this for chaining * @example * app.openapi({ * info: { * title: "My API", * version: "1.0.0" * } * }, '/docs'); */ openapi: (config?: OpenAPIConfig, uiPath?: string) => Codehooks; /** Stored OpenAPI metadata for routes */ openApiMeta: Record; } declare const _coho: Codehooks; /** * Events emitted by the workflow engine */ export type WorkflowEvents = { /** * Emitted when a new workflow is registered * @event */ 'workflowCreated': { name: string; description: string }; /** * Emitted when a new workflow instance is started * @event */ 'workflowStarted': { name: string; initialState: any }; /** * Emitted when a step begins execution * @event */ 'stepStarted': { workflowName: string; step: string; state: any; instanceId: string }; /** * Emitted when a step's state is updated * @event */ 'stateUpdated': { workflowName: string; state: any; instanceId: string }; /** * Emitted when a step is enqueued for execution * @event */ 'stepEnqueued': { workflowName: string; step: string; state: any; instanceId: string }; /** * Emitted when a workflow instance is continued after waiting * @event */ 'workflowContinued': { workflowName: string; step: string; instanceId: string }; /** * Emitted when a workflow instance is completed * @event */ 'completed': { message: string; state: any }; /** * Emitted when a workflow instance is cancelled * @event */ 'cancelled': { id: string }; /** * Emitted when an error occurs * @event */ 'error': { error: Error }; }; /** * Definition of a workflow step function */ export type WorkflowDefinition = Record void, waiterFunction?: (waiter?: any) => void ) => Promise>; /** * Configuration options for a workflow step */ export type StepOptions = { /** Timeout in milliseconds for this specific step */ timeout?: number; /** Maximum number of retries for this step */ maxRetries?: number; }; /** * Configuration options for the Workflow engine */ export type WorkflowConfig = { /** Collection name for storing workflow data */ collectionName?: string; /** Queue prefix for workflow jobs */ queuePrefix?: string; /** Global timeout in milliseconds for workflow steps */ timeout?: number; /** Maximum number of times a step can be executed */ maxStepCount?: number; /** Step-specific configuration options */ steps?: Record; }; /** * Workflow engine for managing step-based applications * @extends EventEmitter */ export type Workflow = { /** * Configure the workflow engine * @param options - Configuration options * @param options.collectionName - Collection name for storing workflow data * @param options.queuePrefix - Queue prefix for workflow jobs * @param options.timeout - Timeout in milliseconds for workflow steps * @param options.maxStepCount - Maximum number of times a step can be executed * @param options.steps - Workflow step configuration * @example * workflow.configure({ * collectionName: 'workflows', * queuePrefix: 'workflow', * timeout: 30000, * maxStepCount: 3, * steps: { * stepName: { * timeout: 3000, * maxRetries: 3 * } * } * }); */ configure: (options: WorkflowConfig) => void; /** * Get the collection name for storing workflow data * @returns The collection name */ getCollectionName: () => string; /** * Set the collection name for storing workflow data * @param name - Collection name */ setCollectionName: (name: string) => void; /** * Get the queue prefix for workflow jobs * @returns The queue prefix */ getQueuePrefix: () => string; /** * Set the queue prefix for workflow jobs * @param prefix - Queue prefix */ setQueuePrefix: (prefix: string) => void; /** * Get the timeout for workflow steps * @returns The timeout in milliseconds */ getTimeout: () => number; /** * Set the timeout for workflow steps * @param timeout - Timeout in milliseconds */ setTimeout: (timeout: number) => void; /** * Get the maximum step count * @returns The maximum step count */ getMaxStepCount: () => number; /** * Set the maximum step count * @param maxStepCount - Maximum step count */ setMaxStepCount: (maxStepCount: number) => void; /** * Get the steps configuration * @returns The steps configuration */ getStepsConfig: () => Record; /** * Set the steps configuration * @param steps - Steps configuration */ setStepsConfig: (steps: Record) => void; /** * Get the step definition for a specific step * @param workflowName - Name of the workflow * @param stepName - Name of the step * @returns The step function */ getDefinition: (workflowName: string, stepName: string) => Function; /** * Register a new workflow with a Codehooks application * @param app - Codehooks application instance * @returns Promise with the registered workflow name */ register: (app: Codehooks) => Promise; /** * Start a new workflow instance * @param initialState - Initial state for the workflow instance * @returns Promise with the workflow instance */ start: (initialState: any) => Promise; /** * Update the state of a workflow instance * @param instanceId - ID of the workflow instance * @param state - New state to update with * @param options - Options for the update, { continue: false } to avoid continuing the step * @returns Promise with the updated state */ updateState: (instanceId: string, state: any, options?: UpdateOptions) => Promise; /** * Set the complete state of a workflow instance * @param instanceId - ID of the workflow instance * @param stateData - Object containing _id and state * @returns Promise */ setState: (instanceId: string, stateData: { _id: string; state: any }) => Promise; /** * Continue a paused workflow instance * @param instanceId - ID of the workflow instance * @param reset - Whether to reset all step counts (true) or just the current step (false) * @returns Promise with the queue ID for the continued step */ continue: (instanceId: string, reset?: boolean) => Promise<{ instanceId: string }>; /** * Get the status of a workflow instance * @param id - ID of the workflow instance * @returns Promise with the workflow status */ getStepsStatus: (id: string) => Promise; /** * Get all workflow instances matching a filter * @param filter - Filter criteria for workflows * @returns Promise with list of workflow instances */ getInstances: (filter: any) => Promise; /** * Cancel a workflow instance * @param id - ID of the workflow instance to cancel * @returns Promise with the cancellation result */ cancelSteps: (id: string) => Promise; /** * Get the status of a workflow instance (alias for getStepsStatus) * @param id - ID of the workflow instance * @returns Promise with the workflow status */ getWorkflowStatus: (id: string) => Promise; /** * Get the state of a workflow instance (alias for getStepsStatus) * @param id - ID of the workflow instance * @returns Promise with the workflow state */ getState: (id: string) => Promise; /** * Cancel a workflow instance (alias for cancelSteps) * @param id - ID of the workflow instance to cancel * @returns Promise with the cancellation result */ cancelWorkflow: (id: string) => Promise; /** * Register an event listener * @param event - Name of the event to listen for * @param listener - Callback function to handle the event * @example * workflow.on('stepStarted', ({ workflowName, step, state, instanceId }) => { * console.log(`Step ${step} started in workflow ${workflowName}`); * }); */ on: (event: WorkflowEvent, listener: (data: WorkflowEventData) => void) => Workflow; /** * Register a one-time event listener * @param event - Name of the event to listen for * @param listener - Callback function to handle the event */ once: (event: WorkflowEvent, listener: (data: WorkflowEventData) => void) => Workflow; /** * Remove an event listener * @param event - Name of the event * @param listener - Callback function to remove */ off: (event: WorkflowEvent, listener: (data: WorkflowEventData) => void) => Workflow; /** * Emit an event * @param event - Name of the event to emit * @param data - Event data */ emit: (event: WorkflowEvent, data: WorkflowEventData) => boolean; /** * Continue all timed out workflow instances * @returns Promise with array of results containing queue IDs for continued workflows */ continueAllTimedOut: () => Promise>; /** * Check if a specific step in a workflow instance has timed out * @param workflow - The workflow instance to check * @returns Object containing timeout status and details * @example * const status = workflow.isStepTimedOut(workflowInstance); * // Returns: * // { * // isTimedOut: boolean, * // executionTime?: number, // if step has finished * // runningTime?: number, // if step is still running * // timeout: number, // actual timeout value used * // step: string, // name of the step checked * // startTime: string, // ISO timestamp * // finishTime?: string, // if step has finished * // currentTime?: string, // if step is still running * // timeoutSource: 'stepConfig' | 'defaultOptions' | 'globalTimeout' * // reason?: string // if step not found * // } */ isStepTimedOut: (workflow: any) => { isTimedOut: boolean; executionTime?: number; runningTime?: number; timeout: number; step: string; startTime: string; finishTime?: string; currentTime?: string; timeoutSource: 'stepConfig' | 'defaultOptions' | 'globalTimeout'; reason?: string; }; /** * Find all workflow instances with timed out steps * @param filter - Optional filter criteria for workflows * @returns Promise with array of workflow instances that have timed out steps * @example * const timedOutWorkflows = await workflow.findTimedOutSteps(); * // Returns array of workflows with timeout details: * // [{ * // workflowId: string, * // workflowName: string, * // isTimedOut: true, * // executionTime?: number, * // runningTime?: number, * // timeout: number, * // step: string, * // startTime: string, * // finishTime?: string, * // currentTime?: string, * // timeoutSource: string * // }] */ findTimedOutSteps: (filter?: any) => Promise>; }; /** * Options for updating workflow state */ export type UpdateOptions = { /** Whether to continue to the next step after update */ continue?: boolean; }; /** * Workflow event types */ export type WorkflowEvent = | 'workflowCreated' | 'workflowStarted' | 'workflowContinued' | 'stepStarted' | 'stepEnqueued' | 'stateUpdated' | 'completed' | 'cancelled' | 'error'; /** * Data structure for workflow events */ export type WorkflowEventData = { workflowName?: string; name?: string; description?: string; step?: string; state?: any; instanceId?: string; error?: Error; id?: string; [key: string]: any; }; // ============================================ // OpenAPI Documentation Types // ============================================ /** * OpenAPI JSON Schema type (subset) */ export type OpenAPISchema = { type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object'; format?: string; items?: OpenAPISchema; properties?: Record; required?: string[]; $ref?: string; enum?: any[]; default?: any; example?: any; description?: string; nullable?: boolean; allOf?: OpenAPISchema[]; oneOf?: OpenAPISchema[]; anyOf?: OpenAPISchema[]; [key: string]: any; }; /** * OpenAPI Parameter specification */ export type OpenAPIParameter = { name: string; in: 'path' | 'query' | 'header' | 'cookie'; description?: string; required?: boolean; schema: OpenAPISchema; example?: any; }; /** * OpenAPI Request Body specification */ export type OpenAPIRequestBody = { description?: string; required?: boolean; content: Record; }; /** * OpenAPI Response specification */ export type OpenAPIResponse = { description: string; content?: Record; headers?: Record; }; /** * OpenAPI Route specification for openapi() wrapper */ export type OpenAPIRouteSpec = { /** Short summary of what the operation does */ summary?: string; /** Verbose explanation of the operation */ description?: string; /** Tags for API documentation grouping */ tags?: string[]; /** Unique operation identifier for code generation */ operationId?: string; /** Parameters (path, query, header, cookie) */ parameters?: OpenAPIParameter[]; /** Request body specification */ requestBody?: OpenAPIRequestBody; /** Response specifications by status code */ responses?: Record; /** Security requirements for this operation */ security?: Array>; /** Whether this operation is deprecated */ deprecated?: boolean; }; /** * OpenAPI Info object */ export type OpenAPIInfo = { title?: string; description?: string; version?: string; termsOfService?: string; contact?: { name?: string; url?: string; email?: string }; license?: { name: string; url?: string }; }; /** * OpenAPI Server object */ export type OpenAPIServer = { url: string; description?: string; variables?: Record; }; /** * OpenAPI Tag object */ export type OpenAPITag = { name: string; description?: string; externalDocs?: { url: string; description?: string }; }; /** * Filter operation object passed to the filter function */ export type OpenAPIFilterOperation = { /** HTTP method (lowercase): 'get', 'post', 'put', 'patch', 'delete' */ method: string; /** Route path: '/todos', '/todos/{ID}' */ path: string; /** Operation ID if set */ operationId?: string; /** Array of tags */ tags: string[]; /** Operation summary */ summary?: string; }; /** * OpenAPI Configuration for app.openapi() */ export type OpenAPIConfig = { /** OpenAPI Info object */ info?: OpenAPIInfo; /** Server definitions */ servers?: OpenAPIServer[]; /** Custom schemas to add to components */ components?: { schemas?: Record; securitySchemes?: Record; }; /** Global security requirements */ security?: Array>; /** Path to serve the OpenAPI JSON spec (default: '/openapi.json') */ specPath?: string; /** Swagger UI configuration */ swaggerUi?: { oauth2RedirectUrl?: string; validatorUrl?: string | null; favicon?: string; }; /** Tags for grouping endpoints */ tags?: OpenAPITag[]; /** External documentation */ externalDocs?: { url: string; description?: string }; /** * Filter function to control which operations appear in the documentation. * Return true to include the operation, false to exclude it. * @example * // Exclude DELETE operations * filter: (op) => op.method !== 'delete' * * // Exclude internal routes * filter: (op) => !op.path.startsWith('/internal') * * // Only include specific tags * filter: (op) => op.tags.includes('Public') */ filter?: (op: OpenAPIFilterOperation) => boolean; }; /** * Wrap a route handler with OpenAPI documentation * @param spec - OpenAPI specification for this route * @returns Middleware function with attached metadata * @example * app.get('/users/:id', * openapi({ * summary: "Get user by ID", * tags: ["Users"], * responses: { 200: { description: "Success" } } * }), * (req, res) => res.json({ id: req.params.id }) * ); */ export function openapi(spec: OpenAPIRouteSpec): ( req: httpRequest, res: httpResponse, next: nextFunction ) => void; /** * Helper to create response specification * @param description - Response description * @param schema - Response schema (JSON Schema or Zod/Yup) * @param contentType - Content type (default: 'application/json') */ export function response( description: string, schema?: OpenAPISchema, contentType?: string ): OpenAPIResponse; /** * Helper to create request body specification * @param schema - Request body schema * @param options - Additional options */ export function body( schema: OpenAPISchema, options?: { required?: boolean; description?: string; contentType?: string } ): OpenAPIRequestBody; /** * Helper to create path parameter specification * @param name - Parameter name * @param options - Parameter options */ export function param( name: string, options?: { description?: string; schema?: OpenAPISchema; example?: any } ): OpenAPIParameter; /** * Helper to create query parameter specification * @param name - Parameter name * @param options - Parameter options */ export function query( name: string, options?: { description?: string; required?: boolean; schema?: OpenAPISchema; example?: any } ): OpenAPIParameter; /** * Helper to create header parameter specification * @param name - Header name * @param options - Parameter options */ export function header( name: string, options?: { description?: string; required?: boolean; schema?: OpenAPISchema; example?: any } ): OpenAPIParameter; //# sourceMappingURL=index.d.ts.map