/* eslint-disable */ // @ts-ignore import type {IncomingHttpHeaders} from "http"; // @ts-ignore import type { Buffer, Buffer as NonSharedBuffer } from "buffer"; // @ts-ignore import type { RequestInit, Response } from "node-fetch"; declare global { /** * A hash array representing an Excel Row. * @desc Keys are the labels defined in the 1st row. */ type ExcelRowHash = Record; /** * excel2JS conversion options. * @type {Object} * @property {string|number} [sheetName] Parse only this sheet, by name or index number. Defaults to every non-empty sheet * @property {boolean} [keepEmptyRows] Defaults to false * @property {number} [skipRowsBeforeHeader] Defaults to 0 * @property {number} [skipRowsAfterHeader] Defaults to 0 */ interface Excel2JsOptions { sheetName?: string | number; keepEmptyRows?: boolean; skipRowsBeforeHeader?: number; skipRowsAfterHeader?: number; } /** * The input of an Excel conversion can be a Buffer /decoded or the path to a file */ type Excel2JsInput = Buffer|string; /** * Read the content of a file and returns an object. * @desc object keys are sheet names, content is an array of rows, * @desc Each row is an array of hash arrays, whose keys are first row values (labels) * @function * @async * @param {Excel2JsInput} content The file content, a buffer object or the absolute path to a static file * @param {Excel2JsOptions} [options] Conversion options object * @param {string|number} [options.sheetName] Parse only this sheet, by name or index number. Defaults to every non-empty sheet * @param {boolean} [options.keepEmptyRows] Defaults to false * @param {number} [options.skipRowsBeforeHeader] Defaults to 0 * @param {number} [options.skipRowsAfterHeader] Defaults to 0 * @return { Promise> } */ type Excel2JS = ( content: Excel2JsInput, options?: Excel2JsOptions ) => Promise>; /** * The simplified object of a mail. * @desc Mandatory properties: "to", "text" or "html" * @summary All recipients' properties can be a single recipient string, an array of strings or a comma-separated recipient's string. * @summary All the recipient strings can be simple email addresses or in the form "Name ". * @summary "from" isn't allowed, it's set by server's configuration (in any case config can be passed different on each message) * @type {Object} * @property {string|string[]} to Array or comma-separated list of recipients * @property {string|string[]} [cc] Array or comma-separated list of recipients * @property {string|string[]} [bcc] Array or comma-separated list of recipients * @property {Record} [headers] Additional headers, if any * @property {'high'|'normal'|'low'} [priority] Defaults to "normal" * @property {string} subject Email subject * @property {string} [text] Text version of the mail * @property {string} [html] HTML version of the mail */ interface DrsMailMessageObject { to : string|string[]; cc?: string|string[]; bcc?: string|string[]; headers?: Record; priority?: 'high'|'normal'|'low'; subject?: string; text?: string; html?: string; } /** * Mailer configuration * @type {Object} * @property {string} host SMTP address (IP or iname) * @property {number} port SMTP port * @property {string} from Sender,as email address or "name
" * @property {boolean} [secure] Start the connection secure (defaults to false, can start TLS later) * @property {string} [authType] Defaults to "login" * @property {string} [authUser] User ID for SMTP authentication * @property {string} [authPassword] Password for SMTP authentication */ interface DrsMailMessageConfig { host: string; port: number; from: string; secure?: boolean; authType?: string; authUser?: string; authPassword?: string; } /** * The param object to send an email * @type {Object} * @property {DrsMailMessageObject} message The message * @property {DrsMailMessageConfig} [mailConfig] Optional mail configuration */ interface DrsMailMessageParams { message: DrsMailMessageObject; mailConfig?: DrsMailMessageConfig; } interface DrsHelperNewItemCoordinates { id?: string; entity?: string; schema?: string; } interface DrsHelperItemCoordinates { id:string; entity?: string; schema?: string; } /** * Import a script (js or mjs) or fetch a file (JSON or text) external to the operation .mjs file * @abstract This method can be used to read various file types: * * .json files: are converted into a data object * * .js/.mjs files: are imported, acting exactly like drs.import() * * any other file type: its content is returned in a string, parsed UTF-8. * @function * @async * @param {string} path * @return {Promise} */ type DrsHelperFunctionFetchConfig = (path:string) => Promise; /** * List a dataset, a schema or an entity * * In case of dataset or schema directory names are returned without the trailing "/" * * The list is aware of transaction changes not committed yet * @function * @param {string} [schema] * @param {string} [entity] * @return {string[]} */ type DrsHelperFunctionList = (schema?:string, entity?:string ) => string[]; /** * Returns true if memory cell exists and isn't empty, false otherwise. * @function * @param {DrsHelperItemCoordinates|string} coords coordinates or ID * @return {boolean} Memory cell file exists and has at least one key */ type DrsHelperFunctionExists = (coords: DrsHelperItemCoordinates|string ) => boolean; /** * Read a JSON file from data, returns undefined if file doesn't exist. * @function * @param {DrsHelperItemCoordinates|string} coords coordinates or ID * @return {object|undefined} File content parsed, undefined if file doesn't exist */ type DrsHelperFunctionGet = (coords: DrsHelperItemCoordinates|string ) => object|undefined; /** * Set a JSON file in data, deletes it if content is undefined * @function * @param {DrsHelperNewItemCoordinates|string} [coords] coordinates or ID, defaults to current values and auto-generated ID * @param {object|string} [content] An Object, or its JSON, or undefined to delete the file * @return {string} The ID */ type DrsHelperFunctionSet = (coords: DrsHelperNewItemCoordinates|string|undefined, content?: object|string ) => string; /** * Delete a JSON file in data * @function * @param {DrsHelperNewItemCoordinates|string} coords coordinates or ID, defaults to current values and auto-generated ID * @return {string} The ID */ type DrsHelperFunctionRm = (coords: DrsHelperNewItemCoordinates|string ) => string; /** * Execute a MariaDB statement (with or without bind values) and returns result (if any). * @function * @async * @param {string} sql The SQL statement to be executed * @param {Array} [values] Values to bind, if any * @return {Promise} */ type DrsHelperFunctionSql = (sql: string, values?:Array ) => Promise; /** * @desc Postgres only: `ON CONFLICT` management * @abstract Possible values are: * * `undefined|"*"`: same behavior as MariaDB, automatically detects all possible conflicts * * `true`: smooth insert, i.e.: `ON CONFLICT DO NOTHING` * * `false`: no `ON CONFLICT` management at all, throws an error in case of conflicts * * `string|string[]`: enumerates column names and/or foreign key names to be considered for `ON CONFLICT DO UPDATE` */ type DrsHelperInsertConflicts = undefined|"*"|boolean|string|Array; /** * Execute a INSERT/ON DUPLICATE KEY UPDATE returning inserted rows * @function * @async * @param {string} table Table name * @param {Record|Array>} data The data to be inserted * @param {DrsHelperInsertConflicts} [conflicts] Postgres only: ON CONFLICT management * @return {Promise>>} */ type DrsHelperFunctionInsert = ( table: string, data: Record|Array>, conflicts?: DrsHelperInsertConflicts ) => Promise>>; interface DrsHelperTableColumnDefinition { type: string; comment?: string; length?: number; scale?: number; autoIncrement?: boolean; defaultValue?: any; nullable?: boolean; primaryKey?: boolean; } interface DrsHelperTableIndexDefinition { columns: string[]; unique?: boolean; primary?: boolean; } interface DrsHelperTableDefinition { columns: Record; indexes?: Record; comment?: string; } /** * Check if table exists, otherwise optionally create it * @function * @async * @param {string} tableName * @param {string} [creationSql] * @return {Promise} */ type DrsHelperFunctionCheckSqlTable = (tableName: string, creationSql?:string ) => Promise; /** * Send an email * @function * @param {DrsMailMessageParams|DrsMailMessageObject} params * @return {Promise} */ type DrsHelperFunctionMail = (params: DrsMailMessageParams|DrsMailMessageObject ) => Promise; interface DrsHelperDumpItemCoordinates { dumpKey?: string; path?: string; } /** * List the content of a dir under (a) dump location * * Returns false if not allowed or not recognized * * Throws a 403 if trying to lost out of allowed scope(s) defined by dumpRoot location(s) * * Returns a list of file names and directory names (with trailing "/"). * * The list is aware of transaction changes not committed yet * @function * @param {string} [path] In the form "dumpKey:relative/path", "dumpKey:", "relativePath" or "" * @return {string[]|false} */ type DrsHelperFunctionDumpList = (path?: string ) => string[]|false; /** * Get the content of a static file under (some) dumpRoot * * Returns undefined if file doesn't exist * * Throws a 403 if trying to lost out of allowed scope(s) defined by dumpRoot location(s) * * Returns UTF-8 content of file otherwise. * @function * @param {string} path In the form "dumpKey:relative/path/to/file" or "relative/path/to/file" * @return {string|undefined} */ type DrsHelperFunctionDumpGet = (path: string ) => string|undefined; /** * Set the content of a static file under (some) dumpRoot, deletes it if content is undefined * * Throws a 403 if trying to lost out of allowed scope(s) defined by dumpRoot location(s) * * Returns file name * @function * @param {string} path In the form "dumpKey:relative/path/to/file" or "relative/path/to/file" * @param {any} [content] * @return {string|undefined} */ type DrsHelperFunctionDumpSet = (path: string, content?:any ) => string|undefined; /** * Commit changes to DB and file-system * @function * @param {boolean} [releaseConnection] * @return {void} */ type DrsHelperFunctionCommit = ( releaseConnection?: boolean ) => void; /** * Revert non-committed changed to DB and file-system * @function * @return {void} */ type DrsHelperFunctionRollback = () => void; /** * Send (once) the output for request, while further send action(s) will be ignored * @abstract Send is automatically performe with the returned result of the operation. * @abstract On the other hand, especially in case of time-consuming async processes, or in case of processes * requiring a callback, it's possible to send quickly a response and then keep the operation running. * @abstract Note: sending an error doesn't stop the script, nor perform rollback. * If you want to stop the script and perform a drs.rollback() throw instead an Error(). * @function * @param {object|string|Error} what The content to be sent * @param {string} [ContentType] The optional content-type (ignored for a javascript object) * @return {void} * @see {DrsHelperFunctionRollback} * @example * drs.send( { foo: "bar" }); * drs.send( "Hello world!"); * drs.send( new Error("Scrambled data") ); */ type DrsHelperFunctionSend = ( what: object|string|Error, ContentType?:string ) => void; /** * The params for a sub-operation * @type {Record} * @property {string} [schema] The schema name, overwritten if derived from URI * @property {string} [entity] The entity name, overwritten if derived from URI * @property {string} operation The operation, overwritten if derived from URI * @property {boolean|number|"true"|"false"|"Yes"|"Y"|"No"|"N"} [dry_run] Set to true or deleted after backend analysis. * If true, all changes to files and DB aren't committed. */ interface DrsDbOperationSubObjectParams { schema?: string; entity?: string; operation: string; dry_run?: boolean|number|"true"|"false"|"Yes"|"Y"|"No"|"N"; } /** * Can be an object or operation name. * @see {DrsDbOperationSubObjectParams} */ type DrsDbOperationSubParams = DrsDbOperationSubObjectParams|string; /** * A subprocess internal call * @function * @async * @param {DrsDbOperationSubParams} params * @param {Object} [data] * @return {Promise} * @see {DrsDbOperationSubObjectParams} */ type DrsHelperFunctionSub = ( params: DrsDbOperationSubParams, data?: object ) => Promise; /** * A subprocess detached call * @function * @param {DrsDbOperationSubParams} params Call parameters * @param {Object} [data] Defaults to {} * @param {number} [delay] Defaults to 10 (10 mSec, 0.01s) * @return {void} * @see {DrsHelperFunctionSub} * @see {DrsDbOperationSubObjectParams} */ type DrsHelperFunctionDetach = ( params: DrsDbOperationSubParams, data?: object, delay?: number ) => void; /** * Fetch a resource using node-fetch * @function * @param {string} URL * @param {RequestInit} [RequestInit] * @param {boolean} [ignoreSslVerification] * @return {Promise} */ type DrsHelperFunctionFetch = ( URL: string, RequestInit?: RequestInit, ignoreSslVerification?: boolean ) => Promise; /** * Import an external javascript using node-fetch * @function * @param {string} URL * @param {RequestInit} [RequestInit] * @return {Promise} */ type DrsHelperFunctionImport = ( URL: string, RequestInit?: RequestInit ) => Promise; /** * Debug: console some values * @function * @params {any[]} * @return {void} */ type DrsHelperFunctionConsole = ( any: any ) => void; /** * Debug: Send log to dataset's log.txt * @function * @param {string|Error|number|Object} what The content to be sent * @return {void} */ type DrsHelperFunctionLog = ( what: string|Error|number|Object ) => void; /** * Import an extension module * @function * @param {string} extName * @return {Promise} */ type DrsHelperFunctionExtension = ( extName?: string ) => Promise; /** * Helper to manage ZIP archives to be sent in response * @type {Object} * @property {(coords: DrsHelperItemCoordinates|string): Promise} add Add item(s) or a whole entity to the Zip archive, returns archive size * @property {()=>void} dispose Remove temporary files, automatically managed by DrsHelperObject * @property { ( fileName?: string )=> NonSharedBuffer } send Sets response headers and return buffer for operation "return": return myZip.send() */ interface zipHelperObject { add(coords: DrsHelperItemCoordinates|string): Promise; send( fileName?: string ): NonSharedBuffer; dispose(): void; } interface DrsHelperFunctionReturn { stdout: string, stderr: string, errorcode?: number, error?: Error } /** * Exec a shell command * @function * @async * @param {string} command * @param {Record|string} options options object or Current Work Directory * @return {Promise} */ type DrsHelperFunctionExec = ( command: string, options: Record|string ) => Promise; /** * @method * @desc A shelf where we can put and retrieve stuff * @abstract Notes about the shelf: * * The shelf lives as soon as the ```drs``` object lives, initially empty * * It can hold objects of whatever nature, because object themselves are returned - not a clone * * Implication: in case of objects (arrays, etc.) changes propagate to the original item stored in the shelf * @param {string} [key] The name of the item on the shelf. If missing (```undefined```) a list of object names is returned. * @param {null|any} [value] The value of the object. ```null``` deletes the object, if missing (```undefined```) the actual value is returned * @return {Array|undefined|any} * @usage There are 4 ways to use ```drs.shelf()```: * ```javascript * // List all defined shelf keys, returns string[]: * drs.shelf() * // Store a value * drs.shelf('propertyName', value ); * // Retrieve a value * drs.shelf('propertyName'); * // Delete a value * drs.shelf('propertyName', null ); * ``` */ type DrsHelperFunctionShelf = ( key?: string, value?: null|any ) => Array|undefined|any; /** * @desc Extend the DrsHelperObject itself * @abstract Notes about extensions: * * The extension lives as soon as the drs object lives * * Can extend with objects of whatever nature, because object themselves are returned - not a clone * * Implication: in case of objects (arrays, etc.) changes propagate to the original item * * An ```undefined``` value deletes extension * * Don't forget to declare global interface extension * * All pre-defined drs methods are protected, cannot be deleted, changed or overwritten - neither acting directly on ```drs``` object nor through ```drs.extend()```. **Any attempt to re-define them will throw an exception**. * @function * @param {string} [key] The name of the property for the extension. * @param {any} [value] The associated value. If undefined (missing) deletes the object * @return {void} * @usage * In operation, autoexec or some .d.ts: * ```typescript * interface global { * export interface DrsHelperObject { * myLibrary?: MyLibraryHelperInterface; * } * } * ``` * Later on, define extension in some JS/TS function: * ```typescript * drs.extend('myLibrary', (await drs.config('/MyLibrary.mjs')).default() ); * ``` * Using the extension in some JS/TS function: * ```typescript * drs.myLibrary( … ); * ``` * To remove extension: * ```typescript * drs.extend('myLibrary'); * ``` */ type DrsHelperFunctionExtend = ( key?: string, value?: null|any ) => void; type DrsHelperFunctionGetEnv = () => DrsDbOperationEnv; type DrsHelperFunctionGetParams = () => DrsDbOperationParams; /** * The DRS helper object sent to operation scripts. * @abstract This object provides interaction with the backend of DRS. * @abstract At the same time it strictly limits the action to the current dataset: * * SQL access is restricted to the only defined db, if any * * Memory cell files can be read/write only under the dataset's umbrella (defined dataRoot) * * Config scripts/files can be retrieved only under the dataset's configRoot * * Static files are restricted to defined dumpRoot location(s), if any. * @type {Object} */ interface DrsHelperObject { /** Import a script (js or mjs) or fetch a file (JSON or text) external to the operation .mjs file */ config: DrsHelperFunctionFetchConfig; getEnv: DrsHelperFunctionGetEnv; getParams: DrsHelperFunctionGetParams; /** Base64 decode */ atob( x:string):string; /** Base64 encode */ btoa(x:string):string; /** Clone a structured object */ clone( src: any) : any; /** Hash-encrypt a clear text */ encrypt( clearText: string ): Promise; /** Verify match with encrypted value */ cryptVerify(encrypted:string,clearText:string,options?:{secret?: Buffer}): Promise; /** List a dataset, a schema or an entity */ list : DrsHelperFunctionList; /** Generate a UUID */ generateUid(): string; /** Manage DRS object's shelf */ shelf: DrsHelperFunctionShelf; /** True if memory cell file exists and has at least one key */ exists: DrsHelperFunctionExists; /** Read a JSON file from data, returns undefined if file doesn't exist. */ get : DrsHelperFunctionGet; /** Set a JSON file in data, deletes it if content is undefined */ set : DrsHelperFunctionSet; /** Delete a JSON file in data */ rm : DrsHelperFunctionRm; /** Execute a SQL statement (with or without bind values) and returns result (if any), choosing between postgres (if any) or mariadb */ sql: DrsHelperFunctionSql; /** Execute a Postgres statement (with or without bind values) and returns result (if any). */ pg: DrsHelperFunctionSql; /** Execute a MariaDB statement (with or without bind values) and returns result (if any). */ mdb: DrsHelperFunctionSql; /** Execute a INSERT/ON DUPLICATE KEY UPDATE returning inserted rows, choosing between postgres (if any) or mariadb */ insert: DrsHelperFunctionInsert; /** Execute a MariaDB INSERT/ON DUPLICATE KEY UPDATE returning inserted rows */ mdbInsert: DrsHelperFunctionInsert; /** Execute on Postgres INSERT/ON CONFLICT UPDATE returning inserted rows */ pgInsert: DrsHelperFunctionInsert; /** Check if table exists, otherwise optionally creates it, choosing between postgres (if any) or mariadb */ checkSqlTable: DrsHelperFunctionCheckSqlTable; /** Check if MariaDB table exists, otherwise optionally creates it */ checkMdbTable: DrsHelperFunctionCheckSqlTable; /** Check if Postgres table exists, otherwise optionally creates it */ checkPgTable: DrsHelperFunctionCheckSqlTable; /** Send an email */ mail: DrsHelperFunctionMail; /** Set the content of a static file under (some) dumpRoot, deletes it if content is undefined */ dump: DrsHelperFunctionDumpSet; /** List the content of a dir under (a) dump location */ dumpList: DrsHelperFunctionDumpList; /** Get the content of a static file under (some) dumpRoot */ dumpGet: DrsHelperFunctionDumpGet; /** Commit changes to DB and file-system */ commit: DrsHelperFunctionCommit; /** Revert non-committed changed to DB and file-system */ rollback: DrsHelperFunctionRollback; /** Send (once) the output for request, while further send action(s) will be ignored */ send: DrsHelperFunctionSend; /** A subprocess internal call */ sub: DrsHelperFunctionSub; /** Fetch a resource using node-fetch */ fetch: DrsHelperFunctionFetch; /** Import an external javascript */ import: DrsHelperFunctionImport; /** Debug: console some values */ console: DrsHelperFunctionConsole, /** Debug: Send log to dataset's log.txt */ log: DrsHelperFunctionLog, /** Executes an external shell command */ exec: DrsHelperFunctionExec, /** Returns a new zipHelperObject for response */ zipOut: zipHelperObject; /** Import an extension module */ extension: DrsHelperFunctionExtension; /** Extend the DrsHelperObject itself */ extend: DrsHelperFunctionExtend; } interface DrsOperationEnv extends Record { dataset: Record; headers: IncomingHttpHeaders; } /** * The params the operation script will receive. * @abstract The params are sent with request, but besides those input params: * * these keys are set by the backend, * * or are deleted if necessary * @type {Record} * @property {string} dataset The dataset name, overwritten if derived from URI * @property {string} schema The schema name, overwritten if derived from URI * @property {string} entity The entity name, overwritten if derived from URI * @property {string} operation The operation, overwritten if derived from URI * @property {boolean|number|"true"|"false"|"Yes"|"Y"|"No"|"N"} [dry_run] Set to true or deleted after backend analysis. * If true, all changes to files and DB aren't committed. * @property {string|false} [auth_type] Written/deleted by backend depending on dataset configuration. * False means that no authentication is requested. * @property {string} [auth_user] Written/deleted by backend, reports user authenticated if any. * @property {Record} [auth_flags] Written/deleted by backend, reports optional flags associated to an authenticated user. * @property {"xml"|"json} [output] Output format */ interface DrsDbOperationParams extends Record { dataset: string; schema: string; entity: string; operation: string; dry_run?: boolean|number|"true"|"false"|"Yes"|"Y"|"No"|"N"; auth_type?: string|string[]|false; auth_user?: string; auth_flags?: Record; output?: "xml"|"json"; } interface DrsDbOperationEnv extends Record { dataset: Record; headers: IncomingHttpHeaders; } interface DrsDbOperationIncomingContext { params: DrsDbOperationParams; env: DrsDbOperationEnv; data: Record; } type DrsOperation = (ctx: DrsDbOperationIncomingContext, drs: DrsHelperObject ) => Promise; /** * Autoexec cascading middleware function executed before the main operation. * Can be defined at dataset, schema, or entity level as autoexec.ts or autoexec.mjs. * Allows extending the drs object, mutating incoming context/data, or aborting execution early by throwing an Error. * @type {Function} * @param {DrsDbOperationIncomingContext} ctx Incoming request context (params, env, data) * @param {DrsHelperObject} drs DRS helper instance (can be extended with custom properties/methods) * @return {Promise} */ type DrsAutoexec = (ctx: DrsDbOperationIncomingContext, drs: DrsHelperObject ) => Promise; type DrsContext = DrsDbOperationIncomingContext; type DrsHelper = DrsHelperObject; type ExcelCellValue = (string | number | boolean | Date); type ExcelRow = ExcelCellValue[]; type ExcelSheet = ExcelRow[]; } export type { ExcelRowHash, Excel2JsOptions, Excel2JsInput, Excel2JS, DrsMailMessageObject, DrsMailMessageConfig, DrsMailMessageParams, DrsHelperNewItemCoordinates, DrsHelperItemCoordinates, DrsHelperFunctionFetchConfig, DrsHelperFunctionList, DrsHelperFunctionExists, DrsHelperFunctionGet, DrsHelperFunctionSet, DrsHelperFunctionRm, DrsHelperFunctionSql, DrsHelperInsertConflicts, DrsHelperFunctionInsert, DrsHelperTableColumnDefinition, DrsHelperTableIndexDefinition, DrsHelperTableDefinition, DrsHelperFunctionCheckSqlTable, DrsHelperFunctionMail, DrsHelperDumpItemCoordinates, DrsHelperFunctionDumpSet, DrsHelperFunctionDumpList, DrsHelperFunctionDumpGet, DrsHelperFunctionCommit, DrsHelperFunctionRollback, DrsHelperFunctionSend, DrsDbOperationSubObjectParams, DrsDbOperationSubParams, DrsHelperFunctionSub, DrsHelperFunctionDetach, DrsHelperFunctionFetch, DrsHelperFunctionImport, DrsHelperFunctionConsole, DrsHelperFunctionLog, DrsHelperFunctionExtension, zipHelperObject, DrsHelperFunctionReturn, DrsHelperFunctionExec, DrsHelperFunctionShelf, DrsHelperFunctionGetEnv, DrsHelperFunctionGetParams, DrsHelperObject, DrsOperationEnv, DrsDbOperationParams, DrsDbOperationEnv, DrsDbOperationIncomingContext, DrsOperation, DrsAutoexec, DrsContext, DrsHelper, ExcelCellValue, ExcelRow, ExcelSheet, DrsHelperFunctionExtend, };