@restura/core 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +5 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logger/logger.ts","../src/logger/loggerConfigSchema.ts","../src/restura/eventManager.ts","../src/restura/generators/apiGenerator.ts","../src/restura/sql/SqlUtils.ts","../src/restura/RsError.ts","../src/restura/validators/ResponseValidator.ts","../src/restura/generators/modelGenerator.ts","../src/restura/generators/resturaGlobalTypesGenerator.ts","../src/restura/restura.ts","../../../node_modules/.pnpm/autobind-decorator@2.4.0/node_modules/autobind-decorator/lib/esm/index.js","../src/restura/compareSchema.ts","../src/restura/customApiFactory.ts","../src/restura/generators/customTypeValidationGenerator.ts","../src/restura/middleware/addApiResponseFunctions.ts","../src/restura/middleware/authenticateRequester.ts","../src/restura/middleware/getMulterUpload.ts","../src/restura/schemas/resturaSchema.ts","../src/restura/schemas/validatorDataSchema.ts","../src/restura/validators/requestValidator.ts","../src/restura/utils/utils.ts","../src/restura/middleware/schemaValidation.ts","../src/restura/schemas/resturaConfigSchema.ts","../src/restura/sql/PsqlEngine.ts","../src/restura/sql/PsqlPool.ts","../src/restura/sql/PsqlConnection.ts","../src/restura/sql/PsqlUtils.ts","../src/restura/sql/SqlEngine.ts","../src/restura/sql/filterPsqlParser.ts","../src/restura/utils/TempCache.ts","../src/restura/sql/PsqlTransaction.ts"],"sourcesContent":["import { config } from '@restura/internal';\nimport winston from 'winston';\n// We use the logform module instead of bundled winston.format because then we can enable stack errors in the console output\nimport { format } from 'logform';\nimport { loggerConfigSchema } from './loggerConfigSchema.js';\n\nconst loggerConfig = await config.validate('logger', loggerConfigSchema);\n\nconst consoleFormat = format.combine(\n\tformat.timestamp({\n\t\tformat: 'YYYY-MM-DD HH:mm:ss.sss'\n\t}),\n\tformat.errors({ stack: true }),\n\tformat.padLevels(),\n\tformat.colorize({ all: true }),\n\tformat.printf((info) => {\n\t\treturn `[${info.timestamp}] ${info.level} ${info.message}`;\n\t})\n);\n\n// Create a default logger that works immediately\nconst logger = winston.createLogger({\n\tlevel: loggerConfig.level,\n\tformat: format.combine(\n\t\tformat.timestamp({\n\t\t\tformat: 'YYYY-MM-DD HH:mm:ss.sss'\n\t\t}),\n\t\tformat.errors({ stack: true }),\n\t\tformat.json()\n\t),\n\ttransports: [new winston.transports.Console({ format: consoleFormat })]\n});\n\nexport { logger };\n","import { z } from 'zod';\n\nexport const loggerConfigSchema = z.object({\n\tlevel: z.enum(['info', 'warn', 'error', 'debug', 'silly']).default('info')\n});\nexport type LoggerConfigSchema = z.infer<typeof loggerConfigSchema>;\n","import Bluebird from 'bluebird';\nimport { UUID } from 'crypto';\nimport { DynamicObject, RequesterDetails } from './types/customExpressTypes.js';\n\nexport type EventType = 'DATABASE_ROW_DELETE' | 'DATABASE_ROW_INSERT' | 'DATABASE_COLUMN_UPDATE' | 'WEBHOOK';\nexport type MutationType = 'INSERT' | 'UPDATE' | 'DELETE';\nexport interface SqlMutationData {\n\tmutationType: MutationType;\n\tqueryMetadata: QueryMetadata;\n}\n\nexport interface DatabaseActionData {\n\ttableName: string;\n\tqueryMetadata: QueryMetadata;\n}\n\nexport interface ActionRowInsertData<T = DynamicObject> extends DatabaseActionData {\n\tinsertedId: number;\n\tinsertObject: T;\n}\n\nexport interface ActionRowDeleteData<T = DynamicObject> extends DatabaseActionData {\n\tdeletedId: number;\n\tdeletedRow: T;\n}\n\nexport interface ActionColumnChangeData<T = DynamicObject> extends DatabaseActionData {\n\ttableName: string;\n\tchangedId: number;\n\tnewData: T;\n\toldData: T;\n}\n\nexport interface ActionRowInsertFilter {\n\ttableName: string;\n}\n\nexport interface ActionRowDeleteFilter {\n\ttableName: string;\n}\n\nexport interface ActionColumnChangeFilter {\n\ttableName: string;\n\tcolumns: string[];\n}\n\nexport type TriggerResult = {\n\ttable: string;\n\tinsertedId?: number;\n\tchangedId?: number;\n\tdeletedId?: number;\n\tqueryMetadata: QueryMetadata;\n\trecord: DynamicObject;\n\tpreviousRecord: DynamicObject;\n\trequesterId: number;\n};\n\nexport type QueryMetadata = RequesterDetails & {\n\tconnectionInstanceId: UUID;\n};\n\nclass EventManager {\n\tprivate actionHandlers: {\n\t\tDATABASE_ROW_DELETE: {\n\t\t\tcallback: (data: ActionRowDeleteData, queryMetadata: QueryMetadata) => Promise<void>;\n\t\t\tfilter?: ActionRowDeleteFilter;\n\t\t}[];\n\t\tDATABASE_ROW_INSERT: {\n\t\t\tcallback: (data: ActionRowInsertData, queryMetadata: QueryMetadata) => Promise<void>; // Non-generic here\n\t\t\tfilter?: ActionRowInsertFilter;\n\t\t}[];\n\t\tDATABASE_COLUMN_UPDATE: {\n\t\t\tcallback: (data: ActionColumnChangeData, queryMetadata: QueryMetadata) => Promise<void>;\n\t\t\tfilter?: ActionColumnChangeFilter;\n\t\t}[];\n\t} = {\n\t\tDATABASE_ROW_DELETE: [],\n\t\tDATABASE_ROW_INSERT: [],\n\t\tDATABASE_COLUMN_UPDATE: []\n\t};\n\n\taddRowInsertHandler<T>(\n\t\tonInsert: (data: ActionRowInsertData<T>, queryMetadata: QueryMetadata) => Promise<void>,\n\t\tfilter?: ActionRowInsertFilter\n\t) {\n\t\tthis.actionHandlers.DATABASE_ROW_INSERT.push({\n\t\t\tcallback: onInsert as (data: ActionRowInsertData, queryMetadata: QueryMetadata) => Promise<void>,\n\t\t\tfilter\n\t\t});\n\t}\n\n\taddColumnChangeHandler<T>(\n\t\tonUpdate: (data: ActionColumnChangeData<T>, queryMetadata: QueryMetadata) => Promise<void>,\n\t\tfilter: ActionColumnChangeFilter\n\t) {\n\t\tthis.actionHandlers.DATABASE_COLUMN_UPDATE.push({\n\t\t\tcallback: onUpdate as (data: ActionColumnChangeData, queryMetadata: QueryMetadata) => Promise<void>,\n\t\t\tfilter\n\t\t});\n\t}\n\n\taddRowDeleteHandler<T>(\n\t\tonDelete: (data: ActionRowDeleteData<T>, queryMetadata: QueryMetadata) => Promise<void>,\n\t\tfilter?: ActionRowDeleteFilter\n\t) {\n\t\tthis.actionHandlers.DATABASE_ROW_DELETE.push({\n\t\t\tcallback: onDelete as (data: ActionRowDeleteData, queryMetadata: QueryMetadata) => Promise<void>,\n\t\t\tfilter\n\t\t});\n\t}\n\n\tasync fireActionFromDbTrigger(sqlMutationData: SqlMutationData, result: TriggerResult) {\n\t\tif (sqlMutationData.mutationType === 'INSERT') {\n\t\t\tawait this.fireInsertActions(sqlMutationData, result);\n\t\t} else if (sqlMutationData.mutationType === 'UPDATE') {\n\t\t\tawait this.fireUpdateActions(sqlMutationData, result);\n\t\t} else if (sqlMutationData.mutationType === 'DELETE') {\n\t\t\tawait this.fireDeleteActions(sqlMutationData, result);\n\t\t}\n\t}\n\n\tprivate async fireInsertActions(data: SqlMutationData, triggerResult: TriggerResult) {\n\t\tawait Bluebird.map(\n\t\t\tthis.actionHandlers.DATABASE_ROW_INSERT,\n\t\t\t({ callback, filter }) => {\n\t\t\t\tif (!this.hasHandlersForEventType('DATABASE_ROW_INSERT', filter, triggerResult)) return;\n\t\t\t\tconst insertData: ActionRowInsertData = {\n\t\t\t\t\ttableName: triggerResult.table,\n\t\t\t\t\tinsertedId: triggerResult.insertedId || 0,\n\t\t\t\t\tinsertObject: triggerResult.record,\n\t\t\t\t\tqueryMetadata: data.queryMetadata\n\t\t\t\t};\n\t\t\t\tcallback(insertData, data.queryMetadata);\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n\tprivate async fireDeleteActions(data: SqlMutationData, triggerResult: TriggerResult) {\n\t\tawait Bluebird.map(\n\t\t\tthis.actionHandlers.DATABASE_ROW_DELETE,\n\t\t\t({ callback, filter }) => {\n\t\t\t\tif (!this.hasHandlersForEventType('DATABASE_ROW_DELETE', filter, triggerResult)) return;\n\t\t\t\tconst deleteData: ActionRowDeleteData = {\n\t\t\t\t\ttableName: triggerResult.table,\n\t\t\t\t\tdeletedId: triggerResult.deletedId || 0,\n\t\t\t\t\tdeletedRow: triggerResult.previousRecord,\n\t\t\t\t\tqueryMetadata: data.queryMetadata\n\t\t\t\t};\n\t\t\t\tcallback(deleteData, data.queryMetadata);\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n\tprivate async fireUpdateActions(data: SqlMutationData, triggerResult: TriggerResult) {\n\t\tawait Bluebird.map(\n\t\t\tthis.actionHandlers.DATABASE_COLUMN_UPDATE,\n\t\t\t({ callback, filter }) => {\n\t\t\t\tif (!this.hasHandlersForEventType('DATABASE_COLUMN_UPDATE', filter, triggerResult)) return;\n\t\t\t\tconst columnChangeData: ActionColumnChangeData = {\n\t\t\t\t\ttableName: triggerResult.table,\n\t\t\t\t\tchangedId: triggerResult.changedId || 0,\n\t\t\t\t\tnewData: triggerResult.record,\n\t\t\t\t\toldData: triggerResult.previousRecord,\n\t\t\t\t\tqueryMetadata: data.queryMetadata\n\t\t\t\t};\n\t\t\t\tcallback(columnChangeData, data.queryMetadata);\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n\n\tprivate hasHandlersForEventType(\n\t\teventType: EventType,\n\t\tfilter: { tableName?: string; columns?: string[] } | undefined,\n\t\ttriggerResult: TriggerResult\n\t): boolean {\n\t\tif (filter) {\n\t\t\tswitch (eventType) {\n\t\t\t\tcase 'DATABASE_ROW_INSERT':\n\t\t\t\tcase 'DATABASE_ROW_DELETE':\n\t\t\t\t\tif (filter.tableName && filter.tableName !== triggerResult.table) return false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'DATABASE_COLUMN_UPDATE':\n\t\t\t\t\tconst filterColumnChange = filter as ActionColumnChangeFilter;\n\n\t\t\t\t\tif (filterColumnChange.tableName !== triggerResult.table) return false;\n\n\t\t\t\t\tif (filterColumnChange.columns.length === 1) {\n\t\t\t\t\t\tconst firstColumn = filterColumnChange.columns[0];\n\t\t\t\t\t\tif (firstColumn === '*') return true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t!filterColumnChange.columns.some((item) => {\n\t\t\t\t\t\t\tconst updatedColumns = Object.keys(\n\t\t\t\t\t\t\t\tchangedValues(triggerResult.record, triggerResult.previousRecord)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn updatedColumns.includes(item);\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n\nconst eventManager = new EventManager();\nexport default eventManager;\n\nfunction changedValues(record: DynamicObject, previousRecord: DynamicObject) {\n\tconst changed: DynamicObject = {};\n\tfor (const i in previousRecord) {\n\t\tif (previousRecord[i] !== record[i]) {\n\t\t\tif (typeof previousRecord[i] === 'object' && typeof record[i] === 'object') {\n\t\t\t\tconst nestedChanged = changedValues(record[i] as DynamicObject, previousRecord[i] as DynamicObject);\n\t\t\t\tif (Object.keys(nestedChanged).length > 0) {\n\t\t\t\t\tchanged[i] = record[i];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tchanged[i] = record[i];\n\t\t\t}\n\t\t}\n\t}\n\treturn changed;\n}\n","import { ObjectUtils, StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport { logger } from '../../logger/logger.js';\nimport type {\n\tEndpointData,\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tRouteData,\n\tTableData\n} from '../schemas/resturaSchema.js';\nimport { SqlUtils } from '../sql/SqlUtils.js';\nimport ResponseValidator from '../validators/ResponseValidator.js';\n\ntype TreeData = RouteData | EndpointData;\n\nclass ApiTree {\n\treadonly namespace: string | null;\n\tprivate data: TreeData[] = [];\n\tprivate children: Map<string, ApiTree>;\n\n\tprivate constructor(\n\t\tnamespace: string | null,\n\t\tprivate readonly database: Array<TableData>\n\t) {\n\t\tthis.namespace = namespace;\n\t\tthis.children = new Map();\n\t}\n\n\tstatic createRootNode(database: Array<TableData>) {\n\t\treturn new ApiTree(null, database);\n\t}\n\n\tstatic isRouteData(data: TreeData): data is RouteData {\n\t\treturn (data as RouteData).method !== undefined;\n\t}\n\n\tstatic isEndpointData(data: TreeData): data is EndpointData {\n\t\treturn (data as EndpointData).routes !== undefined;\n\t}\n\n\taddData(namespaces: string[], route: RouteData | EndpointData) {\n\t\tif (ObjectUtils.isEmpty(namespaces)) {\n\t\t\tthis.data.push(route);\n\t\t\treturn;\n\t\t}\n\t\tconst childName: string = namespaces[0];\n\t\tthis.children.set(childName, this.children.get(childName) || new ApiTree(childName, this.database));\n\t\tthis.children.get(childName)!.addData(namespaces.slice(1), route);\n\t}\n\n\tcreateApiModels(): string {\n\t\tlet result = '';\n\t\tfor (const child of this.children.values()) {\n\t\t\tresult += child.createApiModelImpl(true);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate createApiModelImpl(isBase: boolean): string {\n\t\tlet result = ``;\n\t\tfor (const data of this.data) {\n\t\t\tif (ApiTree.isEndpointData(data)) {\n\t\t\t\tresult += ApiTree.generateEndpointComments(data);\n\t\t\t}\n\t\t}\n\t\tresult += isBase\n\t\t\t? `\n\t\t\tdeclare namespace ${this.namespace} {`\n\t\t\t: `\n\t\t\texport namespace ${this.namespace} {`;\n\n\t\tfor (const data of this.data) {\n\t\t\tif (ApiTree.isRouteData(data)) {\n\t\t\t\tresult += this.generateRouteModels(data);\n\t\t\t}\n\t\t}\n\n\t\tfor (const child of this.children.values()) {\n\t\t\tresult += child.createApiModelImpl(false);\n\t\t}\n\t\tresult += '}';\n\t\treturn result;\n\t}\n\n\tstatic generateEndpointComments(endpoint: EndpointData): string {\n\t\treturn `\n\t\t// ${endpoint.name}\n\t\t// ${endpoint.description}`;\n\t}\n\n\tgenerateRouteModels(route: RouteData): string {\n\t\tlet modelString: string = ``;\n\t\tmodelString += `\n\t\t\t\t// ${route.name}\n\t\t\t\t// ${route.description}\n\t\t\t\texport namespace ${StringUtils.capitalizeFirst(route.method.toLowerCase())} {\n\t\t\t\t ${this.generateRequestParameters(route)}\n\t\t\t\t ${this.generateResponseParameters(route)}\n\t\t\t\t}`;\n\t\treturn modelString;\n\t}\n\n\tgenerateRequestParameters(route: RouteData): string {\n\t\tlet modelString: string = ``;\n\t\tif (ResponseValidator.isCustomRoute(route) && route.requestType) {\n\t\t\tmodelString += `\n\t\t\t\texport type Req = CustomTypes.${route.requestType}`;\n\t\t\treturn modelString;\n\t\t}\n\n\t\tif (!route.request) return modelString;\n\n\t\tmodelString += `\n\t\t \texport interface Req{\n\t\t \t\t\t\t\t${route.request\n\t\t\t\t\t\t\t\t.map((p) => {\n\t\t\t\t\t\t\t\t\tlet requestType = 'any';\n\t\t\t\t\t\t\t\t\tconst oneOfValidator = p.validator.find((v) => v.type === 'ONE_OF');\n\t\t\t\t\t\t\t\t\tconst typeCheckValidator = p.validator.find((v) => v.type === 'TYPE_CHECK');\n\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\toneOfValidator &&\n\t\t\t\t\t\t\t\t\t\tObjectUtils.isArrayWithData(oneOfValidator.value as string[])\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\trequestType = (oneOfValidator.value as string[])\n\t\t\t\t\t\t\t\t\t\t\t.map((v) => `'${v}'`)\n\t\t\t\t\t\t\t\t\t\t\t.join(' | ');\n\t\t\t\t\t\t\t\t\t} else if (typeCheckValidator) {\n\t\t\t\t\t\t\t\t\t\tswitch (typeCheckValidator.value) {\n\t\t\t\t\t\t\t\t\t\t\tcase 'string':\n\t\t\t\t\t\t\t\t\t\t\tcase 'number':\n\t\t\t\t\t\t\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\t\t\t\t\t\tcase 'string[]':\n\t\t\t\t\t\t\t\t\t\t\tcase 'number[]':\n\t\t\t\t\t\t\t\t\t\t\tcase 'any[]':\n\t\t\t\t\t\t\t\t\t\t\t\trequestType = typeCheckValidator.value;\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn `'${p.name}'${p.required ? '' : '?'}:${requestType}${p.isNullable ? ' | null' : ''}`;\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.join(';\\n')}${ObjectUtils.isArrayWithData(route.request) ? ';' : ''}\n\t\t `;\n\n\t\tmodelString += `}`;\n\t\treturn modelString;\n\t}\n\n\tgenerateResponseParameters(route: RouteData): string {\n\t\tif (ResponseValidator.isCustomRoute(route)) {\n\t\t\t// Look for simple type for response\n\t\t\tif (['number', 'string', 'boolean'].includes(route.responseType))\n\t\t\t\treturn `export type Res = ${route.responseType}`;\n\t\t\telse if (['CUSTOM_ARRAY', 'CUSTOM_PAGED'].includes(route.type))\n\t\t\t\treturn `export type Res = CustomTypes.${route.responseType}[]`;\n\t\t\telse return `export type Res = CustomTypes.${route.responseType}`;\n\t\t}\n\t\treturn `export interface Res ${this.getFields(route.response, route.table, route.joins)}`;\n\t}\n\n\tgetFields(fields: ReadonlyArray<ResponseData>, routeBaseTable: string, joins: JoinData[]): string {\n\t\tconst nameFields = fields.map((f) => this.getNameAndType(f, routeBaseTable, joins));\n\t\tconst nested: string = `{\n\t\t\t${nameFields.join(';\\n\\t')}${ObjectUtils.isArrayWithData(nameFields) ? ';' : ''}\n\t\t}`;\n\t\treturn nested;\n\t}\n\n\tgetNameAndType(p: ResponseData, routeBaseTable: string, joins: JoinData[]): string {\n\t\tlet responseType = 'any',\n\t\t\tisNullable = false,\n\t\t\tarray = false;\n\n\t\tif (p.type) {\n\t\t\tresponseType = p.type;\n\t\t} else if (p.selector) {\n\t\t\t({ responseType, isNullable } = this.getTypeFromTable(p.selector, p.name));\n\n\t\t\t// If selector is not from the baseTable, then we need to determine if the join is inner join or not.\n\t\t\t// If it is not an inner join, then it is nullable.\n\t\t\tconst selectorKey = p.selector.split('.')[0];\n\t\t\tif (selectorKey !== routeBaseTable) {\n\t\t\t\tconst join = joins.find((j) => j.alias === selectorKey);\n\t\t\t\tif (join && join.type !== 'INNER') {\n\t\t\t\t\tisNullable = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (p.subquery) {\n\t\t\tresponseType = this.getFields(p.subquery.properties, p.subquery.table, p.subquery.joins);\n\t\t\tarray = true;\n\t\t}\n\n\t\treturn `${p.name}:${responseType}${array ? '[]' : ''}${isNullable ? ' | null' : ''}`;\n\t}\n\n\tgetTypeFromTable(selector: string, name: string): { responseType: string; isNullable: boolean } {\n\t\tconst path = selector.split('.');\n\t\tif (path.length === 0 || path.length > 2 || path[0] === '') return { responseType: 'any', isNullable: false };\n\n\t\tlet tableName = path.length == 2 ? path[0] : name;\n\t\tconst columnName = path.length == 2 ? path[1] : path[0];\n\t\tlet table = this.database.find((t) => t.name == tableName);\n\t\tif (!table && tableName.includes('_')) {\n\t\t\tconst tableAliasSplit = tableName.split('_');\n\t\t\ttableName = tableAliasSplit[1];\n\t\t\ttable = this.database.find((t) => t.name == tableName);\n\t\t}\n\n\t\tconst column = table?.columns.find((c) => c.name == columnName);\n\t\tif (!table || !column) return { responseType: 'any', isNullable: false };\n\n\t\treturn {\n\t\t\tresponseType: SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value),\n\t\t\tisNullable: column.roles.length > 0 || column.isNullable\n\t\t};\n\t}\n}\n\nfunction createNotificationTypes(databases: Array<TableData>): string {\n\tlet result = 'declare namespace NotificationTypes {';\n\tfor (const database of databases) {\n\t\tif (!database.notify) continue;\n\t\tif (database.notify === 'ALL') {\n\t\t\t// We need to get all the columns from the database and create a type for each one.\n\t\t\tresult += `export type ${StringUtils.capitalizeFirst(database.name)} = Pick<Model.${StringUtils.capitalizeFirst(database.name)}, `;\n\t\t\tconst columnStrings: string[] = [];\n\t\t\tfor (const column of database.columns) {\n\t\t\t\tcolumnStrings.push(`'${column.name}'`);\n\t\t\t}\n\t\t\tresult += columnStrings.join(' | ');\n\t\t\tresult += `>;`;\n\t\t} else {\n\t\t\t// database.notify is an array of column names\n\t\t\tresult += `export type ${StringUtils.capitalizeFirst(database.name)} = Pick<Model.${StringUtils.capitalizeFirst(database.name)}, `;\n\t\t\tconst columnStrings: string[] = [];\n\t\t\tfor (const column of database.notify) {\n\t\t\t\tconst columnData = database.columns.find((c) => c.name === column);\n\t\t\t\tif (!columnData) {\n\t\t\t\t\tlogger.warn(`Notification: Could not find column: ${column} in table: ${database.name}`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcolumnStrings.push(`'${column}'`);\n\t\t\t}\n\t\t\tresult += columnStrings.join(' | ');\n\t\t\tresult += `>;`;\n\t\t}\n\t}\n\tresult += `}`;\n\treturn result;\n}\n\nfunction pathToNamespaces(path: string): string[] {\n\treturn path\n\t\t.split('/')\n\t\t.map((e) => StringUtils.toPascalCasing(e))\n\t\t.filter((e) => e);\n}\n\nexport default function apiGenerator(schema: ResturaSchema): Promise<string> {\n\tlet apiString = `/** Auto generated file. DO NOT MODIFY **/\\n`;\n\t// Routes\n\tconst rootNamespace = ApiTree.createRootNode(schema.database);\n\tfor (const endpoint of schema.endpoints) {\n\t\tconst endpointNamespaces = pathToNamespaces(endpoint.baseUrl);\n\t\trootNamespace.addData(endpointNamespaces, endpoint);\n\t\tfor (const route of endpoint.routes) {\n\t\t\tconst fullNamespace: string[] = [...endpointNamespaces, ...pathToNamespaces(route.path)];\n\t\t\trootNamespace.addData(fullNamespace, route);\n\t\t}\n\t}\n\tapiString += rootNamespace.createApiModels();\n\n\t// Custom Types\n\tif (schema.customTypes.length > 0) {\n\t\tapiString += `\\n\n\t\tdeclare namespace CustomTypes {\n\t\t\t${schema.customTypes.join('\\n')}\n\t\t}`;\n\t}\n\n\t// Notification Types\n\tapiString += `\\n\\n`;\n\tapiString += createNotificationTypes(schema.database);\n\n\treturn prettier.format(apiString, {\n\t\tparser: 'typescript',\n\t\t...{\n\t\t\ttrailingComma: 'none',\n\t\t\ttabWidth: 4,\n\t\t\tuseTabs: true,\n\t\t\tendOfLine: 'lf',\n\t\t\tprintWidth: 120,\n\t\t\tsingleQuote: true\n\t\t}\n\t});\n}\n","import { ValidatorString } from '../validators/ResponseValidator.js';\n\nclass SqlUtils {\n\tstatic convertDatabaseTypeToTypescript(type: string): ValidatorString | string;\n\tstatic convertDatabaseTypeToTypescript(type: string, value?: string): ValidatorString | string;\n\tstatic convertDatabaseTypeToTypescript(type: string, value?: string): ValidatorString | string {\n\t\ttype = type.toLocaleLowerCase();\n\t\tif (type.startsWith('tinyint') || type.startsWith('boolean')) return 'boolean';\n\t\tif (type.startsWith('decimal') || type.startsWith('numeric')) return 'string';\n\t\tif (\n\t\t\ttype.indexOf('int') > -1 ||\n\t\t\ttype.startsWith('double') ||\n\t\t\ttype.startsWith('float') ||\n\t\t\ttype.indexOf('serial') > -1 ||\n\t\t\ttype.startsWith('real') ||\n\t\t\ttype.startsWith('double precision')\n\t\t)\n\t\t\treturn 'number';\n\t\tif (type === 'json') {\n\t\t\tif (!value) return 'object';\n\t\t\t// Split the value by comma and remove any single or double quote characters, and then join with \" | \"\n\t\t\treturn value\n\t\t\t\t.split(',')\n\t\t\t\t.map((val) => {\n\t\t\t\t\treturn val.replace(/['\"]/g, '');\n\t\t\t\t})\n\t\t\t\t.join(' | ');\n\t\t}\n\t\tif (\n\t\t\ttype.startsWith('varchar') ||\n\t\t\ttype.indexOf('text') > -1 ||\n\t\t\ttype.startsWith('char') ||\n\t\t\ttype.indexOf('blob') > -1 ||\n\t\t\ttype.startsWith('binary')\n\t\t)\n\t\t\treturn 'string';\n\t\tif (type.startsWith('date') || type.startsWith('time')) return 'string';\n\t\tif (type.startsWith('enum')) return SqlUtils.convertDatabaseEnumToStringUnion(value || type);\n\t\treturn 'any';\n\t}\n\n\tstatic convertDatabaseEnumToStringUnion(type: string): string {\n\t\treturn type\n\t\t\t.replace(/^enum\\(|\\)/g, '')\n\t\t\t.split(',')\n\t\t\t.map((value) => {\n\t\t\t\treturn `'${value.replace(/'/g, '')}'`;\n\t\t\t})\n\t\t\t.join(' | ');\n\t}\n}\n\nexport { SqlUtils };\n","/* Note: We tried our best to find matching HTML codes for some of the things\n we are doing. However there isn't a perfect match because the HTML status\n codes were meant as a server signaling a client about some error either in the request\n and not the necessarily that a credit card was declined for example.\n */\n\n// Internal data is used for passing around until we finally get to the sending externally\nexport interface RsErrorInternalData {\n\terr: ErrorCode;\n\tmsg: string;\n\tstack: string;\n\tstatus: number;\n\tmessage?: string; // I don't think this is ever here\n}\n\nexport enum HtmlStatusCodes {\n\tBAD_REQUEST = 400,\n\tUNAUTHORIZED = 401,\n\tFORBIDDEN = 403,\n\tNOT_FOUND = 404,\n\tMETHOD_NOT_ALLOWED = 405,\n\tCONFLICT = 409,\n\tVERSION_OUT_OF_DATE = 418, // Technically this is the I'm a teapot code that was a joke.\n\tUNPROCESSABLE_ENTITY = 422,\n\tSERVER_ERROR = 500,\n\tSERVICE_UNAVAILABLE = 503,\n\tNETWORK_CONNECT_TIMEOUT = 599\n}\n\nexport type ErrorCode =\n\t| 'UNKNOWN_ERROR'\n\t| 'NOT_FOUND'\n\t| 'EMAIL_TAKEN'\n\t| 'UNAUTHORIZED'\n\t| 'FORBIDDEN'\n\t| 'CONFLICT'\n\t| 'UPDATE_FORBIDDEN'\n\t| 'CREATE_FORBIDDEN'\n\t| 'DELETE_FORBIDDEN'\n\t| 'DELETE_FAILURE'\n\t| 'BAD_REQUEST'\n\t| 'INVALID_TOKEN'\n\t| 'INCORRECT_EMAIL_OR_PASSWORD'\n\t| 'DUPLICATE_TOKEN'\n\t| 'DUPLICATE_USERNAME'\n\t| 'DUPLICATE_EMAIL'\n\t| 'DUPLICATE'\n\t| 'EMAIL_NOT_VERIFIED'\n\t| 'UPDATE_WITHOUT_ID'\n\t| 'CONNECTION_ERROR'\n\t| 'INVALID_PAYMENT'\n\t| 'DECLINED_PAYMENT'\n\t| 'INTEGRATION_ERROR'\n\t| 'CANNOT_RESERVE'\n\t| 'REFUND_FAILURE'\n\t| 'INVALID_INVOICE'\n\t| 'INVALID_COUPON'\n\t| 'SERVICE_UNAVAILABLE'\n\t| 'METHOD_UNALLOWED'\n\t| 'LOGIN_EXPIRED'\n\t| 'THIRD_PARTY_ERROR'\n\t| 'ACCESS_DENIED'\n\t| 'DATABASE_ERROR'\n\t| 'SCHEMA_ERROR'\n\t| 'DATA_INCOMPLETE';\n\nexport class RsError {\n\terr: ErrorCode;\n\tmsg: string;\n\tstatus?: number;\n\tstack: string;\n\n\tconstructor(errCode: ErrorCode, message?: string) {\n\t\tthis.err = errCode;\n\t\tthis.msg = message || '';\n\t\tthis.status = RsError.htmlStatus(errCode);\n\t\tthis.stack = new Error().stack || '';\n\t}\n\n\tstatic htmlStatus(code: ErrorCode): number {\n\t\treturn htmlStatusMap[code];\n\t}\n\n\tstatic isRsError(error: unknown): error is RsError {\n\t\treturn error instanceof RsError;\n\t}\n}\n\n// MAKE SURE TO ADD A NEW ERROR TO BOTH THE LIST AND AN APPROPRIATE HTML CODE\n// -- otherwise we default to error 500 --\n\nconst htmlStatusMap: Record<ErrorCode, number> = {\n\tUNKNOWN_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tNOT_FOUND: HtmlStatusCodes.NOT_FOUND,\n\tEMAIL_TAKEN: HtmlStatusCodes.CONFLICT,\n\tFORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tCONFLICT: HtmlStatusCodes.CONFLICT,\n\tUNAUTHORIZED: HtmlStatusCodes.UNAUTHORIZED,\n\tUPDATE_FORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tCREATE_FORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tDELETE_FORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tDELETE_FAILURE: HtmlStatusCodes.SERVER_ERROR,\n\tBAD_REQUEST: HtmlStatusCodes.BAD_REQUEST,\n\tINVALID_TOKEN: HtmlStatusCodes.UNAUTHORIZED,\n\tINCORRECT_EMAIL_OR_PASSWORD: HtmlStatusCodes.UNAUTHORIZED,\n\tDUPLICATE_TOKEN: HtmlStatusCodes.CONFLICT,\n\tDUPLICATE_USERNAME: HtmlStatusCodes.CONFLICT,\n\tDUPLICATE_EMAIL: HtmlStatusCodes.CONFLICT,\n\tDUPLICATE: HtmlStatusCodes.CONFLICT,\n\tEMAIL_NOT_VERIFIED: HtmlStatusCodes.BAD_REQUEST,\n\tUPDATE_WITHOUT_ID: HtmlStatusCodes.BAD_REQUEST,\n\tCONNECTION_ERROR: HtmlStatusCodes.NETWORK_CONNECT_TIMEOUT,\n\tINVALID_PAYMENT: HtmlStatusCodes.FORBIDDEN,\n\tDECLINED_PAYMENT: HtmlStatusCodes.FORBIDDEN,\n\tINTEGRATION_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tCANNOT_RESERVE: HtmlStatusCodes.FORBIDDEN,\n\tREFUND_FAILURE: HtmlStatusCodes.FORBIDDEN,\n\tINVALID_INVOICE: HtmlStatusCodes.FORBIDDEN,\n\tINVALID_COUPON: HtmlStatusCodes.FORBIDDEN,\n\tSERVICE_UNAVAILABLE: HtmlStatusCodes.SERVICE_UNAVAILABLE,\n\tMETHOD_UNALLOWED: HtmlStatusCodes.METHOD_NOT_ALLOWED,\n\tLOGIN_EXPIRED: HtmlStatusCodes.UNAUTHORIZED,\n\tTHIRD_PARTY_ERROR: HtmlStatusCodes.BAD_REQUEST,\n\tACCESS_DENIED: HtmlStatusCodes.FORBIDDEN,\n\tDATABASE_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tSCHEMA_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tDATA_INCOMPLETE: HtmlStatusCodes.UNPROCESSABLE_ENTITY\n};\n","import { logger } from '../../logger/logger.js';\nimport { RsError } from '../RsError.js';\n\nimport {\n\tCustomRouteData,\n\tResponseData,\n\tResturaSchema,\n\tRouteData,\n\tStandardRouteData,\n\tTableData\n} from '../schemas/resturaSchema.js';\nimport { SqlUtils } from '../sql/SqlUtils.js';\n\n// The `string` type is to handle for enums\nexport type ValidatorString = 'boolean' | 'string' | 'number' | 'object' | 'any';\n\ninterface ResponseType {\n\tisOptionalOrNullable?: boolean;\n\tisArray?: boolean;\n\tvalidator: ValidatorString | ResponseTypeMap | string[];\n}\n\ninterface ResponseTypeMap {\n\t[property: string]: ResponseType;\n}\n\nexport default class ResponseValidator {\n\tprivate readonly rootMap: ResponseTypeMap;\n\tprivate readonly database: ReadonlyArray<TableData>;\n\n\tconstructor(schema: ResturaSchema) {\n\t\tthis.database = schema.database;\n\t\tthis.rootMap = {};\n\t\tfor (const endpoint of schema.endpoints) {\n\t\t\tconst endpointMap: ResponseTypeMap = {};\n\t\t\tfor (const route of endpoint.routes) {\n\t\t\t\tif (ResponseValidator.isCustomRoute(route)) {\n\t\t\t\t\tendpointMap[`${route.method}:${route.path}`] = { validator: 'any' };\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tendpointMap[`${route.method}:${route.path}`] = this.getRouteResponseType(route);\n\t\t\t}\n\t\t\tconst endpointUrl = endpoint.baseUrl.endsWith('/') ? endpoint.baseUrl.slice(0, -1) : endpoint.baseUrl;\n\t\t\tthis.rootMap[endpointUrl] = { validator: endpointMap };\n\t\t}\n\t}\n\n\tpublic validateResponseParams(data: unknown, endpointUrl: string, routeData: RouteData): void {\n\t\tif (!this.rootMap) {\n\t\t\tthrow new RsError('BAD_REQUEST', 'Cannot validate response without type maps');\n\t\t}\n\n\t\tconst routeMap = (this.rootMap[endpointUrl].validator as ResponseTypeMap)[\n\t\t\t`${routeData.method}:${routeData.path}`\n\t\t];\n\t\tdata = this.validateAndCoerceMap('_base', data, routeMap);\n\t}\n\n\tprivate getRouteResponseType(route: StandardRouteData): ResponseType {\n\t\tconst map: ResponseTypeMap = {};\n\t\tfor (const field of route.response) {\n\t\t\tmap[field.name] = this.getFieldResponseType(field, route.table, route);\n\t\t}\n\n\t\tif (route.type === 'PAGED') {\n\t\t\treturn {\n\t\t\t\tvalidator: {\n\t\t\t\t\tdata: { validator: map, isArray: true },\n\t\t\t\t\ttotal: { validator: 'number' }\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tif (route.method === 'DELETE') {\n\t\t\treturn {\n\t\t\t\tvalidator: 'boolean'\n\t\t\t};\n\t\t}\n\n\t\treturn { validator: map, isArray: route.type === 'ARRAY' };\n\t}\n\n\tprivate getFieldResponseType(field: ResponseData, tableName: string, routeData: StandardRouteData): ResponseType {\n\t\tif (field.type) {\n\t\t\tif (ResponseValidator.validatorIsValidString(field.type)) {\n\t\t\t\treturn { validator: field.type };\n\t\t\t}\n\t\t\tif (field.type.includes('|')) {\n\t\t\t\treturn { validator: this.parseValidationEnum(field.type) };\n\t\t\t}\n\t\t\treturn { validator: 'object' };\n\t\t} else if (field.selector) {\n\t\t\treturn this.getTypeFromTable(field.selector, tableName, routeData);\n\t\t} else if (field.subquery) {\n\t\t\tconst table = this.database.find((t) => t.name == tableName);\n\t\t\tif (!table) return { isArray: true, validator: 'any' };\n\t\t\tconst isOptionalOrNullable = table.roles.length > 0 || table.scopes.length > 0;\n\t\t\tconst validator: ResponseTypeMap = {};\n\t\t\tfor (const prop of field.subquery.properties) {\n\t\t\t\tvalidator[prop.name] = this.getFieldResponseType(prop, field.subquery.table, routeData);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tisArray: true,\n\t\t\t\tisOptionalOrNullable,\n\t\t\t\tvalidator\n\t\t\t};\n\t\t}\n\t\treturn { validator: 'any' };\n\t}\n\n\tprivate getTypeFromTable(selector: string, name: string, routeData: StandardRouteData): ResponseType {\n\t\tconst selectorParts = selector.split('.');\n\t\tif (selectorParts.length === 0 || selectorParts.length > 2 || selectorParts[0] === '') {\n\t\t\t// Here we can't tell what type it is, so we return any, but make an assumption that it's not optional.\n\t\t\t// We should investigate if this is a good assumption.\n\t\t\tlogger.warn(`ResponseValidator: Could not determine type for selector: ${selector} in table: ${name}`);\n\t\t\treturn { validator: 'any', isOptionalOrNullable: false };\n\t\t}\n\n\t\tconst tableOrAliasName = selectorParts.length == 2 ? selectorParts[0] : name;\n\t\tconst columnName = selectorParts.length == 2 ? selectorParts[1] : selectorParts[0];\n\n\t\tlet table = this.database.find((t) => t.name == tableOrAliasName);\n\t\tlet isNullable = false;\n\t\tif (!table) {\n\t\t\t// Try to look for the alias in the joins\n\t\t\tconst join = routeData.joins.find((j) => j.alias == tableOrAliasName);\n\t\t\tif (join) {\n\t\t\t\ttable = this.database.find((t) => t.name == join.table);\n\t\t\t\tif (join.type === 'LEFT' || join.type === 'RIGHT') isNullable = true;\n\t\t\t}\n\t\t}\n\t\tif (!table) {\n\t\t\tlogger.warn(\n\t\t\t\t`ResponseValidator: Could not find table: ${tableOrAliasName} in database using selector: ${selector}`\n\t\t\t);\n\t\t\treturn { validator: 'any', isOptionalOrNullable: false };\n\t\t}\n\t\tconst column = table.columns.find((c) => c.name == columnName);\n\t\tif (!column) {\n\t\t\tlogger.warn(\n\t\t\t\t`ResponseValidator: Could not find column: ${columnName} in table: ${tableOrAliasName} using selector: ${selector}`\n\t\t\t);\n\t\t\treturn { validator: 'any', isOptionalOrNullable: false };\n\t\t}\n\n\t\tlet validator: ValidatorString | string | string[] = SqlUtils.convertDatabaseTypeToTypescript(\n\t\t\tcolumn.type,\n\t\t\tcolumn.value\n\t\t);\n\t\tif (!ResponseValidator.validatorIsValidString(validator)) validator = this.parseValidationEnum(validator);\n\n\t\treturn {\n\t\t\tvalidator,\n\t\t\tisOptionalOrNullable: isNullable || column.roles.length > 0 || column.scopes.length > 0 || column.isNullable\n\t\t};\n\t}\n\n\tprivate parseValidationEnum(validator: string): string[] {\n\t\tlet terms = validator.split('|');\n\t\tterms = terms.map((v) => v.replace(/'/g, '').trim());\n\t\treturn terms;\n\t}\n\n\tprivate validateAndCoerceMap(\n\t\tname: string,\n\t\tvalue: unknown,\n\t\t{ isOptionalOrNullable, isArray, validator }: ResponseTypeMap[string]\n\t): unknown {\n\t\tif (validator === 'any') return value;\n\t\tconst valueType = typeof value;\n\t\tif (value == null) {\n\t\t\tif (isOptionalOrNullable) return value;\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is required`);\n\t\t}\n\t\tif (isArray) {\n\t\t\tif (!Array.isArray(value)) {\n\t\t\t\tthrow new RsError(\n\t\t\t\t\t'DATABASE_ERROR',\n\t\t\t\t\t`Response param (${name}) is a/an ${valueType} instead of an array`\n\t\t\t\t);\n\t\t\t}\n\t\t\tvalue.forEach((v, i) => this.validateAndCoerceMap(`${name}[${i}]`, v, { validator }));\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof validator === 'string') {\n\t\t\t// Nested objects do not coerce boolean values or dates properly. Fix that here if needed.\n\t\t\t// Database returns number but schema expects boolean\n\t\t\tif (validator === 'boolean' && valueType === 'number') {\n\t\t\t\tif (value !== 0 && value !== 1)\n\t\t\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is of the wrong type (${valueType})`);\n\t\t\t\treturn value === 1;\n\t\t\t} else if (validator === 'string' && valueType === 'string') {\n\t\t\t\t// Check if the string is a SQL datetime, date, time, timestamp format\n\t\t\t\tif (\n\t\t\t\t\ttypeof value === 'string' &&\n\t\t\t\t\tvalue.match(\n\t\t\t\t\t\t/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.?\\d*$|\\d{2}:\\d{2}:\\d{2}.?\\d*$|^\\d{4}-\\d{2}-\\d{2}$/\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tconst date = new Date(value);\n\t\t\t\t\tif (date.toISOString() === '1970-01-01T00:00:00.000Z') return null;\n\t\t\t\t\tconst timezoneOffset = date.getTimezoneOffset() * 60000;\n\t\t\t\t\treturn new Date(date.getTime() - timezoneOffset * 2).toISOString();\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t} else if (valueType === validator) {\n\t\t\t\treturn value;\n\t\t\t} else if (valueType === 'object') {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is of the wrong type (${valueType})`);\n\t\t}\n\t\tif (Array.isArray(validator) && typeof value === 'string') {\n\t\t\tif (validator.includes(value)) return value;\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is not one of the enum options (${value})`);\n\t\t}\n\t\tif (valueType !== 'object') {\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is of the wrong type (${valueType})`);\n\t\t}\n\t\tfor (const prop in value) {\n\t\t\t// @ts-expect-error - not sure types but we will be changing to zod soon\n\t\t\tif (!validator[prop])\n\t\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}.${prop}) is not allowed`);\n\t\t}\n\t\tfor (const prop in validator) {\n\t\t\t// @ts-expect-error - not sure types but we will be changing to zod soon\n\t\t\tvalue[prop] = this.validateAndCoerceMap(`${name}.${prop}`, value[prop], validator[prop]);\n\t\t}\n\t\treturn value;\n\t}\n\n\tstatic isCustomRoute(route: RouteData): route is CustomRouteData {\n\t\treturn route.type === 'CUSTOM_ONE' || route.type === 'CUSTOM_ARRAY' || route.type === 'CUSTOM_PAGED';\n\t}\n\n\tprivate static validatorIsValidString(validator: string): validator is ValidatorString {\n\t\treturn !validator.includes('|');\n\t}\n}\n","import { StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport type { ResturaSchema, TableData } from '../schemas/resturaSchema.js';\nimport { SqlUtils } from '../sql/SqlUtils.js';\n\nexport default function modelGenerator(schema: ResturaSchema): Promise<string> {\n\tlet modelString = `/** Auto generated file. DO NOT MODIFY **/\\n\\n`;\n\tmodelString += `declare namespace Model {\\n`;\n\tfor (const table of schema.database) {\n\t\tmodelString += convertTable(table);\n\t}\n\tmodelString += `}`;\n\treturn prettier.format(modelString, {\n\t\tparser: 'typescript',\n\t\t...{\n\t\t\ttrailingComma: 'none',\n\t\t\ttabWidth: 4,\n\t\t\tuseTabs: true,\n\t\t\tendOfLine: 'lf',\n\t\t\tprintWidth: 120,\n\t\t\tsingleQuote: true\n\t\t}\n\t});\n}\n\nfunction convertTable(table: TableData): string {\n\tlet modelString = `\\texport interface ${StringUtils.capitalizeFirst(table.name)} {\\n`;\n\tfor (const column of table.columns) {\n\t\tmodelString += `\\t\\t${column.name}: ${SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value)}${column.isNullable ? ' | null' : ''};\\n`;\n\t}\n\tmodelString += `\\t}\\n`;\n\treturn modelString;\n}\n","export default function resturaGlobalTypesGenerator(): string {\n\treturn `/** Auto generated file. DO NOT MODIFY **/\n/** This file contains types that may be used in the CustomTypes of Restura **/\n/** For example export interface MyPagedQuery extends Restura.PageQuery { } **/\n\ndeclare namespace Restura {\n\texport type StandardOrderTypes = 'ASC' | 'DESC' | 'RAND' | 'NONE';\n\texport interface PageQuery {\n\t\tpage?: number;\n\t\tperPage?: number;\n\t\tsortBy?: string;\n\t\tsortOrder?: StandardOrderTypes;\n\t\tfilter?: string;\n\t}\n}\n`;\n}\n","import { ObjectUtils, StringUtils } from '@redskytech/core-utils';\nimport { config } from '@restura/internal';\nimport { boundMethod } from 'autobind-decorator';\nimport bodyParser from 'body-parser';\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport * as express from 'express';\nimport { RequestHandler } from 'express';\nimport fs from 'fs';\nimport multer from 'multer';\nimport path from 'path';\nimport * as prettier from 'prettier';\nimport { logger } from '../logger/logger.js';\nimport { RsError } from './RsError.js';\nimport compareSchema from './compareSchema.js';\nimport customApiFactory from './customApiFactory.js';\nimport apiGenerator from './generators/apiGenerator.js';\nimport customTypeValidationGenerator from './generators/customTypeValidationGenerator.js';\nimport modelGenerator from './generators/modelGenerator.js';\nimport resturaGlobalTypesGenerator from './generators/resturaGlobalTypesGenerator.js';\nimport addApiResponseFunctions from './middleware/addApiResponseFunctions.js';\nimport { authenticateRequester } from './middleware/authenticateRequester.js';\nimport { getMulterUpload } from './middleware/getMulterUpload.js';\nimport { schemaValidation } from './middleware/schemaValidation.js';\nimport { resturaConfigSchema, type ResturaConfigSchema } from './schemas/resturaConfigSchema.js';\nimport {\n\tisSchemaValid,\n\tStandardRouteData,\n\ttype CustomRouteData,\n\ttype ResturaSchema,\n\ttype RouteData\n} from './schemas/resturaSchema.js';\nimport { PsqlEngine } from './sql/PsqlEngine.js';\nimport { PsqlPool } from './sql/PsqlPool.js';\nimport type { RsRequest, RsResponse } from './types/customExpressTypes.js';\nimport type { AuthenticateHandler } from './types/resturaTypes.js';\nimport TempCache from './utils/TempCache.js';\nimport { sortObjectKeysAlphabetically } from './utils/utils.js';\nimport ResponseValidator from './validators/ResponseValidator.js';\nimport requestValidator, { ValidationDictionary } from './validators/requestValidator.js';\n\nclass ResturaEngine {\n\t// Make public so other modules can access without re-parsing the config\n\tresturaConfig!: ResturaConfigSchema;\n\n\tprivate multerCommonUpload!: multer.Multer;\n\tprivate resturaRouter!: express.Router;\n\tprivate publicEndpoints: { GET: string[]; POST: string[]; PUT: string[]; PATCH: string[]; DELETE: string[] } = {\n\t\tGET: [],\n\t\tPOST: [],\n\t\tPUT: [],\n\t\tPATCH: [],\n\t\tDELETE: []\n\t};\n\tprivate expressApp!: express.Application;\n\tprivate schema!: ResturaSchema;\n\tprivate responseValidator!: ResponseValidator;\n\tprivate authenticationHandler!: AuthenticateHandler;\n\tprivate customTypeValidation!: ValidationDictionary;\n\tprivate psqlConnectionPool!: PsqlPool;\n\tprivate psqlEngine!: PsqlEngine;\n\n\t/**\n\t * Initializes the Restura engine with the provided Express application.\n\t *\n\t * @param app - The Express application instance to initialize with Restura.\n\t * @returns A promise that resolves when the initialization is complete.\n\t */\n\tasync init(\n\t\tapp: express.Application,\n\t\tauthenticationHandler: AuthenticateHandler,\n\t\tpsqlConnectionPool: PsqlPool\n\t): Promise<void> {\n\t\t// Try to load config first. If it fails, we can't continue.\n\t\tthis.resturaConfig = await config.validate('restura', resturaConfigSchema);\n\n\t\tthis.multerCommonUpload = getMulterUpload(this.resturaConfig.fileTempCachePath);\n\t\tnew TempCache(this.resturaConfig.fileTempCachePath);\n\t\tthis.psqlConnectionPool = psqlConnectionPool;\n\t\tthis.psqlEngine = new PsqlEngine(this.psqlConnectionPool, true, this.resturaConfig.scratchDatabaseSuffix);\n\n\t\tawait customApiFactory.loadApiFiles(this.resturaConfig.customApiFolderPath);\n\n\t\tthis.authenticationHandler = authenticationHandler;\n\n\t\t// Middleware and general setup\n\t\tapp.use(compression());\n\t\tapp.use(bodyParser.json({ limit: '32mb' }));\n\t\tapp.use(bodyParser.urlencoded({ limit: '32mb', extended: false }));\n\t\tapp.use(cookieParser());\n\t\t// Disable the X-Powered-By header\n\t\tapp.disable('x-powered-by');\n\n\t\tapp.use('/', addApiResponseFunctions as unknown as express.RequestHandler);\n\t\tapp.use('/api/', authenticateRequester(this.authenticationHandler) as unknown as express.RequestHandler);\n\t\tapp.use('/restura', this.resturaAuthentication);\n\n\t\t// Routes specific to Restura\n\t\tapp.put(\n\t\t\t'/restura/v1/schema',\n\t\t\tschemaValidation as unknown as express.RequestHandler,\n\t\t\tthis.updateSchema as unknown as express.RequestHandler\n\t\t);\n\t\tapp.post(\n\t\t\t'/restura/v1/schema/preview',\n\t\t\tschemaValidation as unknown as express.RequestHandler,\n\t\t\tthis.previewCreateSchema as unknown as express.RequestHandler\n\t\t);\n\t\tapp.get('/restura/v1/schema', this.getSchema);\n\t\tapp.get('/restura/v1/schema/types', this.getSchemaAndTypes);\n\n\t\tthis.expressApp = app;\n\n\t\tawait this.reloadEndpoints();\n\t\tawait this.initializeGeneratedTypesFolder();\n\n\t\tlogger.info('Restura Engine Initialized');\n\t}\n\n\t/**\n\t * Determines if a given endpoint is public based on the HTTP method and full URL. This\n\t * is determined on whether the endpoint in the schema has no roles or scopes assigned to it.\n\t *\n\t * @param method - The HTTP method (e.g., 'GET', 'POST', 'PUT', 'PATCH', 'DELETE').\n\t * @param fullUrl - The full URL of the endpoint.\n\t * @returns A boolean indicating whether the endpoint is public.\n\t */\n\tisEndpointPublic(method: string, fullUrl: string): boolean {\n\t\tif (!['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) return false;\n\t\treturn this.publicEndpoints[method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'].includes(fullUrl);\n\t}\n\n\t/**\n\t * Checks if an endpoint exists for a given HTTP method and full URL.\n\t *\n\t * @param method - The HTTP method to check (e.g., 'GET', 'POST', 'PUT', 'PATCH', 'DELETE').\n\t * @param fullUrl - The full URL of the endpoint to check.\n\t * @returns `true` if the endpoint exists, otherwise `false`.\n\t */\n\tdoesEndpointExist(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', fullUrl: string): boolean {\n\t\treturn this.schema.endpoints.some((endpoint) => {\n\t\t\tif (!fullUrl.startsWith(endpoint.baseUrl)) return false;\n\t\t\tconst pathWithoutBaseUrl = fullUrl.replace(endpoint.baseUrl, '');\n\t\t\treturn endpoint.routes.some((route) => {\n\t\t\t\treturn route.method === method && route.path === pathWithoutBaseUrl;\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Generates an API from the provided schema and writes it to the specified output file.\n\t *\n\t * @param outputFile - The path to the file where the generated API will be written.\n\t * @param providedSchema - The schema from which the API will be generated.\n\t * @returns A promise that resolves when the API has been successfully generated and written to the output file.\n\t */\n\tasync generateApiFromSchema(outputFile: string, providedSchema: ResturaSchema): Promise<void> {\n\t\tfs.writeFileSync(outputFile, await apiGenerator(providedSchema));\n\t}\n\n\t/**\n\t * Generates a model from the provided schema and writes it to the specified output file.\n\t *\n\t * @param outputFile - The path to the file where the generated model will be written.\n\t * @param providedSchema - The schema from which the model will be generated.\n\t * @returns A promise that resolves when the model has been successfully written to the output file.\n\t */\n\tasync generateModelFromSchema(outputFile: string, providedSchema: ResturaSchema): Promise<void> {\n\t\tfs.writeFileSync(outputFile, await modelGenerator(providedSchema));\n\t}\n\n\t/**\n\t * Generates the ambient module declaration for Restura global types and writes it to the specified output file.\n\t * These types are used sometimes in the CustomTypes\n\t * @param outputFile\n\t */\n\tgenerateResturaGlobalTypes(outputFile: string): void {\n\t\tfs.writeFileSync(outputFile, resturaGlobalTypesGenerator());\n\t}\n\n\t/**\n\t * Retrieves the latest file system schema for Restura.\n\t *\n\t * @returns {Promise<ResturaSchema>} A promise that resolves to the latest Restura schema.\n\t * @throws {Error} If the schema file is missing or the schema is not valid.\n\t */\n\tasync getLatestFileSystemSchema(): Promise<ResturaSchema> {\n\t\tif (!fs.existsSync(this.resturaConfig.schemaFilePath)) {\n\t\t\tlogger.error(`Missing restura schema file, expected path: ${this.resturaConfig.schemaFilePath}`);\n\t\t\tthrow new Error('Missing restura schema file');\n\t\t}\n\n\t\tconst schemaFileData = fs.readFileSync(this.resturaConfig.schemaFilePath, { encoding: 'utf8' });\n\t\tconst schema: ResturaSchema = ObjectUtils.safeParse(schemaFileData) as ResturaSchema;\n\t\tconst isValid = await isSchemaValid(schema);\n\t\tif (!isValid) {\n\t\t\tlogger.error('Schema is not valid');\n\t\t\tthrow new Error('Schema is not valid');\n\t\t}\n\t\treturn schema;\n\t}\n\n\tprivate async reloadEndpoints() {\n\t\tthis.schema = await this.getLatestFileSystemSchema();\n\t\tthis.customTypeValidation = customTypeValidationGenerator(this.schema);\n\t\tthis.resturaRouter = express.Router();\n\t\tthis.resetPublicEndpoints();\n\n\t\tlet routeCount = 0;\n\t\tfor (const endpoint of this.schema.endpoints) {\n\t\t\tconst baseUrl = endpoint.baseUrl.endsWith('/') ? endpoint.baseUrl.slice(0, -1) : endpoint.baseUrl;\n\t\t\tthis.expressApp.use(baseUrl, (req, res, next) => {\n\t\t\t\t// When you do an express use the baseUrl is stripped from the url, so we need to add to the router each baseUrl usage.\n\t\t\t\tthis.resturaRouter(req, res, next);\n\t\t\t});\n\t\t\tfor (const route of endpoint.routes) {\n\t\t\t\troute.path = route.path.startsWith('/') ? route.path : `/${route.path}`;\n\t\t\t\troute.path = route.path.endsWith('/') ? route.path.slice(0, -1) : route.path;\n\t\t\t\tconst fullUrl = `${baseUrl}${route.path}`;\n\n\t\t\t\tif (route.roles.length === 0 && route.scopes.length === 0)\n\t\t\t\t\tthis.publicEndpoints[route.method].push(fullUrl);\n\n\t\t\t\tthis.resturaRouter[route.method.toLowerCase() as Lowercase<typeof route.method>](\n\t\t\t\t\troute.path, // <-- Notice we only use path here since the baseUrl is already added to the router.\n\t\t\t\t\tthis.executeRouteLogic as unknown as express.RequestHandler\n\t\t\t\t);\n\t\t\t\trouteCount++;\n\t\t\t}\n\t\t}\n\t\tthis.responseValidator = new ResponseValidator(this.schema);\n\n\t\tlogger.info(`Restura loaded (${routeCount}) endpoint${routeCount > 1 ? 's' : ''}`);\n\t}\n\n\tprivate async initializeGeneratedTypesFolder() {\n\t\tif (!fs.existsSync(this.resturaConfig.generatedTypesPath)) {\n\t\t\tfs.mkdirSync(this.resturaConfig.generatedTypesPath, { recursive: true });\n\t\t}\n\n\t\tthis.updateTypes();\n\t}\n\n\t@boundMethod\n\tprivate resturaAuthentication(req: express.Request, res: express.Response, next: express.NextFunction) {\n\t\tif (req.headers['x-auth-token'] !== this.resturaConfig.authToken) res.status(401).send('Unauthorized');\n\t\telse next();\n\t}\n\n\t@boundMethod\n\tprivate async previewCreateSchema(req: RsRequest<ResturaSchema>, res: express.Response) {\n\t\ttry {\n\t\t\tconst schemaDiff = await compareSchema.diffSchema(req.data, this.schema, this.psqlEngine);\n\t\t\tres.send({ data: schemaDiff });\n\t\t} catch (err) {\n\t\t\tres.status(400).send(err);\n\t\t}\n\t}\n\n\t@boundMethod\n\tprivate async updateSchema(req: RsRequest<ResturaSchema>, res: express.Response) {\n\t\ttry {\n\t\t\tthis.schema = sortObjectKeysAlphabetically(req.data);\n\t\t\tawait this.storeFileSystemSchema();\n\t\t\tawait this.reloadEndpoints();\n\t\t\tawait this.updateTypes();\n\t\t\tres.send({ data: 'success' });\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error) res.status(400).send(err.message);\n\t\t\telse res.status(400).send('Unknown error');\n\t\t}\n\t}\n\n\tprivate async updateTypes() {\n\t\tawait this.generateApiFromSchema(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'), this.schema);\n\t\tawait this.generateModelFromSchema(\n\t\t\tpath.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\tthis.schema\n\t\t);\n\t\tthis.generateResturaGlobalTypes(path.join(this.resturaConfig.generatedTypesPath, 'restura.d.ts'));\n\t}\n\n\t@boundMethod\n\tprivate async getSchema(_req: express.Request, res: express.Response) {\n\t\tres.send({ data: this.schema });\n\t}\n\n\t@boundMethod\n\tprivate async getSchemaAndTypes(_req: express.Request, res: express.Response) {\n\t\ttry {\n\t\t\tconst schema = await this.getLatestFileSystemSchema();\n\t\t\tconst apiText = await apiGenerator(schema);\n\t\t\tconst modelsText = await modelGenerator(schema);\n\t\t\tres.send({ schema, api: apiText, models: modelsText });\n\t\t} catch (err) {\n\t\t\tres.status(400).send({ error: err });\n\t\t}\n\t}\n\n\t@boundMethod\n\tprivate async getMulterFilesIfAny<T>(req: RsRequest<T>, res: RsResponse<T>, routeData: RouteData) {\n\t\tif (!req.header('content-type')?.includes('multipart/form-data')) return;\n\t\tif (!this.isCustomRoute(routeData)) return;\n\n\t\tif (!routeData.fileUploadType) {\n\t\t\tthrow new RsError('BAD_REQUEST', 'File upload type not defined for route');\n\t\t}\n\n\t\tconst multerFileUploadFunction: RequestHandler =\n\t\t\trouteData.fileUploadType === 'MULTIPLE'\n\t\t\t\t? this.multerCommonUpload.array('files')\n\t\t\t\t: this.multerCommonUpload.single('file');\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tmulterFileUploadFunction(req as unknown as express.Request, res, (err: unknown) => {\n\t\t\t\tif (err) {\n\t\t\t\t\tlogger.warn('Multer error: ' + err);\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t\tif (req.body['data']) req.body = JSON.parse(req.body['data']);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\t@boundMethod\n\tprivate async executeRouteLogic<T>(req: RsRequest<T>, res: RsResponse<T>, next: express.NextFunction) {\n\t\ttry {\n\t\t\t// Locate the route in the schema\n\t\t\tconst routeData = this.getRouteData(req.method, req.baseUrl, req.path);\n\n\t\t\t// Validate the requester has access to the endpoint\n\t\t\tthis.validateAuthorization(req, routeData);\n\n\t\t\t// Check for file uploads\n\t\t\tawait this.getMulterFilesIfAny(req, res, routeData);\n\n\t\t\t// Validate the request and assign to req.data\n\t\t\trequestValidator(req as RsRequest<unknown>, routeData, this.customTypeValidation);\n\n\t\t\t// Check for custom logic\n\t\t\tif (this.isCustomRoute(routeData)) {\n\t\t\t\tawait this.runCustomRouteLogic(req, res, routeData);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Run SQL query\n\t\t\tconst data = await this.psqlEngine.runQueryForRoute(\n\t\t\t\treq as RsRequest<unknown>,\n\t\t\t\trouteData as StandardRouteData,\n\t\t\t\tthis.schema\n\t\t\t);\n\n\t\t\t// Validate the response\n\t\t\tthis.responseValidator.validateResponseParams(data, req.baseUrl, routeData);\n\n\t\t\t// Send response\n\t\t\tif (routeData.type === 'PAGED') res.sendNoWrap(data as T);\n\t\t\telse res.sendData(data as T);\n\t\t} catch (e) {\n\t\t\tnext(e);\n\t\t}\n\t}\n\n\t@boundMethod\n\tprivate isCustomRoute(route: RouteData): route is CustomRouteData {\n\t\treturn route.type === 'CUSTOM_ONE' || route.type === 'CUSTOM_ARRAY' || route.type === 'CUSTOM_PAGED';\n\t}\n\n\t@boundMethod\n\tprivate async runCustomRouteLogic<T>(req: RsRequest<T>, res: RsResponse<T>, routeData: RouteData) {\n\t\tconst version = req.baseUrl.split('/')[2];\n\t\tlet domain = routeData.path.split('/')[1];\n\t\tdomain = domain.split('-').reduce((acc, value, index) => {\n\t\t\tif (index === 0) acc = value;\n\t\t\telse acc += StringUtils.capitalizeFirst(value);\n\t\t\treturn acc;\n\t\t}, '');\n\t\tconst customApiName = `${StringUtils.capitalizeFirst(domain)}Api${StringUtils.capitalizeFirst(version)}`;\n\n\t\tconst customApi = customApiFactory.getCustomApi(customApiName);\n\t\tif (!customApi) throw new RsError('NOT_FOUND', `API domain ${domain}-${version} not found`);\n\n\t\tconst functionName = `${routeData.method.toLowerCase()}${routeData.path\n\t\t\t.replace(new RegExp('-', 'g'), '/')\n\t\t\t.split('/')\n\t\t\t.reduce((acc, cur) => {\n\t\t\t\tif (cur === '') return acc;\n\t\t\t\treturn acc + StringUtils.capitalizeFirst(cur);\n\t\t\t}, '')}`;\n\n\t\t// @ts-expect-error - Here we are dynamically calling the function from a custom class, not sure how to typescript this\n\t\tconst customFunction = customApi[functionName] as (\n\t\t\treq: RsRequest<T>,\n\t\t\tres: RsResponse<T>,\n\t\t\trouteData: RouteData\n\t\t) => Promise<void>;\n\t\tif (!customFunction)\n\t\t\tthrow new RsError('NOT_FOUND', `API path ${routeData.path} not implemented ${functionName}`);\n\t\tawait customFunction(req, res, routeData);\n\t}\n\n\tprivate async storeFileSystemSchema() {\n\t\tconst schemaPrettyStr = await prettier.format(JSON.stringify(this.schema), {\n\t\t\tparser: 'json',\n\t\t\t...{\n\t\t\t\ttrailingComma: 'none',\n\t\t\t\ttabWidth: 4,\n\t\t\t\tuseTabs: true,\n\t\t\t\tendOfLine: 'lf',\n\t\t\t\tprintWidth: 120,\n\t\t\t\tsingleQuote: true\n\t\t\t}\n\t\t});\n\t\tfs.writeFileSync(this.resturaConfig.schemaFilePath, schemaPrettyStr);\n\t}\n\n\tprivate resetPublicEndpoints() {\n\t\tthis.publicEndpoints = {\n\t\t\tGET: [],\n\t\t\tPOST: [],\n\t\t\tPUT: [],\n\t\t\tPATCH: [],\n\t\t\tDELETE: []\n\t\t};\n\t}\n\n\tprivate validateAuthorization(req: RsRequest<unknown>, routeData: RouteData) {\n\t\tconst requesterRole = req.requesterDetails.role;\n\t\tconst requesterScopes = req.requesterDetails.scopes;\n\n\t\t// If route has no roles or scopes, it's public - allow access\n\t\tif (routeData.roles.length === 0 && routeData.scopes.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If route requires roles, check if user has the required role\n\t\tif (routeData.roles.length > 0) {\n\t\t\tif (!requesterRole || !routeData.roles.includes(requesterRole)) {\n\t\t\t\tthrow new RsError('FORBIDDEN', 'Not authorized to access this endpoint - role required');\n\t\t\t}\n\t\t}\n\n\t\t// If route requires scopes, check if user has ALL required scopes\n\t\tif (routeData.scopes.length > 0) {\n\t\t\tconst missingScopes = routeData.scopes.filter((requiredScope) => !requesterScopes.includes(requiredScope));\n\t\t\tif (missingScopes.length > 0) {\n\t\t\t\tthrow new RsError(\n\t\t\t\t\t'FORBIDDEN',\n\t\t\t\t\t`Not authorized to access this endpoint - missing required scopes: ${missingScopes.join(', ')}`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getRouteData(method: string, baseUrl: string, path: string): RouteData {\n\t\tconst endpoint = this.schema.endpoints.find((item) => {\n\t\t\treturn item.baseUrl === baseUrl;\n\t\t});\n\t\tif (!endpoint) throw new RsError('NOT_FOUND', 'Route not found');\n\t\tconst route = endpoint.routes.find((item) => {\n\t\t\treturn item.method === method && item.path === path;\n\t\t});\n\t\tif (!route) throw new RsError('NOT_FOUND', 'Route not found');\n\t\treturn route;\n\t}\n}\n\nconst restura = new ResturaEngine();\nexport { restura };\n","function _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n/**\n * Return a descriptor removing the value and returning a getter\n * The getter will return a .bind version of the function\n * and memoize the result against a symbol on the instance\n */\nexport function boundMethod(target, key, descriptor) {\n var fn = descriptor.value;\n\n if (typeof fn !== 'function') {\n throw new TypeError(\"@boundMethod decorator can only be applied to methods not: \".concat(_typeof(fn)));\n } // In IE11 calling Object.defineProperty has a side-effect of evaluating the\n // getter for the property which is being replaced. This causes infinite\n // recursion and an \"Out of stack space\" error.\n\n\n var definingProperty = false;\n return {\n configurable: true,\n get: function get() {\n // eslint-disable-next-line no-prototype-builtins\n if (definingProperty || this === target.prototype || this.hasOwnProperty(key) || typeof fn !== 'function') {\n return fn;\n }\n\n var boundFn = fn.bind(this);\n definingProperty = true;\n Object.defineProperty(this, key, {\n configurable: true,\n get: function get() {\n return boundFn;\n },\n set: function set(value) {\n fn = value;\n delete this[key];\n }\n });\n definingProperty = false;\n return boundFn;\n },\n set: function set(value) {\n fn = value;\n }\n };\n}\n/**\n * Use boundMethod to bind all methods on the target.prototype\n */\n\nexport function boundClass(target) {\n // (Using reflect to get all keys including symbols)\n var keys; // Use Reflect if exists\n\n if (typeof Reflect !== 'undefined' && typeof Reflect.ownKeys === 'function') {\n keys = Reflect.ownKeys(target.prototype);\n } else {\n keys = Object.getOwnPropertyNames(target.prototype); // Use symbols if support is provided\n\n if (typeof Object.getOwnPropertySymbols === 'function') {\n keys = keys.concat(Object.getOwnPropertySymbols(target.prototype));\n }\n }\n\n keys.forEach(function (key) {\n // Ignore special case target method\n if (key === 'constructor') {\n return;\n }\n\n var descriptor = Object.getOwnPropertyDescriptor(target.prototype, key); // Only methods need binding\n\n if (typeof descriptor.value === 'function') {\n Object.defineProperty(target.prototype, key, boundMethod(target, key, descriptor));\n }\n });\n return target;\n}\nexport default function autobind() {\n if (arguments.length === 1) {\n return boundClass.apply(void 0, arguments);\n }\n\n return boundMethod.apply(void 0, arguments);\n}","import { boundMethod } from 'autobind-decorator';\nimport cloneDeep from 'lodash.clonedeep';\nimport { ResturaSchema, RouteData } from './schemas/resturaSchema.js';\nimport { PsqlEngine } from './sql/PsqlEngine.js';\nimport { SchemaChangeValue, SchemaPreview } from './types/resturaTypes.js';\n\nclass CompareSchema {\n\t@boundMethod\n\tasync diffSchema(\n\t\tnewSchema: ResturaSchema,\n\t\tlatestSchema: ResturaSchema,\n\t\tpsqlEngine: PsqlEngine\n\t): Promise<SchemaPreview> {\n\t\tconst endPoints = this.diffEndPoints(newSchema.endpoints![0].routes, latestSchema.endpoints![0].routes);\n\t\tconst globalParams = this.diffStringArray(newSchema.globalParams, latestSchema.globalParams);\n\t\tconst roles = this.diffStringArray(newSchema.roles, latestSchema.roles);\n\n\t\tlet commands = '';\n\t\tif (JSON.stringify(newSchema.database) !== JSON.stringify(latestSchema.database))\n\t\t\tcommands = await psqlEngine.diffDatabaseToSchema(newSchema);\n\n\t\tconst hasCustomTypesChanged =\n\t\t\tJSON.stringify(newSchema.customTypes) !== JSON.stringify(latestSchema.customTypes);\n\t\tconst schemaPreview: SchemaPreview = {\n\t\t\tendPoints,\n\t\t\tglobalParams,\n\t\t\troles,\n\t\t\tcommands,\n\t\t\tcustomTypes: hasCustomTypesChanged\n\t\t};\n\t\treturn schemaPreview;\n\t}\n\n\t@boundMethod\n\tprivate diffStringArray(newArray: string[], originalArray: string[]): SchemaChangeValue[] {\n\t\tconst stringsDiff: SchemaChangeValue[] = [];\n\t\tconst originalClone = new Set(originalArray);\n\t\tnewArray.forEach((item) => {\n\t\t\tconst originalIndex = originalClone.has(item);\n\t\t\tif (!originalIndex) {\n\t\t\t\tstringsDiff.push({\n\t\t\t\t\tname: item,\n\t\t\t\t\tchangeType: 'NEW'\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\toriginalClone.delete(item);\n\t\t\t}\n\t\t});\n\t\toriginalClone.forEach((item) => {\n\t\t\tstringsDiff.push({\n\t\t\t\tname: item,\n\t\t\t\tchangeType: 'DELETED'\n\t\t\t});\n\t\t});\n\t\treturn stringsDiff;\n\t}\n\n\t@boundMethod\n\tprivate diffEndPoints(newEndPoints: RouteData[], originalEndpoints: RouteData[]): SchemaChangeValue[] {\n\t\tconst originalClone = cloneDeep(originalEndpoints);\n\t\tconst diffObj: SchemaChangeValue[] = [];\n\t\tnewEndPoints.forEach((endPoint) => {\n\t\t\tconst { path, method } = endPoint;\n\t\t\tconst endPointIndex = originalClone.findIndex((original) => {\n\t\t\t\treturn original.path === endPoint.path && original.method === endPoint.method;\n\t\t\t});\n\t\t\tif (endPointIndex === -1) {\n\t\t\t\tdiffObj.push({\n\t\t\t\t\tname: `${method} ${path}`,\n\t\t\t\t\tchangeType: 'NEW'\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst original = originalClone.findIndex((original) => {\n\t\t\t\t\treturn this.compareEndPoints(endPoint, original);\n\t\t\t\t});\n\t\t\t\tif (original === -1) {\n\t\t\t\t\tdiffObj.push({\n\t\t\t\t\t\tname: `${method} ${path}`,\n\t\t\t\t\t\tchangeType: 'MODIFIED'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\toriginalClone.splice(endPointIndex, 1);\n\t\t\t}\n\t\t});\n\t\toriginalClone.forEach((original) => {\n\t\t\tconst { path, method } = original;\n\t\t\tdiffObj.push({\n\t\t\t\tname: `${method} ${path}`,\n\t\t\t\tchangeType: 'DELETED'\n\t\t\t});\n\t\t});\n\t\treturn diffObj;\n\t}\n\n\t@boundMethod\n\tprivate compareEndPoints(endPoint1: RouteData, endPoint2: RouteData): boolean {\n\t\treturn JSON.stringify(endPoint1) === JSON.stringify(endPoint2);\n\t}\n}\n\nconst compareSchema = new CompareSchema();\nexport default compareSchema;\n","import Bluebird from 'bluebird';\nimport fs from 'fs';\nimport path from 'path';\nimport { logger } from '../logger/logger.js';\nimport { FileUtils } from '@restura/internal';\n\nclass CustomApiFactory {\n\tprivate customApis: { [key: string]: { name: string } } = {};\n\n\tasync loadApiFiles(baseFolderPath: string) {\n\t\tconst apiVersions = ['v1'];\n\t\tfor (const apiVersion of apiVersions) {\n\t\t\tconst apiVersionFolderPath = path.join(baseFolderPath, apiVersion);\n\n\t\t\tconst directoryExists = await FileUtils.existDir(apiVersionFolderPath);\n\t\t\tif (!directoryExists) continue;\n\t\t\tawait this.addDirectory(apiVersionFolderPath, apiVersion);\n\t\t}\n\t}\n\n\tgetCustomApi(customApiName: string): { name: string } {\n\t\treturn this.customApis[customApiName];\n\t}\n\n\tprivate async addDirectory(directoryPath: string, apiVersion: string) {\n\t\tconst entries = await fs.promises.readdir(directoryPath, {\n\t\t\twithFileTypes: true\n\t\t});\n\t\tconst isTsx = process.argv[1]?.endsWith('.ts');\n\t\tconst isTsNode = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT;\n\t\tconst extension = isTsx || isTsNode ? 'ts' : 'js';\n\t\tconst shouldEndWith = `.api.${apiVersion}.${extension}`;\n\t\tawait Bluebird.map(entries, async (entry) => {\n\t\t\tif (entry.isFile()) {\n\t\t\t\tif (entry.name.endsWith(shouldEndWith) === false) return;\n\n\t\t\t\t// The following try / catch block fixes an issue when looking for the map file giving an exception thrown\n\t\t\t\ttry {\n\t\t\t\t\tconst importPath = `${path.join(directoryPath, entry.name)}`;\n\t\t\t\t\tconst ApiImport = await import(importPath);\n\t\t\t\t\tconst customApiClass = new ApiImport.default();\n\t\t\t\t\tlogger.info(`Registering custom API: ${ApiImport.default.name}`);\n\t\t\t\t\tthis.bindMethodsToInstance(customApiClass);\n\t\t\t\t\tthis.customApis[ApiImport.default.name] = customApiClass;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlogger.error(e);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate bindMethodsToInstance<T extends object>(instance: T): void {\n\t\tconst proto = Object.getPrototypeOf(instance);\n\t\tObject.getOwnPropertyNames(proto).forEach((key) => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst property = (instance as any)[key]; // Temporarily cast for property access\n\t\t\tif (typeof property === 'function' && key !== 'constructor') {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\t(instance as any)[key] = property.bind(instance); // Temporarily cast for binding\n\t\t\t}\n\t\t});\n\t}\n}\n\nconst customApiFactory = new CustomApiFactory();\nexport default customApiFactory;\n","import fs from 'fs';\nimport path, { resolve } from 'path';\nimport tmp from 'tmp';\nimport * as TJS from 'typescript-json-schema';\nimport { restura } from '../restura.js';\nimport { ResturaSchema } from '../schemas/resturaSchema.js';\nimport type { ValidationDictionary } from '../validators/requestValidator.js';\n\n/**\n * This function generates a temporary file with the custom types and then uses typescript-json-schema to generate a JSON schema for each custom type.\n * @param currentSchema - The current schema to generate the validation dictionary for.\n * @returns A dictionary of custom type names and their corresponding JSON schemas.\n */\nexport default function customTypeValidationGenerator(currentSchema: ResturaSchema): ValidationDictionary {\n\tconst schemaObject: ValidationDictionary = {};\n\tconst customInterfaceNames = currentSchema.customTypes\n\t\t.map((customType) => {\n\t\t\tconst matches = customType.match(/(?<=interface\\s)(\\w+)|(?<=type\\s)(\\w+)/g);\n\t\t\tif (matches && matches.length > 0) return matches[0];\n\t\t\treturn '';\n\t\t})\n\t\t.filter(Boolean);\n\tif (!customInterfaceNames) return {};\n\n\tconst temporaryFile = tmp.fileSync({ mode: 0o644, prefix: 'prefix-', postfix: '.ts' });\n\tfs.writeFileSync(temporaryFile.name, currentSchema.customTypes.join('\\n'));\n\n\tconst compilerOptions: TJS.CompilerOptions = {\n\t\tstrictNullChecks: true,\n\t\tskipLibCheck: true // Needed if we are processing ES modules\n\t};\n\n\tconst program = TJS.getProgramFromFiles(\n\t\t[\n\t\t\tresolve(temporaryFile.name),\n\t\t\tpath.join(restura.resturaConfig.generatedTypesPath, 'restura.d.ts'),\n\t\t\tpath.join(restura.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\tpath.join(restura.resturaConfig.generatedTypesPath, 'api.d.ts')\n\t\t],\n\t\tcompilerOptions\n\t);\n\tcustomInterfaceNames.forEach((item) => {\n\t\tconst ddlSchema = TJS.generateSchema(program, item, {\n\t\t\trequired: true\n\t\t});\n\t\tschemaObject[item] = ddlSchema || {};\n\t});\n\n\ttemporaryFile.removeCallback();\n\n\treturn schemaObject;\n}\n","import { NextFunction } from 'express';\nimport { RsError, type ErrorCode, type HtmlStatusCodes } from '../RsError.js';\nimport { restura } from '../restura.js';\nimport type { RsRequest, RsResponse } from '../types/customExpressTypes.js';\nimport type { RsErrorData, RsPagedResponseData } from '../types/resturaTypes.js';\n\nexport default function addApiResponseFunctions(req: RsRequest<unknown>, res: RsResponse<unknown>, next: NextFunction) {\n\t/**\n\t * Sends given data inside { data: data };\n\t */\n\tres.sendData = function (data, statusCode = 200) {\n\t\tres.status(statusCode).send({ data });\n\t};\n\n\t/**\n\t * Sends data exactly as it was given, useful for 3rd party APIs\n\t */\n\tres.sendNoWrap = function (dataNoWrap, statusCode = 200) {\n\t\tres.status(statusCode).send(dataNoWrap);\n\t};\n\n\t/**\n\t * Sends a paginated\n\t * @param pagedData - A Redsky paged object\n\t * @param statusCode\n\t */\n\tres.sendPaginated = function (pagedData: RsPagedResponseData<unknown>, statusCode = 200) {\n\t\tres.status(statusCode).send({ data: pagedData.data, total: pagedData.total });\n\t};\n\n\t/**\n\t * Sends a RedSky RsErrorData\n\t */\n\tres.sendError = function (shortError: ErrorCode, msg: string, htmlStatusCode?: HtmlStatusCodes, stack?: string) {\n\t\tif (htmlStatusCode === undefined) {\n\t\t\tif (RsError.htmlStatus(shortError) !== undefined) {\n\t\t\t\thtmlStatusCode = RsError.htmlStatus(shortError);\n\t\t\t} else {\n\t\t\t\thtmlStatusCode = 500;\n\t\t\t}\n\t\t}\n\n\t\tconst errorData: RsErrorData = {\n\t\t\terr: shortError,\n\t\t\tmsg,\n\t\t\t...(restura.resturaConfig.sendErrorStackTrace && stack ? { stack } : {})\n\t\t};\n\t\tres.status(htmlStatusCode as number).send(errorData);\n\t};\n\n\tnext();\n}\n","import type { NextFunction } from 'express';\nimport type { RsRequest, RsResponse } from '../types/customExpressTypes.js';\nimport type { AuthenticateHandler, AuthenticatedRequesterDetails } from '../types/resturaTypes.js';\n\nexport function authenticateRequester(applicationAuthenticateHandler: AuthenticateHandler) {\n\treturn (req: RsRequest, res: RsResponse, next: NextFunction) => {\n\t\t// Call the custom function from the main application and get the role and other details\n\t\tapplicationAuthenticateHandler(req, res, (authenticatedRequesterDetails: AuthenticatedRequesterDetails) => {\n\t\t\treq.requesterDetails = { host: req.hostname, ipAddress: req.ip || '', ...authenticatedRequesterDetails };\n\t\t\tnext();\n\t\t});\n\t};\n}\n","import { Request } from 'express';\nimport multer from 'multer';\nimport * as os from 'os';\nimport { extname } from 'path';\n\nconst OneHundredMB = 100 * 1024 * 1024;\nlet commonUpload: multer.Multer | null = null;\nexport const getMulterUpload = (directory?: string) => {\n\tif (commonUpload) return commonUpload;\n\tconst storage = multer.diskStorage({\n\t\tdestination: directory || os.tmpdir(),\n\t\tfilename: function (\n\t\t\trequest: Request,\n\t\t\tfile: Express.Multer.File,\n\t\t\tcb: (err: Error | null, success: string) => void\n\t\t) {\n\t\t\tconst extension = extname(file.originalname);\n\t\t\tconst uniqueName = Date.now() + '-' + Math.round(Math.random() * 1000);\n\t\t\tcb(null, `${uniqueName}${extension}`);\n\t\t}\n\t});\n\n\tcommonUpload = multer({\n\t\tstorage,\n\t\tlimits: {\n\t\t\tfileSize: OneHundredMB\n\t\t}\n\t});\n\treturn commonUpload;\n};\n","import { z } from 'zod';\nimport { logger } from '../../logger/logger.js';\nimport { validatorDataSchema } from './validatorDataSchema.js';\n\n// Zod schemas with strict mode\nconst orderBySchema = z\n\t.object({\n\t\tcolumnName: z.string(),\n\t\torder: z.enum(['ASC', 'DESC']),\n\t\ttableName: z.string()\n\t})\n\t.strict();\n\nexport type OrderByData = z.infer<typeof orderBySchema>;\n\nconst groupBySchema = z\n\t.object({\n\t\tcolumnName: z.string(),\n\t\ttableName: z.string()\n\t})\n\t.strict();\n\nexport type GroupByData = z.infer<typeof groupBySchema>;\n\nconst whereDataSchema = z\n\t.object({\n\t\ttableName: z.string().optional(),\n\t\tcolumnName: z.string().optional(),\n\t\toperator: z\n\t\t\t.enum([\n\t\t\t\t'=',\n\t\t\t\t'<',\n\t\t\t\t'>',\n\t\t\t\t'<=',\n\t\t\t\t'>=',\n\t\t\t\t'!=',\n\t\t\t\t'LIKE',\n\t\t\t\t'NOT LIKE',\n\t\t\t\t'IN',\n\t\t\t\t'NOT IN',\n\t\t\t\t'STARTS WITH',\n\t\t\t\t'ENDS WITH',\n\t\t\t\t'IS',\n\t\t\t\t'IS NOT'\n\t\t\t])\n\t\t\t.optional(),\n\t\tvalue: z.string().or(z.number()).optional(),\n\t\tcustom: z.string().optional(),\n\t\tconjunction: z.enum(['AND', 'OR']).optional()\n\t})\n\t.strict();\n\nexport type WhereData = z.infer<typeof whereDataSchema>;\n\nconst assignmentDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tvalue: z.string()\n\t})\n\t.strict();\n\nexport type AssignmentData = z.infer<typeof assignmentDataSchema>;\n\nconst joinDataSchema = z\n\t.object({\n\t\ttable: z.string(),\n\t\tlocalTable: z.string().optional(), // Defaults to base table if not specificed\n\t\tlocalTableAlias: z.string().optional(), // If we are joining a table off of a previous join, this is the alias of the previous join\n\t\tlocalColumnName: z.string().optional(),\n\t\tforeignColumnName: z.string().optional(),\n\t\tcustom: z.string().optional(),\n\t\ttype: z.enum(['LEFT', 'INNER', 'RIGHT']),\n\t\talias: z.string()\n\t})\n\t.strict();\n\nexport type JoinData = z.infer<typeof joinDataSchema>;\n\nconst requestDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\trequired: z.boolean(),\n\t\tisNullable: z.boolean().optional(),\n\t\tvalidator: z.array(validatorDataSchema)\n\t})\n\t.strict();\n\nexport type RequestData = z.infer<typeof requestDataSchema>;\n\nconst responseDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tselector: z.string().optional(),\n\t\tsubquery: z\n\t\t\t.object({\n\t\t\t\ttable: z.string(),\n\t\t\t\tjoins: z.array(joinDataSchema),\n\t\t\t\twhere: z.array(whereDataSchema),\n\t\t\t\tget properties() {\n\t\t\t\t\treturn z.array(responseDataSchema);\n\t\t\t\t},\n\t\t\t\tgroupBy: groupBySchema.optional(),\n\t\t\t\torderBy: orderBySchema.optional()\n\t\t\t})\n\t\t\t.optional(),\n\t\ttype: z.string().optional() // Type allows you to override the type of the response, used in custom selectors\n\t})\n\t.strict();\n\nexport type ResponseData = z.infer<typeof responseDataSchema>;\n\nconst routeDataBaseSchema = z\n\t.object({\n\t\tmethod: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),\n\t\tname: z.string(),\n\t\tdescription: z.string(),\n\t\tpath: z.string(),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string())\n\t})\n\t.strict();\n\nexport type RouteDataBase = z.infer<typeof routeDataBaseSchema>;\n\nconst standardRouteSchema = routeDataBaseSchema\n\t.extend({\n\t\ttype: z.enum(['ONE', 'ARRAY', 'PAGED']),\n\t\ttable: z.string(),\n\t\tjoins: z.array(joinDataSchema),\n\t\tassignments: z.array(assignmentDataSchema),\n\t\twhere: z.array(whereDataSchema),\n\t\trequest: z.array(requestDataSchema),\n\t\tresponse: z.array(responseDataSchema),\n\t\tgroupBy: groupBySchema.optional(),\n\t\torderBy: orderBySchema.optional()\n\t})\n\t.strict();\n\nexport type StandardRouteData = z.infer<typeof standardRouteSchema>;\n\nconst customRouteSchema = routeDataBaseSchema\n\t.extend({\n\t\ttype: z.enum(['CUSTOM_ONE', 'CUSTOM_ARRAY', 'CUSTOM_PAGED']),\n\t\tresponseType: z.union([z.string(), z.enum(['string', 'number', 'boolean'])]),\n\t\trequestType: z.string().optional(),\n\t\trequest: z.array(requestDataSchema).optional(),\n\t\tfileUploadType: z.enum(['SINGLE', 'MULTIPLE']).optional()\n\t})\n\t.strict();\n\nexport type CustomRouteData = z.infer<typeof customRouteSchema>;\n\nexport type RouteData = CustomRouteData | StandardRouteData;\n\nexport const postgresColumnNumericTypesSchema = z.enum([\n\t'SMALLINT', // 2 bytes, -32,768 to 32,767\n\t'INTEGER', // 4 bytes, -2,147,483,648 to 2,147,483,647\n\t'BIGINT', // 8 bytes, -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807\n\t'DECIMAL', // user-specified precision, exact numeric, this is returned as a string type because numbers are not accurate enough\n\t'NUMERIC', // same as DECIMAL\n\t'REAL', // 4 bytes, 6 decimal digits precision (single precision)\n\t'DOUBLE PRECISION', // 8 bytes, 15 decimal digits precision (double precision)\n\t'SERIAL', // auto-incrementing integer\n\t'BIGSERIAL' // auto-incrementing big integer\n]);\nexport type PostgresColumnNumericTypes = z.infer<typeof postgresColumnNumericTypesSchema>;\n\nexport const postgresColumnStringTypesSchema = z.enum([\n\t'CHAR', // fixed-length, blank-padded\n\t'VARCHAR', // variable-length with limit\n\t'TEXT', // variable-length without limit\n\t'BYTEA' // binary data\n]);\nexport type PostgresColumnStringTypes = z.infer<typeof postgresColumnStringTypesSchema>;\n\nexport const postgresColumnDateTypesSchema = z.enum([\n\t'DATE', // calendar date (year, month, day)\n\t'TIMESTAMP', // both date and time (without time zone)\n\t'TIMESTAMPTZ', // both date and time (with time zone)\n\t'TIME', // time of day (without time zone)\n\t'INTERVAL' // time span\n]);\nexport type PostgresColumnDateTypes = z.infer<typeof postgresColumnDateTypesSchema>;\n\nexport const postgresColumnJsonTypesSchema = z.enum([\n\t'JSON', // stores JSON data as raw text\n\t'JSONB' // stores JSON data in a binary format, optimized for query performance\n]);\nexport type PostgresColumnJsonTypes = z.infer<typeof postgresColumnJsonTypesSchema>;\n\nexport const mariaDbColumnNumericTypesSchema = z.enum([\n\t'BOOLEAN', // 1-byte A synonym for \"TINYINT(1)\". Supported from version 1.2.0 onwards.\n\t'TINYINT', // 1-byte A very small integer. Numeric value with scale 0. Signed: -126 to +127. Unsigned: 0 to 253.\n\t'SMALLINT', // 2-bytes A small integer. Signed: -32,766 to 32,767. Unsigned: 0 to 65,533.\n\t'MEDIUMINT', // 3-bytes A medium integer. Signed: -8388608 to 8388607. Unsigned: 0 to 16777215. Supported starting with MariaDB ColumnStore 1.4.2.\n\t'INTEGER', // 4-bytes A normal-size integer. Numeric value with scale 0. Signed: -2,147,483,646 to 2,147,483,647. Unsigned: 0 to 4,294,967,293\n\t'BIGINT', // 8-bytes A large integer. Numeric value with scale 0. Signed: -9,223,372,036,854,775,806 to +9,223,372,036,854,775,807 Unsigned: 0 to +18,446,744,073,709,551,613\n\t'DECIMAL', // 2, 4, or 8 bytes A packed fixed-point number that can have a specific total number of digits and with a set number of digits after a decimal. The maximum precision (total number of digits) that can be specified is 18.\n\t'FLOAT', // 4 bytes Stored in 32-bit IEEE-754 floating point format. As such, the number of significant digits is about 6, and the range of values is approximately +/- 1e38.\n\t'DOUBLE' // 8 bytes Stored in 64-bit IEEE-754 floating point format. As such, the number of significant digits is about 15 and the range of values is approximately +/-1e308.\n]);\nexport type MariaDbColumnNumericTypes = z.infer<typeof mariaDbColumnNumericTypesSchema>;\n\nexport const mariaDbColumnStringTypesSchema = z.enum([\n\t'CHAR', // 1, 2, 4, or 8 bytes Holds letters and special characters of fixed length. Max length is 255. Default and minimum size is 1 byte.\n\t'VARCHAR', // 1, 2, 4, or 8 bytes or 8-byte token Holds letters, numbers, and special characters of variable length. Max length = 8000 bytes or characters and minimum length = 1 byte or character.\n\t'TINYTEXT', // 255 bytes Holds a small amount of letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'TINYBLOB', // 255 bytes Holds a small amount of binary data of variable length. Supported from version 1.1.0 onwards.\n\t'TEXT', // 64 KB Holds letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'BLOB', // 64 KB Holds binary data of variable length. Supported from version 1.1.0 onwards.\n\t'MEDIUMTEXT', // 16 MB Holds a medium amount of letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'MEDIUMBLOB', // 16 MB Holds a medium amount of binary data of variable length. Supported from version 1.1.0 onwards.\n\t'LONGTEXT', // 1.96 GB Holds a large amount of letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'JSON', // Alias for LONGTEXT, creates a CONSTRAINT for JSON_VALID, holds a JSON-formatted string of plain text.\n\t'LONGBLOB', // 1.96 GB Holds a large amount of binary data of variable length. Supported from version 1.1.0 onwards.\n\t'ENUM' // Enum type\n]);\nexport type MariaDbColumnStringTypes = z.infer<typeof mariaDbColumnStringTypesSchema>;\n\n// MariaDbColumnDateTypes Zod enum with PascalCase values and comments\nexport const mariaDbColumnDateTypesSchema = z.enum([\n\t'DATE', // 4-bytes Date has year, month, and day.\n\t'DATETIME', // 8-bytes A date and time combination. Supported range is 1000-01-01 00:00:00 to 9999-12-31 23:59:59. From version 1.2.0 microseconds are also supported.\n\t'TIME', // 8-bytes Holds hour, minute, second and optionally microseconds for time.\n\t'TIMESTAMP' // 4-bytes Values are stored as the number of seconds since 1970-01-01 00:00:00 UTC, and optionally microseconds.\n]);\nexport type MariaDbColumnDateTypes = z.infer<typeof mariaDbColumnDateTypesSchema>;\n\n// Define the ColumnData schema\nconst columnDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\ttype: z.union([\n\t\t\tpostgresColumnNumericTypesSchema,\n\t\t\tpostgresColumnStringTypesSchema,\n\t\t\tpostgresColumnDateTypesSchema,\n\t\t\tpostgresColumnJsonTypesSchema,\n\t\t\tmariaDbColumnNumericTypesSchema,\n\t\t\tmariaDbColumnStringTypesSchema,\n\t\t\tmariaDbColumnDateTypesSchema\n\t\t]),\n\t\tisNullable: z.boolean(),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string()),\n\t\tcomment: z.string().optional(),\n\t\tdefault: z.string().optional(),\n\t\tvalue: z.string().optional(),\n\t\tisPrimary: z.boolean().optional(),\n\t\tisUnique: z.boolean().optional(),\n\t\thasAutoIncrement: z.boolean().optional(),\n\t\tlength: z.number().optional()\n\t})\n\t.strict();\n\nexport type ColumnData = z.infer<typeof columnDataSchema>;\n\nconst indexDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcolumns: z.array(z.string()),\n\t\tisUnique: z.boolean(),\n\t\tisPrimaryKey: z.boolean(),\n\t\torder: z.enum(['ASC', 'DESC'])\n\t})\n\t.strict();\n\nexport type IndexData = z.infer<typeof indexDataSchema>;\n\n// ForeignKeyActions Zod enum with PascalCase values\nexport const foreignKeyActionsSchema = z.enum([\n\t'CASCADE', // CASCADE action for foreign keys\n\t'SET NULL', // SET NULL action for foreign keys\n\t'RESTRICT', // RESTRICT action for foreign keys\n\t'NO ACTION', // NO ACTION for foreign keys\n\t'SET DEFAULT' // SET DEFAULT action for foreign keys\n]);\nexport type ForeignKeyActions = z.infer<typeof foreignKeyActionsSchema>;\n\nconst foreignKeyDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcolumn: z.string(),\n\t\trefTable: z.string(),\n\t\trefColumn: z.string(),\n\t\tonDelete: foreignKeyActionsSchema,\n\t\tonUpdate: foreignKeyActionsSchema\n\t})\n\t.strict();\n\nexport type ForeignKeyData = z.infer<typeof foreignKeyDataSchema>;\n\nconst checkConstraintDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcheck: z.string()\n\t})\n\t.strict();\n\nexport type CheckConstraintData = z.infer<typeof checkConstraintDataSchema>;\n\nconst tableDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcolumns: z.array(columnDataSchema),\n\t\tindexes: z.array(indexDataSchema),\n\t\tforeignKeys: z.array(foreignKeyDataSchema),\n\t\tcheckConstraints: z.array(checkConstraintDataSchema),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string()),\n\t\tnotify: z.union([z.literal('ALL'), z.array(z.string())]).optional()\n\t})\n\t.strict();\n\nexport type TableData = z.infer<typeof tableDataSchema>;\n\nconst endpointDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tdescription: z.string(),\n\t\tbaseUrl: z.string(),\n\t\troutes: z.array(z.union([standardRouteSchema, customRouteSchema]))\n\t})\n\t.strict();\n\nexport type EndpointData = z.infer<typeof endpointDataSchema>;\n\n// The full Schema schema\nexport const resturaSchema = z\n\t.object({\n\t\tdatabase: z.array(tableDataSchema),\n\t\tendpoints: z.array(endpointDataSchema),\n\t\tglobalParams: z.array(z.string()),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string()),\n\t\tcustomTypes: z.array(z.string())\n\t})\n\t.strict();\n\nexport type ResturaSchema = z.infer<typeof resturaSchema>;\n\nexport async function isSchemaValid(schemaToCheck: unknown): Promise<boolean> {\n\ttry {\n\t\tresturaSchema.parse(schemaToCheck);\n\t\treturn true;\n\t} catch (error: unknown) {\n\t\tif (error instanceof z.ZodError) {\n\t\t\tlogger.error('Schema failed to validate with the following error:');\n\t\t\tconsole.error(z.prettifyError(error));\n\t\t} else {\n\t\t\tlogger.error(error);\n\t\t}\n\t\treturn false;\n\t}\n}\n","import { z } from 'zod';\n// created this to break up the restura.schema.ts file (running into dependency issues.)\nexport const validatorDataSchemeValue = z.union([z.string(), z.array(z.string()), z.number(), z.array(z.number())]);\nexport type ValidatorDataSchemeValue = z.infer<typeof validatorDataSchemeValue>;\n\nexport const validatorDataSchema = z\n\t.object({\n\t\ttype: z.enum(['TYPE_CHECK', 'MIN', 'MAX', 'ONE_OF']),\n\t\tvalue: validatorDataSchemeValue\n\t})\n\t.strict();\n\nexport type ValidatorData = z.infer<typeof validatorDataSchema>;\n","import { ObjectUtils } from '@redskytech/core-utils';\nimport jsonschema, { Schema } from 'jsonschema';\nimport { Definition } from 'typescript-json-schema';\nimport { z } from 'zod';\nimport { RsError } from '../RsError.js';\nimport { RequestData, RouteData } from '../schemas/resturaSchema.js';\nimport { ValidatorData, ValidatorDataSchemeValue, validatorDataSchemeValue } from '../schemas/validatorDataSchema.js';\nimport type { DynamicObject, RsRequest } from '../types/customExpressTypes.js';\nimport { addQuotesToStrings } from '../utils/utils.js';\n\nexport interface ValidationDictionary {\n\t[Key: string]: Definition;\n}\n\nexport default function requestValidator(\n\treq: RsRequest<unknown>,\n\trouteData: RouteData,\n\tvalidationSchema: ValidationDictionary\n) {\n\tconst requestData = getRequestData(req as RsRequest<unknown>);\n\treq.data = requestData;\n\n\tif (routeData.request === undefined) {\n\t\tif (routeData.type !== 'CUSTOM_ONE' && routeData.type !== 'CUSTOM_ARRAY' && routeData.type !== 'CUSTOM_PAGED')\n\t\t\tthrow new RsError('BAD_REQUEST', `No request parameters provided for standard request.`);\n\n\t\tif (!routeData.responseType) throw new RsError('BAD_REQUEST', `No response type defined for custom request.`);\n\n\t\tif (!routeData.requestType) throw new RsError('BAD_REQUEST', `No request type defined for custom request.`);\n\n\t\tconst currentInterface = validationSchema[routeData.requestType];\n\t\tconst validator = new jsonschema.Validator();\n\n\t\t// Create strict schema that doesn't allow extra properties\n\t\tconst strictSchema = {\n\t\t\t...currentInterface,\n\t\t\tadditionalProperties: false\n\t\t};\n\n\t\tconst executeValidation = validator.validate(req.data, strictSchema as Schema);\n\t\tif (!executeValidation.valid) {\n\t\t\tthrow new RsError(\n\t\t\t\t'BAD_REQUEST',\n\t\t\t\t`Request custom setup has failed the following check: (${executeValidation.errors})`\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\n\t// Make sure all passed in params are defined in the schema\n\tObject.keys(req.data as object).forEach((requestParamName) => {\n\t\tconst requestParam = routeData.request!.find((param) => param.name === requestParamName);\n\t\tif (!requestParam) {\n\t\t\tthrow new RsError('BAD_REQUEST', `Request param (${requestParamName}) is not allowed`);\n\t\t}\n\t});\n\n\trouteData.request.forEach((requestParam) => {\n\t\t// Find the request param in the request data\n\t\tconst requestValue = requestData[requestParam.name];\n\t\t// If the request param is required and not found in the request data, throw an error\n\t\tif (requestParam.required && requestValue === undefined)\n\t\t\tthrow new RsError('BAD_REQUEST', `Request param (${requestParam.name}) is required but missing`);\n\t\telse if (!requestParam.required && requestValue === undefined) return;\n\n\t\tvalidateRequestSingleParam(requestValue, requestParam);\n\t});\n}\n\nfunction validateRequestSingleParam(requestValue: unknown, requestParam: RequestData) {\n\tif (requestParam.isNullable && requestValue === null) return;\n\n\trequestParam.validator.forEach((validator) => {\n\t\tswitch (validator.type) {\n\t\t\tcase 'TYPE_CHECK':\n\t\t\t\tperformTypeCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t\tcase 'MIN':\n\t\t\t\tperformMinCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t\tcase 'MAX':\n\t\t\t\tperformMaxCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t\tcase 'ONE_OF':\n\t\t\t\tperformOneOfCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t}\n\t});\n}\n\nfunction isValidType(type: ValidatorDataSchemeValue, requestValue: unknown): boolean {\n\ttry {\n\t\texpectValidType(type, requestValue);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction expectValidType(type: ValidatorDataSchemeValue, requestValue: unknown) {\n\tif (type === 'number') {\n\t\treturn z.number().parse(requestValue);\n\t}\n\tif (type === 'string') {\n\t\treturn z.string().parse(requestValue);\n\t}\n\tif (type === 'boolean') {\n\t\treturn z.boolean().parse(requestValue);\n\t}\n\tif (type === 'string[]') {\n\t\treturn z.array(z.string()).parse(requestValue);\n\t}\n\tif (type === 'number[]') {\n\t\treturn z.array(z.number()).parse(requestValue);\n\t}\n\tif (type === 'any[]') {\n\t\treturn z.array(z.any()).parse(requestValue);\n\t}\n\tif (type === 'object') {\n\t\treturn z.object({}).strict().parse(requestValue);\n\t}\n}\n\nexport function performTypeCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\tif (!isValidType(validator.value, requestValue)) {\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${addQuotesToStrings(requestValue)}) is not of type (${validator.value})`\n\t\t);\n\t}\n\ttry {\n\t\tvalidatorDataSchemeValue.parse(validator.value);\n\t} catch {\n\t\tthrow new RsError('SCHEMA_ERROR', `Schema validator value (${validator.value}) is not a valid type`);\n\t}\n}\n\nfunction expectOnlyNumbers(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\tif (!isValueNumber(requestValue))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not of type number`\n\t\t);\n\n\tif (!isValueNumber(validator.value))\n\t\tthrow new RsError('SCHEMA_ERROR', `Schema validator value (${validator.value} is not of type number`);\n}\n\nfunction performMinCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\texpectOnlyNumbers(requestValue, validator, requestParamName);\n\tif ((requestValue as number) < (validator.value as number))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is less than (${validator.value})`\n\t\t);\n}\n\nfunction performMaxCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\texpectOnlyNumbers(requestValue, validator, requestParamName);\n\tif ((requestValue as number) > (validator.value as number))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is more than (${validator.value})`\n\t\t);\n}\n\nfunction performOneOfCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\tif (!ObjectUtils.isArrayWithData(validator.value as unknown[]))\n\t\tthrow new RsError('SCHEMA_ERROR', `Schema validator value (${validator.value}) is not of type array`);\n\tif (typeof requestValue === 'object')\n\t\tthrow new RsError('BAD_REQUEST', `Request param (${requestParamName}) is not of type string or number`);\n\n\tif (!(validator.value as unknown[]).includes(requestValue as string | number))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not one of (${(\n\t\t\t\tvalidator.value as unknown[]\n\t\t\t).join(', ')})`\n\t\t);\n}\n\nfunction isValueNumber(value: unknown): value is number {\n\treturn !isNaN(Number(value));\n}\n\nexport function getRequestData(req: RsRequest<unknown>): DynamicObject {\n\tlet body = '';\n\tif (req.method === 'GET' || req.method === 'DELETE') {\n\t\tbody = 'query';\n\t} else {\n\t\tbody = 'body';\n\t}\n\n\tconst bodyData = req[body as keyof typeof req]; // Cast once and store in a variable\n\n\tif (bodyData && body === 'query') {\n\t\tconst normalizedData: DynamicObject = {};\n\n\t\tfor (const attr in bodyData) {\n\t\t\tif (attr.includes('[]') && !(bodyData[attr] instanceof Array)) {\n\t\t\t\tbodyData[attr] = [bodyData[attr]];\n\t\t\t}\n\n\t\t\t// Remove [] from the key if it exists\n\t\t\tconst cleanAttr = attr.replace(/\\[\\]$/, '');\n\n\t\t\tif (bodyData[attr] instanceof Array) {\n\t\t\t\tconst parsedList = bodyData[attr].map((value: unknown) => {\n\t\t\t\t\tif (value === 'true') return true;\n\t\t\t\t\tif (value === 'false') return false;\n\t\t\t\t\tif (value === undefined) return undefined;\n\t\t\t\t\tif (value === '') return '';\n\t\t\t\t\tconst parsed = ObjectUtils.safeParse(value);\n\t\t\t\t\treturn isNaN(Number(parsed)) ? parsed : Number(parsed);\n\t\t\t\t});\n\n\t\t\t\tnormalizedData[cleanAttr] = parsedList;\n\t\t\t} else {\n\t\t\t\tlet value = bodyData[attr];\n\t\t\t\tif (value === 'true') {\n\t\t\t\t\tvalue = true;\n\t\t\t\t} else if (value === 'false') {\n\t\t\t\t\tvalue = false;\n\t\t\t\t} else if (value === undefined) {\n\t\t\t\t\tvalue = undefined;\n\t\t\t\t} else if (value === '') {\n\t\t\t\t\tvalue = '';\n\t\t\t\t} else {\n\t\t\t\t\tvalue = ObjectUtils.safeParse(value);\n\t\t\t\t\tif (!isNaN(Number(value))) {\n\t\t\t\t\t\tvalue = Number(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnormalizedData[cleanAttr] = value;\n\t\t\t}\n\t\t}\n\n\t\treturn normalizedData;\n\t}\n\n\treturn bodyData;\n}\n","import type { DynamicObject } from '../types/customExpressTypes.js';\n\ntype QuotedValue = string | QuotedValue[] | Exclude<unknown, string | unknown[]>;\n\nexport function addQuotesToStrings(variable: unknown): QuotedValue {\n\tif (typeof variable === 'string') {\n\t\treturn `'${variable}'`;\n\t} else if (Array.isArray(variable)) {\n\t\tconst arrayWithQuotes = variable.map(addQuotesToStrings);\n\t\treturn arrayWithQuotes;\n\t} else {\n\t\treturn variable;\n\t}\n}\n\nexport function sortObjectKeysAlphabetically<T>(obj: T): T {\n\tif (Array.isArray(obj)) {\n\t\t// If the value is an array, recurse for each element\n\t\treturn obj.map(sortObjectKeysAlphabetically) as T;\n\t} else if (obj !== null && typeof obj === 'object') {\n\t\t// If the value is an object, sort its keys\n\t\treturn Object.keys(obj)\n\t\t\t.sort()\n\t\t\t.reduce((sorted: DynamicObject, key: string) => {\n\t\t\t\tsorted[key] = sortObjectKeysAlphabetically((obj as Record<string, T>)[key]);\n\t\t\t\treturn sorted;\n\t\t\t}, {}) as T;\n\t}\n\t// If the value is a primitive, return it as-is\n\treturn obj;\n}\n","import type { NextFunction } from 'express';\nimport { logger } from '../../logger/logger.js';\nimport { HtmlStatusCodes } from '../RsError.js';\nimport { resturaSchema } from '../schemas/resturaSchema.js';\nimport type { RsRequest, RsResponse } from '../types/customExpressTypes.js';\nimport { getRequestData } from '../validators/requestValidator.js';\n\nexport async function schemaValidation(req: RsRequest<unknown>, res: RsResponse<unknown>, next: NextFunction) {\n\treq.data = getRequestData(req as RsRequest<unknown>);\n\n\ttry {\n\t\tresturaSchema.parse(req.data);\n\t\tnext();\n\t} catch (error) {\n\t\tlogger.error(error);\n\t\tres.sendError('BAD_REQUEST', error as string, HtmlStatusCodes.BAD_REQUEST);\n\t}\n}\n","import { z } from 'zod';\n\nconst isTsx = process.argv[1]?.endsWith('.ts');\nconst isTsNode = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT;\nconst customApiFolderPath = isTsx || isTsNode ? '/src/api' : '/dist/api';\n\nexport const resturaConfigSchema = z.object({\n\tauthToken: z.string().min(1, 'Missing Restura Auth Token'),\n\tsendErrorStackTrace: z.boolean().default(false),\n\tschemaFilePath: z.string().default(process.cwd() + '/restura.schema.json'),\n\tcustomApiFolderPath: z.string().default(process.cwd() + customApiFolderPath),\n\tgeneratedTypesPath: z.string().default(process.cwd() + '/src/@types'),\n\tfileTempCachePath: z.string().optional(),\n\tscratchDatabaseSuffix: z.string().optional()\n});\nexport type ResturaConfigSchema = z.infer<typeof resturaConfigSchema>;\n","import { ObjectUtils } from '@redskytech/core-utils';\nimport getDiff from '@wmfs/pg-diff-sync';\nimport pgInfo from '@wmfs/pg-info';\nimport type { Client as ClientType } from 'pg';\nimport pg from 'pg';\nimport { logger } from '../../logger/logger.js';\nimport { RsError } from '../RsError.js';\nimport eventManager, { MutationType, TriggerResult } from '../eventManager.js';\nimport {\n\tCustomRouteData,\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tStandardRouteData,\n\tWhereData,\n\ttype ColumnData\n} from '../schemas/resturaSchema.js';\nimport { DynamicObject, RequesterDetails, RsRequest } from '../types/customExpressTypes.js';\nimport { PageQuery } from '../types/resturaTypes.js';\nimport { PsqlPool } from './PsqlPool.js';\nimport { escapeColumnName, insertObjectQuery, SQL, updateObjectQuery } from './PsqlUtils.js';\nimport SqlEngine from './SqlEngine.js';\nimport { SqlUtils } from './SqlUtils.js';\nimport filterPsqlParser from './filterPsqlParser.js';\nconst { Client, types } = pg;\n\nconst systemUser: RequesterDetails = {\n\trole: '',\n\tscopes: [],\n\thost: '',\n\tipAddress: '',\n\tisSystemUser: true\n};\n\nexport class PsqlEngine extends SqlEngine {\n\tsetupTriggerListeners: Promise<void> | undefined;\n\tprivate triggerClient: ClientType | undefined;\n\tprivate scratchDbName: string = '';\n\tprivate reconnectAttempts = 0;\n\tprivate readonly MAX_RECONNECT_ATTEMPTS = 5;\n\tprivate readonly INITIAL_RECONNECT_DELAY = 5000; // 5 seconds\n\n\tconstructor(\n\t\tprivate psqlConnectionPool: PsqlPool,\n\t\tshouldListenForDbTriggers: boolean = false,\n\t\tscratchDatabaseSuffix: string = ''\n\t) {\n\t\tsuper();\n\n\t\tthis.setupPgReturnTypes();\n\t\tif (shouldListenForDbTriggers) {\n\t\t\tthis.setupTriggerListeners = this.listenForDbTriggers();\n\t\t}\n\n\t\tthis.scratchDbName = `${psqlConnectionPool.poolConfig.database}_scratch${scratchDatabaseSuffix ? `_${scratchDatabaseSuffix}` : ''}`;\n\t}\n\tasync close() {\n\t\tif (this.triggerClient) {\n\t\t\tawait this.triggerClient.end();\n\t\t}\n\t}\n\n\tprivate setupPgReturnTypes() {\n\t\t// OID for timestamptz in Postgres\n\t\tconst TIMESTAMPTZ_OID = 1184;\n\t\t// Set a custom parser for timestamptz to return an ISO string\n\t\ttypes.setTypeParser(TIMESTAMPTZ_OID, (val) => {\n\t\t\treturn val === null ? null : new Date(val).toISOString();\n\t\t});\n\t\tconst BIGINT_OID = 20;\n\t\t// Set a custom parser for BIGINT to return a JavaScript Number\n\t\ttypes.setTypeParser(BIGINT_OID, (val) => {\n\t\t\treturn val === null ? null : Number(val);\n\t\t});\n\t}\n\n\tprivate async reconnectTriggerClient() {\n\t\tif (this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) {\n\t\t\tlogger.error('Max reconnection attempts reached for trigger client. Stopping reconnection attempts.');\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.triggerClient) {\n\t\t\ttry {\n\t\t\t\tawait this.triggerClient.end();\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(`Error closing trigger client: ${error}`);\n\t\t\t}\n\t\t}\n\n\t\t// Exponential backoff: 5s, 10s, 20s, 40s, 80s\n\t\tconst delay = this.INITIAL_RECONNECT_DELAY * Math.pow(2, this.reconnectAttempts);\n\t\tlogger.info(\n\t\t\t`Attempting to reconnect trigger client in ${delay / 1000} seconds... (Attempt ${this.reconnectAttempts + 1}/${this.MAX_RECONNECT_ATTEMPTS})`\n\t\t);\n\n\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\n\t\tthis.reconnectAttempts++;\n\n\t\ttry {\n\t\t\tawait this.listenForDbTriggers();\n\t\t\t// Reset reconnect attempts on successful connection\n\t\t\tthis.reconnectAttempts = 0;\n\t\t} catch (error) {\n\t\t\tlogger.error(`Reconnection attempt ${this.reconnectAttempts} failed: ${error}`);\n\t\t\tif (this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) {\n\t\t\t\tawait this.reconnectTriggerClient();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async listenForDbTriggers() {\n\t\tthis.triggerClient = new Client({\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tdatabase: this.psqlConnectionPool.poolConfig.database,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port,\n\t\t\tconnectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis\n\t\t});\n\n\t\ttry {\n\t\t\tawait this.triggerClient.connect();\n\n\t\t\tconst promises = [];\n\t\t\tpromises.push(this.triggerClient.query('LISTEN insert'));\n\t\t\tpromises.push(this.triggerClient.query('LISTEN update'));\n\t\t\tpromises.push(this.triggerClient.query('LISTEN delete'));\n\t\t\tawait Promise.all(promises);\n\n\t\t\t// Add error handling for the connection\n\t\t\tthis.triggerClient.on('error', async (error) => {\n\t\t\t\tlogger.error(`Trigger client error: ${error}`);\n\t\t\t\t// Attempt to reconnect\n\t\t\t\tawait this.reconnectTriggerClient();\n\t\t\t});\n\n\t\t\t// Handle notifications\n\t\t\tthis.triggerClient.on('notification', async (msg) => {\n\t\t\t\tif (msg.channel === 'insert' || msg.channel === 'update' || msg.channel === 'delete') {\n\t\t\t\t\tconst payload: TriggerResult = ObjectUtils.safeParse(msg.payload) as TriggerResult;\n\t\t\t\t\tawait this.handleTrigger(payload, msg.channel.toUpperCase() as MutationType);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tlogger.info('Successfully connected to database triggers');\n\t\t} catch (error) {\n\t\t\tlogger.error(`Failed to setup trigger listeners: ${error}`);\n\t\t\t// Attempt to reconnect\n\t\t\tawait this.reconnectTriggerClient();\n\t\t}\n\t}\n\n\tprivate async handleTrigger(payload: TriggerResult, mutationType: MutationType) {\n\t\tif (\n\t\t\tpayload.queryMetadata &&\n\t\t\tpayload.queryMetadata.connectionInstanceId === this.psqlConnectionPool.instanceId\n\t\t) {\n\t\t\tawait eventManager.fireActionFromDbTrigger({ queryMetadata: payload.queryMetadata, mutationType }, payload);\n\t\t}\n\t}\n\n\tasync createDatabaseFromSchema(schema: ResturaSchema, connection: PsqlPool): Promise<string> {\n\t\tconst sqlFullStatement = this.generateDatabaseSchemaFromSchema(schema);\n\t\tawait connection.runQuery(sqlFullStatement, [], systemUser);\n\t\treturn sqlFullStatement;\n\t}\n\n\tgenerateDatabaseSchemaFromSchema(schema: ResturaSchema): string {\n\t\tconst sqlStatements = [];\n\t\tconst indexes = [];\n\t\tconst triggers = [];\n\n\t\tfor (const table of schema.database) {\n\t\t\tif (table.notify) {\n\t\t\t\ttriggers.push(this.createInsertTriggers(table.name, table.notify));\n\t\t\t\ttriggers.push(this.createUpdateTrigger(table.name, table.notify));\n\t\t\t\ttriggers.push(this.createDeleteTrigger(table.name, table.notify));\n\t\t\t}\n\n\t\t\tlet sql = `CREATE TABLE \"${table.name}\"\n\t\t\t\t\t ( `;\n\t\t\tconst tableColumns = [];\n\t\t\tfor (const column of table.columns) {\n\t\t\t\tlet columnSql = '';\n\n\t\t\t\tcolumnSql += `\\t\"${column.name}\" ${this.schemaToPsqlType(column)}`;\n\t\t\t\tlet value = column.value;\n\t\t\t\t// JSON's value is used only for typescript not for the database\n\t\t\t\tif (column.type === 'JSON') value = '';\n\t\t\t\tif (column.type === 'JSONB') value = '';\n\t\t\t\tif (column.type === 'DECIMAL' && value) {\n\t\t\t\t\t// replace the character '-' with comma since we use it to separate the values in restura for decimals\n\t\t\t\t\t// also remove single and double quotes\n\t\t\t\t\tvalue = value.replace('-', ',').replace(/['\"]/g, '');\n\t\t\t\t}\n\t\t\t\tif (value && column.type !== 'ENUM') {\n\t\t\t\t\tcolumnSql += `(${value})`;\n\t\t\t\t} else if (column.length) columnSql += `(${column.length})`;\n\t\t\t\tif (column.isPrimary) {\n\t\t\t\t\tcolumnSql += ' PRIMARY KEY ';\n\t\t\t\t}\n\t\t\t\tif (column.isUnique) {\n\t\t\t\t\tcolumnSql += ` CONSTRAINT \"${table.name}_${column.name}_unique_index\" UNIQUE `;\n\t\t\t\t}\n\t\t\t\tif (column.isNullable) columnSql += ' NULL';\n\t\t\t\telse columnSql += ' NOT NULL';\n\t\t\t\tif (column.default) columnSql += ` DEFAULT ${column.default}`;\n\t\t\t\tif (value && column.type === 'ENUM') {\n\t\t\t\t\tcolumnSql += ` CHECK (\"${column.name}\" IN (${value}))`;\n\t\t\t\t}\n\t\t\t\ttableColumns.push(columnSql);\n\t\t\t}\n\t\t\tsql += tableColumns.join(', \\n');\n\t\t\tfor (const index of table.indexes) {\n\t\t\t\tif (!index.isPrimaryKey) {\n\t\t\t\t\tlet unique = ' ';\n\t\t\t\t\tif (index.isUnique) unique = 'UNIQUE ';\n\n\t\t\t\t\tindexes.push(\n\t\t\t\t\t\t`\\tCREATE ${unique}INDEX \"${index.name}\" ON \"${table.name}\" (${index.columns\n\t\t\t\t\t\t\t.map((item) => {\n\t\t\t\t\t\t\t\treturn `\"${item}\" ${index.order}`;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.join(', ')});`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tsql += '\\n);';\n\t\t\tsqlStatements.push(sql);\n\t\t}\n\n\t\t// Now setup foreign keys\n\t\tfor (const table of schema.database) {\n\t\t\tif (!table.foreignKeys.length) continue;\n\t\t\tconst sql = `ALTER TABLE \"${table.name}\" `;\n\t\t\tconst constraints: string[] = [];\n\t\t\tfor (const foreignKey of table.foreignKeys) {\n\t\t\t\tlet constraint = `\\t ADD CONSTRAINT \"${foreignKey.name}\"\n FOREIGN KEY (\"${foreignKey.column}\") REFERENCES \"${foreignKey.refTable}\" (\"${foreignKey.refColumn}\")`;\n\t\t\t\tconstraint += ` ON DELETE ${foreignKey.onDelete}`;\n\t\t\t\tconstraint += ` ON UPDATE ${foreignKey.onUpdate}`;\n\t\t\t\tconstraints.push(constraint);\n\t\t\t}\n\t\t\tsqlStatements.push(sql + constraints.join(',\\n') + ';');\n\t\t}\n\n\t\t// Now setup check constraints\n\t\tfor (const table of schema.database) {\n\t\t\tif (!table.checkConstraints.length) continue;\n\t\t\tconst sql = `ALTER TABLE \"${table.name}\" `;\n\t\t\tconst constraints: string[] = [];\n\t\t\tfor (const check of table.checkConstraints) {\n\t\t\t\tconst constraint = `ADD CONSTRAINT \"${check.name}\" CHECK (${check.check})`;\n\t\t\t\tconstraints.push(constraint);\n\t\t\t}\n\t\t\tsqlStatements.push(sql + constraints.join(',\\n') + ';');\n\t\t}\n\n\t\tsqlStatements.push(indexes.join('\\n'));\n\t\tsqlStatements.push(triggers.join('\\n'));\n\n\t\treturn sqlStatements.join('\\n\\n');\n\t}\n\n\tprivate async getNewPublicSchemaAndScratchPool(): Promise<PsqlPool> {\n\t\tconst scratchDbExists = await this.psqlConnectionPool.runQuery<DynamicObject>(\n\t\t\t`SELECT *\n FROM pg_database\n WHERE datname = '${this.scratchDbName}';`,\n\t\t\t[],\n\t\t\tsystemUser\n\t\t);\n\t\tif (scratchDbExists.length === 0) {\n\t\t\tawait this.psqlConnectionPool.runQuery(`CREATE DATABASE ${this.scratchDbName};`, [], systemUser);\n\t\t}\n\n\t\tconst scratchPool = new PsqlPool({\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port,\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\tdatabase: this.scratchDbName,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\tmax: this.psqlConnectionPool.poolConfig.max,\n\t\t\tidleTimeoutMillis: this.psqlConnectionPool.poolConfig.idleTimeoutMillis,\n\t\t\tconnectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis\n\t\t});\n\t\tawait scratchPool.runQuery(`DROP SCHEMA public CASCADE;`, [], systemUser);\n\t\tawait scratchPool.runQuery(\n\t\t\t`CREATE SCHEMA public AUTHORIZATION ${this.psqlConnectionPool.poolConfig.user};`,\n\t\t\t[],\n\t\t\tsystemUser\n\t\t);\n\t\tconst schemaComment = await this.psqlConnectionPool.runQuery<{ description: string }>(\n\t\t\t`\n\t\t\tSELECT pg_description.description\n\t\t\tFROM pg_description\n\t\t\tJOIN pg_namespace ON pg_namespace.oid = pg_description.objoid\n\t\t\tWHERE pg_namespace.nspname = 'public';`,\n\t\t\t[],\n\t\t\tsystemUser\n\t\t);\n\t\tif (schemaComment[0]?.description) {\n\t\t\tawait scratchPool.runQuery(\n\t\t\t\t`COMMENT ON SCHEMA public IS '${schemaComment[0]?.description}';`,\n\t\t\t\t[],\n\t\t\t\tsystemUser\n\t\t\t);\n\t\t}\n\t\treturn scratchPool;\n\t}\n\n\tasync diffDatabaseToSchema(schema: ResturaSchema): Promise<string> {\n\t\tconst scratchPool = await this.getNewPublicSchemaAndScratchPool();\n\t\tawait this.createDatabaseFromSchema(schema, scratchPool);\n\n\t\tconst originalClient = new Client({\n\t\t\tdatabase: this.psqlConnectionPool.poolConfig.database,\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port\n\t\t});\n\t\tconst scratchClient = new Client({\n\t\t\tdatabase: this.scratchDbName,\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port\n\t\t});\n\t\tconst promises = [originalClient.connect(), scratchClient.connect()];\n\t\tawait Promise.all(promises);\n\n\t\tconst infoPromises = [pgInfo({ client: originalClient }), pgInfo({ client: scratchClient })];\n\t\tconst [info1, info2] = await Promise.all(infoPromises);\n\n\t\tconst diff = getDiff(info1, info2);\n\t\tconst endPromises = [originalClient.end(), scratchClient.end()];\n\t\tawait Promise.all(endPromises);\n\t\treturn diff.join('\\n');\n\t}\n\n\tprotected createNestedSelect(\n\t\treq: RsRequest<unknown>,\n\t\tschema: ResturaSchema,\n\t\titem: ResponseData,\n\t\trouteData: StandardRouteData,\n\t\tsqlParams: string[]\n\t): string {\n\t\tif (!item.subquery) return '';\n\t\tif (\n\t\t\t!ObjectUtils.isArrayWithData(\n\t\t\t\titem.subquery.properties.filter((nestedItem) => {\n\t\t\t\t\treturn this.canRequesterAccessColumn(\n\t\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\tnestedItem,\n\t\t\t\t\t\t[...routeData.joins, ...item.subquery!.joins]\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t)\n\t\t) {\n\t\t\treturn \"'[]'\";\n\t\t}\n\n\t\treturn `COALESCE((SELECT JSON_AGG(JSON_BUILD_OBJECT(\n\t\t\t${item.subquery.properties\n\t\t\t\t.map((nestedItem) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!this.canRequesterAccessColumn(\n\t\t\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\tnestedItem,\n\t\t\t\t\t\t\t[...routeData.joins, ...item.subquery!.joins]\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (nestedItem.subquery) {\n\t\t\t\t\t\treturn `'${nestedItem.name}', ${this.createNestedSelect(\n\t\t\t\t\t\t\t// recursion\n\t\t\t\t\t\t\treq,\n\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\tnestedItem,\n\t\t\t\t\t\t\trouteData,\n\t\t\t\t\t\t\tsqlParams\n\t\t\t\t\t\t)}`;\n\t\t\t\t\t}\n\t\t\t\t\treturn `'${nestedItem.name}', ${escapeColumnName(nestedItem.selector)}`;\n\t\t\t\t})\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(', ')}\n\t\t\t\t\t\t)) \n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\"${item.subquery.table}\"\n\t\t\t\t\t\t\t${this.generateJoinStatements(req, item.subquery.joins, item.subquery.table, routeData, schema, sqlParams)}\n\t\t\t\t\t\t\t${this.generateWhereClause(req, item.subquery.where, routeData, sqlParams)}\n\t\t\t\t\t), '[]')`;\n\t}\n\n\tprotected async executeCreateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject> {\n\t\tconst sqlParams: string[] = [];\n\t\tconst parameterObj: DynamicObject = {};\n\t\t(routeData.assignments || []).forEach((assignment) => {\n\t\t\tparameterObj[assignment.name] = this.replaceParamKeywords(assignment.value, routeData, req, sqlParams);\n\t\t});\n\n\t\tconst query = insertObjectQuery(routeData.table, { ...(req.data as DynamicObject), ...parameterObj });\n\t\tconst createdItem = await this.psqlConnectionPool.queryOne<DynamicObject & { id: number }>(\n\t\t\tquery,\n\t\t\tsqlParams,\n\t\t\treq.requesterDetails\n\t\t);\n\t\tconst insertId = createdItem.id;\n\t\tconst whereId: WhereData = {\n\t\t\ttableName: routeData.table,\n\t\t\tvalue: insertId,\n\t\t\tcolumnName: 'id',\n\t\t\toperator: '='\n\t\t};\n\t\tconst whereData: WhereData[] = [whereId];\n\t\treq.data = { id: insertId };\n\t\treturn this.executeGetRequest(req, { ...routeData, where: whereData }, schema) as Promise<DynamicObject>;\n\t}\n\n\tprotected async executeGetRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t): Promise<DynamicObject | any[]> {\n\t\tconst DEFAULT_PAGED_PAGE_NUMBER = 0;\n\t\tconst DEFAULT_PAGED_PER_PAGE_NUMBER = 25;\n\t\tconst sqlParams: string[] = [];\n\n\t\tlet sqlStatement = '';\n\n\t\tconst selectColumns: ResponseData[] = [];\n\t\trouteData.response.forEach((item) => {\n\t\t\t// For a subquery, we will check the permission when generating the subquery statement, so pass it through\n\t\t\tif (\n\t\t\t\titem.subquery ||\n\t\t\t\tthis.canRequesterAccessColumn(\n\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\tschema,\n\t\t\t\t\titem,\n\t\t\t\t\trouteData.joins\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tselectColumns.push(item);\n\t\t});\n\t\tif (!selectColumns.length) throw new RsError('FORBIDDEN', `You do not have permission to access this data.`);\n\t\tlet selectStatement = 'SELECT \\n';\n\t\tselectStatement += `\\t${selectColumns\n\t\t\t.map((item) => {\n\t\t\t\tif (item.subquery) {\n\t\t\t\t\treturn `${this.createNestedSelect(req, schema, item, routeData, sqlParams)} AS ${escapeColumnName(\n\t\t\t\t\t\titem.name\n\t\t\t\t\t)}`;\n\t\t\t\t}\n\t\t\t\tif (item.type) {\n\t\t\t\t\tconst selectorWithReplacedKeywords = this.replaceParamKeywords(\n\t\t\t\t\t\titem.selector!,\n\t\t\t\t\t\trouteData,\n\t\t\t\t\t\treq,\n\t\t\t\t\t\tsqlParams\n\t\t\t\t\t);\n\t\t\t\t\treturn `${selectorWithReplacedKeywords} AS ${escapeColumnName(item.name)}`;\n\t\t\t\t} else {\n\t\t\t\t\treturn `${escapeColumnName(item.selector)} AS ${escapeColumnName(item.name)}`;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.join(',\\n\\t')}\\n`;\n\t\tsqlStatement += `FROM \"${routeData.table}\"\\n`;\n\t\tsqlStatement += this.generateJoinStatements(\n\t\t\treq,\n\t\t\trouteData.joins,\n\t\t\trouteData.table,\n\t\t\trouteData,\n\t\t\tschema,\n\t\t\tsqlParams\n\t\t);\n\n\t\tsqlStatement += this.generateWhereClause(req, routeData.where, routeData, sqlParams);\n\n\t\tlet groupByOrderByStatement = this.generateGroupBy(routeData);\n\t\tgroupByOrderByStatement += this.generateOrderBy(req, routeData);\n\n\t\tif (routeData.type === 'ONE') {\n\t\t\treturn this.psqlConnectionPool.queryOne(\n\t\t\t\t`${selectStatement}${sqlStatement}${groupByOrderByStatement};`,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\t\t} else if (routeData.type === 'ARRAY') {\n\t\t\t// Array\n\t\t\treturn this.psqlConnectionPool.runQuery(\n\t\t\t\t`${selectStatement}${sqlStatement}${groupByOrderByStatement};`,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\t\t} else if (routeData.type === 'PAGED') {\n\t\t\tconst data = req.data as PageQuery;\n\t\t\t// The COUNT() does not work with group by and order by, so we need to catch that case and act accordingly\n\t\t\tconst pagePromise = this.psqlConnectionPool.runQuery(\n\t\t\t\t`${selectStatement}${sqlStatement}${groupByOrderByStatement}` +\n\t\t\t\t\tSQL`LIMIT ${data.perPage || DEFAULT_PAGED_PER_PAGE_NUMBER} OFFSET ${(data.page - 1) * data.perPage || DEFAULT_PAGED_PAGE_NUMBER};`,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\t\t\tconst totalQuery = `SELECT COUNT(${\n\t\t\t\trouteData.groupBy ? `DISTINCT ${routeData.groupBy.tableName}.${routeData.groupBy.columnName}` : '*'\n\t\t\t}) AS total\\n ${sqlStatement};`;\n\t\t\tconst totalPromise = this.psqlConnectionPool.runQuery<{ total: number }>(\n\t\t\t\ttotalQuery,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\n\t\t\tconst [pageResults, totalResponse] = await Promise.all([pagePromise, totalPromise]);\n\n\t\t\tlet total = 0;\n\t\t\tif (ObjectUtils.isArrayWithData(totalResponse)) {\n\t\t\t\ttotal = totalResponse[0].total;\n\t\t\t}\n\t\t\treturn { data: pageResults, total };\n\t\t} else {\n\t\t\tthrow new RsError('UNKNOWN_ERROR', 'Unknown route type.');\n\t\t}\n\t}\n\n\tprotected async executeUpdateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject> {\n\t\tconst sqlParams: string[] = [];\n\t\t// eslint-disable-next-line\n\t\tconst { id, ...bodyNoId } = req.body;\n\n\t\t// Find the database table\n\t\tconst table = schema.database.find((item) => {\n\t\t\treturn item.name === routeData.table;\n\t\t});\n\t\tif (!table) throw new RsError('UNKNOWN_ERROR', 'Unknown table.');\n\t\tif (table.columns.find((column) => column.name === 'modifiedOn')) {\n\t\t\tbodyNoId.modifiedOn = new Date().toISOString();\n\t\t}\n\n\t\tfor (const assignment of routeData.assignments) {\n\t\t\tconst column = table.columns.find((column) => column.name === assignment.name);\n\t\t\tif (!column) continue;\n\n\t\t\tconst assignmentEscaped = escapeColumnName(assignment.name);\n\n\t\t\tif (SqlUtils.convertDatabaseTypeToTypescript(column.type!) === 'number')\n\t\t\t\tbodyNoId[assignmentEscaped] = Number(assignment.value);\n\t\t\telse bodyNoId[assignmentEscaped] = assignment.value;\n\t\t}\n\n\t\t// Todo: Add joins back in on the update. They are useful for the where clause.\n\t\t// let joinStatement = this.generateJoinStatements(\n\t\t// \treq,\n\t\t// \trouteData.joins!,\n\t\t// \trouteData.table!,\n\t\t// \trouteData!,\n\t\t// \tschema,\n\t\t// \treq.requesterDetails.role,\n\t\t// \tsqlParams\n\t\t// );\n\t\tconst whereClause = this.generateWhereClause(req, routeData.where, routeData, sqlParams);\n\t\tconst query = updateObjectQuery(routeData.table, bodyNoId, whereClause);\n\t\tawait this.psqlConnectionPool.queryOne(query, [...sqlParams], req.requesterDetails);\n\t\treturn this.executeGetRequest(req, routeData, schema) as unknown as DynamicObject;\n\t}\n\n\tprotected async executeDeleteRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<boolean> {\n\t\tconst sqlParams: string[] = [];\n\n\t\tconst joinStatement = this.generateJoinStatements(\n\t\t\treq,\n\t\t\trouteData.joins,\n\t\t\trouteData.table,\n\t\t\trouteData,\n\t\t\tschema,\n\t\t\tsqlParams\n\t\t);\n\t\tconst whereClause = this.generateWhereClause(req, routeData.where, routeData, sqlParams);\n\t\tif (whereClause.replace(/\\s/g, '') === '') {\n\t\t\tthrow new RsError('DELETE_FORBIDDEN', 'Deletes need a where clause');\n\t\t}\n\n\t\tconst deleteStatement = `\nDELETE FROM \"${routeData.table}\" ${joinStatement} ${whereClause}`;\n\t\tawait this.psqlConnectionPool.runQuery(deleteStatement, sqlParams, req.requesterDetails);\n\t\treturn true;\n\t}\n\n\tprotected generateJoinStatements(\n\t\treq: RsRequest<unknown>,\n\t\tjoins: JoinData[],\n\t\tbaseTable: string,\n\t\trouteData: StandardRouteData | CustomRouteData,\n\t\tschema: ResturaSchema,\n\t\tsqlParams: string[]\n\t): string {\n\t\tlet joinStatements = '';\n\t\tjoins.forEach((item) => {\n\t\t\tif (\n\t\t\t\t!this.canRequesterAccessTable(\n\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\tschema,\n\t\t\t\t\titem.table\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tthrow new RsError('FORBIDDEN', 'You do not have permission to access this table');\n\t\t\tif (item.custom) {\n\t\t\t\tconst customReplaced = this.replaceParamKeywords(item.custom, routeData, req, sqlParams);\n\t\t\t\tjoinStatements += `\\t${item.type} JOIN ${escapeColumnName(item.table)} AS ${escapeColumnName(item.alias)} ON ${customReplaced}\\n`;\n\t\t\t} else {\n\t\t\t\tjoinStatements += `\\t${item.type} JOIN ${escapeColumnName(item.table)}`;\n\t\t\t\tjoinStatements += ` AS ${escapeColumnName(item.alias)}`;\n\n\t\t\t\tif (item.localTable) {\n\t\t\t\t\tjoinStatements += ` ON ${escapeColumnName(item.localTableAlias)}.${escapeColumnName(item.localColumnName)} = ${escapeColumnName(item.alias)}.${escapeColumnName(\n\t\t\t\t\t\titem.foreignColumnName\n\t\t\t\t\t)}\\n`;\n\t\t\t\t} else {\n\t\t\t\t\tjoinStatements += ` ON ${escapeColumnName(baseTable)}.${escapeColumnName(item.localColumnName)} = ${escapeColumnName(item.alias)}.${escapeColumnName(\n\t\t\t\t\t\titem.foreignColumnName\n\t\t\t\t\t)}\\n`;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn joinStatements;\n\t}\n\n\tprotected generateGroupBy(routeData: StandardRouteData): string {\n\t\tlet groupBy = '';\n\t\tif (routeData.groupBy) {\n\t\t\tgroupBy = `GROUP BY ${escapeColumnName(routeData.groupBy.tableName)}.${escapeColumnName(routeData.groupBy.columnName)}\\n`;\n\t\t}\n\t\treturn groupBy;\n\t}\n\n\tprotected generateOrderBy(req: RsRequest<unknown>, routeData: StandardRouteData): string {\n\t\tlet orderBy = '';\n\t\tconst orderOptions: { [key: string]: string } = {\n\t\t\tASC: 'ASC',\n\t\t\tDESC: 'DESC'\n\t\t};\n\t\tconst data = req.data as PageQuery;\n\t\tif (routeData.type === 'PAGED' && 'sortBy' in data) {\n\t\t\tconst sortOrder = orderOptions[data.sortOrder] || 'ASC';\n\t\t\torderBy = `ORDER BY ${escapeColumnName(data.sortBy)} ${sortOrder}\\n`;\n\t\t} else if (routeData.orderBy) {\n\t\t\tconst sortOrder = orderOptions[routeData.orderBy.order] || 'ASC';\n\t\t\torderBy = `ORDER BY ${escapeColumnName(routeData.orderBy.tableName)}.${escapeColumnName(routeData.orderBy.columnName)} ${sortOrder}\\n`;\n\t\t}\n\t\treturn orderBy;\n\t}\n\n\tprotected generateWhereClause(\n\t\treq: RsRequest<unknown>,\n\t\twhere: WhereData[],\n\t\trouteData: StandardRouteData | CustomRouteData,\n\t\tsqlParams: string[]\n\t): string {\n\t\tlet whereClause = '';\n\t\twhere.forEach((item, index) => {\n\t\t\tif (index === 0) whereClause = 'WHERE ';\n\t\t\tif (item.custom) {\n\t\t\t\tconst customReplaced = this.replaceParamKeywords(item.custom, routeData, req, sqlParams);\n\t\t\t\twhereClause += `\\t${item.conjunction || ''} ${customReplaced}\\n`;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\titem.operator === undefined ||\n\t\t\t\titem.value === undefined ||\n\t\t\t\titem.columnName === undefined ||\n\t\t\t\titem.tableName === undefined\n\t\t\t)\n\t\t\t\tthrow new RsError(\n\t\t\t\t\t'SCHEMA_ERROR',\n\t\t\t\t\t`Invalid where clause in route ${routeData.name}, missing required fields if not custom`\n\t\t\t\t);\n\n\t\t\tlet operator = item.operator;\n\t\t\tlet value = item.value;\n\n\t\t\tif (operator === 'LIKE') {\n\t\t\t\tvalue = `'%' || ${value} || '%'`;\n\t\t\t} else if (operator === 'NOT LIKE') {\n\t\t\t\tvalue = `'%' || ${value} || '%'`;\n\t\t\t} else if (operator === 'STARTS WITH') {\n\t\t\t\toperator = 'LIKE';\n\t\t\t\tvalue = `${value} || '%'`;\n\t\t\t} else if (operator === 'ENDS WITH') {\n\t\t\t\toperator = 'LIKE';\n\t\t\t\tvalue = `'%' || ${value}`;\n\t\t\t}\n\n\t\t\tconst replacedValue = this.replaceParamKeywords(value, routeData, req, sqlParams);\n\t\t\twhereClause += `\\t${item.conjunction || ''} \"${item.tableName}\".\"${item.columnName}\" ${operator.replace('LIKE', 'ILIKE')} ${\n\t\t\t\t['IN', 'NOT IN'].includes(operator) ? `(${replacedValue})` : replacedValue\n\t\t\t}\\n`;\n\t\t});\n\n\t\tconst data = req.data as PageQuery;\n\t\tif (routeData.type === 'PAGED' && !!data?.filter) {\n\t\t\tlet statement = data.filter.replace(/\\$[a-zA-Z][a-zA-Z0-9_]+/g, (value: string) => {\n\t\t\t\tconst requestParam = routeData.request!.find((item) => {\n\t\t\t\t\treturn item.name === value.replace('$', '');\n\t\t\t\t});\n\t\t\t\tif (!requestParam)\n\t\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Invalid route keyword in route ${routeData.name}`);\n\t\t\t\treturn data[requestParam.name]?.toString() || '';\n\t\t\t});\n\n\t\t\tstatement = statement.replace(/#[a-zA-Z][a-zA-Z0-9_]+/g, (value: string) => {\n\t\t\t\tconst requestParam = routeData.request!.find((item) => {\n\t\t\t\t\treturn item.name === value.replace('#', '');\n\t\t\t\t});\n\t\t\t\tif (!requestParam)\n\t\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Invalid route keyword in route ${routeData.name}`);\n\t\t\t\treturn data[requestParam.name]?.toString() || '';\n\t\t\t});\n\n\t\t\tstatement = filterPsqlParser.parse(statement);\n\t\t\tif (whereClause.startsWith('WHERE')) {\n\t\t\t\twhereClause += ` AND (${statement})\\n`;\n\t\t\t} else {\n\t\t\t\twhereClause += `WHERE ${statement}\\n`;\n\t\t\t}\n\t\t}\n\n\t\treturn whereClause;\n\t}\n\n\tprivate createUpdateTrigger(tableName: string, notify: ResturaSchema['database'][0]['notify']): string {\n\t\tif (!notify) return '';\n\t\tif (notify === 'ALL') {\n\t\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_update()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t\t(regexp_match(\n\t\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'update',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'changedId', NEW.id,\n\t\t\t\t\t\t'record', NEW,\n\t\t\t\t\t\t'previousRecord', OLD\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER ${tableName}_update\n\tAFTER UPDATE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_update();\n`;\n\t\t}\n\n\t\tconst notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW.\"${column}\"`).join(',\\n');\n\t\tconst notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD.\"${column}\"`).join(',\\n');\n\n\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_update()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t\t(regexp_match(\n\t\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'update',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'changedId', NEW.id,\n\t\t\t\t\t\t'record', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnNewBuildString}\n\t\t\t\t\t\t),\n\t\t\t\t\t\t'previousRecord', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnOldBuildString}\n\t\t\t\t\t\t)\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER ${tableName}_update\n\tAFTER UPDATE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_update();\n\t\t`;\n\t}\n\n\tprivate createDeleteTrigger(tableName: string, notify: ResturaSchema['database'][0]['notify']): string {\n\t\tif (!notify) return '';\n\t\tif (notify === 'ALL') {\n\t\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_delete()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'delete',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'deletedId', OLD.id,\n\t\t\t\t\t\t'previousRecord', OLD\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_delete\"\n\tAFTER DELETE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_delete();\n`;\n\t\t}\n\n\t\tconst notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD.\"${column}\"`).join(',\\n');\n\n\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_delete()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'delete',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'deletedId', OLD.id,\n\t\t\t\t\t\t'previousRecord', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnOldBuildString}\n\t\t\t\t\t\t)\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_delete\"\n\tAFTER DELETE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_delete();\n\t\t`;\n\t}\n\n\tprivate createInsertTriggers(tableName: string, notify: ResturaSchema['database'][0]['notify']): string {\n\t\tif (!notify) return '';\n\t\tif (notify === 'ALL') {\n\t\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_insert()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'insert',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'insertedId', NEW.id,\n\t\t\t\t\t\t'record', NEW\n\t\t)::text\n\t\t);\n\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_insert\"\n\tAFTER INSERT ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_insert();\n`;\n\t\t}\n\n\t\tconst notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW.\"${column}\"`).join(',\\n');\n\n\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_insert()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'insert',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'insertedId', NEW.id,\n\t\t\t\t\t\t'record', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnNewBuildString}\n\t\t\t\t\t\t)\n\t\t)::text\n\t\t);\n\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_insert\"\n\tAFTER INSERT ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_insert();\n`;\n\t}\n\n\tprivate schemaToPsqlType(column: ColumnData) {\n\t\tif (column.hasAutoIncrement) return 'BIGSERIAL';\n\t\tif (column.type === 'ENUM') return `TEXT`;\n\t\tif (column.type === 'DATETIME') return 'TIMESTAMPTZ';\n\t\tif (column.type === 'MEDIUMINT') return 'INT';\n\t\treturn column.type;\n\t}\n}\n","import pg, { QueryResult, QueryResultRow } from 'pg';\n// See this github issue for why we need to do this https://github.com/brianc/node-postgres/issues/2819\nimport type { PoolConfig, Pool as PoolType, QueryConfigValues } from 'pg';\nimport { logger } from '../../logger/logger.js';\nimport { PsqlConnection } from './PsqlConnection.js';\nconst { Pool } = pg;\n\nexport class PsqlPool extends PsqlConnection {\n\tpublic pool: PoolType;\n\tconstructor(public poolConfig: PoolConfig) {\n\t\tsuper();\n\t\tthis.pool = new Pool(poolConfig);\n\t\t// Run a test query to ensure the connection is working\n\t\tthis.queryOne('SELECT NOW();', [], {\n\t\t\tisSystemUser: true,\n\t\t\trole: '',\n\t\t\thost: 'localhost',\n\t\t\tipAddress: '',\n\t\t\tscopes: []\n\t\t})\n\t\t\t.then(() => {\n\t\t\t\tlogger.info('Connected to PostgreSQL database');\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tlogger.error('Error connecting to database', error);\n\t\t\t\tprocess.exit(1);\n\t\t\t});\n\t}\n\n\tprotected async query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(\n\t\tquery: string,\n\t\tvalues?: QueryConfigValues<T>\n\t): Promise<QueryResult<R>> {\n\t\treturn this.pool.query(query, values) as Promise<QueryResult<R>>;\n\t}\n}\n","import crypto, { UUID } from 'crypto';\nimport { QueryConfigValues, QueryResult, QueryResultRow } from 'pg';\nimport format from 'pg-format';\nimport { format as sqlFormat } from 'sql-formatter';\nimport { z } from 'zod';\nimport { logger } from '../../logger/logger.js';\nimport { RsError } from '../RsError.js';\nimport { QueryMetadata } from '../eventManager.js';\nimport { RequesterDetails } from '../types/customExpressTypes.js';\nimport { questionMarksToOrderedParams } from './PsqlUtils.js';\n\nexport abstract class PsqlConnection {\n\treadonly instanceId: UUID;\n\tprotected constructor(instanceId?: UUID) {\n\t\tthis.instanceId = instanceId || crypto.randomUUID();\n\t}\n\n\tprotected abstract query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(\n\t\tquery: string,\n\t\tvalues?: QueryConfigValues<T>\n\t): Promise<QueryResult<R>>;\n\n\tasync queryOne<T>(query: string, options: unknown[], requesterDetails: RequesterDetails): Promise<T> {\n\t\tconst formattedQuery = questionMarksToOrderedParams(query);\n\t\tconst meta: QueryMetadata = { connectionInstanceId: this.instanceId, ...requesterDetails };\n\t\tthis.logSqlStatement(formattedQuery, options, meta);\n\t\tconst queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})\\n`;\n\n\t\tconst startTime = process.hrtime();\n\t\ttry {\n\t\t\tconst response = await this.query(queryMetadata + formattedQuery, options as QueryConfigValues<unknown>);\n\n\t\t\tthis.logQueryDuration(startTime);\n\n\t\t\t// There should be one and only one row returned\n\t\t\tif (response.rows.length === 0) throw new RsError('NOT_FOUND', 'No results found');\n\t\t\telse if (response.rows.length > 1) throw new RsError('DUPLICATE', 'More than one result found');\n\n\t\t\treturn response.rows[0] as T;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tif (RsError.isRsError(error)) throw error;\n\n\t\t\tif (error?.routine === '_bt_check_unique') {\n\t\t\t\tthrow new RsError('DUPLICATE', error.message);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `${error.message}`);\n\t\t}\n\t}\n\n\tasync queryOneSchema<T>(\n\t\tquery: string,\n\t\tparams: unknown[],\n\t\trequesterDetails: RequesterDetails,\n\t\tzodSchema: z.ZodSchema<T>\n\t): Promise<T> {\n\t\tconst result = await this.queryOne(query, params, requesterDetails);\n\t\ttry {\n\t\t\treturn zodSchema.parse(result);\n\t\t} catch (error) {\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tlogger.error('Invalid data returned from database:');\n\t\t\t\tlogger.silly('\\n' + JSON.stringify(result, null, 2));\n\t\t\t\tlogger.error('\\n' + z.prettifyError(error));\n\t\t\t} else {\n\t\t\t\tlogger.error(error);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `Invalid data returned from database`);\n\t\t}\n\t}\n\n\tasync runQuery<T>(query: string, options: unknown[], requesterDetails: RequesterDetails): Promise<T[]> {\n\t\tconst formattedQuery = questionMarksToOrderedParams(query);\n\t\tconst meta: QueryMetadata = { connectionInstanceId: this.instanceId, ...requesterDetails };\n\t\tthis.logSqlStatement(formattedQuery, options, meta);\n\t\tconst queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})\\n`;\n\t\tconst startTime = process.hrtime();\n\t\ttry {\n\t\t\tconst response = await this.query(queryMetadata + formattedQuery, options as QueryConfigValues<unknown>);\n\n\t\t\tthis.logQueryDuration(startTime);\n\n\t\t\treturn response.rows as T[];\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tif (error?.routine === '_bt_check_unique') {\n\t\t\t\tthrow new RsError('DUPLICATE', error.message);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `${error.message}`);\n\t\t}\n\t}\n\n\tasync runQuerySchema<T>(\n\t\tquery: string,\n\t\tparams: unknown[],\n\t\trequesterDetails: RequesterDetails,\n\t\tzodSchema: z.ZodSchema<T>\n\t): Promise<T[]> {\n\t\tconst result = await this.runQuery(query, params, requesterDetails);\n\t\ttry {\n\t\t\treturn z.array(zodSchema).parse(result);\n\t\t} catch (error) {\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tlogger.error('Invalid data returned from database:');\n\t\t\t\tlogger.silly('\\n' + JSON.stringify(result, null, 2));\n\t\t\t\tlogger.error('\\n' + z.prettifyError(error));\n\t\t\t} else {\n\t\t\t\tlogger.error(error);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `Invalid data returned from database`);\n\t\t}\n\t}\n\n\tprivate logQueryDuration(startTime: [number, number]): void {\n\t\tif (logger.level === 'silly') {\n\t\t\tconst [seconds, nanoseconds] = process.hrtime(startTime);\n\t\t\tconst duration = seconds * 1000 + nanoseconds / 1000000;\n\t\t\tlogger.silly(`Query duration: ${duration.toFixed(2)}ms`);\n\t\t}\n\t}\n\n\tprivate logSqlStatement(query: string, options: unknown[], queryMetadata: QueryMetadata, prefix: string = '') {\n\t\tif (logger.level !== 'silly') return;\n\n\t\tlet sqlStatement = '';\n\t\tif (options.length === 0) {\n\t\t\tsqlStatement = query;\n\t\t} else {\n\t\t\tsqlStatement = query.replace(/\\$\\d+/g, (match) => {\n\t\t\t\tconst paramIndex = parseInt(match.substring(1)) - 1; // Extract number from $1, $2, etc.\n\t\t\t\tif (paramIndex < 0 || paramIndex >= options.length) {\n\t\t\t\t\treturn 'INVALID_PARAM_INDEX';\n\t\t\t\t}\n\t\t\t\tconst value = options[paramIndex];\n\t\t\t\tif (typeof value === 'number') return value.toString();\n\t\t\t\treturn format.literal(value as string | number | boolean | object | Date | null | undefined);\n\t\t\t});\n\t\t}\n\n\t\tconst formattedSql = sqlFormat(sqlStatement, {\n\t\t\tlanguage: 'postgresql',\n\t\t\tlinesBetweenQueries: 2,\n\t\t\tindentStyle: 'standard',\n\t\t\tkeywordCase: 'upper',\n\t\t\tuseTabs: true,\n\t\t\ttabWidth: 4\n\t\t});\n\n\t\tlet initiator = 'Anonymous';\n\t\tif ('userId' in queryMetadata && queryMetadata.userId)\n\t\t\tinitiator = `User Id (${queryMetadata.userId.toString()})`;\n\t\tif ('isSystemUser' in queryMetadata && queryMetadata.isSystemUser) initiator = 'SYSTEM';\n\n\t\tlogger.silly(`${prefix}query by ${initiator}, Query ->\\n${formattedSql}`);\n\t}\n}\n","import format from 'pg-format';\nimport { DynamicObject } from '../types/customExpressTypes.js';\n\n/**\n * This method does a couple of things:\n * 1. It escapes the column name to prevent SQL injection by removing any double quotes.\n * 2. It wraps the column name in double quotes to prevent any issues with reserved words or casing.\n * 3. It replaces any periods in the column name with a period wrapped in double quotes to prevent any issues with schema names.\n * NOTE: I looked into using pg-format ident() method but that will strip the double quotes when not needed.\n * @param columnName\n * @returns\n */\nexport function escapeColumnName(columnName: string | undefined): string {\n\tif (columnName === undefined) return '';\n\treturn `\"${columnName.replace(/\"/g, '')}\"`.replace('.', '\".\"');\n}\n\n/**\n * Converts a query with question marks to a query with numbered parameters,\n * however it ignores question marks inside single or double quotes.\n * @param query PostgreSQL query with question marks\n * @returns A string with numbered parameters such as $1, $2 in replacement of question marks\n */\nexport function questionMarksToOrderedParams(query: string) {\n\tlet count = 1;\n\tlet inSingleQuote = false;\n\tlet inDoubleQuote = false;\n\n\treturn query.replace(/('|\"|\\?)/g, (char) => {\n\t\tif (char === \"'\") {\n\t\t\tinSingleQuote = !inSingleQuote && !inDoubleQuote;\n\t\t\treturn char;\n\t\t}\n\t\tif (char === '\"') {\n\t\t\tinDoubleQuote = !inDoubleQuote && !inSingleQuote;\n\t\t\treturn char;\n\t\t}\n\t\tif (char === '?' && !inSingleQuote && !inDoubleQuote) {\n\t\t\treturn `$${count++}`;\n\t\t}\n\t\treturn char; // Return ? unchanged if inside quotes\n\t});\n}\n\n/**\n * Creates a query to insert an object into a table.\n * @param table Table name to insert the object into\n * @param obj Data to insert into the table\n * @returns the query to insert the object into the table\n */\nexport function insertObjectQuery(table: string, obj: DynamicObject): string {\n\tconst keys = Object.keys(obj);\n\tconst params = Object.values(obj);\n\n\tconst columns = keys.map((column) => escapeColumnName(column)).join(', ');\n\tconst values = params.map((value) => SQL`${value}`).join(', ');\n\n\tlet query = `\nINSERT INTO \"${table}\" (${columns})\n VALUES (${values})\n RETURNING *`;\n\n\tquery = query.replace(/'(\\?)'/, '?');\n\treturn query;\n}\n\n/**\n * Creates a query to update an object in a table.\n * @param table Table name to update the object in\n * @param obj Data to update in the table\n * @param whereStatement Where clause to determine which rows to update\n * @returns the query to update the object in the table\n */\nexport function updateObjectQuery(table: string, obj: DynamicObject, whereStatement: string): string {\n\tconst setArray = [];\n\tfor (const i in obj) {\n\t\tsetArray.push(`${escapeColumnName(i)} = ` + SQL`${obj[i]}`);\n\t}\n\n\treturn `\nUPDATE ${escapeColumnName(table)}\n SET ${setArray.join(', ')} ${whereStatement}\n RETURNING *`;\n}\n\n// Todo: Move this method into @redsky/core-utils package under NumberUtils\nexport function isValueNumber(value: unknown): value is number {\n\treturn !isNaN(Number(value));\n}\n\n/**\n * This method is used to format a query and escape user input.\n * Use this with the SQL tag to escape user input. For example:\n * SQL`UPDATE \"USER\" SET \"firstName\" = ${firstName}, \"isActive\" = ${isActive} WHERE \"id\" = ${id} RETURNING *`\n * @param strings template strings array\n * @param values values to escape\n * @returns An escaped query with user input\n */\nexport function SQL(strings: TemplateStringsArray, ...values: unknown[]) {\n\tlet query = strings[0];\n\tvalues.forEach((value: unknown, index: number) => {\n\t\tif (typeof value === 'boolean') {\n\t\t\tquery += value;\n\t\t} else if (typeof value === 'number') {\n\t\t\tquery += value;\n\t\t} else if (Array.isArray(value)) {\n\t\t\t// JSON arrays in the pg-format are stripped of their array brackets and used for grouped list conversions.\n\t\t\t// This is a workaround to fix this issue. Where we are expecting JSON arrays as the root element of the object.\n\t\t\tquery += format.literal(JSON.stringify(value)) + '::jsonb';\n\t\t} else {\n\t\t\tquery += format.literal(value as string); // escape input\n\t\t}\n\t\tquery += strings[index + 1];\n\t});\n\n\treturn query;\n}\n","import { ObjectUtils } from '@redskytech/core-utils';\nimport { RsError } from '../RsError.js';\nimport {\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tRouteData,\n\tStandardRouteData,\n\tTableData,\n\tWhereData\n} from '../schemas/resturaSchema.js';\nimport { DynamicObject, RsRequest } from '../types/customExpressTypes.js';\n\nexport default abstract class SqlEngine {\n\tasync runQueryForRoute(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t): Promise<DynamicObject | any[] | boolean> {\n\t\tif (\n\t\t\t!this.canRequesterAccessTable(\n\t\t\t\treq.requesterDetails.role,\n\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\tschema,\n\t\t\t\trouteData.table\n\t\t\t)\n\t\t)\n\t\t\tthrow new RsError('FORBIDDEN', 'You do not have permission to access this table');\n\n\t\tswitch (routeData.method) {\n\t\t\tcase 'POST':\n\t\t\t\treturn this.executeCreateRequest(req, routeData, schema);\n\t\t\tcase 'GET':\n\t\t\t\treturn this.executeGetRequest(req, routeData, schema);\n\t\t\tcase 'PUT':\n\t\t\tcase 'PATCH':\n\t\t\t\treturn this.executeUpdateRequest(req, routeData, schema);\n\t\t\tcase 'DELETE':\n\t\t\t\treturn this.executeDeleteRequest(req, routeData, schema);\n\t\t}\n\t}\n\tprotected getTableSchema(schema: ResturaSchema, tableName: string): TableData {\n\t\tconst tableSchema = schema.database.find((item) => item.name === tableName);\n\t\tif (!tableSchema) throw new RsError('SCHEMA_ERROR', `Table ${tableName} not found in schema`);\n\t\treturn tableSchema;\n\t}\n\n\tprotected canRequesterAccessColumn(\n\t\trequesterRole: string | undefined | null,\n\t\trequesterScopes: string[] | undefined | null,\n\t\tschema: ResturaSchema,\n\t\titem: ResponseData,\n\t\tjoins: JoinData[]\n\t): boolean {\n\t\tif (item.type) return true;\n\t\tif (item.selector) {\n\t\t\tlet tableName = item.selector.split('.')[0];\n\t\t\tconst columnName = item.selector.split('.')[1];\n\t\t\tlet tableSchema = schema.database.find((item) => item.name === tableName);\n\t\t\tif (!tableSchema) {\n\t\t\t\t// check to see if this is an alias join table\n\t\t\t\tconst join = joins.find((join) => join.alias === tableName);\n\t\t\t\tif (!join) throw new RsError('SCHEMA_ERROR', `Table ${tableName} not found in schema`);\n\t\t\t\ttableName = join.table;\n\t\t\t\ttableSchema = schema.database.find((item) => item.name === tableName);\n\t\t\t}\n\t\t\tif (!tableSchema) throw new RsError('SCHEMA_ERROR', `Table ${tableName} not found in schema`);\n\t\t\tconst columnSchema = tableSchema.columns.find((item) => item.name === columnName);\n\t\t\tif (!columnSchema)\n\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Column ${columnName} not found in table ${tableName}`);\n\n\t\t\tif (ObjectUtils.isArrayWithData(columnSchema.roles)) {\n\t\t\t\tif (!requesterRole) return false;\n\t\t\t\treturn columnSchema.roles.includes(requesterRole);\n\t\t\t}\n\t\t\tif (ObjectUtils.isArrayWithData(columnSchema.scopes)) {\n\t\t\t\tif (!requesterScopes) return false;\n\t\t\t\treturn columnSchema.scopes.every((scope) => requesterScopes.includes(scope));\n\t\t\t}\n\t\t\treturn true; // Public column, any role can access\n\t\t}\n\t\tif (item.subquery) {\n\t\t\treturn ObjectUtils.isArrayWithData(\n\t\t\t\titem.subquery.properties.filter((nestedItem) => {\n\t\t\t\t\treturn this.canRequesterAccessColumn(requesterRole, requesterScopes, schema, nestedItem, joins);\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprotected canRequesterAccessTable(\n\t\trequesterRole: string | undefined,\n\t\trequesterScopes: string[] | undefined,\n\t\tschema: ResturaSchema,\n\t\ttableName: string\n\t): boolean {\n\t\tconst tableSchema = this.getTableSchema(schema, tableName);\n\t\tif (ObjectUtils.isArrayWithData(tableSchema.roles)) {\n\t\t\tif (!requesterRole) return false; // Table has roles, but no role provided (no access)\n\t\t\treturn tableSchema.roles.includes(requesterRole);\n\t\t}\n\t\tif (ObjectUtils.isArrayWithData(tableSchema.scopes)) {\n\t\t\tif (!requesterScopes) return false;\n\t\t\treturn tableSchema.scopes.some((scope) => requesterScopes.includes(scope));\n\t\t}\n\t\treturn true; // Public table, any role can access\n\t}\n\n\tprotected abstract generateJoinStatements(\n\t\treq: RsRequest<unknown>,\n\t\tjoins: JoinData[],\n\t\tbaseTable: string,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema,\n\t\tsqlParams: string[]\n\t): string;\n\n\tprotected abstract generateGroupBy(routeData: StandardRouteData): string;\n\n\tprotected abstract generateOrderBy(req: RsRequest<unknown>, routeData: StandardRouteData): string;\n\n\tprotected abstract generateWhereClause(\n\t\treq: RsRequest<unknown>,\n\t\twhere: WhereData[],\n\t\trouteData: StandardRouteData,\n\t\tsqlParams: string[]\n\t): string;\n\n\tprotected replaceParamKeywords(\n\t\tvalue: string | number,\n\t\trouteData: RouteData,\n\t\treq: RsRequest<unknown>,\n\t\tsqlParams: string[]\n\t): string | number {\n\t\tlet returnValue = value;\n\t\treturnValue = this.replaceLocalParamKeywords(returnValue, routeData, req, sqlParams);\n\t\treturnValue = this.replaceGlobalParamKeywords(returnValue, routeData, req, sqlParams);\n\t\treturn returnValue;\n\t}\n\n\tprotected replaceLocalParamKeywords(\n\t\tvalue: string | number,\n\t\trouteData: RouteData,\n\t\treq: RsRequest<unknown>,\n\t\tsqlParams: string[]\n\t): string | number {\n\t\tif (!routeData.request) return value;\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\tconst data = req.data as DynamicObject<any>;\n\t\tif (typeof value === 'string') {\n\t\t\t// Match any value that starts with a $\n\t\t\tvalue.match(/\\$[a-zA-Z][a-zA-Z0-9_]+/g)?.forEach((param) => {\n\t\t\t\tconst requestParam = routeData.request!.find((item) => {\n\t\t\t\t\treturn item.name === param.replace('$', '');\n\t\t\t\t});\n\t\t\t\tif (!requestParam)\n\t\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Invalid route keyword in route ${routeData.name}`);\n\t\t\t\tsqlParams.push(data[requestParam.name]); // pass by reference\n\t\t\t});\n\t\t\treturn value.replace(new RegExp(/\\$[a-zA-Z][a-zA-Z0-9_]+/g), '?');\n\t\t}\n\t\treturn value;\n\t}\n\n\tprotected replaceGlobalParamKeywords(\n\t\tvalue: string | number,\n\t\trouteData: RouteData,\n\t\treq: RsRequest<unknown>,\n\t\tsqlParams: string[]\n\t): string | number {\n\t\tif (typeof value === 'string') {\n\t\t\t// Match any value that starts with a #\n\t\t\tvalue.match(/#[a-zA-Z][a-zA-Z0-9_]+/g)?.forEach((param) => {\n\t\t\t\tparam = param.replace('#', '');\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tconst globalParamValue = (req.requesterDetails as any)[param];\n\t\t\t\tif (!globalParamValue)\n\t\t\t\t\tthrow new RsError(\n\t\t\t\t\t\t'SCHEMA_ERROR',\n\t\t\t\t\t\t`Invalid global keyword clause in route (${routeData.path}) when looking for (#${param})`\n\t\t\t\t\t);\n\t\t\t\tsqlParams.push(globalParamValue); // pass by reference\n\t\t\t});\n\t\t\treturn value.replace(new RegExp(/#[a-zA-Z][a-zA-Z0-9_]+/g), '?');\n\t\t}\n\t\treturn value;\n\t}\n\n\tabstract generateDatabaseSchemaFromSchema(schema: ResturaSchema): string;\n\tabstract diffDatabaseToSchema(schema: ResturaSchema): Promise<string>;\n\n\tprotected abstract createNestedSelect(\n\t\treq: RsRequest<unknown>,\n\t\tschema: ResturaSchema,\n\t\titem: ResponseData,\n\t\trouteData: StandardRouteData,\n\t\tsqlParams: string[]\n\t): string;\n\n\tprotected abstract executeCreateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject>;\n\n\tprotected abstract executeGetRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema // eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t): Promise<DynamicObject | any[]>;\n\tprotected abstract executeUpdateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject>;\n\n\tprotected abstract executeDeleteRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<boolean>;\n}\n","import peg, { ParserBuildOptions } from 'pegjs';\n\nconst filterSqlGrammar = `\n{\n// ported from pg-format but intentionally will add double quotes to every column\n function quoteSqlIdentity(value) {\n if (value === undefined || value === null) {\n throw new Error('SQL identifier cannot be null or undefined');\n } else if (value === false) {\n return '\"f\"';\n } else if (value === true) {\n return '\"t\"';\n } else if (value instanceof Date) {\n // return '\"' + formatDate(value.toISOString()) + '\"';\n } else if (value instanceof Buffer) {\n throw new Error('SQL identifier cannot be a buffer');\n } else if (Array.isArray(value) === true) {\n var temp = [];\n for (var i = 0; i < value.length; i++) {\n if (Array.isArray(value[i]) === true) {\n throw new Error('Nested array to grouped list conversion is not supported for SQL identifier');\n } else {\n // temp.push(quoteIdent(value[i]));\n }\n }\n return temp.toString();\n } else if (value === Object(value)) {\n throw new Error('SQL identifier cannot be an object');\n }\n\n var ident = value.toString().slice(0); // create copy\n\n // do not quote a valid, unquoted identifier\n // if (/^[a-z_][a-z0-9_$]*$/.test(ident) === true && isReserved(ident) === false) {\n // return ident;\n // }\n\n var quoted = '\"';\n\n for (var i = 0; i < ident.length; i++) {\n var c = ident[i];\n if (c === '\"') {\n quoted += c + c;\n } else {\n quoted += c;\n }\n }\n\n quoted += '\"';\n\n return quoted;\n};\n}\n\nstart = expressionList\n\n_ = [ \\\\t\\\\r\\\\n]* // Matches spaces, tabs, and line breaks\n\nexpressionList =\n leftExpression:expression _ operator:operator _ rightExpression:expressionList \n { return \\`\\${leftExpression} \\${operator} \\${rightExpression}\\`;}\n / expression\n\nexpression = \n negate:negate? _ \"(\" _ \"column\" _ \":\" column:column _ \",\"? _ value:value? \",\"? _ type:type? _ \")\"_\n {return \\`\\${negate? \" NOT \" : \"\"}(\\${type? type(column, value) : \\`\\${column\\} = \\${format.literal(value)}\\`})\\`;}\n /\n negate:negate?\"(\"expression:expressionList\")\" { return \\`\\${negate? \" NOT \" : \"\"}(\\${expression})\\`; }\n\nnegate = \"!\"\n \noperator = \"and\"i / \"or\"i\n\n\t \ncolumn = first:text rest:(\".\" text)* { \n const partsArray = [first];\n if (rest && rest.length > 0) {\n partsArray.push(...rest.map(item => item[1]));\n }\n \n if (partsArray.length > 3) {\n throw new SyntaxError('Column path cannot have more than 3 parts (table.column.jsonField)');\n }\n \n if (partsArray.length === 1) {\n return quoteSqlIdentity(partsArray[0]);\n }\n const tableName = quoteSqlIdentity(partsArray[0]);\n \n // If we only have two parts (table.column), use regular dot notation\n if (partsArray.length === 2) {\n return tableName + \".\" + quoteSqlIdentity(partsArray[1]);\n }\n \n // For JSON paths (more than 2 parts), first part is a column, last part uses ->>\n const jsonColumn = quoteSqlIdentity(partsArray[1]);\n const lastPart = partsArray[partsArray.length - 1];\n const result = tableName + \".\" + jsonColumn + \"->>'\" + lastPart + \"'\";\n return result;\n}\n\ntext = text:[a-z0-9 \\\\t\\\\r\\\\n\\\\-_:@']i+ { return text.join(\"\"); }\n\n\ntype = \"type\" _ \":\" _ type:typeString { return type; }\ntypeString = text:\"startsWith\" { return function(column, value) { return \\`\\${column} ILIKE '\\${format.literal(value).slice(1,-1)}%'\\`; } } /\n text:\"endsWith\" { return function(column, value) { return \\`\\${column} ILIKE '%\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"contains\" { return function(column, value) { return \\`\\${column} ILIKE '%\\${format.literal(value).slice(1,-1)}%'\\`; } } /\n text:\"exact\" { return function(column, value) { return \\`\\${column} = '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"greaterThanEqual\" { return function(column, value) { return \\`\\${column} >= '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"greaterThan\" { return function(column, value) { return \\`\\${column} > '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"lessThanEqual\" { return function(column, value) { return \\`\\${column} <= '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"lessThan\" { return function(column, value) { return \\`\\${column} < '\\${format.literal(value).slice(1,-1)}'\\`; } } / \n text:\"isNull\" { return function(column, value) { return \\`isNull(\\${column})\\`; } } \n\nvalue = \"value\" _ \":\" value:text { return value; }\n\n\n`;\n\nconst filterPsqlParser = peg.generate(filterSqlGrammar, {\n\tformat: 'commonjs',\n\tdependencies: { format: 'pg-format' }\n} as ParserBuildOptions);\nexport default filterPsqlParser;\n","import fs from 'fs';\nimport path from 'path';\n\nimport { DateUtils } from '@redskytech/core-utils';\nimport { FileUtils } from '@restura/internal';\nimport Bluebird from 'bluebird';\nimport * as os from 'os';\nimport { logger } from '../../logger/logger.js';\n\nexport default class TempCache {\n\tlocation: string;\n\tprivate readonly maxDurationDays = 7;\n\n\tconstructor(location?: string) {\n\t\tthis.location = location || os.tmpdir();\n\t\tFileUtils.ensureDir(this.location).catch((e) => {\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tasync cleanup() {\n\t\tconst fileList = await fs.promises.readdir(this.location);\n\t\tawait Bluebird.map(\n\t\t\tfileList,\n\t\t\tasync (file) => {\n\t\t\t\tconst fullFilePath = path.join(this.location, file);\n\t\t\t\tconst fileStats = await fs.promises.stat(fullFilePath);\n\t\t\t\tif (\n\t\t\t\t\tDateUtils.daysBetweenStartAndEndDates(new Date(fileStats.mtimeMs), new Date()) >\n\t\t\t\t\tthis.maxDurationDays\n\t\t\t\t) {\n\t\t\t\t\tlogger.info(`Deleting old temp file: ${file}`);\n\t\t\t\t\tawait fs.promises.unlink(fullFilePath);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n}\n","import { UUID } from 'crypto';\nimport type { ClientConfig, Client as ClientType, QueryConfigValues, QueryResult, QueryResultRow } from 'pg';\nimport pg from 'pg';\nimport { PsqlConnection } from './PsqlConnection.js';\n\nconst { Client } = pg;\n\nexport class PsqlTransaction extends PsqlConnection {\n\tpublic client: ClientType;\n\tprivate beginTransactionPromise: Promise<QueryResult<QueryResultRow>>;\n\tprivate connectPromise: Promise<void>;\n\n\tconstructor(\n\t\tpublic clientConfig: ClientConfig,\n\t\tinstanceId?: UUID\n\t) {\n\t\tsuper(instanceId);\n\t\tthis.client = new Client(clientConfig);\n\t\tthis.connectPromise = this.client.connect();\n\t\tthis.beginTransactionPromise = this.beginTransaction();\n\t}\n\tasync close() {\n\t\tif (this.client) {\n\t\t\tawait this.client.end();\n\t\t}\n\t}\n\n\tprivate async beginTransaction() {\n\t\tawait this.connectPromise;\n\t\treturn this.client.query('BEGIN');\n\t}\n\n\tasync rollback() {\n\t\treturn this.query('ROLLBACK');\n\t}\n\n\tasync commit() {\n\t\treturn this.query('COMMIT');\n\t}\n\n\tasync release() {\n\t\treturn this.client.end();\n\t}\n\n\tprotected async query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(\n\t\tquery: string,\n\t\tvalues?: QueryConfigValues<T>\n\t): Promise<QueryResult<R>> {\n\t\tawait this.connectPromise;\n\t\tawait this.beginTransactionPromise;\n\t\treturn this.client.query(query, values);\n\t}\n}\n"],"mappings":"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","names":["HtmlStatusCodes","path","StringUtils","prettier","prettier","StringUtils","ObjectUtils","StringUtils","config","_typeof","obj","get","fs","path","prettier","path","original","Bluebird","isTsx","isTsNode","Bluebird","fs","path","fs","path","z","z","z","ObjectUtils","z","z","ObjectUtils","z","ObjectUtils","pg","format","z","format","isValueNumber","z","format","ObjectUtils","item","join","ObjectUtils","pg","resolve","ObjectUtils","column","fs","path","FileUtils","Bluebird","os","FileUtils","fs","Bluebird","path","config","fs","ObjectUtils","path","resolve","StringUtils","pg","Client","pg"]}
|
|
1
|
+
{"version":3,"sources":["../src/logger/logger.ts","../src/logger/loggerConfigSchema.ts","../src/restura/eventManager.ts","../src/restura/generators/apiGenerator.ts","../src/restura/sql/SqlUtils.ts","../src/restura/RsError.ts","../src/restura/validators/ResponseValidator.ts","../src/restura/generators/modelGenerator.ts","../src/restura/generators/resturaGlobalTypesGenerator.ts","../src/restura/restura.ts","../../../node_modules/.pnpm/autobind-decorator@2.4.0/node_modules/autobind-decorator/lib/esm/index.js","../src/restura/compareSchema.ts","../src/restura/customApiFactory.ts","../src/restura/generators/customTypeValidationGenerator.ts","../src/restura/middleware/addApiResponseFunctions.ts","../src/restura/middleware/authenticateRequester.ts","../src/restura/middleware/getMulterUpload.ts","../src/restura/schemas/resturaSchema.ts","../src/restura/schemas/validatorDataSchema.ts","../src/restura/validators/requestValidator.ts","../src/restura/utils/utils.ts","../src/restura/middleware/schemaValidation.ts","../src/restura/schemas/resturaConfigSchema.ts","../src/restura/sql/PsqlEngine.ts","../src/restura/sql/PsqlPool.ts","../src/restura/sql/PsqlConnection.ts","../src/restura/sql/PsqlUtils.ts","../src/restura/sql/SqlEngine.ts","../src/restura/sql/filterPsqlParser.ts","../src/restura/utils/TempCache.ts","../src/restura/sql/PsqlTransaction.ts"],"sourcesContent":["import { config } from '@restura/internal';\nimport winston from 'winston';\n// We use the logform module instead of bundled winston.format because then we can enable stack errors in the console output\nimport { format } from 'logform';\nimport { loggerConfigSchema } from './loggerConfigSchema.js';\n\nconst loggerConfig = await config.validate('logger', loggerConfigSchema);\n\nconst consoleFormat = format.combine(\n\tformat.timestamp({\n\t\tformat: 'YYYY-MM-DD HH:mm:ss.sss'\n\t}),\n\tformat.errors({ stack: true }),\n\tformat.padLevels(),\n\tformat.colorize({ all: true }),\n\tformat.printf((info) => {\n\t\treturn `[${info.timestamp}] ${info.level} ${info.message}`;\n\t})\n);\n\n// Create a default logger that works immediately\nconst logger = winston.createLogger({\n\tlevel: loggerConfig.level,\n\tformat: format.combine(\n\t\tformat.timestamp({\n\t\t\tformat: 'YYYY-MM-DD HH:mm:ss.sss'\n\t\t}),\n\t\tformat.errors({ stack: true }),\n\t\tformat.json()\n\t),\n\ttransports: [new winston.transports.Console({ format: consoleFormat })]\n});\n\nexport { logger };\n","import { z } from 'zod';\n\nexport const loggerConfigSchema = z.object({\n\tlevel: z.enum(['info', 'warn', 'error', 'debug', 'silly']).default('info')\n});\nexport type LoggerConfigSchema = z.infer<typeof loggerConfigSchema>;\n","import Bluebird from 'bluebird';\nimport { UUID } from 'crypto';\nimport { DynamicObject, RequesterDetails } from './types/customExpressTypes.js';\n\nexport type EventType = 'DATABASE_ROW_DELETE' | 'DATABASE_ROW_INSERT' | 'DATABASE_COLUMN_UPDATE' | 'WEBHOOK';\nexport type MutationType = 'INSERT' | 'UPDATE' | 'DELETE';\nexport interface SqlMutationData {\n\tmutationType: MutationType;\n\tqueryMetadata: QueryMetadata;\n}\n\nexport interface DatabaseActionData {\n\ttableName: string;\n\tqueryMetadata: QueryMetadata;\n}\n\nexport interface ActionRowInsertData<T = DynamicObject> extends DatabaseActionData {\n\tinsertedId: number;\n\tinsertObject: T;\n}\n\nexport interface ActionRowDeleteData<T = DynamicObject> extends DatabaseActionData {\n\tdeletedId: number;\n\tdeletedRow: T;\n}\n\nexport interface ActionColumnChangeData<T = DynamicObject> extends DatabaseActionData {\n\ttableName: string;\n\tchangedId: number;\n\tnewData: T;\n\toldData: T;\n}\n\nexport interface ActionRowInsertFilter {\n\ttableName: string;\n}\n\nexport interface ActionRowDeleteFilter {\n\ttableName: string;\n}\n\nexport interface ActionColumnChangeFilter {\n\ttableName: string;\n\tcolumns: string[];\n}\n\nexport type TriggerResult = {\n\ttable: string;\n\tinsertedId?: number;\n\tchangedId?: number;\n\tdeletedId?: number;\n\tqueryMetadata: QueryMetadata;\n\trecord: DynamicObject;\n\tpreviousRecord: DynamicObject;\n\trequesterId: number;\n};\n\nexport type QueryMetadata = RequesterDetails & {\n\tconnectionInstanceId: UUID;\n};\n\nclass EventManager {\n\tprivate actionHandlers: {\n\t\tDATABASE_ROW_DELETE: {\n\t\t\tcallback: (data: ActionRowDeleteData, queryMetadata: QueryMetadata) => Promise<void>;\n\t\t\tfilter?: ActionRowDeleteFilter;\n\t\t}[];\n\t\tDATABASE_ROW_INSERT: {\n\t\t\tcallback: (data: ActionRowInsertData, queryMetadata: QueryMetadata) => Promise<void>; // Non-generic here\n\t\t\tfilter?: ActionRowInsertFilter;\n\t\t}[];\n\t\tDATABASE_COLUMN_UPDATE: {\n\t\t\tcallback: (data: ActionColumnChangeData, queryMetadata: QueryMetadata) => Promise<void>;\n\t\t\tfilter?: ActionColumnChangeFilter;\n\t\t}[];\n\t} = {\n\t\tDATABASE_ROW_DELETE: [],\n\t\tDATABASE_ROW_INSERT: [],\n\t\tDATABASE_COLUMN_UPDATE: []\n\t};\n\n\taddRowInsertHandler<T>(\n\t\tonInsert: (data: ActionRowInsertData<T>, queryMetadata: QueryMetadata) => Promise<void>,\n\t\tfilter?: ActionRowInsertFilter\n\t) {\n\t\tthis.actionHandlers.DATABASE_ROW_INSERT.push({\n\t\t\tcallback: onInsert as (data: ActionRowInsertData, queryMetadata: QueryMetadata) => Promise<void>,\n\t\t\tfilter\n\t\t});\n\t}\n\n\taddColumnChangeHandler<T>(\n\t\tonUpdate: (data: ActionColumnChangeData<T>, queryMetadata: QueryMetadata) => Promise<void>,\n\t\tfilter: ActionColumnChangeFilter\n\t) {\n\t\tthis.actionHandlers.DATABASE_COLUMN_UPDATE.push({\n\t\t\tcallback: onUpdate as (data: ActionColumnChangeData, queryMetadata: QueryMetadata) => Promise<void>,\n\t\t\tfilter\n\t\t});\n\t}\n\n\taddRowDeleteHandler<T>(\n\t\tonDelete: (data: ActionRowDeleteData<T>, queryMetadata: QueryMetadata) => Promise<void>,\n\t\tfilter?: ActionRowDeleteFilter\n\t) {\n\t\tthis.actionHandlers.DATABASE_ROW_DELETE.push({\n\t\t\tcallback: onDelete as (data: ActionRowDeleteData, queryMetadata: QueryMetadata) => Promise<void>,\n\t\t\tfilter\n\t\t});\n\t}\n\n\tasync fireActionFromDbTrigger(sqlMutationData: SqlMutationData, result: TriggerResult) {\n\t\tif (sqlMutationData.mutationType === 'INSERT') {\n\t\t\tawait this.fireInsertActions(sqlMutationData, result);\n\t\t} else if (sqlMutationData.mutationType === 'UPDATE') {\n\t\t\tawait this.fireUpdateActions(sqlMutationData, result);\n\t\t} else if (sqlMutationData.mutationType === 'DELETE') {\n\t\t\tawait this.fireDeleteActions(sqlMutationData, result);\n\t\t}\n\t}\n\n\tprivate async fireInsertActions(data: SqlMutationData, triggerResult: TriggerResult) {\n\t\tawait Bluebird.map(\n\t\t\tthis.actionHandlers.DATABASE_ROW_INSERT,\n\t\t\t({ callback, filter }) => {\n\t\t\t\tif (!this.hasHandlersForEventType('DATABASE_ROW_INSERT', filter, triggerResult)) return;\n\t\t\t\tconst insertData: ActionRowInsertData = {\n\t\t\t\t\ttableName: triggerResult.table,\n\t\t\t\t\tinsertedId: triggerResult.insertedId || 0,\n\t\t\t\t\tinsertObject: triggerResult.record,\n\t\t\t\t\tqueryMetadata: data.queryMetadata\n\t\t\t\t};\n\t\t\t\tcallback(insertData, data.queryMetadata);\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n\tprivate async fireDeleteActions(data: SqlMutationData, triggerResult: TriggerResult) {\n\t\tawait Bluebird.map(\n\t\t\tthis.actionHandlers.DATABASE_ROW_DELETE,\n\t\t\t({ callback, filter }) => {\n\t\t\t\tif (!this.hasHandlersForEventType('DATABASE_ROW_DELETE', filter, triggerResult)) return;\n\t\t\t\tconst deleteData: ActionRowDeleteData = {\n\t\t\t\t\ttableName: triggerResult.table,\n\t\t\t\t\tdeletedId: triggerResult.deletedId || 0,\n\t\t\t\t\tdeletedRow: triggerResult.previousRecord,\n\t\t\t\t\tqueryMetadata: data.queryMetadata\n\t\t\t\t};\n\t\t\t\tcallback(deleteData, data.queryMetadata);\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n\tprivate async fireUpdateActions(data: SqlMutationData, triggerResult: TriggerResult) {\n\t\tawait Bluebird.map(\n\t\t\tthis.actionHandlers.DATABASE_COLUMN_UPDATE,\n\t\t\t({ callback, filter }) => {\n\t\t\t\tif (!this.hasHandlersForEventType('DATABASE_COLUMN_UPDATE', filter, triggerResult)) return;\n\t\t\t\tconst columnChangeData: ActionColumnChangeData = {\n\t\t\t\t\ttableName: triggerResult.table,\n\t\t\t\t\tchangedId: triggerResult.changedId || 0,\n\t\t\t\t\tnewData: triggerResult.record,\n\t\t\t\t\toldData: triggerResult.previousRecord,\n\t\t\t\t\tqueryMetadata: data.queryMetadata\n\t\t\t\t};\n\t\t\t\tcallback(columnChangeData, data.queryMetadata);\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n\n\tprivate hasHandlersForEventType(\n\t\teventType: EventType,\n\t\tfilter: { tableName?: string; columns?: string[] } | undefined,\n\t\ttriggerResult: TriggerResult\n\t): boolean {\n\t\tif (filter) {\n\t\t\tswitch (eventType) {\n\t\t\t\tcase 'DATABASE_ROW_INSERT':\n\t\t\t\tcase 'DATABASE_ROW_DELETE':\n\t\t\t\t\tif (filter.tableName && filter.tableName !== triggerResult.table) return false;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'DATABASE_COLUMN_UPDATE':\n\t\t\t\t\tconst filterColumnChange = filter as ActionColumnChangeFilter;\n\n\t\t\t\t\tif (filterColumnChange.tableName !== triggerResult.table) return false;\n\n\t\t\t\t\tif (filterColumnChange.columns.length === 1) {\n\t\t\t\t\t\tconst firstColumn = filterColumnChange.columns[0];\n\t\t\t\t\t\tif (firstColumn === '*') return true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t!filterColumnChange.columns.some((item) => {\n\t\t\t\t\t\t\tconst updatedColumns = Object.keys(\n\t\t\t\t\t\t\t\tchangedValues(triggerResult.record, triggerResult.previousRecord)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn updatedColumns.includes(item);\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\t\treturn false;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n}\n\nconst eventManager = new EventManager();\nexport default eventManager;\n\nfunction changedValues(record: DynamicObject, previousRecord: DynamicObject) {\n\tconst changed: DynamicObject = {};\n\tfor (const i in previousRecord) {\n\t\tif (previousRecord[i] !== record[i]) {\n\t\t\tif (typeof previousRecord[i] === 'object' && typeof record[i] === 'object') {\n\t\t\t\tconst nestedChanged = changedValues(record[i] as DynamicObject, previousRecord[i] as DynamicObject);\n\t\t\t\tif (Object.keys(nestedChanged).length > 0) {\n\t\t\t\t\tchanged[i] = record[i];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tchanged[i] = record[i];\n\t\t\t}\n\t\t}\n\t}\n\treturn changed;\n}\n","import { ObjectUtils, StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport { logger } from '../../logger/logger.js';\nimport type {\n\tEndpointData,\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tRouteData,\n\tTableData\n} from '../schemas/resturaSchema.js';\nimport { SqlUtils } from '../sql/SqlUtils.js';\nimport ResponseValidator from '../validators/ResponseValidator.js';\n\ntype TreeData = RouteData | EndpointData;\n\nclass ApiTree {\n\treadonly namespace: string | null;\n\tprivate data: TreeData[] = [];\n\tprivate children: Map<string, ApiTree>;\n\n\tprivate constructor(\n\t\tnamespace: string | null,\n\t\tprivate readonly database: Array<TableData>\n\t) {\n\t\tthis.namespace = namespace;\n\t\tthis.children = new Map();\n\t}\n\n\tstatic createRootNode(database: Array<TableData>) {\n\t\treturn new ApiTree(null, database);\n\t}\n\n\tstatic isRouteData(data: TreeData): data is RouteData {\n\t\treturn (data as RouteData).method !== undefined;\n\t}\n\n\tstatic isEndpointData(data: TreeData): data is EndpointData {\n\t\treturn (data as EndpointData).routes !== undefined;\n\t}\n\n\taddData(namespaces: string[], route: RouteData | EndpointData) {\n\t\tif (ObjectUtils.isEmpty(namespaces)) {\n\t\t\tthis.data.push(route);\n\t\t\treturn;\n\t\t}\n\t\tconst childName: string = namespaces[0];\n\t\tthis.children.set(childName, this.children.get(childName) || new ApiTree(childName, this.database));\n\t\tthis.children.get(childName)!.addData(namespaces.slice(1), route);\n\t}\n\n\tcreateApiModels(): string {\n\t\tlet result = '';\n\t\tfor (const child of this.children.values()) {\n\t\t\tresult += child.createApiModelImpl(true);\n\t\t}\n\t\treturn result;\n\t}\n\n\tprivate createApiModelImpl(isBase: boolean): string {\n\t\tlet result = ``;\n\t\tfor (const data of this.data) {\n\t\t\tif (ApiTree.isEndpointData(data)) {\n\t\t\t\tresult += ApiTree.generateEndpointComments(data);\n\t\t\t}\n\t\t}\n\t\tresult += isBase\n\t\t\t? `\n\t\t\tdeclare namespace ${this.namespace} {`\n\t\t\t: `\n\t\t\texport namespace ${this.namespace} {`;\n\n\t\tfor (const data of this.data) {\n\t\t\tif (ApiTree.isRouteData(data)) {\n\t\t\t\tresult += this.generateRouteModels(data);\n\t\t\t}\n\t\t}\n\n\t\tfor (const child of this.children.values()) {\n\t\t\tresult += child.createApiModelImpl(false);\n\t\t}\n\t\tresult += '}';\n\t\treturn result;\n\t}\n\n\tstatic generateEndpointComments(endpoint: EndpointData): string {\n\t\treturn `\n\t\t// ${endpoint.name}\n\t\t// ${endpoint.description}`;\n\t}\n\n\tgenerateRouteModels(route: RouteData): string {\n\t\tlet modelString: string = ``;\n\t\tmodelString += `\n\t\t\t\t// ${route.name}\n\t\t\t\t// ${route.description}\n\t\t\t\texport namespace ${StringUtils.capitalizeFirst(route.method.toLowerCase())} {\n\t\t\t\t ${this.generateRequestParameters(route)}\n\t\t\t\t ${this.generateResponseParameters(route)}\n\t\t\t\t}`;\n\t\treturn modelString;\n\t}\n\n\tgenerateRequestParameters(route: RouteData): string {\n\t\tlet modelString: string = ``;\n\t\tif (ResponseValidator.isCustomRoute(route) && route.requestType) {\n\t\t\tmodelString += `\n\t\t\t\texport type Req = CustomTypes.${route.requestType}`;\n\t\t\treturn modelString;\n\t\t}\n\n\t\tif (!route.request) return modelString;\n\n\t\tmodelString += `\n\t\t \texport interface Req{\n\t\t \t\t\t\t\t${route.request\n\t\t\t\t\t\t\t\t.map((p) => {\n\t\t\t\t\t\t\t\t\tlet requestType = 'any';\n\t\t\t\t\t\t\t\t\tconst oneOfValidator = p.validator.find((v) => v.type === 'ONE_OF');\n\t\t\t\t\t\t\t\t\tconst typeCheckValidator = p.validator.find((v) => v.type === 'TYPE_CHECK');\n\t\t\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t\t\toneOfValidator &&\n\t\t\t\t\t\t\t\t\t\tObjectUtils.isArrayWithData(oneOfValidator.value as string[])\n\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\trequestType = (oneOfValidator.value as string[])\n\t\t\t\t\t\t\t\t\t\t\t.map((v) => `'${v}'`)\n\t\t\t\t\t\t\t\t\t\t\t.join(' | ');\n\t\t\t\t\t\t\t\t\t} else if (typeCheckValidator) {\n\t\t\t\t\t\t\t\t\t\tswitch (typeCheckValidator.value) {\n\t\t\t\t\t\t\t\t\t\t\tcase 'string':\n\t\t\t\t\t\t\t\t\t\t\tcase 'number':\n\t\t\t\t\t\t\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\t\t\t\t\t\tcase 'string[]':\n\t\t\t\t\t\t\t\t\t\t\tcase 'number[]':\n\t\t\t\t\t\t\t\t\t\t\tcase 'any[]':\n\t\t\t\t\t\t\t\t\t\t\t\trequestType = typeCheckValidator.value;\n\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn `'${p.name}'${p.required ? '' : '?'}:${requestType}${p.isNullable ? ' | null' : ''}`;\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.join(';\\n')}${ObjectUtils.isArrayWithData(route.request) ? ';' : ''}\n\t\t `;\n\n\t\tmodelString += `}`;\n\t\treturn modelString;\n\t}\n\n\tgenerateResponseParameters(route: RouteData): string {\n\t\tif (ResponseValidator.isCustomRoute(route)) {\n\t\t\t// Look for simple type for response\n\t\t\tif (['number', 'string', 'boolean'].includes(route.responseType))\n\t\t\t\treturn `export type Res = ${route.responseType}`;\n\t\t\telse if (['CUSTOM_ARRAY', 'CUSTOM_PAGED'].includes(route.type))\n\t\t\t\treturn `export type Res = CustomTypes.${route.responseType}[]`;\n\t\t\telse return `export type Res = CustomTypes.${route.responseType}`;\n\t\t}\n\t\treturn `export interface Res ${this.getFields(route.response, route.table, route.joins)}`;\n\t}\n\n\tgetFields(fields: ReadonlyArray<ResponseData>, routeBaseTable: string, joins: JoinData[]): string {\n\t\tconst nameFields = fields.map((f) => this.getNameAndType(f, routeBaseTable, joins));\n\t\tconst nested: string = `{\n\t\t\t${nameFields.join(';\\n\\t')}${ObjectUtils.isArrayWithData(nameFields) ? ';' : ''}\n\t\t}`;\n\t\treturn nested;\n\t}\n\n\tgetNameAndType(p: ResponseData, routeBaseTable: string, joins: JoinData[]): string {\n\t\tlet responseType = 'any',\n\t\t\tisNullable = false,\n\t\t\tarray = false;\n\n\t\tif (p.type) {\n\t\t\tresponseType = p.type;\n\t\t} else if (p.selector) {\n\t\t\t({ responseType, isNullable } = this.getTypeFromTable(p.selector, p.name));\n\n\t\t\t// If selector is not from the baseTable, then we need to determine if the join is inner join or not.\n\t\t\t// If it is not an inner join, then it is nullable.\n\t\t\tconst selectorKey = p.selector.split('.')[0];\n\t\t\tif (selectorKey !== routeBaseTable) {\n\t\t\t\tconst join = joins.find((j) => j.alias === selectorKey);\n\t\t\t\tif (join && join.type !== 'INNER') {\n\t\t\t\t\tisNullable = true;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (p.subquery) {\n\t\t\tresponseType = this.getFields(p.subquery.properties, p.subquery.table, p.subquery.joins);\n\t\t\tarray = true;\n\t\t}\n\n\t\treturn `${p.name}:${responseType}${array ? '[]' : ''}${isNullable ? ' | null' : ''}`;\n\t}\n\n\tgetTypeFromTable(selector: string, name: string): { responseType: string; isNullable: boolean } {\n\t\tconst path = selector.split('.');\n\t\tif (path.length === 0 || path.length > 2 || path[0] === '') return { responseType: 'any', isNullable: false };\n\n\t\tlet tableName = path.length == 2 ? path[0] : name;\n\t\tconst columnName = path.length == 2 ? path[1] : path[0];\n\t\tlet table = this.database.find((t) => t.name == tableName);\n\t\tif (!table && tableName.includes('_')) {\n\t\t\tconst tableAliasSplit = tableName.split('_');\n\t\t\ttableName = tableAliasSplit[1];\n\t\t\ttable = this.database.find((t) => t.name == tableName);\n\t\t}\n\n\t\tconst column = table?.columns.find((c) => c.name == columnName);\n\t\tif (!table || !column) return { responseType: 'any', isNullable: false };\n\n\t\treturn {\n\t\t\tresponseType: SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value),\n\t\t\tisNullable: column.roles.length > 0 || column.isNullable\n\t\t};\n\t}\n}\n\nfunction createNotificationTypes(databases: Array<TableData>): string {\n\tlet result = 'declare namespace NotificationTypes {';\n\tfor (const database of databases) {\n\t\tif (!database.notify) continue;\n\t\tif (database.notify === 'ALL') {\n\t\t\t// We need to get all the columns from the database and create a type for each one.\n\t\t\tresult += `export type ${StringUtils.capitalizeFirst(database.name)} = Pick<Model.${StringUtils.capitalizeFirst(database.name)}, `;\n\t\t\tconst columnStrings: string[] = [];\n\t\t\tfor (const column of database.columns) {\n\t\t\t\tcolumnStrings.push(`'${column.name}'`);\n\t\t\t}\n\t\t\tresult += columnStrings.join(' | ');\n\t\t\tresult += `>;`;\n\t\t} else {\n\t\t\t// database.notify is an array of column names\n\t\t\tresult += `export type ${StringUtils.capitalizeFirst(database.name)} = Pick<Model.${StringUtils.capitalizeFirst(database.name)}, `;\n\t\t\tconst columnStrings: string[] = [];\n\t\t\tfor (const column of database.notify) {\n\t\t\t\tconst columnData = database.columns.find((c) => c.name === column);\n\t\t\t\tif (!columnData) {\n\t\t\t\t\tlogger.warn(`Notification: Could not find column: ${column} in table: ${database.name}`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcolumnStrings.push(`'${column}'`);\n\t\t\t}\n\t\t\tresult += columnStrings.join(' | ');\n\t\t\tresult += `>;`;\n\t\t}\n\t}\n\tresult += `}`;\n\treturn result;\n}\n\nfunction pathToNamespaces(path: string): string[] {\n\treturn path\n\t\t.split('/')\n\t\t.map((e) => StringUtils.toPascalCasing(e))\n\t\t.filter((e) => e);\n}\n\nexport default function apiGenerator(schema: ResturaSchema): Promise<string> {\n\tlet apiString = `/** Auto generated file. DO NOT MODIFY **/\\n`;\n\t// Routes\n\tconst rootNamespace = ApiTree.createRootNode(schema.database);\n\tfor (const endpoint of schema.endpoints) {\n\t\tconst endpointNamespaces = pathToNamespaces(endpoint.baseUrl);\n\t\trootNamespace.addData(endpointNamespaces, endpoint);\n\t\tfor (const route of endpoint.routes) {\n\t\t\tconst fullNamespace: string[] = [...endpointNamespaces, ...pathToNamespaces(route.path)];\n\t\t\trootNamespace.addData(fullNamespace, route);\n\t\t}\n\t}\n\tapiString += rootNamespace.createApiModels();\n\n\t// Custom Types\n\tif (schema.customTypes.length > 0) {\n\t\tapiString += `\\n\n\t\tdeclare namespace CustomTypes {\n\t\t\t${schema.customTypes.join('\\n')}\n\t\t}`;\n\t}\n\n\t// Notification Types\n\tapiString += `\\n\\n`;\n\tapiString += createNotificationTypes(schema.database);\n\n\treturn prettier.format(apiString, {\n\t\tparser: 'typescript',\n\t\t...{\n\t\t\ttrailingComma: 'none',\n\t\t\ttabWidth: 4,\n\t\t\tuseTabs: true,\n\t\t\tendOfLine: 'lf',\n\t\t\tprintWidth: 120,\n\t\t\tsingleQuote: true\n\t\t}\n\t});\n}\n","import { ValidatorString } from '../validators/ResponseValidator.js';\n\nclass SqlUtils {\n\tstatic convertDatabaseTypeToTypescript(type: string): ValidatorString | string;\n\tstatic convertDatabaseTypeToTypescript(type: string, value?: string): ValidatorString | string;\n\tstatic convertDatabaseTypeToTypescript(type: string, value?: string): ValidatorString | string {\n\t\ttype = type.toLocaleLowerCase();\n\t\tif (type.startsWith('tinyint') || type.startsWith('boolean')) return 'boolean';\n\t\tif (type.startsWith('decimal') || type.startsWith('numeric')) return 'string';\n\t\tif (\n\t\t\ttype.indexOf('int') > -1 ||\n\t\t\ttype.startsWith('double') ||\n\t\t\ttype.startsWith('float') ||\n\t\t\ttype.indexOf('serial') > -1 ||\n\t\t\ttype.startsWith('real') ||\n\t\t\ttype.startsWith('double precision')\n\t\t)\n\t\t\treturn 'number';\n\t\tif (type === 'json') {\n\t\t\tif (!value) return 'object';\n\t\t\t// Split the value by comma and remove any single or double quote characters, and then join with \" | \"\n\t\t\treturn value\n\t\t\t\t.split(',')\n\t\t\t\t.map((val) => {\n\t\t\t\t\treturn val.replace(/['\"]/g, '');\n\t\t\t\t})\n\t\t\t\t.join(' | ');\n\t\t}\n\t\tif (\n\t\t\ttype.startsWith('varchar') ||\n\t\t\ttype.indexOf('text') > -1 ||\n\t\t\ttype.startsWith('char') ||\n\t\t\ttype.indexOf('blob') > -1 ||\n\t\t\ttype.startsWith('binary')\n\t\t)\n\t\t\treturn 'string';\n\t\tif (type.startsWith('date') || type.startsWith('time')) return 'string';\n\t\tif (type.startsWith('enum')) return SqlUtils.convertDatabaseEnumToStringUnion(value || type);\n\t\treturn 'any';\n\t}\n\n\tstatic convertDatabaseEnumToStringUnion(type: string): string {\n\t\treturn type\n\t\t\t.replace(/^enum\\(|\\)/g, '')\n\t\t\t.split(',')\n\t\t\t.map((value) => {\n\t\t\t\treturn `'${value.replace(/'/g, '')}'`;\n\t\t\t})\n\t\t\t.join(' | ');\n\t}\n}\n\nexport { SqlUtils };\n","/* Note: We tried our best to find matching HTML codes for some of the things\n we are doing. However there isn't a perfect match because the HTML status\n codes were meant as a server signaling a client about some error either in the request\n and not the necessarily that a credit card was declined for example.\n */\n\n// Internal data is used for passing around until we finally get to the sending externally\nexport interface RsErrorInternalData {\n\terr: ErrorCode;\n\tmsg: string;\n\tstack: string;\n\tstatus: number;\n\tmessage?: string; // I don't think this is ever here\n}\n\nexport enum HtmlStatusCodes {\n\tBAD_REQUEST = 400,\n\tUNAUTHORIZED = 401,\n\tPAYMENT_REQUIRED = 402,\n\tFORBIDDEN = 403,\n\tNOT_FOUND = 404,\n\tMETHOD_NOT_ALLOWED = 405,\n\tCONFLICT = 409,\n\tVERSION_OUT_OF_DATE = 418, // Technically this is the I'm a teapot code that was a joke.\n\tUNPROCESSABLE_ENTITY = 422,\n\tTOO_MANY_REQUESTS = 429,\n\tSERVER_ERROR = 500,\n\tBAD_GATEWAY = 502,\n\tSERVICE_UNAVAILABLE = 503,\n\tGATEWAY_TIMEOUT = 504,\n\tNETWORK_CONNECT_TIMEOUT = 599\n}\n\nexport type ErrorCode =\n\t| 'UNKNOWN_ERROR'\n\t| 'NOT_FOUND'\n\t| 'EMAIL_TAKEN'\n\t| 'UNAUTHORIZED'\n\t| 'PAYMENT_FAILURE'\n\t| 'RATE_LIMIT_EXCEEDED'\n\t| 'FORBIDDEN'\n\t| 'CONFLICT'\n\t| 'UPDATE_FORBIDDEN'\n\t| 'CREATE_FORBIDDEN'\n\t| 'DELETE_FORBIDDEN'\n\t| 'DELETE_FAILURE'\n\t| 'BAD_REQUEST'\n\t| 'INVALID_TOKEN'\n\t| 'INCORRECT_EMAIL_OR_PASSWORD'\n\t| 'DUPLICATE_TOKEN'\n\t| 'DUPLICATE_USERNAME'\n\t| 'DUPLICATE_EMAIL'\n\t| 'DUPLICATE'\n\t| 'EMAIL_NOT_VERIFIED'\n\t| 'UPDATE_WITHOUT_ID'\n\t| 'CONNECTION_ERROR'\n\t| 'INVALID_PAYMENT'\n\t| 'DECLINED_PAYMENT'\n\t| 'INTEGRATION_ERROR'\n\t| 'CANNOT_RESERVE'\n\t| 'REFUND_FAILURE'\n\t| 'INVALID_INVOICE'\n\t| 'INVALID_COUPON'\n\t| 'SERVICE_UNAVAILABLE'\n\t| 'METHOD_UNALLOWED'\n\t| 'LOGIN_EXPIRED'\n\t| 'THIRD_PARTY_ERROR'\n\t| 'ACCESS_DENIED'\n\t| 'DATABASE_ERROR'\n\t| 'SCHEMA_ERROR'\n\t| 'DATA_INCOMPLETE';\n\nexport class RsError {\n\terr: ErrorCode;\n\tmsg: string;\n\tstatus?: number;\n\tstack: string;\n\n\tconstructor(errCode: ErrorCode, message?: string) {\n\t\tthis.err = errCode;\n\t\tthis.msg = message || '';\n\t\tthis.status = RsError.htmlStatus(errCode);\n\t\tthis.stack = new Error().stack || '';\n\t}\n\n\tstatic htmlStatus(code: ErrorCode): number {\n\t\treturn htmlStatusMap[code];\n\t}\n\n\tstatic isRsError(error: unknown): error is RsError {\n\t\treturn error instanceof RsError;\n\t}\n}\n\n// MAKE SURE TO ADD A NEW ERROR TO BOTH THE LIST AND AN APPROPRIATE HTML CODE\n// -- otherwise we default to error 500 --\n\nconst htmlStatusMap: Record<ErrorCode, number> = {\n\tUNKNOWN_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tNOT_FOUND: HtmlStatusCodes.NOT_FOUND,\n\tEMAIL_TAKEN: HtmlStatusCodes.CONFLICT,\n\tPAYMENT_FAILURE: HtmlStatusCodes.PAYMENT_REQUIRED,\n\tRATE_LIMIT_EXCEEDED: HtmlStatusCodes.TOO_MANY_REQUESTS,\n\tFORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tCONFLICT: HtmlStatusCodes.CONFLICT,\n\tUNAUTHORIZED: HtmlStatusCodes.UNAUTHORIZED,\n\tUPDATE_FORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tCREATE_FORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tDELETE_FORBIDDEN: HtmlStatusCodes.FORBIDDEN,\n\tDELETE_FAILURE: HtmlStatusCodes.SERVER_ERROR,\n\tBAD_REQUEST: HtmlStatusCodes.BAD_REQUEST,\n\tINVALID_TOKEN: HtmlStatusCodes.UNAUTHORIZED,\n\tINCORRECT_EMAIL_OR_PASSWORD: HtmlStatusCodes.UNAUTHORIZED,\n\tDUPLICATE_TOKEN: HtmlStatusCodes.CONFLICT,\n\tDUPLICATE_USERNAME: HtmlStatusCodes.CONFLICT,\n\tDUPLICATE_EMAIL: HtmlStatusCodes.CONFLICT,\n\tDUPLICATE: HtmlStatusCodes.CONFLICT,\n\tEMAIL_NOT_VERIFIED: HtmlStatusCodes.BAD_REQUEST,\n\tUPDATE_WITHOUT_ID: HtmlStatusCodes.BAD_REQUEST,\n\tCONNECTION_ERROR: HtmlStatusCodes.NETWORK_CONNECT_TIMEOUT,\n\tINVALID_PAYMENT: HtmlStatusCodes.FORBIDDEN,\n\tDECLINED_PAYMENT: HtmlStatusCodes.FORBIDDEN,\n\tINTEGRATION_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tCANNOT_RESERVE: HtmlStatusCodes.FORBIDDEN,\n\tREFUND_FAILURE: HtmlStatusCodes.FORBIDDEN,\n\tINVALID_INVOICE: HtmlStatusCodes.FORBIDDEN,\n\tINVALID_COUPON: HtmlStatusCodes.FORBIDDEN,\n\tSERVICE_UNAVAILABLE: HtmlStatusCodes.SERVICE_UNAVAILABLE,\n\tMETHOD_UNALLOWED: HtmlStatusCodes.METHOD_NOT_ALLOWED,\n\tLOGIN_EXPIRED: HtmlStatusCodes.UNAUTHORIZED,\n\tTHIRD_PARTY_ERROR: HtmlStatusCodes.BAD_REQUEST,\n\tACCESS_DENIED: HtmlStatusCodes.FORBIDDEN,\n\tDATABASE_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tSCHEMA_ERROR: HtmlStatusCodes.SERVER_ERROR,\n\tDATA_INCOMPLETE: HtmlStatusCodes.UNPROCESSABLE_ENTITY\n};\n","import { logger } from '../../logger/logger.js';\nimport { RsError } from '../RsError.js';\n\nimport {\n\tCustomRouteData,\n\tResponseData,\n\tResturaSchema,\n\tRouteData,\n\tStandardRouteData,\n\tTableData\n} from '../schemas/resturaSchema.js';\nimport { SqlUtils } from '../sql/SqlUtils.js';\n\n// The `string` type is to handle for enums\nexport type ValidatorString = 'boolean' | 'string' | 'number' | 'object' | 'any';\n\ninterface ResponseType {\n\tisOptionalOrNullable?: boolean;\n\tisArray?: boolean;\n\tvalidator: ValidatorString | ResponseTypeMap | string[];\n}\n\ninterface ResponseTypeMap {\n\t[property: string]: ResponseType;\n}\n\nexport default class ResponseValidator {\n\tprivate readonly rootMap: ResponseTypeMap;\n\tprivate readonly database: ReadonlyArray<TableData>;\n\n\tconstructor(schema: ResturaSchema) {\n\t\tthis.database = schema.database;\n\t\tthis.rootMap = {};\n\t\tfor (const endpoint of schema.endpoints) {\n\t\t\tconst endpointMap: ResponseTypeMap = {};\n\t\t\tfor (const route of endpoint.routes) {\n\t\t\t\tif (ResponseValidator.isCustomRoute(route)) {\n\t\t\t\t\tendpointMap[`${route.method}:${route.path}`] = { validator: 'any' };\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tendpointMap[`${route.method}:${route.path}`] = this.getRouteResponseType(route);\n\t\t\t}\n\t\t\tconst endpointUrl = endpoint.baseUrl.endsWith('/') ? endpoint.baseUrl.slice(0, -1) : endpoint.baseUrl;\n\t\t\tthis.rootMap[endpointUrl] = { validator: endpointMap };\n\t\t}\n\t}\n\n\tpublic validateResponseParams(data: unknown, endpointUrl: string, routeData: RouteData): void {\n\t\tif (!this.rootMap) {\n\t\t\tthrow new RsError('BAD_REQUEST', 'Cannot validate response without type maps');\n\t\t}\n\n\t\tconst routeMap = (this.rootMap[endpointUrl].validator as ResponseTypeMap)[\n\t\t\t`${routeData.method}:${routeData.path}`\n\t\t];\n\t\tdata = this.validateAndCoerceMap('_base', data, routeMap);\n\t}\n\n\tprivate getRouteResponseType(route: StandardRouteData): ResponseType {\n\t\tconst map: ResponseTypeMap = {};\n\t\tfor (const field of route.response) {\n\t\t\tmap[field.name] = this.getFieldResponseType(field, route.table, route);\n\t\t}\n\n\t\tif (route.type === 'PAGED') {\n\t\t\treturn {\n\t\t\t\tvalidator: {\n\t\t\t\t\tdata: { validator: map, isArray: true },\n\t\t\t\t\ttotal: { validator: 'number' }\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tif (route.method === 'DELETE') {\n\t\t\treturn {\n\t\t\t\tvalidator: 'boolean'\n\t\t\t};\n\t\t}\n\n\t\treturn { validator: map, isArray: route.type === 'ARRAY' };\n\t}\n\n\tprivate getFieldResponseType(field: ResponseData, tableName: string, routeData: StandardRouteData): ResponseType {\n\t\tif (field.type) {\n\t\t\tif (ResponseValidator.validatorIsValidString(field.type)) {\n\t\t\t\treturn { validator: field.type };\n\t\t\t}\n\t\t\tif (field.type.includes('|')) {\n\t\t\t\treturn { validator: this.parseValidationEnum(field.type) };\n\t\t\t}\n\t\t\treturn { validator: 'object' };\n\t\t} else if (field.selector) {\n\t\t\treturn this.getTypeFromTable(field.selector, tableName, routeData);\n\t\t} else if (field.subquery) {\n\t\t\tconst table = this.database.find((t) => t.name == tableName);\n\t\t\tif (!table) return { isArray: true, validator: 'any' };\n\t\t\tconst isOptionalOrNullable = table.roles.length > 0 || table.scopes.length > 0;\n\t\t\tconst validator: ResponseTypeMap = {};\n\t\t\tfor (const prop of field.subquery.properties) {\n\t\t\t\tvalidator[prop.name] = this.getFieldResponseType(prop, field.subquery.table, routeData);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tisArray: true,\n\t\t\t\tisOptionalOrNullable,\n\t\t\t\tvalidator\n\t\t\t};\n\t\t}\n\t\treturn { validator: 'any' };\n\t}\n\n\tprivate getTypeFromTable(selector: string, name: string, routeData: StandardRouteData): ResponseType {\n\t\tconst selectorParts = selector.split('.');\n\t\tif (selectorParts.length === 0 || selectorParts.length > 2 || selectorParts[0] === '') {\n\t\t\t// Here we can't tell what type it is, so we return any, but make an assumption that it's not optional.\n\t\t\t// We should investigate if this is a good assumption.\n\t\t\tlogger.warn(`ResponseValidator: Could not determine type for selector: ${selector} in table: ${name}`);\n\t\t\treturn { validator: 'any', isOptionalOrNullable: false };\n\t\t}\n\n\t\tconst tableOrAliasName = selectorParts.length == 2 ? selectorParts[0] : name;\n\t\tconst columnName = selectorParts.length == 2 ? selectorParts[1] : selectorParts[0];\n\n\t\tlet table = this.database.find((t) => t.name == tableOrAliasName);\n\t\tlet isNullable = false;\n\t\tif (!table) {\n\t\t\t// Try to look for the alias in the joins\n\t\t\tconst join = routeData.joins.find((j) => j.alias == tableOrAliasName);\n\t\t\tif (join) {\n\t\t\t\ttable = this.database.find((t) => t.name == join.table);\n\t\t\t\tif (join.type === 'LEFT' || join.type === 'RIGHT') isNullable = true;\n\t\t\t}\n\t\t}\n\t\tif (!table) {\n\t\t\tlogger.warn(\n\t\t\t\t`ResponseValidator: Could not find table: ${tableOrAliasName} in database using selector: ${selector}`\n\t\t\t);\n\t\t\treturn { validator: 'any', isOptionalOrNullable: false };\n\t\t}\n\t\tconst column = table.columns.find((c) => c.name == columnName);\n\t\tif (!column) {\n\t\t\tlogger.warn(\n\t\t\t\t`ResponseValidator: Could not find column: ${columnName} in table: ${tableOrAliasName} using selector: ${selector}`\n\t\t\t);\n\t\t\treturn { validator: 'any', isOptionalOrNullable: false };\n\t\t}\n\n\t\tlet validator: ValidatorString | string | string[] = SqlUtils.convertDatabaseTypeToTypescript(\n\t\t\tcolumn.type,\n\t\t\tcolumn.value\n\t\t);\n\t\tif (!ResponseValidator.validatorIsValidString(validator)) validator = this.parseValidationEnum(validator);\n\n\t\treturn {\n\t\t\tvalidator,\n\t\t\tisOptionalOrNullable: isNullable || column.roles.length > 0 || column.scopes.length > 0 || column.isNullable\n\t\t};\n\t}\n\n\tprivate parseValidationEnum(validator: string): string[] {\n\t\tlet terms = validator.split('|');\n\t\tterms = terms.map((v) => v.replace(/'/g, '').trim());\n\t\treturn terms;\n\t}\n\n\tprivate validateAndCoerceMap(\n\t\tname: string,\n\t\tvalue: unknown,\n\t\t{ isOptionalOrNullable, isArray, validator }: ResponseTypeMap[string]\n\t): unknown {\n\t\tif (validator === 'any') return value;\n\t\tconst valueType = typeof value;\n\t\tif (value == null) {\n\t\t\tif (isOptionalOrNullable) return value;\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is required`);\n\t\t}\n\t\tif (isArray) {\n\t\t\tif (!Array.isArray(value)) {\n\t\t\t\tthrow new RsError(\n\t\t\t\t\t'DATABASE_ERROR',\n\t\t\t\t\t`Response param (${name}) is a/an ${valueType} instead of an array`\n\t\t\t\t);\n\t\t\t}\n\t\t\tvalue.forEach((v, i) => this.validateAndCoerceMap(`${name}[${i}]`, v, { validator }));\n\t\t\treturn value;\n\t\t}\n\t\tif (typeof validator === 'string') {\n\t\t\t// Nested objects do not coerce boolean values or dates properly. Fix that here if needed.\n\t\t\t// Database returns number but schema expects boolean\n\t\t\tif (validator === 'boolean' && valueType === 'number') {\n\t\t\t\tif (value !== 0 && value !== 1)\n\t\t\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is of the wrong type (${valueType})`);\n\t\t\t\treturn value === 1;\n\t\t\t} else if (validator === 'string' && valueType === 'string') {\n\t\t\t\t// Check if the string is a SQL datetime, date, time, timestamp format\n\t\t\t\tif (\n\t\t\t\t\ttypeof value === 'string' &&\n\t\t\t\t\tvalue.match(\n\t\t\t\t\t\t/^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.?\\d*$|\\d{2}:\\d{2}:\\d{2}.?\\d*$|^\\d{4}-\\d{2}-\\d{2}$/\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tconst date = new Date(value);\n\t\t\t\t\tif (date.toISOString() === '1970-01-01T00:00:00.000Z') return null;\n\t\t\t\t\tconst timezoneOffset = date.getTimezoneOffset() * 60000;\n\t\t\t\t\treturn new Date(date.getTime() - timezoneOffset * 2).toISOString();\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t} else if (valueType === validator) {\n\t\t\t\treturn value;\n\t\t\t} else if (valueType === 'object') {\n\t\t\t\treturn value;\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is of the wrong type (${valueType})`);\n\t\t}\n\t\tif (Array.isArray(validator) && typeof value === 'string') {\n\t\t\tif (validator.includes(value)) return value;\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is not one of the enum options (${value})`);\n\t\t}\n\t\tif (valueType !== 'object') {\n\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}) is of the wrong type (${valueType})`);\n\t\t}\n\t\tfor (const prop in value) {\n\t\t\t// @ts-expect-error - not sure types but we will be changing to zod soon\n\t\t\tif (!validator[prop])\n\t\t\t\tthrow new RsError('DATABASE_ERROR', `Response param (${name}.${prop}) is not allowed`);\n\t\t}\n\t\tfor (const prop in validator) {\n\t\t\t// @ts-expect-error - not sure types but we will be changing to zod soon\n\t\t\tvalue[prop] = this.validateAndCoerceMap(`${name}.${prop}`, value[prop], validator[prop]);\n\t\t}\n\t\treturn value;\n\t}\n\n\tstatic isCustomRoute(route: RouteData): route is CustomRouteData {\n\t\treturn route.type === 'CUSTOM_ONE' || route.type === 'CUSTOM_ARRAY' || route.type === 'CUSTOM_PAGED';\n\t}\n\n\tprivate static validatorIsValidString(validator: string): validator is ValidatorString {\n\t\treturn !validator.includes('|');\n\t}\n}\n","import { StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport type { ResturaSchema, TableData } from '../schemas/resturaSchema.js';\nimport { SqlUtils } from '../sql/SqlUtils.js';\n\nexport default function modelGenerator(schema: ResturaSchema): Promise<string> {\n\tlet modelString = `/** Auto generated file. DO NOT MODIFY **/\\n\\n`;\n\tmodelString += `declare namespace Model {\\n`;\n\tfor (const table of schema.database) {\n\t\tmodelString += convertTable(table);\n\t}\n\tmodelString += `}`;\n\treturn prettier.format(modelString, {\n\t\tparser: 'typescript',\n\t\t...{\n\t\t\ttrailingComma: 'none',\n\t\t\ttabWidth: 4,\n\t\t\tuseTabs: true,\n\t\t\tendOfLine: 'lf',\n\t\t\tprintWidth: 120,\n\t\t\tsingleQuote: true\n\t\t}\n\t});\n}\n\nfunction convertTable(table: TableData): string {\n\tlet modelString = `\\texport interface ${StringUtils.capitalizeFirst(table.name)} {\\n`;\n\tfor (const column of table.columns) {\n\t\tmodelString += `\\t\\t${column.name}: ${SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value)}${column.isNullable ? ' | null' : ''};\\n`;\n\t}\n\tmodelString += `\\t}\\n`;\n\treturn modelString;\n}\n","export default function resturaGlobalTypesGenerator(): string {\n\treturn `/** Auto generated file. DO NOT MODIFY **/\n/** This file contains types that may be used in the CustomTypes of Restura **/\n/** For example export interface MyPagedQuery extends Restura.PageQuery { } **/\n\ndeclare namespace Restura {\n\texport type StandardOrderTypes = 'ASC' | 'DESC' | 'RAND' | 'NONE';\n\texport interface PageQuery {\n\t\tpage?: number;\n\t\tperPage?: number;\n\t\tsortBy?: string;\n\t\tsortOrder?: StandardOrderTypes;\n\t\tfilter?: string;\n\t}\n}\n`;\n}\n","import { ObjectUtils, StringUtils } from '@redskytech/core-utils';\nimport { config } from '@restura/internal';\nimport { boundMethod } from 'autobind-decorator';\nimport bodyParser from 'body-parser';\nimport compression from 'compression';\nimport cookieParser from 'cookie-parser';\nimport * as express from 'express';\nimport { RequestHandler } from 'express';\nimport fs from 'fs';\nimport multer from 'multer';\nimport path from 'path';\nimport * as prettier from 'prettier';\nimport { logger } from '../logger/logger.js';\nimport { RsError } from './RsError.js';\nimport compareSchema from './compareSchema.js';\nimport customApiFactory from './customApiFactory.js';\nimport apiGenerator from './generators/apiGenerator.js';\nimport customTypeValidationGenerator from './generators/customTypeValidationGenerator.js';\nimport modelGenerator from './generators/modelGenerator.js';\nimport resturaGlobalTypesGenerator from './generators/resturaGlobalTypesGenerator.js';\nimport addApiResponseFunctions from './middleware/addApiResponseFunctions.js';\nimport { authenticateRequester } from './middleware/authenticateRequester.js';\nimport { getMulterUpload } from './middleware/getMulterUpload.js';\nimport { schemaValidation } from './middleware/schemaValidation.js';\nimport { resturaConfigSchema, type ResturaConfigSchema } from './schemas/resturaConfigSchema.js';\nimport {\n\tisSchemaValid,\n\tStandardRouteData,\n\ttype CustomRouteData,\n\ttype ResturaSchema,\n\ttype RouteData\n} from './schemas/resturaSchema.js';\nimport { PsqlEngine } from './sql/PsqlEngine.js';\nimport { PsqlPool } from './sql/PsqlPool.js';\nimport type { RsRequest, RsResponse } from './types/customExpressTypes.js';\nimport type { AuthenticateHandler } from './types/resturaTypes.js';\nimport TempCache from './utils/TempCache.js';\nimport { sortObjectKeysAlphabetically } from './utils/utils.js';\nimport ResponseValidator from './validators/ResponseValidator.js';\nimport requestValidator, { ValidationDictionary } from './validators/requestValidator.js';\n\nclass ResturaEngine {\n\t// Make public so other modules can access without re-parsing the config\n\tresturaConfig!: ResturaConfigSchema;\n\n\tprivate multerCommonUpload!: multer.Multer;\n\tprivate resturaRouter!: express.Router;\n\tprivate publicEndpoints: { GET: string[]; POST: string[]; PUT: string[]; PATCH: string[]; DELETE: string[] } = {\n\t\tGET: [],\n\t\tPOST: [],\n\t\tPUT: [],\n\t\tPATCH: [],\n\t\tDELETE: []\n\t};\n\tprivate expressApp!: express.Application;\n\tprivate schema!: ResturaSchema;\n\tprivate responseValidator!: ResponseValidator;\n\tprivate authenticationHandler!: AuthenticateHandler;\n\tprivate customTypeValidation!: ValidationDictionary;\n\tprivate psqlConnectionPool!: PsqlPool;\n\tprivate psqlEngine!: PsqlEngine;\n\n\t/**\n\t * Initializes the Restura engine with the provided Express application.\n\t *\n\t * @param app - The Express application instance to initialize with Restura.\n\t * @returns A promise that resolves when the initialization is complete.\n\t */\n\tasync init(\n\t\tapp: express.Application,\n\t\tauthenticationHandler: AuthenticateHandler,\n\t\tpsqlConnectionPool: PsqlPool\n\t): Promise<void> {\n\t\t// Try to load config first. If it fails, we can't continue.\n\t\tthis.resturaConfig = await config.validate('restura', resturaConfigSchema);\n\n\t\tthis.multerCommonUpload = getMulterUpload(this.resturaConfig.fileTempCachePath);\n\t\tnew TempCache(this.resturaConfig.fileTempCachePath);\n\t\tthis.psqlConnectionPool = psqlConnectionPool;\n\t\tthis.psqlEngine = new PsqlEngine(this.psqlConnectionPool, true, this.resturaConfig.scratchDatabaseSuffix);\n\n\t\tawait customApiFactory.loadApiFiles(this.resturaConfig.customApiFolderPath);\n\n\t\tthis.authenticationHandler = authenticationHandler;\n\n\t\t// Middleware and general setup\n\t\tapp.use(compression());\n\t\tapp.use(bodyParser.json({ limit: '32mb' }));\n\t\tapp.use(bodyParser.urlencoded({ limit: '32mb', extended: false }));\n\t\tapp.use(cookieParser());\n\t\t// Disable the X-Powered-By header\n\t\tapp.disable('x-powered-by');\n\n\t\tapp.use('/', addApiResponseFunctions as unknown as express.RequestHandler);\n\t\tapp.use('/api/', authenticateRequester(this.authenticationHandler) as unknown as express.RequestHandler);\n\t\tapp.use('/restura', this.resturaAuthentication);\n\n\t\t// Routes specific to Restura\n\t\tapp.put(\n\t\t\t'/restura/v1/schema',\n\t\t\tschemaValidation as unknown as express.RequestHandler,\n\t\t\tthis.updateSchema as unknown as express.RequestHandler\n\t\t);\n\t\tapp.post(\n\t\t\t'/restura/v1/schema/preview',\n\t\t\tschemaValidation as unknown as express.RequestHandler,\n\t\t\tthis.previewCreateSchema as unknown as express.RequestHandler\n\t\t);\n\t\tapp.get('/restura/v1/schema', this.getSchema);\n\t\tapp.get('/restura/v1/schema/types', this.getSchemaAndTypes);\n\n\t\tthis.expressApp = app;\n\n\t\tawait this.reloadEndpoints();\n\t\tawait this.initializeGeneratedTypesFolder();\n\n\t\tlogger.info('Restura Engine Initialized');\n\t}\n\n\t/**\n\t * Determines if a given endpoint is public based on the HTTP method and full URL. This\n\t * is determined on whether the endpoint in the schema has no roles or scopes assigned to it.\n\t *\n\t * @param method - The HTTP method (e.g., 'GET', 'POST', 'PUT', 'PATCH', 'DELETE').\n\t * @param fullUrl - The full URL of the endpoint.\n\t * @returns A boolean indicating whether the endpoint is public.\n\t */\n\tisEndpointPublic(method: string, fullUrl: string): boolean {\n\t\tif (!['GET', 'POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) return false;\n\t\treturn this.publicEndpoints[method as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'].includes(fullUrl);\n\t}\n\n\t/**\n\t * Checks if an endpoint exists for a given HTTP method and full URL.\n\t *\n\t * @param method - The HTTP method to check (e.g., 'GET', 'POST', 'PUT', 'PATCH', 'DELETE').\n\t * @param fullUrl - The full URL of the endpoint to check.\n\t * @returns `true` if the endpoint exists, otherwise `false`.\n\t */\n\tdoesEndpointExist(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE', fullUrl: string): boolean {\n\t\treturn this.schema.endpoints.some((endpoint) => {\n\t\t\tif (!fullUrl.startsWith(endpoint.baseUrl)) return false;\n\t\t\tconst pathWithoutBaseUrl = fullUrl.replace(endpoint.baseUrl, '');\n\t\t\treturn endpoint.routes.some((route) => {\n\t\t\t\treturn route.method === method && route.path === pathWithoutBaseUrl;\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Generates an API from the provided schema and writes it to the specified output file.\n\t *\n\t * @param outputFile - The path to the file where the generated API will be written.\n\t * @param providedSchema - The schema from which the API will be generated.\n\t * @returns A promise that resolves when the API has been successfully generated and written to the output file.\n\t */\n\tasync generateApiFromSchema(outputFile: string, providedSchema: ResturaSchema): Promise<void> {\n\t\tfs.writeFileSync(outputFile, await apiGenerator(providedSchema));\n\t}\n\n\t/**\n\t * Generates a model from the provided schema and writes it to the specified output file.\n\t *\n\t * @param outputFile - The path to the file where the generated model will be written.\n\t * @param providedSchema - The schema from which the model will be generated.\n\t * @returns A promise that resolves when the model has been successfully written to the output file.\n\t */\n\tasync generateModelFromSchema(outputFile: string, providedSchema: ResturaSchema): Promise<void> {\n\t\tfs.writeFileSync(outputFile, await modelGenerator(providedSchema));\n\t}\n\n\t/**\n\t * Generates the ambient module declaration for Restura global types and writes it to the specified output file.\n\t * These types are used sometimes in the CustomTypes\n\t * @param outputFile\n\t */\n\tgenerateResturaGlobalTypes(outputFile: string): void {\n\t\tfs.writeFileSync(outputFile, resturaGlobalTypesGenerator());\n\t}\n\n\t/**\n\t * Retrieves the latest file system schema for Restura.\n\t *\n\t * @returns {Promise<ResturaSchema>} A promise that resolves to the latest Restura schema.\n\t * @throws {Error} If the schema file is missing or the schema is not valid.\n\t */\n\tasync getLatestFileSystemSchema(): Promise<ResturaSchema> {\n\t\tif (!fs.existsSync(this.resturaConfig.schemaFilePath)) {\n\t\t\tlogger.error(`Missing restura schema file, expected path: ${this.resturaConfig.schemaFilePath}`);\n\t\t\tthrow new Error('Missing restura schema file');\n\t\t}\n\n\t\tconst schemaFileData = fs.readFileSync(this.resturaConfig.schemaFilePath, { encoding: 'utf8' });\n\t\tconst schema: ResturaSchema = ObjectUtils.safeParse(schemaFileData) as ResturaSchema;\n\t\tconst isValid = await isSchemaValid(schema);\n\t\tif (!isValid) {\n\t\t\tlogger.error('Schema is not valid');\n\t\t\tthrow new Error('Schema is not valid');\n\t\t}\n\t\treturn schema;\n\t}\n\n\tprivate async reloadEndpoints() {\n\t\tthis.schema = await this.getLatestFileSystemSchema();\n\t\tthis.customTypeValidation = customTypeValidationGenerator(this.schema);\n\t\tthis.resturaRouter = express.Router();\n\t\tthis.resetPublicEndpoints();\n\n\t\tlet routeCount = 0;\n\t\tfor (const endpoint of this.schema.endpoints) {\n\t\t\tconst baseUrl = endpoint.baseUrl.endsWith('/') ? endpoint.baseUrl.slice(0, -1) : endpoint.baseUrl;\n\t\t\tthis.expressApp.use(baseUrl, (req, res, next) => {\n\t\t\t\t// When you do an express use the baseUrl is stripped from the url, so we need to add to the router each baseUrl usage.\n\t\t\t\tthis.resturaRouter(req, res, next);\n\t\t\t});\n\t\t\tfor (const route of endpoint.routes) {\n\t\t\t\troute.path = route.path.startsWith('/') ? route.path : `/${route.path}`;\n\t\t\t\troute.path = route.path.endsWith('/') ? route.path.slice(0, -1) : route.path;\n\t\t\t\tconst fullUrl = `${baseUrl}${route.path}`;\n\n\t\t\t\tif (route.roles.length === 0 && route.scopes.length === 0)\n\t\t\t\t\tthis.publicEndpoints[route.method].push(fullUrl);\n\n\t\t\t\tthis.resturaRouter[route.method.toLowerCase() as Lowercase<typeof route.method>](\n\t\t\t\t\troute.path, // <-- Notice we only use path here since the baseUrl is already added to the router.\n\t\t\t\t\tthis.executeRouteLogic as unknown as express.RequestHandler\n\t\t\t\t);\n\t\t\t\trouteCount++;\n\t\t\t}\n\t\t}\n\t\tthis.responseValidator = new ResponseValidator(this.schema);\n\n\t\tlogger.info(`Restura loaded (${routeCount}) endpoint${routeCount > 1 ? 's' : ''}`);\n\t}\n\n\tprivate async initializeGeneratedTypesFolder() {\n\t\tif (!fs.existsSync(this.resturaConfig.generatedTypesPath)) {\n\t\t\tfs.mkdirSync(this.resturaConfig.generatedTypesPath, { recursive: true });\n\t\t}\n\n\t\tthis.updateTypes();\n\t}\n\n\t@boundMethod\n\tprivate resturaAuthentication(req: express.Request, res: express.Response, next: express.NextFunction) {\n\t\tif (req.headers['x-auth-token'] !== this.resturaConfig.authToken) res.status(401).send('Unauthorized');\n\t\telse next();\n\t}\n\n\t@boundMethod\n\tprivate async previewCreateSchema(req: RsRequest<ResturaSchema>, res: express.Response) {\n\t\ttry {\n\t\t\tconst schemaDiff = await compareSchema.diffSchema(req.data, this.schema, this.psqlEngine);\n\t\t\tres.send({ data: schemaDiff });\n\t\t} catch (err) {\n\t\t\tres.status(400).send(err);\n\t\t}\n\t}\n\n\t@boundMethod\n\tprivate async updateSchema(req: RsRequest<ResturaSchema>, res: express.Response) {\n\t\ttry {\n\t\t\tthis.schema = sortObjectKeysAlphabetically(req.data);\n\t\t\tawait this.storeFileSystemSchema();\n\t\t\tawait this.reloadEndpoints();\n\t\t\tawait this.updateTypes();\n\t\t\tres.send({ data: 'success' });\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error) res.status(400).send(err.message);\n\t\t\telse res.status(400).send('Unknown error');\n\t\t}\n\t}\n\n\tprivate async updateTypes() {\n\t\tawait this.generateApiFromSchema(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'), this.schema);\n\t\tawait this.generateModelFromSchema(\n\t\t\tpath.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\tthis.schema\n\t\t);\n\t\tthis.generateResturaGlobalTypes(path.join(this.resturaConfig.generatedTypesPath, 'restura.d.ts'));\n\t}\n\n\t@boundMethod\n\tprivate async getSchema(_req: express.Request, res: express.Response) {\n\t\tres.send({ data: this.schema });\n\t}\n\n\t@boundMethod\n\tprivate async getSchemaAndTypes(_req: express.Request, res: express.Response) {\n\t\ttry {\n\t\t\tconst schema = await this.getLatestFileSystemSchema();\n\t\t\tconst apiText = await apiGenerator(schema);\n\t\t\tconst modelsText = await modelGenerator(schema);\n\t\t\tres.send({ schema, api: apiText, models: modelsText });\n\t\t} catch (err) {\n\t\t\tres.status(400).send({ error: err });\n\t\t}\n\t}\n\n\t@boundMethod\n\tprivate async getMulterFilesIfAny<T>(req: RsRequest<T>, res: RsResponse<T>, routeData: RouteData) {\n\t\tif (!req.header('content-type')?.includes('multipart/form-data')) return;\n\t\tif (!this.isCustomRoute(routeData)) return;\n\n\t\tif (!routeData.fileUploadType) {\n\t\t\tthrow new RsError('BAD_REQUEST', 'File upload type not defined for route');\n\t\t}\n\n\t\tconst multerFileUploadFunction: RequestHandler =\n\t\t\trouteData.fileUploadType === 'MULTIPLE'\n\t\t\t\t? this.multerCommonUpload.array('files')\n\t\t\t\t: this.multerCommonUpload.single('file');\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tmulterFileUploadFunction(req as unknown as express.Request, res, (err: unknown) => {\n\t\t\t\tif (err) {\n\t\t\t\t\tlogger.warn('Multer error: ' + err);\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t\tif (req.body['data']) req.body = JSON.parse(req.body['data']);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\t@boundMethod\n\tprivate async executeRouteLogic<T>(req: RsRequest<T>, res: RsResponse<T>, next: express.NextFunction) {\n\t\ttry {\n\t\t\t// Locate the route in the schema\n\t\t\tconst routeData = this.getRouteData(req.method, req.baseUrl, req.path);\n\n\t\t\t// Validate the requester has access to the endpoint\n\t\t\tthis.validateAuthorization(req, routeData);\n\n\t\t\t// Check for file uploads\n\t\t\tawait this.getMulterFilesIfAny(req, res, routeData);\n\n\t\t\t// Validate the request and assign to req.data\n\t\t\trequestValidator(req as RsRequest<unknown>, routeData, this.customTypeValidation);\n\n\t\t\t// Check for custom logic\n\t\t\tif (this.isCustomRoute(routeData)) {\n\t\t\t\tawait this.runCustomRouteLogic(req, res, routeData);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Run SQL query\n\t\t\tconst data = await this.psqlEngine.runQueryForRoute(\n\t\t\t\treq as RsRequest<unknown>,\n\t\t\t\trouteData as StandardRouteData,\n\t\t\t\tthis.schema\n\t\t\t);\n\n\t\t\t// Validate the response\n\t\t\tthis.responseValidator.validateResponseParams(data, req.baseUrl, routeData);\n\n\t\t\t// Send response\n\t\t\tif (routeData.type === 'PAGED') res.sendNoWrap(data as T);\n\t\t\telse res.sendData(data as T);\n\t\t} catch (e) {\n\t\t\tnext(e);\n\t\t}\n\t}\n\n\t@boundMethod\n\tprivate isCustomRoute(route: RouteData): route is CustomRouteData {\n\t\treturn route.type === 'CUSTOM_ONE' || route.type === 'CUSTOM_ARRAY' || route.type === 'CUSTOM_PAGED';\n\t}\n\n\t@boundMethod\n\tprivate async runCustomRouteLogic<T>(req: RsRequest<T>, res: RsResponse<T>, routeData: RouteData) {\n\t\tconst version = req.baseUrl.split('/')[2];\n\t\tlet domain = routeData.path.split('/')[1];\n\t\tdomain = domain.split('-').reduce((acc, value, index) => {\n\t\t\tif (index === 0) acc = value;\n\t\t\telse acc += StringUtils.capitalizeFirst(value);\n\t\t\treturn acc;\n\t\t}, '');\n\t\tconst customApiName = `${StringUtils.capitalizeFirst(domain)}Api${StringUtils.capitalizeFirst(version)}`;\n\n\t\tconst customApi = customApiFactory.getCustomApi(customApiName);\n\t\tif (!customApi) throw new RsError('NOT_FOUND', `API domain ${domain}-${version} not found`);\n\n\t\tconst functionName = `${routeData.method.toLowerCase()}${routeData.path\n\t\t\t.replace(new RegExp('-', 'g'), '/')\n\t\t\t.split('/')\n\t\t\t.reduce((acc, cur) => {\n\t\t\t\tif (cur === '') return acc;\n\t\t\t\treturn acc + StringUtils.capitalizeFirst(cur);\n\t\t\t}, '')}`;\n\n\t\t// @ts-expect-error - Here we are dynamically calling the function from a custom class, not sure how to typescript this\n\t\tconst customFunction = customApi[functionName] as (\n\t\t\treq: RsRequest<T>,\n\t\t\tres: RsResponse<T>,\n\t\t\trouteData: RouteData\n\t\t) => Promise<void>;\n\t\tif (!customFunction)\n\t\t\tthrow new RsError('NOT_FOUND', `API path ${routeData.path} not implemented ${functionName}`);\n\t\tawait customFunction(req, res, routeData);\n\t}\n\n\tprivate async storeFileSystemSchema() {\n\t\tconst schemaPrettyStr = await prettier.format(JSON.stringify(this.schema), {\n\t\t\tparser: 'json',\n\t\t\t...{\n\t\t\t\ttrailingComma: 'none',\n\t\t\t\ttabWidth: 4,\n\t\t\t\tuseTabs: true,\n\t\t\t\tendOfLine: 'lf',\n\t\t\t\tprintWidth: 120,\n\t\t\t\tsingleQuote: true\n\t\t\t}\n\t\t});\n\t\tfs.writeFileSync(this.resturaConfig.schemaFilePath, schemaPrettyStr);\n\t}\n\n\tprivate resetPublicEndpoints() {\n\t\tthis.publicEndpoints = {\n\t\t\tGET: [],\n\t\t\tPOST: [],\n\t\t\tPUT: [],\n\t\t\tPATCH: [],\n\t\t\tDELETE: []\n\t\t};\n\t}\n\n\tprivate validateAuthorization(req: RsRequest<unknown>, routeData: RouteData) {\n\t\tconst requesterRole = req.requesterDetails.role;\n\t\tconst requesterScopes = req.requesterDetails.scopes;\n\n\t\t// If route has no roles or scopes, it's public - allow access\n\t\tif (routeData.roles.length === 0 && routeData.scopes.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If route requires roles, check if user has the required role\n\t\tif (routeData.roles.length > 0) {\n\t\t\tif (!requesterRole || !routeData.roles.includes(requesterRole)) {\n\t\t\t\tthrow new RsError('FORBIDDEN', 'Not authorized to access this endpoint - role required');\n\t\t\t}\n\t\t}\n\n\t\t// If route requires scopes, check if user has ALL required scopes\n\t\tif (routeData.scopes.length > 0) {\n\t\t\tconst missingScopes = routeData.scopes.filter((requiredScope) => !requesterScopes.includes(requiredScope));\n\t\t\tif (missingScopes.length > 0) {\n\t\t\t\tthrow new RsError(\n\t\t\t\t\t'FORBIDDEN',\n\t\t\t\t\t`Not authorized to access this endpoint - missing required scopes: ${missingScopes.join(', ')}`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getRouteData(method: string, baseUrl: string, path: string): RouteData {\n\t\tconst endpoint = this.schema.endpoints.find((item) => {\n\t\t\treturn item.baseUrl === baseUrl;\n\t\t});\n\t\tif (!endpoint) throw new RsError('NOT_FOUND', 'Route not found');\n\t\tconst route = endpoint.routes.find((item) => {\n\t\t\treturn item.method === method && item.path === path;\n\t\t});\n\t\tif (!route) throw new RsError('NOT_FOUND', 'Route not found');\n\t\treturn route;\n\t}\n}\n\nconst restura = new ResturaEngine();\nexport { restura };\n","function _typeof(obj) { if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n\n/**\n * Return a descriptor removing the value and returning a getter\n * The getter will return a .bind version of the function\n * and memoize the result against a symbol on the instance\n */\nexport function boundMethod(target, key, descriptor) {\n var fn = descriptor.value;\n\n if (typeof fn !== 'function') {\n throw new TypeError(\"@boundMethod decorator can only be applied to methods not: \".concat(_typeof(fn)));\n } // In IE11 calling Object.defineProperty has a side-effect of evaluating the\n // getter for the property which is being replaced. This causes infinite\n // recursion and an \"Out of stack space\" error.\n\n\n var definingProperty = false;\n return {\n configurable: true,\n get: function get() {\n // eslint-disable-next-line no-prototype-builtins\n if (definingProperty || this === target.prototype || this.hasOwnProperty(key) || typeof fn !== 'function') {\n return fn;\n }\n\n var boundFn = fn.bind(this);\n definingProperty = true;\n Object.defineProperty(this, key, {\n configurable: true,\n get: function get() {\n return boundFn;\n },\n set: function set(value) {\n fn = value;\n delete this[key];\n }\n });\n definingProperty = false;\n return boundFn;\n },\n set: function set(value) {\n fn = value;\n }\n };\n}\n/**\n * Use boundMethod to bind all methods on the target.prototype\n */\n\nexport function boundClass(target) {\n // (Using reflect to get all keys including symbols)\n var keys; // Use Reflect if exists\n\n if (typeof Reflect !== 'undefined' && typeof Reflect.ownKeys === 'function') {\n keys = Reflect.ownKeys(target.prototype);\n } else {\n keys = Object.getOwnPropertyNames(target.prototype); // Use symbols if support is provided\n\n if (typeof Object.getOwnPropertySymbols === 'function') {\n keys = keys.concat(Object.getOwnPropertySymbols(target.prototype));\n }\n }\n\n keys.forEach(function (key) {\n // Ignore special case target method\n if (key === 'constructor') {\n return;\n }\n\n var descriptor = Object.getOwnPropertyDescriptor(target.prototype, key); // Only methods need binding\n\n if (typeof descriptor.value === 'function') {\n Object.defineProperty(target.prototype, key, boundMethod(target, key, descriptor));\n }\n });\n return target;\n}\nexport default function autobind() {\n if (arguments.length === 1) {\n return boundClass.apply(void 0, arguments);\n }\n\n return boundMethod.apply(void 0, arguments);\n}","import { boundMethod } from 'autobind-decorator';\nimport cloneDeep from 'lodash.clonedeep';\nimport { ResturaSchema, RouteData } from './schemas/resturaSchema.js';\nimport { PsqlEngine } from './sql/PsqlEngine.js';\nimport { SchemaChangeValue, SchemaPreview } from './types/resturaTypes.js';\n\nclass CompareSchema {\n\t@boundMethod\n\tasync diffSchema(\n\t\tnewSchema: ResturaSchema,\n\t\tlatestSchema: ResturaSchema,\n\t\tpsqlEngine: PsqlEngine\n\t): Promise<SchemaPreview> {\n\t\tconst endPoints = this.diffEndPoints(newSchema.endpoints![0].routes, latestSchema.endpoints![0].routes);\n\t\tconst globalParams = this.diffStringArray(newSchema.globalParams, latestSchema.globalParams);\n\t\tconst roles = this.diffStringArray(newSchema.roles, latestSchema.roles);\n\n\t\tlet commands = '';\n\t\tif (JSON.stringify(newSchema.database) !== JSON.stringify(latestSchema.database))\n\t\t\tcommands = await psqlEngine.diffDatabaseToSchema(newSchema);\n\n\t\tconst hasCustomTypesChanged =\n\t\t\tJSON.stringify(newSchema.customTypes) !== JSON.stringify(latestSchema.customTypes);\n\t\tconst schemaPreview: SchemaPreview = {\n\t\t\tendPoints,\n\t\t\tglobalParams,\n\t\t\troles,\n\t\t\tcommands,\n\t\t\tcustomTypes: hasCustomTypesChanged\n\t\t};\n\t\treturn schemaPreview;\n\t}\n\n\t@boundMethod\n\tprivate diffStringArray(newArray: string[], originalArray: string[]): SchemaChangeValue[] {\n\t\tconst stringsDiff: SchemaChangeValue[] = [];\n\t\tconst originalClone = new Set(originalArray);\n\t\tnewArray.forEach((item) => {\n\t\t\tconst originalIndex = originalClone.has(item);\n\t\t\tif (!originalIndex) {\n\t\t\t\tstringsDiff.push({\n\t\t\t\t\tname: item,\n\t\t\t\t\tchangeType: 'NEW'\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\toriginalClone.delete(item);\n\t\t\t}\n\t\t});\n\t\toriginalClone.forEach((item) => {\n\t\t\tstringsDiff.push({\n\t\t\t\tname: item,\n\t\t\t\tchangeType: 'DELETED'\n\t\t\t});\n\t\t});\n\t\treturn stringsDiff;\n\t}\n\n\t@boundMethod\n\tprivate diffEndPoints(newEndPoints: RouteData[], originalEndpoints: RouteData[]): SchemaChangeValue[] {\n\t\tconst originalClone = cloneDeep(originalEndpoints);\n\t\tconst diffObj: SchemaChangeValue[] = [];\n\t\tnewEndPoints.forEach((endPoint) => {\n\t\t\tconst { path, method } = endPoint;\n\t\t\tconst endPointIndex = originalClone.findIndex((original) => {\n\t\t\t\treturn original.path === endPoint.path && original.method === endPoint.method;\n\t\t\t});\n\t\t\tif (endPointIndex === -1) {\n\t\t\t\tdiffObj.push({\n\t\t\t\t\tname: `${method} ${path}`,\n\t\t\t\t\tchangeType: 'NEW'\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst original = originalClone.findIndex((original) => {\n\t\t\t\t\treturn this.compareEndPoints(endPoint, original);\n\t\t\t\t});\n\t\t\t\tif (original === -1) {\n\t\t\t\t\tdiffObj.push({\n\t\t\t\t\t\tname: `${method} ${path}`,\n\t\t\t\t\t\tchangeType: 'MODIFIED'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\toriginalClone.splice(endPointIndex, 1);\n\t\t\t}\n\t\t});\n\t\toriginalClone.forEach((original) => {\n\t\t\tconst { path, method } = original;\n\t\t\tdiffObj.push({\n\t\t\t\tname: `${method} ${path}`,\n\t\t\t\tchangeType: 'DELETED'\n\t\t\t});\n\t\t});\n\t\treturn diffObj;\n\t}\n\n\t@boundMethod\n\tprivate compareEndPoints(endPoint1: RouteData, endPoint2: RouteData): boolean {\n\t\treturn JSON.stringify(endPoint1) === JSON.stringify(endPoint2);\n\t}\n}\n\nconst compareSchema = new CompareSchema();\nexport default compareSchema;\n","import Bluebird from 'bluebird';\nimport fs from 'fs';\nimport path from 'path';\nimport { logger } from '../logger/logger.js';\nimport { FileUtils } from '@restura/internal';\n\nclass CustomApiFactory {\n\tprivate customApis: { [key: string]: { name: string } } = {};\n\n\tasync loadApiFiles(baseFolderPath: string) {\n\t\tconst apiVersions = ['v1'];\n\t\tfor (const apiVersion of apiVersions) {\n\t\t\tconst apiVersionFolderPath = path.join(baseFolderPath, apiVersion);\n\n\t\t\tconst directoryExists = await FileUtils.existDir(apiVersionFolderPath);\n\t\t\tif (!directoryExists) continue;\n\t\t\tawait this.addDirectory(apiVersionFolderPath, apiVersion);\n\t\t}\n\t}\n\n\tgetCustomApi(customApiName: string): { name: string } {\n\t\treturn this.customApis[customApiName];\n\t}\n\n\tprivate async addDirectory(directoryPath: string, apiVersion: string) {\n\t\tconst entries = await fs.promises.readdir(directoryPath, {\n\t\t\twithFileTypes: true\n\t\t});\n\t\tconst isTsx = process.argv[1]?.endsWith('.ts');\n\t\tconst isTsNode = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT;\n\t\tconst extension = isTsx || isTsNode ? 'ts' : 'js';\n\t\tconst shouldEndWith = `.api.${apiVersion}.${extension}`;\n\t\tawait Bluebird.map(entries, async (entry) => {\n\t\t\tif (entry.isFile()) {\n\t\t\t\tif (entry.name.endsWith(shouldEndWith) === false) return;\n\n\t\t\t\t// The following try / catch block fixes an issue when looking for the map file giving an exception thrown\n\t\t\t\ttry {\n\t\t\t\t\tconst importPath = `${path.join(directoryPath, entry.name)}`;\n\t\t\t\t\tconst ApiImport = await import(importPath);\n\t\t\t\t\tconst customApiClass = new ApiImport.default();\n\t\t\t\t\tlogger.info(`Registering custom API: ${ApiImport.default.name}`);\n\t\t\t\t\tthis.bindMethodsToInstance(customApiClass);\n\t\t\t\t\tthis.customApis[ApiImport.default.name] = customApiClass;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlogger.error(e);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate bindMethodsToInstance<T extends object>(instance: T): void {\n\t\tconst proto = Object.getPrototypeOf(instance);\n\t\tObject.getOwnPropertyNames(proto).forEach((key) => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst property = (instance as any)[key]; // Temporarily cast for property access\n\t\t\tif (typeof property === 'function' && key !== 'constructor') {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\t(instance as any)[key] = property.bind(instance); // Temporarily cast for binding\n\t\t\t}\n\t\t});\n\t}\n}\n\nconst customApiFactory = new CustomApiFactory();\nexport default customApiFactory;\n","import fs from 'fs';\nimport path, { resolve } from 'path';\nimport tmp from 'tmp';\nimport * as TJS from 'typescript-json-schema';\nimport { restura } from '../restura.js';\nimport { ResturaSchema } from '../schemas/resturaSchema.js';\nimport type { ValidationDictionary } from '../validators/requestValidator.js';\n\n/**\n * This function generates a temporary file with the custom types and then uses typescript-json-schema to generate a JSON schema for each custom type.\n * @param currentSchema - The current schema to generate the validation dictionary for.\n * @returns A dictionary of custom type names and their corresponding JSON schemas.\n */\nexport default function customTypeValidationGenerator(currentSchema: ResturaSchema): ValidationDictionary {\n\tconst schemaObject: ValidationDictionary = {};\n\tconst customInterfaceNames = currentSchema.customTypes\n\t\t.map((customType) => {\n\t\t\tconst matches = customType.match(/(?<=interface\\s)(\\w+)|(?<=type\\s)(\\w+)/g);\n\t\t\tif (matches && matches.length > 0) return matches[0];\n\t\t\treturn '';\n\t\t})\n\t\t.filter(Boolean);\n\tif (!customInterfaceNames) return {};\n\n\tconst temporaryFile = tmp.fileSync({ mode: 0o644, prefix: 'prefix-', postfix: '.ts' });\n\tfs.writeFileSync(temporaryFile.name, currentSchema.customTypes.join('\\n'));\n\n\tconst compilerOptions: TJS.CompilerOptions = {\n\t\tstrictNullChecks: true,\n\t\tskipLibCheck: true // Needed if we are processing ES modules\n\t};\n\n\tconst program = TJS.getProgramFromFiles(\n\t\t[\n\t\t\tresolve(temporaryFile.name),\n\t\t\tpath.join(restura.resturaConfig.generatedTypesPath, 'restura.d.ts'),\n\t\t\tpath.join(restura.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\tpath.join(restura.resturaConfig.generatedTypesPath, 'api.d.ts')\n\t\t],\n\t\tcompilerOptions\n\t);\n\tcustomInterfaceNames.forEach((item) => {\n\t\tconst ddlSchema = TJS.generateSchema(program, item, {\n\t\t\trequired: true\n\t\t});\n\t\tschemaObject[item] = ddlSchema || {};\n\t});\n\n\ttemporaryFile.removeCallback();\n\n\treturn schemaObject;\n}\n","import { NextFunction } from 'express';\nimport { RsError, type ErrorCode, type HtmlStatusCodes } from '../RsError.js';\nimport { restura } from '../restura.js';\nimport type { RsRequest, RsResponse } from '../types/customExpressTypes.js';\nimport type { RsErrorData, RsPagedResponseData } from '../types/resturaTypes.js';\n\nexport default function addApiResponseFunctions(req: RsRequest<unknown>, res: RsResponse<unknown>, next: NextFunction) {\n\t/**\n\t * Sends given data inside { data: data };\n\t */\n\tres.sendData = function (data, statusCode = 200) {\n\t\tres.status(statusCode).send({ data });\n\t};\n\n\t/**\n\t * Sends data exactly as it was given, useful for 3rd party APIs\n\t */\n\tres.sendNoWrap = function (dataNoWrap, statusCode = 200) {\n\t\tres.status(statusCode).send(dataNoWrap);\n\t};\n\n\t/**\n\t * Sends a paginated\n\t * @param pagedData - A Redsky paged object\n\t * @param statusCode\n\t */\n\tres.sendPaginated = function (pagedData: RsPagedResponseData<unknown>, statusCode = 200) {\n\t\tres.status(statusCode).send({ data: pagedData.data, total: pagedData.total });\n\t};\n\n\t/**\n\t * Sends a RedSky RsErrorData\n\t */\n\tres.sendError = function (shortError: ErrorCode, msg: string, htmlStatusCode?: HtmlStatusCodes, stack?: string) {\n\t\tif (htmlStatusCode === undefined) {\n\t\t\tif (RsError.htmlStatus(shortError) !== undefined) {\n\t\t\t\thtmlStatusCode = RsError.htmlStatus(shortError);\n\t\t\t} else {\n\t\t\t\thtmlStatusCode = 500;\n\t\t\t}\n\t\t}\n\n\t\tconst errorData: RsErrorData = {\n\t\t\terr: shortError,\n\t\t\tmsg,\n\t\t\t...(restura.resturaConfig.sendErrorStackTrace && stack ? { stack } : {})\n\t\t};\n\t\tres.status(htmlStatusCode as number).send(errorData);\n\t};\n\n\tnext();\n}\n","import type { NextFunction } from 'express';\nimport type { RsRequest, RsResponse } from '../types/customExpressTypes.js';\nimport type { AuthenticateHandler, AuthenticatedRequesterDetails } from '../types/resturaTypes.js';\n\nexport function authenticateRequester(applicationAuthenticateHandler: AuthenticateHandler) {\n\treturn (req: RsRequest, res: RsResponse, next: NextFunction) => {\n\t\t// Call the custom function from the main application and get the role and other details\n\t\tapplicationAuthenticateHandler(req, res, (authenticatedRequesterDetails: AuthenticatedRequesterDetails) => {\n\t\t\treq.requesterDetails = { host: req.hostname, ipAddress: req.ip || '', ...authenticatedRequesterDetails };\n\t\t\tnext();\n\t\t});\n\t};\n}\n","import { Request } from 'express';\nimport multer from 'multer';\nimport * as os from 'os';\nimport { extname } from 'path';\n\nconst OneHundredMB = 100 * 1024 * 1024;\nlet commonUpload: multer.Multer | null = null;\nexport const getMulterUpload = (directory?: string) => {\n\tif (commonUpload) return commonUpload;\n\tconst storage = multer.diskStorage({\n\t\tdestination: directory || os.tmpdir(),\n\t\tfilename: function (\n\t\t\trequest: Request,\n\t\t\tfile: Express.Multer.File,\n\t\t\tcb: (err: Error | null, success: string) => void\n\t\t) {\n\t\t\tconst extension = extname(file.originalname);\n\t\t\tconst uniqueName = Date.now() + '-' + Math.round(Math.random() * 1000);\n\t\t\tcb(null, `${uniqueName}${extension}`);\n\t\t}\n\t});\n\n\tcommonUpload = multer({\n\t\tstorage,\n\t\tlimits: {\n\t\t\tfileSize: OneHundredMB\n\t\t}\n\t});\n\treturn commonUpload;\n};\n","import { z } from 'zod';\nimport { logger } from '../../logger/logger.js';\nimport { validatorDataSchema } from './validatorDataSchema.js';\n\n// Zod schemas with strict mode\nconst orderBySchema = z\n\t.object({\n\t\tcolumnName: z.string(),\n\t\torder: z.enum(['ASC', 'DESC']),\n\t\ttableName: z.string()\n\t})\n\t.strict();\n\nexport type OrderByData = z.infer<typeof orderBySchema>;\n\nconst groupBySchema = z\n\t.object({\n\t\tcolumnName: z.string(),\n\t\ttableName: z.string()\n\t})\n\t.strict();\n\nexport type GroupByData = z.infer<typeof groupBySchema>;\n\nconst whereDataSchema = z\n\t.object({\n\t\ttableName: z.string().optional(),\n\t\tcolumnName: z.string().optional(),\n\t\toperator: z\n\t\t\t.enum([\n\t\t\t\t'=',\n\t\t\t\t'<',\n\t\t\t\t'>',\n\t\t\t\t'<=',\n\t\t\t\t'>=',\n\t\t\t\t'!=',\n\t\t\t\t'LIKE',\n\t\t\t\t'NOT LIKE',\n\t\t\t\t'IN',\n\t\t\t\t'NOT IN',\n\t\t\t\t'STARTS WITH',\n\t\t\t\t'ENDS WITH',\n\t\t\t\t'IS',\n\t\t\t\t'IS NOT'\n\t\t\t])\n\t\t\t.optional(),\n\t\tvalue: z.string().or(z.number()).optional(),\n\t\tcustom: z.string().optional(),\n\t\tconjunction: z.enum(['AND', 'OR']).optional()\n\t})\n\t.strict();\n\nexport type WhereData = z.infer<typeof whereDataSchema>;\n\nconst assignmentDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tvalue: z.string()\n\t})\n\t.strict();\n\nexport type AssignmentData = z.infer<typeof assignmentDataSchema>;\n\nconst joinDataSchema = z\n\t.object({\n\t\ttable: z.string(),\n\t\tlocalTable: z.string().optional(), // Defaults to base table if not specificed\n\t\tlocalTableAlias: z.string().optional(), // If we are joining a table off of a previous join, this is the alias of the previous join\n\t\tlocalColumnName: z.string().optional(),\n\t\tforeignColumnName: z.string().optional(),\n\t\tcustom: z.string().optional(),\n\t\ttype: z.enum(['LEFT', 'INNER', 'RIGHT']),\n\t\talias: z.string()\n\t})\n\t.strict();\n\nexport type JoinData = z.infer<typeof joinDataSchema>;\n\nconst requestDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\trequired: z.boolean(),\n\t\tisNullable: z.boolean().optional(),\n\t\tvalidator: z.array(validatorDataSchema)\n\t})\n\t.strict();\n\nexport type RequestData = z.infer<typeof requestDataSchema>;\n\nconst responseDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tselector: z.string().optional(),\n\t\tsubquery: z\n\t\t\t.object({\n\t\t\t\ttable: z.string(),\n\t\t\t\tjoins: z.array(joinDataSchema),\n\t\t\t\twhere: z.array(whereDataSchema),\n\t\t\t\tget properties() {\n\t\t\t\t\treturn z.array(responseDataSchema);\n\t\t\t\t},\n\t\t\t\tgroupBy: groupBySchema.optional(),\n\t\t\t\torderBy: orderBySchema.optional()\n\t\t\t})\n\t\t\t.optional(),\n\t\ttype: z.string().optional() // Type allows you to override the type of the response, used in custom selectors\n\t})\n\t.strict();\n\nexport type ResponseData = z.infer<typeof responseDataSchema>;\n\nconst routeDataBaseSchema = z\n\t.object({\n\t\tmethod: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),\n\t\tname: z.string(),\n\t\tdescription: z.string(),\n\t\tpath: z.string(),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string())\n\t})\n\t.strict();\n\nexport type RouteDataBase = z.infer<typeof routeDataBaseSchema>;\n\nconst standardRouteSchema = routeDataBaseSchema\n\t.extend({\n\t\ttype: z.enum(['ONE', 'ARRAY', 'PAGED']),\n\t\ttable: z.string(),\n\t\tjoins: z.array(joinDataSchema),\n\t\tassignments: z.array(assignmentDataSchema),\n\t\twhere: z.array(whereDataSchema),\n\t\trequest: z.array(requestDataSchema),\n\t\tresponse: z.array(responseDataSchema),\n\t\tgroupBy: groupBySchema.optional(),\n\t\torderBy: orderBySchema.optional()\n\t})\n\t.strict();\n\nexport type StandardRouteData = z.infer<typeof standardRouteSchema>;\n\nconst customRouteSchema = routeDataBaseSchema\n\t.extend({\n\t\ttype: z.enum(['CUSTOM_ONE', 'CUSTOM_ARRAY', 'CUSTOM_PAGED']),\n\t\tresponseType: z.union([z.string(), z.enum(['string', 'number', 'boolean'])]),\n\t\trequestType: z.string().optional(),\n\t\trequest: z.array(requestDataSchema).optional(),\n\t\tfileUploadType: z.enum(['SINGLE', 'MULTIPLE']).optional()\n\t})\n\t.strict();\n\nexport type CustomRouteData = z.infer<typeof customRouteSchema>;\n\nexport type RouteData = CustomRouteData | StandardRouteData;\n\nexport const postgresColumnNumericTypesSchema = z.enum([\n\t'SMALLINT', // 2 bytes, -32,768 to 32,767\n\t'INTEGER', // 4 bytes, -2,147,483,648 to 2,147,483,647\n\t'BIGINT', // 8 bytes, -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807\n\t'DECIMAL', // user-specified precision, exact numeric, this is returned as a string type because numbers are not accurate enough\n\t'NUMERIC', // same as DECIMAL\n\t'REAL', // 4 bytes, 6 decimal digits precision (single precision)\n\t'DOUBLE PRECISION', // 8 bytes, 15 decimal digits precision (double precision)\n\t'SERIAL', // auto-incrementing integer\n\t'BIGSERIAL' // auto-incrementing big integer\n]);\nexport type PostgresColumnNumericTypes = z.infer<typeof postgresColumnNumericTypesSchema>;\n\nexport const postgresColumnStringTypesSchema = z.enum([\n\t'CHAR', // fixed-length, blank-padded\n\t'VARCHAR', // variable-length with limit\n\t'TEXT', // variable-length without limit\n\t'BYTEA' // binary data\n]);\nexport type PostgresColumnStringTypes = z.infer<typeof postgresColumnStringTypesSchema>;\n\nexport const postgresColumnDateTypesSchema = z.enum([\n\t'DATE', // calendar date (year, month, day)\n\t'TIMESTAMP', // both date and time (without time zone)\n\t'TIMESTAMPTZ', // both date and time (with time zone)\n\t'TIME', // time of day (without time zone)\n\t'INTERVAL' // time span\n]);\nexport type PostgresColumnDateTypes = z.infer<typeof postgresColumnDateTypesSchema>;\n\nexport const postgresColumnJsonTypesSchema = z.enum([\n\t'JSON', // stores JSON data as raw text\n\t'JSONB' // stores JSON data in a binary format, optimized for query performance\n]);\nexport type PostgresColumnJsonTypes = z.infer<typeof postgresColumnJsonTypesSchema>;\n\nexport const mariaDbColumnNumericTypesSchema = z.enum([\n\t'BOOLEAN', // 1-byte A synonym for \"TINYINT(1)\". Supported from version 1.2.0 onwards.\n\t'TINYINT', // 1-byte A very small integer. Numeric value with scale 0. Signed: -126 to +127. Unsigned: 0 to 253.\n\t'SMALLINT', // 2-bytes A small integer. Signed: -32,766 to 32,767. Unsigned: 0 to 65,533.\n\t'MEDIUMINT', // 3-bytes A medium integer. Signed: -8388608 to 8388607. Unsigned: 0 to 16777215. Supported starting with MariaDB ColumnStore 1.4.2.\n\t'INTEGER', // 4-bytes A normal-size integer. Numeric value with scale 0. Signed: -2,147,483,646 to 2,147,483,647. Unsigned: 0 to 4,294,967,293\n\t'BIGINT', // 8-bytes A large integer. Numeric value with scale 0. Signed: -9,223,372,036,854,775,806 to +9,223,372,036,854,775,807 Unsigned: 0 to +18,446,744,073,709,551,613\n\t'DECIMAL', // 2, 4, or 8 bytes A packed fixed-point number that can have a specific total number of digits and with a set number of digits after a decimal. The maximum precision (total number of digits) that can be specified is 18.\n\t'FLOAT', // 4 bytes Stored in 32-bit IEEE-754 floating point format. As such, the number of significant digits is about 6, and the range of values is approximately +/- 1e38.\n\t'DOUBLE' // 8 bytes Stored in 64-bit IEEE-754 floating point format. As such, the number of significant digits is about 15 and the range of values is approximately +/-1e308.\n]);\nexport type MariaDbColumnNumericTypes = z.infer<typeof mariaDbColumnNumericTypesSchema>;\n\nexport const mariaDbColumnStringTypesSchema = z.enum([\n\t'CHAR', // 1, 2, 4, or 8 bytes Holds letters and special characters of fixed length. Max length is 255. Default and minimum size is 1 byte.\n\t'VARCHAR', // 1, 2, 4, or 8 bytes or 8-byte token Holds letters, numbers, and special characters of variable length. Max length = 8000 bytes or characters and minimum length = 1 byte or character.\n\t'TINYTEXT', // 255 bytes Holds a small amount of letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'TINYBLOB', // 255 bytes Holds a small amount of binary data of variable length. Supported from version 1.1.0 onwards.\n\t'TEXT', // 64 KB Holds letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'BLOB', // 64 KB Holds binary data of variable length. Supported from version 1.1.0 onwards.\n\t'MEDIUMTEXT', // 16 MB Holds a medium amount of letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'MEDIUMBLOB', // 16 MB Holds a medium amount of binary data of variable length. Supported from version 1.1.0 onwards.\n\t'LONGTEXT', // 1.96 GB Holds a large amount of letters, numbers, and special characters of variable length. Supported from version 1.1.0 onwards.\n\t'JSON', // Alias for LONGTEXT, creates a CONSTRAINT for JSON_VALID, holds a JSON-formatted string of plain text.\n\t'LONGBLOB', // 1.96 GB Holds a large amount of binary data of variable length. Supported from version 1.1.0 onwards.\n\t'ENUM' // Enum type\n]);\nexport type MariaDbColumnStringTypes = z.infer<typeof mariaDbColumnStringTypesSchema>;\n\n// MariaDbColumnDateTypes Zod enum with PascalCase values and comments\nexport const mariaDbColumnDateTypesSchema = z.enum([\n\t'DATE', // 4-bytes Date has year, month, and day.\n\t'DATETIME', // 8-bytes A date and time combination. Supported range is 1000-01-01 00:00:00 to 9999-12-31 23:59:59. From version 1.2.0 microseconds are also supported.\n\t'TIME', // 8-bytes Holds hour, minute, second and optionally microseconds for time.\n\t'TIMESTAMP' // 4-bytes Values are stored as the number of seconds since 1970-01-01 00:00:00 UTC, and optionally microseconds.\n]);\nexport type MariaDbColumnDateTypes = z.infer<typeof mariaDbColumnDateTypesSchema>;\n\n// Define the ColumnData schema\nconst columnDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\ttype: z.union([\n\t\t\tpostgresColumnNumericTypesSchema,\n\t\t\tpostgresColumnStringTypesSchema,\n\t\t\tpostgresColumnDateTypesSchema,\n\t\t\tpostgresColumnJsonTypesSchema,\n\t\t\tmariaDbColumnNumericTypesSchema,\n\t\t\tmariaDbColumnStringTypesSchema,\n\t\t\tmariaDbColumnDateTypesSchema\n\t\t]),\n\t\tisNullable: z.boolean(),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string()),\n\t\tcomment: z.string().optional(),\n\t\tdefault: z.string().optional(),\n\t\tvalue: z.string().optional(),\n\t\tisPrimary: z.boolean().optional(),\n\t\tisUnique: z.boolean().optional(),\n\t\thasAutoIncrement: z.boolean().optional(),\n\t\tlength: z.number().optional()\n\t})\n\t.strict();\n\nexport type ColumnData = z.infer<typeof columnDataSchema>;\n\nconst indexDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcolumns: z.array(z.string()),\n\t\tisUnique: z.boolean(),\n\t\tisPrimaryKey: z.boolean(),\n\t\torder: z.enum(['ASC', 'DESC'])\n\t})\n\t.strict();\n\nexport type IndexData = z.infer<typeof indexDataSchema>;\n\n// ForeignKeyActions Zod enum with PascalCase values\nexport const foreignKeyActionsSchema = z.enum([\n\t'CASCADE', // CASCADE action for foreign keys\n\t'SET NULL', // SET NULL action for foreign keys\n\t'RESTRICT', // RESTRICT action for foreign keys\n\t'NO ACTION', // NO ACTION for foreign keys\n\t'SET DEFAULT' // SET DEFAULT action for foreign keys\n]);\nexport type ForeignKeyActions = z.infer<typeof foreignKeyActionsSchema>;\n\nconst foreignKeyDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcolumn: z.string(),\n\t\trefTable: z.string(),\n\t\trefColumn: z.string(),\n\t\tonDelete: foreignKeyActionsSchema,\n\t\tonUpdate: foreignKeyActionsSchema\n\t})\n\t.strict();\n\nexport type ForeignKeyData = z.infer<typeof foreignKeyDataSchema>;\n\nconst checkConstraintDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcheck: z.string()\n\t})\n\t.strict();\n\nexport type CheckConstraintData = z.infer<typeof checkConstraintDataSchema>;\n\nconst tableDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tcolumns: z.array(columnDataSchema),\n\t\tindexes: z.array(indexDataSchema),\n\t\tforeignKeys: z.array(foreignKeyDataSchema),\n\t\tcheckConstraints: z.array(checkConstraintDataSchema),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string()),\n\t\tnotify: z.union([z.literal('ALL'), z.array(z.string())]).optional()\n\t})\n\t.strict();\n\nexport type TableData = z.infer<typeof tableDataSchema>;\n\nconst endpointDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\tdescription: z.string(),\n\t\tbaseUrl: z.string(),\n\t\troutes: z.array(z.union([standardRouteSchema, customRouteSchema]))\n\t})\n\t.strict();\n\nexport type EndpointData = z.infer<typeof endpointDataSchema>;\n\n// The full Schema schema\nexport const resturaSchema = z\n\t.object({\n\t\tdatabase: z.array(tableDataSchema),\n\t\tendpoints: z.array(endpointDataSchema),\n\t\tglobalParams: z.array(z.string()),\n\t\troles: z.array(z.string()),\n\t\tscopes: z.array(z.string()),\n\t\tcustomTypes: z.array(z.string())\n\t})\n\t.strict();\n\nexport type ResturaSchema = z.infer<typeof resturaSchema>;\n\nexport async function isSchemaValid(schemaToCheck: unknown): Promise<boolean> {\n\ttry {\n\t\tresturaSchema.parse(schemaToCheck);\n\t\treturn true;\n\t} catch (error: unknown) {\n\t\tif (error instanceof z.ZodError) {\n\t\t\tlogger.error('Schema failed to validate with the following error:');\n\t\t\tconsole.error(z.prettifyError(error));\n\t\t} else {\n\t\t\tlogger.error(error);\n\t\t}\n\t\treturn false;\n\t}\n}\n","import { z } from 'zod';\n// created this to break up the restura.schema.ts file (running into dependency issues.)\nexport const validatorDataSchemeValue = z.union([z.string(), z.array(z.string()), z.number(), z.array(z.number())]);\nexport type ValidatorDataSchemeValue = z.infer<typeof validatorDataSchemeValue>;\n\nexport const validatorDataSchema = z\n\t.object({\n\t\ttype: z.enum(['TYPE_CHECK', 'MIN', 'MAX', 'ONE_OF']),\n\t\tvalue: validatorDataSchemeValue\n\t})\n\t.strict();\n\nexport type ValidatorData = z.infer<typeof validatorDataSchema>;\n","import { ObjectUtils } from '@redskytech/core-utils';\nimport jsonschema, { Schema } from 'jsonschema';\nimport { Definition } from 'typescript-json-schema';\nimport { z } from 'zod';\nimport { RsError } from '../RsError.js';\nimport { RequestData, RouteData } from '../schemas/resturaSchema.js';\nimport { ValidatorData, ValidatorDataSchemeValue, validatorDataSchemeValue } from '../schemas/validatorDataSchema.js';\nimport type { DynamicObject, RsRequest } from '../types/customExpressTypes.js';\nimport { addQuotesToStrings } from '../utils/utils.js';\n\nexport interface ValidationDictionary {\n\t[Key: string]: Definition;\n}\n\nexport default function requestValidator(\n\treq: RsRequest<unknown>,\n\trouteData: RouteData,\n\tvalidationSchema: ValidationDictionary\n) {\n\tconst requestData = getRequestData(req as RsRequest<unknown>);\n\treq.data = requestData;\n\n\tif (routeData.request === undefined) {\n\t\tif (routeData.type !== 'CUSTOM_ONE' && routeData.type !== 'CUSTOM_ARRAY' && routeData.type !== 'CUSTOM_PAGED')\n\t\t\tthrow new RsError('BAD_REQUEST', `No request parameters provided for standard request.`);\n\n\t\tif (!routeData.responseType) throw new RsError('BAD_REQUEST', `No response type defined for custom request.`);\n\n\t\tif (!routeData.requestType) throw new RsError('BAD_REQUEST', `No request type defined for custom request.`);\n\n\t\tconst currentInterface = validationSchema[routeData.requestType];\n\t\tconst validator = new jsonschema.Validator();\n\n\t\t// Create strict schema that doesn't allow extra properties\n\t\tconst strictSchema = {\n\t\t\t...currentInterface,\n\t\t\tadditionalProperties: false\n\t\t};\n\n\t\tconst executeValidation = validator.validate(req.data, strictSchema as Schema);\n\t\tif (!executeValidation.valid) {\n\t\t\tthrow new RsError(\n\t\t\t\t'BAD_REQUEST',\n\t\t\t\t`Request custom setup has failed the following check: (${executeValidation.errors})`\n\t\t\t);\n\t\t}\n\t\treturn;\n\t}\n\n\t// Make sure all passed in params are defined in the schema\n\tObject.keys(req.data as object).forEach((requestParamName) => {\n\t\tconst requestParam = routeData.request!.find((param) => param.name === requestParamName);\n\t\tif (!requestParam) {\n\t\t\tthrow new RsError('BAD_REQUEST', `Request param (${requestParamName}) is not allowed`);\n\t\t}\n\t});\n\n\trouteData.request.forEach((requestParam) => {\n\t\t// Find the request param in the request data\n\t\tconst requestValue = requestData[requestParam.name];\n\t\t// If the request param is required and not found in the request data, throw an error\n\t\tif (requestParam.required && requestValue === undefined)\n\t\t\tthrow new RsError('BAD_REQUEST', `Request param (${requestParam.name}) is required but missing`);\n\t\telse if (!requestParam.required && requestValue === undefined) return;\n\n\t\tvalidateRequestSingleParam(requestValue, requestParam);\n\t});\n}\n\nfunction validateRequestSingleParam(requestValue: unknown, requestParam: RequestData) {\n\tif (requestParam.isNullable && requestValue === null) return;\n\n\trequestParam.validator.forEach((validator) => {\n\t\tswitch (validator.type) {\n\t\t\tcase 'TYPE_CHECK':\n\t\t\t\tperformTypeCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t\tcase 'MIN':\n\t\t\t\tperformMinCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t\tcase 'MAX':\n\t\t\t\tperformMaxCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t\tcase 'ONE_OF':\n\t\t\t\tperformOneOfCheck(requestValue, validator, requestParam.name);\n\t\t\t\tbreak;\n\t\t}\n\t});\n}\n\nfunction isValidType(type: ValidatorDataSchemeValue, requestValue: unknown): boolean {\n\ttry {\n\t\texpectValidType(type, requestValue);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction expectValidType(type: ValidatorDataSchemeValue, requestValue: unknown) {\n\tif (type === 'number') {\n\t\treturn z.number().parse(requestValue);\n\t}\n\tif (type === 'string') {\n\t\treturn z.string().parse(requestValue);\n\t}\n\tif (type === 'boolean') {\n\t\treturn z.boolean().parse(requestValue);\n\t}\n\tif (type === 'string[]') {\n\t\treturn z.array(z.string()).parse(requestValue);\n\t}\n\tif (type === 'number[]') {\n\t\treturn z.array(z.number()).parse(requestValue);\n\t}\n\tif (type === 'any[]') {\n\t\treturn z.array(z.any()).parse(requestValue);\n\t}\n\tif (type === 'object') {\n\t\treturn z.object({}).strict().parse(requestValue);\n\t}\n}\n\nexport function performTypeCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\tif (!isValidType(validator.value, requestValue)) {\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${addQuotesToStrings(requestValue)}) is not of type (${validator.value})`\n\t\t);\n\t}\n\ttry {\n\t\tvalidatorDataSchemeValue.parse(validator.value);\n\t} catch {\n\t\tthrow new RsError('SCHEMA_ERROR', `Schema validator value (${validator.value}) is not a valid type`);\n\t}\n}\n\nfunction expectOnlyNumbers(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\tif (!isValueNumber(requestValue))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not of type number`\n\t\t);\n\n\tif (!isValueNumber(validator.value))\n\t\tthrow new RsError('SCHEMA_ERROR', `Schema validator value (${validator.value} is not of type number`);\n}\n\nfunction performMinCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\texpectOnlyNumbers(requestValue, validator, requestParamName);\n\tif ((requestValue as number) < (validator.value as number))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is less than (${validator.value})`\n\t\t);\n}\n\nfunction performMaxCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\texpectOnlyNumbers(requestValue, validator, requestParamName);\n\tif ((requestValue as number) > (validator.value as number))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is more than (${validator.value})`\n\t\t);\n}\n\nfunction performOneOfCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\tif (!ObjectUtils.isArrayWithData(validator.value as unknown[]))\n\t\tthrow new RsError('SCHEMA_ERROR', `Schema validator value (${validator.value}) is not of type array`);\n\tif (typeof requestValue === 'object')\n\t\tthrow new RsError('BAD_REQUEST', `Request param (${requestParamName}) is not of type string or number`);\n\n\tif (!(validator.value as unknown[]).includes(requestValue as string | number))\n\t\tthrow new RsError(\n\t\t\t'BAD_REQUEST',\n\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not one of (${(\n\t\t\t\tvalidator.value as unknown[]\n\t\t\t).join(', ')})`\n\t\t);\n}\n\nfunction isValueNumber(value: unknown): value is number {\n\treturn !isNaN(Number(value));\n}\n\nexport function getRequestData(req: RsRequest<unknown>): DynamicObject {\n\tlet body = '';\n\tif (req.method === 'GET' || req.method === 'DELETE') {\n\t\tbody = 'query';\n\t} else {\n\t\tbody = 'body';\n\t}\n\n\tconst bodyData = req[body as keyof typeof req]; // Cast once and store in a variable\n\n\tif (bodyData && body === 'query') {\n\t\tconst normalizedData: DynamicObject = {};\n\n\t\tfor (const attr in bodyData) {\n\t\t\tif (attr.includes('[]') && !(bodyData[attr] instanceof Array)) {\n\t\t\t\tbodyData[attr] = [bodyData[attr]];\n\t\t\t}\n\n\t\t\t// Remove [] from the key if it exists\n\t\t\tconst cleanAttr = attr.replace(/\\[\\]$/, '');\n\n\t\t\tif (bodyData[attr] instanceof Array) {\n\t\t\t\tconst parsedList = bodyData[attr].map((value: unknown) => {\n\t\t\t\t\tif (value === 'true') return true;\n\t\t\t\t\tif (value === 'false') return false;\n\t\t\t\t\tif (value === undefined) return undefined;\n\t\t\t\t\tif (value === '') return '';\n\t\t\t\t\tconst parsed = ObjectUtils.safeParse(value);\n\t\t\t\t\treturn isNaN(Number(parsed)) ? parsed : Number(parsed);\n\t\t\t\t});\n\n\t\t\t\tnormalizedData[cleanAttr] = parsedList;\n\t\t\t} else {\n\t\t\t\tlet value = bodyData[attr];\n\t\t\t\tif (value === 'true') {\n\t\t\t\t\tvalue = true;\n\t\t\t\t} else if (value === 'false') {\n\t\t\t\t\tvalue = false;\n\t\t\t\t} else if (value === undefined) {\n\t\t\t\t\tvalue = undefined;\n\t\t\t\t} else if (value === '') {\n\t\t\t\t\tvalue = '';\n\t\t\t\t} else {\n\t\t\t\t\tvalue = ObjectUtils.safeParse(value);\n\t\t\t\t\tif (!isNaN(Number(value))) {\n\t\t\t\t\t\tvalue = Number(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnormalizedData[cleanAttr] = value;\n\t\t\t}\n\t\t}\n\n\t\treturn normalizedData;\n\t}\n\n\treturn bodyData;\n}\n","import type { DynamicObject } from '../types/customExpressTypes.js';\n\ntype QuotedValue = string | QuotedValue[] | Exclude<unknown, string | unknown[]>;\n\nexport function addQuotesToStrings(variable: unknown): QuotedValue {\n\tif (typeof variable === 'string') {\n\t\treturn `'${variable}'`;\n\t} else if (Array.isArray(variable)) {\n\t\tconst arrayWithQuotes = variable.map(addQuotesToStrings);\n\t\treturn arrayWithQuotes;\n\t} else {\n\t\treturn variable;\n\t}\n}\n\nexport function sortObjectKeysAlphabetically<T>(obj: T): T {\n\tif (Array.isArray(obj)) {\n\t\t// If the value is an array, recurse for each element\n\t\treturn obj.map(sortObjectKeysAlphabetically) as T;\n\t} else if (obj !== null && typeof obj === 'object') {\n\t\t// If the value is an object, sort its keys\n\t\treturn Object.keys(obj)\n\t\t\t.sort()\n\t\t\t.reduce((sorted: DynamicObject, key: string) => {\n\t\t\t\tsorted[key] = sortObjectKeysAlphabetically((obj as Record<string, T>)[key]);\n\t\t\t\treturn sorted;\n\t\t\t}, {}) as T;\n\t}\n\t// If the value is a primitive, return it as-is\n\treturn obj;\n}\n","import type { NextFunction } from 'express';\nimport { logger } from '../../logger/logger.js';\nimport { HtmlStatusCodes } from '../RsError.js';\nimport { resturaSchema } from '../schemas/resturaSchema.js';\nimport type { RsRequest, RsResponse } from '../types/customExpressTypes.js';\nimport { getRequestData } from '../validators/requestValidator.js';\n\nexport async function schemaValidation(req: RsRequest<unknown>, res: RsResponse<unknown>, next: NextFunction) {\n\treq.data = getRequestData(req as RsRequest<unknown>);\n\n\ttry {\n\t\tresturaSchema.parse(req.data);\n\t\tnext();\n\t} catch (error) {\n\t\tlogger.error(error);\n\t\tres.sendError('BAD_REQUEST', error as string, HtmlStatusCodes.BAD_REQUEST);\n\t}\n}\n","import { z } from 'zod';\n\nconst isTsx = process.argv[1]?.endsWith('.ts');\nconst isTsNode = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT;\nconst customApiFolderPath = isTsx || isTsNode ? '/src/api' : '/dist/api';\n\nexport const resturaConfigSchema = z.object({\n\tauthToken: z.string().min(1, 'Missing Restura Auth Token'),\n\tsendErrorStackTrace: z.boolean().default(false),\n\tschemaFilePath: z.string().default(process.cwd() + '/restura.schema.json'),\n\tcustomApiFolderPath: z.string().default(process.cwd() + customApiFolderPath),\n\tgeneratedTypesPath: z.string().default(process.cwd() + '/src/@types'),\n\tfileTempCachePath: z.string().optional(),\n\tscratchDatabaseSuffix: z.string().optional()\n});\nexport type ResturaConfigSchema = z.infer<typeof resturaConfigSchema>;\n","import { ObjectUtils } from '@redskytech/core-utils';\nimport getDiff from '@wmfs/pg-diff-sync';\nimport pgInfo from '@wmfs/pg-info';\nimport type { Client as ClientType } from 'pg';\nimport pg from 'pg';\nimport { logger } from '../../logger/logger.js';\nimport { RsError } from '../RsError.js';\nimport eventManager, { MutationType, TriggerResult } from '../eventManager.js';\nimport {\n\tCustomRouteData,\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tStandardRouteData,\n\tWhereData,\n\ttype ColumnData\n} from '../schemas/resturaSchema.js';\nimport { DynamicObject, RequesterDetails, RsRequest } from '../types/customExpressTypes.js';\nimport { PageQuery } from '../types/resturaTypes.js';\nimport { PsqlPool } from './PsqlPool.js';\nimport { escapeColumnName, insertObjectQuery, SQL, updateObjectQuery } from './PsqlUtils.js';\nimport SqlEngine from './SqlEngine.js';\nimport { SqlUtils } from './SqlUtils.js';\nimport filterPsqlParser from './filterPsqlParser.js';\nconst { Client, types } = pg;\n\nconst systemUser: RequesterDetails = {\n\trole: '',\n\tscopes: [],\n\thost: '',\n\tipAddress: '',\n\tisSystemUser: true\n};\n\nexport class PsqlEngine extends SqlEngine {\n\tsetupTriggerListeners: Promise<void> | undefined;\n\tprivate triggerClient: ClientType | undefined;\n\tprivate scratchDbName: string = '';\n\tprivate reconnectAttempts = 0;\n\tprivate readonly MAX_RECONNECT_ATTEMPTS = 5;\n\tprivate readonly INITIAL_RECONNECT_DELAY = 5000; // 5 seconds\n\n\tconstructor(\n\t\tprivate psqlConnectionPool: PsqlPool,\n\t\tshouldListenForDbTriggers: boolean = false,\n\t\tscratchDatabaseSuffix: string = ''\n\t) {\n\t\tsuper();\n\n\t\tthis.setupPgReturnTypes();\n\t\tif (shouldListenForDbTriggers) {\n\t\t\tthis.setupTriggerListeners = this.listenForDbTriggers();\n\t\t}\n\n\t\tthis.scratchDbName = `${psqlConnectionPool.poolConfig.database}_scratch${scratchDatabaseSuffix ? `_${scratchDatabaseSuffix}` : ''}`;\n\t}\n\tasync close() {\n\t\tif (this.triggerClient) {\n\t\t\tawait this.triggerClient.end();\n\t\t}\n\t}\n\n\tprivate setupPgReturnTypes() {\n\t\t// OID for timestamptz in Postgres\n\t\tconst TIMESTAMPTZ_OID = 1184;\n\t\t// Set a custom parser for timestamptz to return an ISO string\n\t\ttypes.setTypeParser(TIMESTAMPTZ_OID, (val) => {\n\t\t\treturn val === null ? null : new Date(val).toISOString();\n\t\t});\n\t\tconst BIGINT_OID = 20;\n\t\t// Set a custom parser for BIGINT to return a JavaScript Number\n\t\ttypes.setTypeParser(BIGINT_OID, (val) => {\n\t\t\treturn val === null ? null : Number(val);\n\t\t});\n\t}\n\n\tprivate async reconnectTriggerClient() {\n\t\tif (this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) {\n\t\t\tlogger.error('Max reconnection attempts reached for trigger client. Stopping reconnection attempts.');\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.triggerClient) {\n\t\t\ttry {\n\t\t\t\tawait this.triggerClient.end();\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(`Error closing trigger client: ${error}`);\n\t\t\t}\n\t\t}\n\n\t\t// Exponential backoff: 5s, 10s, 20s, 40s, 80s\n\t\tconst delay = this.INITIAL_RECONNECT_DELAY * Math.pow(2, this.reconnectAttempts);\n\t\tlogger.info(\n\t\t\t`Attempting to reconnect trigger client in ${delay / 1000} seconds... (Attempt ${this.reconnectAttempts + 1}/${this.MAX_RECONNECT_ATTEMPTS})`\n\t\t);\n\n\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\n\t\tthis.reconnectAttempts++;\n\n\t\ttry {\n\t\t\tawait this.listenForDbTriggers();\n\t\t\t// Reset reconnect attempts on successful connection\n\t\t\tthis.reconnectAttempts = 0;\n\t\t} catch (error) {\n\t\t\tlogger.error(`Reconnection attempt ${this.reconnectAttempts} failed: ${error}`);\n\t\t\tif (this.reconnectAttempts < this.MAX_RECONNECT_ATTEMPTS) {\n\t\t\t\tawait this.reconnectTriggerClient();\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async listenForDbTriggers() {\n\t\tthis.triggerClient = new Client({\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tdatabase: this.psqlConnectionPool.poolConfig.database,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port,\n\t\t\tconnectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis\n\t\t});\n\n\t\ttry {\n\t\t\tawait this.triggerClient.connect();\n\n\t\t\tconst promises = [];\n\t\t\tpromises.push(this.triggerClient.query('LISTEN insert'));\n\t\t\tpromises.push(this.triggerClient.query('LISTEN update'));\n\t\t\tpromises.push(this.triggerClient.query('LISTEN delete'));\n\t\t\tawait Promise.all(promises);\n\n\t\t\t// Add error handling for the connection\n\t\t\tthis.triggerClient.on('error', async (error) => {\n\t\t\t\tlogger.error(`Trigger client error: ${error}`);\n\t\t\t\t// Attempt to reconnect\n\t\t\t\tawait this.reconnectTriggerClient();\n\t\t\t});\n\n\t\t\t// Handle notifications\n\t\t\tthis.triggerClient.on('notification', async (msg) => {\n\t\t\t\tif (msg.channel === 'insert' || msg.channel === 'update' || msg.channel === 'delete') {\n\t\t\t\t\tconst payload: TriggerResult = ObjectUtils.safeParse(msg.payload) as TriggerResult;\n\t\t\t\t\tawait this.handleTrigger(payload, msg.channel.toUpperCase() as MutationType);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tlogger.info('Successfully connected to database triggers');\n\t\t} catch (error) {\n\t\t\tlogger.error(`Failed to setup trigger listeners: ${error}`);\n\t\t\t// Attempt to reconnect\n\t\t\tawait this.reconnectTriggerClient();\n\t\t}\n\t}\n\n\tprivate async handleTrigger(payload: TriggerResult, mutationType: MutationType) {\n\t\tif (\n\t\t\tpayload.queryMetadata &&\n\t\t\tpayload.queryMetadata.connectionInstanceId === this.psqlConnectionPool.instanceId\n\t\t) {\n\t\t\tawait eventManager.fireActionFromDbTrigger({ queryMetadata: payload.queryMetadata, mutationType }, payload);\n\t\t}\n\t}\n\n\tasync createDatabaseFromSchema(schema: ResturaSchema, connection: PsqlPool): Promise<string> {\n\t\tconst sqlFullStatement = this.generateDatabaseSchemaFromSchema(schema);\n\t\tawait connection.runQuery(sqlFullStatement, [], systemUser);\n\t\treturn sqlFullStatement;\n\t}\n\n\tgenerateDatabaseSchemaFromSchema(schema: ResturaSchema): string {\n\t\tconst sqlStatements = [];\n\t\tconst indexes = [];\n\t\tconst triggers = [];\n\n\t\tfor (const table of schema.database) {\n\t\t\tif (table.notify) {\n\t\t\t\ttriggers.push(this.createInsertTriggers(table.name, table.notify));\n\t\t\t\ttriggers.push(this.createUpdateTrigger(table.name, table.notify));\n\t\t\t\ttriggers.push(this.createDeleteTrigger(table.name, table.notify));\n\t\t\t}\n\n\t\t\tlet sql = `CREATE TABLE \"${table.name}\"\n\t\t\t\t\t ( `;\n\t\t\tconst tableColumns = [];\n\t\t\tfor (const column of table.columns) {\n\t\t\t\tlet columnSql = '';\n\n\t\t\t\tcolumnSql += `\\t\"${column.name}\" ${this.schemaToPsqlType(column)}`;\n\t\t\t\tlet value = column.value;\n\t\t\t\t// JSON's value is used only for typescript not for the database\n\t\t\t\tif (column.type === 'JSON') value = '';\n\t\t\t\tif (column.type === 'JSONB') value = '';\n\t\t\t\tif (column.type === 'DECIMAL' && value) {\n\t\t\t\t\t// replace the character '-' with comma since we use it to separate the values in restura for decimals\n\t\t\t\t\t// also remove single and double quotes\n\t\t\t\t\tvalue = value.replace('-', ',').replace(/['\"]/g, '');\n\t\t\t\t}\n\t\t\t\tif (value && column.type !== 'ENUM') {\n\t\t\t\t\tcolumnSql += `(${value})`;\n\t\t\t\t} else if (column.length) columnSql += `(${column.length})`;\n\t\t\t\tif (column.isPrimary) {\n\t\t\t\t\tcolumnSql += ' PRIMARY KEY ';\n\t\t\t\t}\n\t\t\t\tif (column.isUnique) {\n\t\t\t\t\tcolumnSql += ` CONSTRAINT \"${table.name}_${column.name}_unique_index\" UNIQUE `;\n\t\t\t\t}\n\t\t\t\tif (column.isNullable) columnSql += ' NULL';\n\t\t\t\telse columnSql += ' NOT NULL';\n\t\t\t\tif (column.default) columnSql += ` DEFAULT ${column.default}`;\n\t\t\t\tif (value && column.type === 'ENUM') {\n\t\t\t\t\tcolumnSql += ` CHECK (\"${column.name}\" IN (${value}))`;\n\t\t\t\t}\n\t\t\t\ttableColumns.push(columnSql);\n\t\t\t}\n\t\t\tsql += tableColumns.join(', \\n');\n\t\t\tfor (const index of table.indexes) {\n\t\t\t\tif (!index.isPrimaryKey) {\n\t\t\t\t\tlet unique = ' ';\n\t\t\t\t\tif (index.isUnique) unique = 'UNIQUE ';\n\n\t\t\t\t\tindexes.push(\n\t\t\t\t\t\t`\\tCREATE ${unique}INDEX \"${index.name}\" ON \"${table.name}\" (${index.columns\n\t\t\t\t\t\t\t.map((item) => {\n\t\t\t\t\t\t\t\treturn `\"${item}\" ${index.order}`;\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t.join(', ')});`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tsql += '\\n);';\n\t\t\tsqlStatements.push(sql);\n\t\t}\n\n\t\t// Now setup foreign keys\n\t\tfor (const table of schema.database) {\n\t\t\tif (!table.foreignKeys.length) continue;\n\t\t\tconst sql = `ALTER TABLE \"${table.name}\" `;\n\t\t\tconst constraints: string[] = [];\n\t\t\tfor (const foreignKey of table.foreignKeys) {\n\t\t\t\tlet constraint = `\\t ADD CONSTRAINT \"${foreignKey.name}\"\n FOREIGN KEY (\"${foreignKey.column}\") REFERENCES \"${foreignKey.refTable}\" (\"${foreignKey.refColumn}\")`;\n\t\t\t\tconstraint += ` ON DELETE ${foreignKey.onDelete}`;\n\t\t\t\tconstraint += ` ON UPDATE ${foreignKey.onUpdate}`;\n\t\t\t\tconstraints.push(constraint);\n\t\t\t}\n\t\t\tsqlStatements.push(sql + constraints.join(',\\n') + ';');\n\t\t}\n\n\t\t// Now setup check constraints\n\t\tfor (const table of schema.database) {\n\t\t\tif (!table.checkConstraints.length) continue;\n\t\t\tconst sql = `ALTER TABLE \"${table.name}\" `;\n\t\t\tconst constraints: string[] = [];\n\t\t\tfor (const check of table.checkConstraints) {\n\t\t\t\tconst constraint = `ADD CONSTRAINT \"${check.name}\" CHECK (${check.check})`;\n\t\t\t\tconstraints.push(constraint);\n\t\t\t}\n\t\t\tsqlStatements.push(sql + constraints.join(',\\n') + ';');\n\t\t}\n\n\t\tsqlStatements.push(indexes.join('\\n'));\n\t\tsqlStatements.push(triggers.join('\\n'));\n\n\t\treturn sqlStatements.join('\\n\\n');\n\t}\n\n\tprivate async getNewPublicSchemaAndScratchPool(): Promise<PsqlPool> {\n\t\tconst scratchDbExists = await this.psqlConnectionPool.runQuery<DynamicObject>(\n\t\t\t`SELECT *\n FROM pg_database\n WHERE datname = '${this.scratchDbName}';`,\n\t\t\t[],\n\t\t\tsystemUser\n\t\t);\n\t\tif (scratchDbExists.length === 0) {\n\t\t\tawait this.psqlConnectionPool.runQuery(`CREATE DATABASE ${this.scratchDbName};`, [], systemUser);\n\t\t}\n\n\t\tconst scratchPool = new PsqlPool({\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port,\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\tdatabase: this.scratchDbName,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\tmax: this.psqlConnectionPool.poolConfig.max,\n\t\t\tidleTimeoutMillis: this.psqlConnectionPool.poolConfig.idleTimeoutMillis,\n\t\t\tconnectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis\n\t\t});\n\t\tawait scratchPool.runQuery(`DROP SCHEMA public CASCADE;`, [], systemUser);\n\t\tawait scratchPool.runQuery(\n\t\t\t`CREATE SCHEMA public AUTHORIZATION ${this.psqlConnectionPool.poolConfig.user};`,\n\t\t\t[],\n\t\t\tsystemUser\n\t\t);\n\t\tconst schemaComment = await this.psqlConnectionPool.runQuery<{ description: string }>(\n\t\t\t`\n\t\t\tSELECT pg_description.description\n\t\t\tFROM pg_description\n\t\t\tJOIN pg_namespace ON pg_namespace.oid = pg_description.objoid\n\t\t\tWHERE pg_namespace.nspname = 'public';`,\n\t\t\t[],\n\t\t\tsystemUser\n\t\t);\n\t\tif (schemaComment[0]?.description) {\n\t\t\tawait scratchPool.runQuery(\n\t\t\t\t`COMMENT ON SCHEMA public IS '${schemaComment[0]?.description}';`,\n\t\t\t\t[],\n\t\t\t\tsystemUser\n\t\t\t);\n\t\t}\n\t\treturn scratchPool;\n\t}\n\n\tasync diffDatabaseToSchema(schema: ResturaSchema): Promise<string> {\n\t\tconst scratchPool = await this.getNewPublicSchemaAndScratchPool();\n\t\tawait this.createDatabaseFromSchema(schema, scratchPool);\n\n\t\tconst originalClient = new Client({\n\t\t\tdatabase: this.psqlConnectionPool.poolConfig.database,\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port\n\t\t});\n\t\tconst scratchClient = new Client({\n\t\t\tdatabase: this.scratchDbName,\n\t\t\tuser: this.psqlConnectionPool.poolConfig.user,\n\t\t\tpassword: this.psqlConnectionPool.poolConfig.password,\n\t\t\thost: this.psqlConnectionPool.poolConfig.host,\n\t\t\tport: this.psqlConnectionPool.poolConfig.port\n\t\t});\n\t\tconst promises = [originalClient.connect(), scratchClient.connect()];\n\t\tawait Promise.all(promises);\n\n\t\tconst infoPromises = [pgInfo({ client: originalClient }), pgInfo({ client: scratchClient })];\n\t\tconst [info1, info2] = await Promise.all(infoPromises);\n\n\t\tconst diff = getDiff(info1, info2);\n\t\tconst endPromises = [originalClient.end(), scratchClient.end()];\n\t\tawait Promise.all(endPromises);\n\t\treturn diff.join('\\n');\n\t}\n\n\tprotected createNestedSelect(\n\t\treq: RsRequest<unknown>,\n\t\tschema: ResturaSchema,\n\t\titem: ResponseData,\n\t\trouteData: StandardRouteData,\n\t\tsqlParams: string[]\n\t): string {\n\t\tif (!item.subquery) return '';\n\t\tif (\n\t\t\t!ObjectUtils.isArrayWithData(\n\t\t\t\titem.subquery.properties.filter((nestedItem) => {\n\t\t\t\t\treturn this.canRequesterAccessColumn(\n\t\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\t\tschema,\n\t\t\t\t\t\tnestedItem,\n\t\t\t\t\t\t[...routeData.joins, ...item.subquery!.joins]\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t)\n\t\t) {\n\t\t\treturn \"'[]'\";\n\t\t}\n\n\t\treturn `COALESCE((SELECT JSON_AGG(JSON_BUILD_OBJECT(\n\t\t\t${item.subquery.properties\n\t\t\t\t.map((nestedItem) => {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!this.canRequesterAccessColumn(\n\t\t\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\tnestedItem,\n\t\t\t\t\t\t\t[...routeData.joins, ...item.subquery!.joins]\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (nestedItem.subquery) {\n\t\t\t\t\t\treturn `'${nestedItem.name}', ${this.createNestedSelect(\n\t\t\t\t\t\t\t// recursion\n\t\t\t\t\t\t\treq,\n\t\t\t\t\t\t\tschema,\n\t\t\t\t\t\t\tnestedItem,\n\t\t\t\t\t\t\trouteData,\n\t\t\t\t\t\t\tsqlParams\n\t\t\t\t\t\t)}`;\n\t\t\t\t\t}\n\t\t\t\t\treturn `'${nestedItem.name}', ${escapeColumnName(nestedItem.selector)}`;\n\t\t\t\t})\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(', ')}\n\t\t\t\t\t\t)) \n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\t\"${item.subquery.table}\"\n\t\t\t\t\t\t\t${this.generateJoinStatements(req, item.subquery.joins, item.subquery.table, routeData, schema, sqlParams)}\n\t\t\t\t\t\t\t${this.generateWhereClause(req, item.subquery.where, routeData, sqlParams)}\n\t\t\t\t\t), '[]')`;\n\t}\n\n\tprotected async executeCreateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject> {\n\t\tconst sqlParams: string[] = [];\n\t\tconst parameterObj: DynamicObject = {};\n\t\t(routeData.assignments || []).forEach((assignment) => {\n\t\t\tparameterObj[assignment.name] = this.replaceParamKeywords(assignment.value, routeData, req, sqlParams);\n\t\t});\n\n\t\tconst query = insertObjectQuery(routeData.table, { ...(req.data as DynamicObject), ...parameterObj });\n\t\tconst createdItem = await this.psqlConnectionPool.queryOne<DynamicObject & { id: number }>(\n\t\t\tquery,\n\t\t\tsqlParams,\n\t\t\treq.requesterDetails\n\t\t);\n\t\tconst insertId = createdItem.id;\n\t\tconst whereId: WhereData = {\n\t\t\ttableName: routeData.table,\n\t\t\tvalue: insertId,\n\t\t\tcolumnName: 'id',\n\t\t\toperator: '='\n\t\t};\n\t\tconst whereData: WhereData[] = [whereId];\n\t\treq.data = { id: insertId };\n\t\treturn this.executeGetRequest(req, { ...routeData, where: whereData }, schema) as Promise<DynamicObject>;\n\t}\n\n\tprotected async executeGetRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t): Promise<DynamicObject | any[]> {\n\t\tconst DEFAULT_PAGED_PAGE_NUMBER = 0;\n\t\tconst DEFAULT_PAGED_PER_PAGE_NUMBER = 25;\n\t\tconst sqlParams: string[] = [];\n\n\t\tlet sqlStatement = '';\n\n\t\tconst selectColumns: ResponseData[] = [];\n\t\trouteData.response.forEach((item) => {\n\t\t\t// For a subquery, we will check the permission when generating the subquery statement, so pass it through\n\t\t\tif (\n\t\t\t\titem.subquery ||\n\t\t\t\tthis.canRequesterAccessColumn(\n\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\tschema,\n\t\t\t\t\titem,\n\t\t\t\t\trouteData.joins\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tselectColumns.push(item);\n\t\t});\n\t\tif (!selectColumns.length) throw new RsError('FORBIDDEN', `You do not have permission to access this data.`);\n\t\tlet selectStatement = 'SELECT \\n';\n\t\tselectStatement += `\\t${selectColumns\n\t\t\t.map((item) => {\n\t\t\t\tif (item.subquery) {\n\t\t\t\t\treturn `${this.createNestedSelect(req, schema, item, routeData, sqlParams)} AS ${escapeColumnName(\n\t\t\t\t\t\titem.name\n\t\t\t\t\t)}`;\n\t\t\t\t}\n\t\t\t\tif (item.type) {\n\t\t\t\t\tconst selectorWithReplacedKeywords = this.replaceParamKeywords(\n\t\t\t\t\t\titem.selector!,\n\t\t\t\t\t\trouteData,\n\t\t\t\t\t\treq,\n\t\t\t\t\t\tsqlParams\n\t\t\t\t\t);\n\t\t\t\t\treturn `${selectorWithReplacedKeywords} AS ${escapeColumnName(item.name)}`;\n\t\t\t\t} else {\n\t\t\t\t\treturn `${escapeColumnName(item.selector)} AS ${escapeColumnName(item.name)}`;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.join(',\\n\\t')}\\n`;\n\t\tsqlStatement += `FROM \"${routeData.table}\"\\n`;\n\t\tsqlStatement += this.generateJoinStatements(\n\t\t\treq,\n\t\t\trouteData.joins,\n\t\t\trouteData.table,\n\t\t\trouteData,\n\t\t\tschema,\n\t\t\tsqlParams\n\t\t);\n\n\t\tsqlStatement += this.generateWhereClause(req, routeData.where, routeData, sqlParams);\n\n\t\tlet groupByOrderByStatement = this.generateGroupBy(routeData);\n\t\tgroupByOrderByStatement += this.generateOrderBy(req, routeData);\n\n\t\tif (routeData.type === 'ONE') {\n\t\t\treturn this.psqlConnectionPool.queryOne(\n\t\t\t\t`${selectStatement}${sqlStatement}${groupByOrderByStatement};`,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\t\t} else if (routeData.type === 'ARRAY') {\n\t\t\t// Array\n\t\t\treturn this.psqlConnectionPool.runQuery(\n\t\t\t\t`${selectStatement}${sqlStatement}${groupByOrderByStatement};`,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\t\t} else if (routeData.type === 'PAGED') {\n\t\t\tconst data = req.data as PageQuery;\n\t\t\t// The COUNT() does not work with group by and order by, so we need to catch that case and act accordingly\n\t\t\tconst pagePromise = this.psqlConnectionPool.runQuery(\n\t\t\t\t`${selectStatement}${sqlStatement}${groupByOrderByStatement}` +\n\t\t\t\t\tSQL`LIMIT ${data.perPage || DEFAULT_PAGED_PER_PAGE_NUMBER} OFFSET ${(data.page - 1) * data.perPage || DEFAULT_PAGED_PAGE_NUMBER};`,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\t\t\tconst totalQuery = `SELECT COUNT(${\n\t\t\t\trouteData.groupBy ? `DISTINCT ${routeData.groupBy.tableName}.${routeData.groupBy.columnName}` : '*'\n\t\t\t}) AS total\\n ${sqlStatement};`;\n\t\t\tconst totalPromise = this.psqlConnectionPool.runQuery<{ total: number }>(\n\t\t\t\ttotalQuery,\n\t\t\t\tsqlParams,\n\t\t\t\treq.requesterDetails\n\t\t\t);\n\n\t\t\tconst [pageResults, totalResponse] = await Promise.all([pagePromise, totalPromise]);\n\n\t\t\tlet total = 0;\n\t\t\tif (ObjectUtils.isArrayWithData(totalResponse)) {\n\t\t\t\ttotal = totalResponse[0].total;\n\t\t\t}\n\t\t\treturn { data: pageResults, total };\n\t\t} else {\n\t\t\tthrow new RsError('UNKNOWN_ERROR', 'Unknown route type.');\n\t\t}\n\t}\n\n\tprotected async executeUpdateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject> {\n\t\tconst sqlParams: string[] = [];\n\t\t// eslint-disable-next-line\n\t\tconst { id, ...bodyNoId } = req.body;\n\n\t\t// Find the database table\n\t\tconst table = schema.database.find((item) => {\n\t\t\treturn item.name === routeData.table;\n\t\t});\n\t\tif (!table) throw new RsError('UNKNOWN_ERROR', 'Unknown table.');\n\t\tif (table.columns.find((column) => column.name === 'modifiedOn')) {\n\t\t\tbodyNoId.modifiedOn = new Date().toISOString();\n\t\t}\n\n\t\tfor (const assignment of routeData.assignments) {\n\t\t\tconst column = table.columns.find((column) => column.name === assignment.name);\n\t\t\tif (!column) continue;\n\n\t\t\tconst assignmentEscaped = escapeColumnName(assignment.name);\n\n\t\t\tif (SqlUtils.convertDatabaseTypeToTypescript(column.type!) === 'number')\n\t\t\t\tbodyNoId[assignmentEscaped] = Number(assignment.value);\n\t\t\telse bodyNoId[assignmentEscaped] = assignment.value;\n\t\t}\n\n\t\t// Todo: Add joins back in on the update. They are useful for the where clause.\n\t\t// let joinStatement = this.generateJoinStatements(\n\t\t// \treq,\n\t\t// \trouteData.joins!,\n\t\t// \trouteData.table!,\n\t\t// \trouteData!,\n\t\t// \tschema,\n\t\t// \treq.requesterDetails.role,\n\t\t// \tsqlParams\n\t\t// );\n\t\tconst whereClause = this.generateWhereClause(req, routeData.where, routeData, sqlParams);\n\t\tconst query = updateObjectQuery(routeData.table, bodyNoId, whereClause);\n\t\tawait this.psqlConnectionPool.queryOne(query, [...sqlParams], req.requesterDetails);\n\t\treturn this.executeGetRequest(req, routeData, schema) as unknown as DynamicObject;\n\t}\n\n\tprotected async executeDeleteRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<boolean> {\n\t\tconst sqlParams: string[] = [];\n\n\t\tconst joinStatement = this.generateJoinStatements(\n\t\t\treq,\n\t\t\trouteData.joins,\n\t\t\trouteData.table,\n\t\t\trouteData,\n\t\t\tschema,\n\t\t\tsqlParams\n\t\t);\n\t\tconst whereClause = this.generateWhereClause(req, routeData.where, routeData, sqlParams);\n\t\tif (whereClause.replace(/\\s/g, '') === '') {\n\t\t\tthrow new RsError('DELETE_FORBIDDEN', 'Deletes need a where clause');\n\t\t}\n\n\t\tconst deleteStatement = `\nDELETE FROM \"${routeData.table}\" ${joinStatement} ${whereClause}`;\n\t\tawait this.psqlConnectionPool.runQuery(deleteStatement, sqlParams, req.requesterDetails);\n\t\treturn true;\n\t}\n\n\tprotected generateJoinStatements(\n\t\treq: RsRequest<unknown>,\n\t\tjoins: JoinData[],\n\t\tbaseTable: string,\n\t\trouteData: StandardRouteData | CustomRouteData,\n\t\tschema: ResturaSchema,\n\t\tsqlParams: string[]\n\t): string {\n\t\tlet joinStatements = '';\n\t\tjoins.forEach((item) => {\n\t\t\tif (\n\t\t\t\t!this.canRequesterAccessTable(\n\t\t\t\t\treq.requesterDetails.role,\n\t\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\t\tschema,\n\t\t\t\t\titem.table\n\t\t\t\t)\n\t\t\t)\n\t\t\t\tthrow new RsError('FORBIDDEN', 'You do not have permission to access this table');\n\t\t\tif (item.custom) {\n\t\t\t\tconst customReplaced = this.replaceParamKeywords(item.custom, routeData, req, sqlParams);\n\t\t\t\tjoinStatements += `\\t${item.type} JOIN ${escapeColumnName(item.table)} AS ${escapeColumnName(item.alias)} ON ${customReplaced}\\n`;\n\t\t\t} else {\n\t\t\t\tjoinStatements += `\\t${item.type} JOIN ${escapeColumnName(item.table)}`;\n\t\t\t\tjoinStatements += ` AS ${escapeColumnName(item.alias)}`;\n\n\t\t\t\tif (item.localTable) {\n\t\t\t\t\tjoinStatements += ` ON ${escapeColumnName(item.localTableAlias)}.${escapeColumnName(item.localColumnName)} = ${escapeColumnName(item.alias)}.${escapeColumnName(\n\t\t\t\t\t\titem.foreignColumnName\n\t\t\t\t\t)}\\n`;\n\t\t\t\t} else {\n\t\t\t\t\tjoinStatements += ` ON ${escapeColumnName(baseTable)}.${escapeColumnName(item.localColumnName)} = ${escapeColumnName(item.alias)}.${escapeColumnName(\n\t\t\t\t\t\titem.foreignColumnName\n\t\t\t\t\t)}\\n`;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn joinStatements;\n\t}\n\n\tprotected generateGroupBy(routeData: StandardRouteData): string {\n\t\tlet groupBy = '';\n\t\tif (routeData.groupBy) {\n\t\t\tgroupBy = `GROUP BY ${escapeColumnName(routeData.groupBy.tableName)}.${escapeColumnName(routeData.groupBy.columnName)}\\n`;\n\t\t}\n\t\treturn groupBy;\n\t}\n\n\tprotected generateOrderBy(req: RsRequest<unknown>, routeData: StandardRouteData): string {\n\t\tlet orderBy = '';\n\t\tconst orderOptions: { [key: string]: string } = {\n\t\t\tASC: 'ASC',\n\t\t\tDESC: 'DESC'\n\t\t};\n\t\tconst data = req.data as PageQuery;\n\t\tif (routeData.type === 'PAGED' && 'sortBy' in data) {\n\t\t\tconst sortOrder = orderOptions[data.sortOrder] || 'ASC';\n\t\t\torderBy = `ORDER BY ${escapeColumnName(data.sortBy)} ${sortOrder}\\n`;\n\t\t} else if (routeData.orderBy) {\n\t\t\tconst sortOrder = orderOptions[routeData.orderBy.order] || 'ASC';\n\t\t\torderBy = `ORDER BY ${escapeColumnName(routeData.orderBy.tableName)}.${escapeColumnName(routeData.orderBy.columnName)} ${sortOrder}\\n`;\n\t\t}\n\t\treturn orderBy;\n\t}\n\n\tprotected generateWhereClause(\n\t\treq: RsRequest<unknown>,\n\t\twhere: WhereData[],\n\t\trouteData: StandardRouteData | CustomRouteData,\n\t\tsqlParams: string[]\n\t): string {\n\t\tlet whereClause = '';\n\t\twhere.forEach((item, index) => {\n\t\t\tif (index === 0) whereClause = 'WHERE ';\n\t\t\tif (item.custom) {\n\t\t\t\tconst customReplaced = this.replaceParamKeywords(item.custom, routeData, req, sqlParams);\n\t\t\t\twhereClause += `\\t${item.conjunction || ''} ${customReplaced}\\n`;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\titem.operator === undefined ||\n\t\t\t\titem.value === undefined ||\n\t\t\t\titem.columnName === undefined ||\n\t\t\t\titem.tableName === undefined\n\t\t\t)\n\t\t\t\tthrow new RsError(\n\t\t\t\t\t'SCHEMA_ERROR',\n\t\t\t\t\t`Invalid where clause in route ${routeData.name}, missing required fields if not custom`\n\t\t\t\t);\n\n\t\t\tlet operator = item.operator;\n\t\t\tlet value = item.value;\n\n\t\t\tif (operator === 'LIKE') {\n\t\t\t\tvalue = `'%' || ${value} || '%'`;\n\t\t\t} else if (operator === 'NOT LIKE') {\n\t\t\t\tvalue = `'%' || ${value} || '%'`;\n\t\t\t} else if (operator === 'STARTS WITH') {\n\t\t\t\toperator = 'LIKE';\n\t\t\t\tvalue = `${value} || '%'`;\n\t\t\t} else if (operator === 'ENDS WITH') {\n\t\t\t\toperator = 'LIKE';\n\t\t\t\tvalue = `'%' || ${value}`;\n\t\t\t}\n\n\t\t\tconst replacedValue = this.replaceParamKeywords(value, routeData, req, sqlParams);\n\t\t\twhereClause += `\\t${item.conjunction || ''} \"${item.tableName}\".\"${item.columnName}\" ${operator.replace('LIKE', 'ILIKE')} ${\n\t\t\t\t['IN', 'NOT IN'].includes(operator) ? `(${replacedValue})` : replacedValue\n\t\t\t}\\n`;\n\t\t});\n\n\t\tconst data = req.data as PageQuery;\n\t\tif (routeData.type === 'PAGED' && !!data?.filter) {\n\t\t\tlet statement = data.filter.replace(/\\$[a-zA-Z][a-zA-Z0-9_]+/g, (value: string) => {\n\t\t\t\tconst requestParam = routeData.request!.find((item) => {\n\t\t\t\t\treturn item.name === value.replace('$', '');\n\t\t\t\t});\n\t\t\t\tif (!requestParam)\n\t\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Invalid route keyword in route ${routeData.name}`);\n\t\t\t\treturn data[requestParam.name]?.toString() || '';\n\t\t\t});\n\n\t\t\tstatement = statement.replace(/#[a-zA-Z][a-zA-Z0-9_]+/g, (value: string) => {\n\t\t\t\tconst requestParam = routeData.request!.find((item) => {\n\t\t\t\t\treturn item.name === value.replace('#', '');\n\t\t\t\t});\n\t\t\t\tif (!requestParam)\n\t\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Invalid route keyword in route ${routeData.name}`);\n\t\t\t\treturn data[requestParam.name]?.toString() || '';\n\t\t\t});\n\n\t\t\tstatement = filterPsqlParser.parse(statement);\n\t\t\tif (whereClause.startsWith('WHERE')) {\n\t\t\t\twhereClause += ` AND (${statement})\\n`;\n\t\t\t} else {\n\t\t\t\twhereClause += `WHERE ${statement}\\n`;\n\t\t\t}\n\t\t}\n\n\t\treturn whereClause;\n\t}\n\n\tprivate createUpdateTrigger(tableName: string, notify: ResturaSchema['database'][0]['notify']): string {\n\t\tif (!notify) return '';\n\t\tif (notify === 'ALL') {\n\t\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_update()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t\t(regexp_match(\n\t\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'update',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'changedId', NEW.id,\n\t\t\t\t\t\t'record', NEW,\n\t\t\t\t\t\t'previousRecord', OLD\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER ${tableName}_update\n\tAFTER UPDATE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_update();\n`;\n\t\t}\n\n\t\tconst notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW.\"${column}\"`).join(',\\n');\n\t\tconst notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD.\"${column}\"`).join(',\\n');\n\n\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_update()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t\t(regexp_match(\n\t\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'update',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'changedId', NEW.id,\n\t\t\t\t\t\t'record', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnNewBuildString}\n\t\t\t\t\t\t),\n\t\t\t\t\t\t'previousRecord', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnOldBuildString}\n\t\t\t\t\t\t)\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER ${tableName}_update\n\tAFTER UPDATE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_update();\n\t\t`;\n\t}\n\n\tprivate createDeleteTrigger(tableName: string, notify: ResturaSchema['database'][0]['notify']): string {\n\t\tif (!notify) return '';\n\t\tif (notify === 'ALL') {\n\t\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_delete()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'delete',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'deletedId', OLD.id,\n\t\t\t\t\t\t'previousRecord', OLD\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_delete\"\n\tAFTER DELETE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_delete();\n`;\n\t\t}\n\n\t\tconst notifyColumnOldBuildString = notify.map((column) => `'${column}', OLD.\"${column}\"`).join(',\\n');\n\n\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_delete()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'delete',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'deletedId', OLD.id,\n\t\t\t\t\t\t'previousRecord', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnOldBuildString}\n\t\t\t\t\t\t)\n\t\t)::text\n\t\t);\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_delete\"\n\tAFTER DELETE ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_delete();\n\t\t`;\n\t}\n\n\tprivate createInsertTriggers(tableName: string, notify: ResturaSchema['database'][0]['notify']): string {\n\t\tif (!notify) return '';\n\t\tif (notify === 'ALL') {\n\t\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_insert()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'insert',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'insertedId', NEW.id,\n\t\t\t\t\t\t'record', NEW\n\t\t)::text\n\t\t);\n\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_insert\"\n\tAFTER INSERT ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_insert();\n`;\n\t\t}\n\n\t\tconst notifyColumnNewBuildString = notify.map((column) => `'${column}', NEW.\"${column}\"`).join(',\\n');\n\n\t\treturn `\nCREATE OR REPLACE FUNCTION notify_${tableName}_insert()\n\tRETURNS TRIGGER AS $$\nDECLARE\n\tquery_metadata JSON;\nBEGIN\n\tSELECT INTO query_metadata\n\t\t\t(regexp_match(\n\t\t\t\t\tcurrent_query(),\n\t\t\t\t\t'^--QUERY_METADATA\\\\(({.*})', 'n'\n\t\t\t))[1]::json;\n\n\tPERFORM pg_notify(\n\t\t'insert',\n\t\tjson_build_object(\n\t\t\t\t\t\t'table', '${tableName}',\n\t\t\t\t\t\t'queryMetadata', query_metadata,\n\t\t\t\t\t\t'insertedId', NEW.id,\n\t\t\t\t\t\t'record', json_build_object(\n\t\t\t\t\t\t\t${notifyColumnNewBuildString}\n\t\t\t\t\t\t)\n\t\t)::text\n\t\t);\n\n\tRETURN NEW;\nEND;\n$$ LANGUAGE plpgsql;\n\nCREATE OR REPLACE TRIGGER \"${tableName}_insert\"\n\tAFTER INSERT ON \"${tableName}\"\n\tFOR EACH ROW\nEXECUTE FUNCTION notify_${tableName}_insert();\n`;\n\t}\n\n\tprivate schemaToPsqlType(column: ColumnData) {\n\t\tif (column.hasAutoIncrement) return 'BIGSERIAL';\n\t\tif (column.type === 'ENUM') return `TEXT`;\n\t\tif (column.type === 'DATETIME') return 'TIMESTAMPTZ';\n\t\tif (column.type === 'MEDIUMINT') return 'INT';\n\t\treturn column.type;\n\t}\n}\n","import pg, { QueryResult, QueryResultRow } from 'pg';\n// See this github issue for why we need to do this https://github.com/brianc/node-postgres/issues/2819\nimport type { PoolConfig, Pool as PoolType, QueryConfigValues } from 'pg';\nimport { logger } from '../../logger/logger.js';\nimport { PsqlConnection } from './PsqlConnection.js';\nconst { Pool } = pg;\n\nexport class PsqlPool extends PsqlConnection {\n\tpublic pool: PoolType;\n\tconstructor(public poolConfig: PoolConfig) {\n\t\tsuper();\n\t\tthis.pool = new Pool(poolConfig);\n\t\t// Run a test query to ensure the connection is working\n\t\tthis.queryOne('SELECT NOW();', [], {\n\t\t\tisSystemUser: true,\n\t\t\trole: '',\n\t\t\thost: 'localhost',\n\t\t\tipAddress: '',\n\t\t\tscopes: []\n\t\t})\n\t\t\t.then(() => {\n\t\t\t\tlogger.info('Connected to PostgreSQL database');\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tlogger.error('Error connecting to database', error);\n\t\t\t\tprocess.exit(1);\n\t\t\t});\n\t}\n\n\tprotected async query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(\n\t\tquery: string,\n\t\tvalues?: QueryConfigValues<T>\n\t): Promise<QueryResult<R>> {\n\t\treturn this.pool.query(query, values) as Promise<QueryResult<R>>;\n\t}\n}\n","import crypto, { UUID } from 'crypto';\nimport { QueryConfigValues, QueryResult, QueryResultRow } from 'pg';\nimport format from 'pg-format';\nimport { format as sqlFormat } from 'sql-formatter';\nimport { z } from 'zod';\nimport { logger } from '../../logger/logger.js';\nimport { RsError } from '../RsError.js';\nimport { QueryMetadata } from '../eventManager.js';\nimport { RequesterDetails } from '../types/customExpressTypes.js';\nimport { questionMarksToOrderedParams } from './PsqlUtils.js';\n\nexport abstract class PsqlConnection {\n\treadonly instanceId: UUID;\n\tprotected constructor(instanceId?: UUID) {\n\t\tthis.instanceId = instanceId || crypto.randomUUID();\n\t}\n\n\tprotected abstract query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(\n\t\tquery: string,\n\t\tvalues?: QueryConfigValues<T>\n\t): Promise<QueryResult<R>>;\n\n\tasync queryOne<T>(query: string, options: unknown[], requesterDetails: RequesterDetails): Promise<T> {\n\t\tconst formattedQuery = questionMarksToOrderedParams(query);\n\t\tconst meta: QueryMetadata = { connectionInstanceId: this.instanceId, ...requesterDetails };\n\t\tthis.logSqlStatement(formattedQuery, options, meta);\n\t\tconst queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})\\n`;\n\n\t\tconst startTime = process.hrtime();\n\t\ttry {\n\t\t\tconst response = await this.query(queryMetadata + formattedQuery, options as QueryConfigValues<unknown>);\n\n\t\t\tthis.logQueryDuration(startTime);\n\n\t\t\t// There should be one and only one row returned\n\t\t\tif (response.rows.length === 0) throw new RsError('NOT_FOUND', 'No results found');\n\t\t\telse if (response.rows.length > 1) throw new RsError('DUPLICATE', 'More than one result found');\n\n\t\t\treturn response.rows[0] as T;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tif (RsError.isRsError(error)) throw error;\n\n\t\t\tif (error?.routine === '_bt_check_unique') {\n\t\t\t\tthrow new RsError('DUPLICATE', error.message);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `${error.message}`);\n\t\t}\n\t}\n\n\tasync queryOneSchema<T>(\n\t\tquery: string,\n\t\tparams: unknown[],\n\t\trequesterDetails: RequesterDetails,\n\t\tzodSchema: z.ZodSchema<T>\n\t): Promise<T> {\n\t\tconst result = await this.queryOne(query, params, requesterDetails);\n\t\ttry {\n\t\t\treturn zodSchema.parse(result);\n\t\t} catch (error) {\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tlogger.error('Invalid data returned from database:');\n\t\t\t\tlogger.silly('\\n' + JSON.stringify(result, null, 2));\n\t\t\t\tlogger.error('\\n' + z.prettifyError(error));\n\t\t\t} else {\n\t\t\t\tlogger.error(error);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `Invalid data returned from database`);\n\t\t}\n\t}\n\n\tasync runQuery<T>(query: string, options: unknown[], requesterDetails: RequesterDetails): Promise<T[]> {\n\t\tconst formattedQuery = questionMarksToOrderedParams(query);\n\t\tconst meta: QueryMetadata = { connectionInstanceId: this.instanceId, ...requesterDetails };\n\t\tthis.logSqlStatement(formattedQuery, options, meta);\n\t\tconst queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})\\n`;\n\t\tconst startTime = process.hrtime();\n\t\ttry {\n\t\t\tconst response = await this.query(queryMetadata + formattedQuery, options as QueryConfigValues<unknown>);\n\n\t\t\tthis.logQueryDuration(startTime);\n\n\t\t\treturn response.rows as T[];\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tif (error?.routine === '_bt_check_unique') {\n\t\t\t\tthrow new RsError('DUPLICATE', error.message);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `${error.message}`);\n\t\t}\n\t}\n\n\tasync runQuerySchema<T>(\n\t\tquery: string,\n\t\tparams: unknown[],\n\t\trequesterDetails: RequesterDetails,\n\t\tzodSchema: z.ZodSchema<T>\n\t): Promise<T[]> {\n\t\tconst result = await this.runQuery(query, params, requesterDetails);\n\t\ttry {\n\t\t\treturn z.array(zodSchema).parse(result);\n\t\t} catch (error) {\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tlogger.error('Invalid data returned from database:');\n\t\t\t\tlogger.silly('\\n' + JSON.stringify(result, null, 2));\n\t\t\t\tlogger.error('\\n' + z.prettifyError(error));\n\t\t\t} else {\n\t\t\t\tlogger.error(error);\n\t\t\t}\n\t\t\tthrow new RsError('DATABASE_ERROR', `Invalid data returned from database`);\n\t\t}\n\t}\n\n\tprivate logQueryDuration(startTime: [number, number]): void {\n\t\tif (logger.level === 'silly') {\n\t\t\tconst [seconds, nanoseconds] = process.hrtime(startTime);\n\t\t\tconst duration = seconds * 1000 + nanoseconds / 1000000;\n\t\t\tlogger.silly(`Query duration: ${duration.toFixed(2)}ms`);\n\t\t}\n\t}\n\n\tprivate logSqlStatement(query: string, options: unknown[], queryMetadata: QueryMetadata, prefix: string = '') {\n\t\tif (logger.level !== 'silly') return;\n\n\t\tlet sqlStatement = '';\n\t\tif (options.length === 0) {\n\t\t\tsqlStatement = query;\n\t\t} else {\n\t\t\tsqlStatement = query.replace(/\\$\\d+/g, (match) => {\n\t\t\t\tconst paramIndex = parseInt(match.substring(1)) - 1; // Extract number from $1, $2, etc.\n\t\t\t\tif (paramIndex < 0 || paramIndex >= options.length) {\n\t\t\t\t\treturn 'INVALID_PARAM_INDEX';\n\t\t\t\t}\n\t\t\t\tconst value = options[paramIndex];\n\t\t\t\tif (typeof value === 'number') return value.toString();\n\t\t\t\tif (typeof value === 'boolean') return value.toString();\n\t\t\t\treturn format.literal(value as string | object | Date | null | undefined);\n\t\t\t});\n\t\t}\n\n\t\tconst formattedSql = sqlFormat(sqlStatement, {\n\t\t\tlanguage: 'postgresql',\n\t\t\tlinesBetweenQueries: 2,\n\t\t\tindentStyle: 'standard',\n\t\t\tkeywordCase: 'upper',\n\t\t\tuseTabs: true,\n\t\t\ttabWidth: 4\n\t\t});\n\n\t\tlet initiator = 'Anonymous';\n\t\tif ('userId' in queryMetadata && queryMetadata.userId)\n\t\t\tinitiator = `User Id (${queryMetadata.userId.toString()})`;\n\t\tif ('isSystemUser' in queryMetadata && queryMetadata.isSystemUser) initiator = 'SYSTEM';\n\n\t\tlogger.silly(`${prefix}query by ${initiator}, Query ->\\n${formattedSql}`);\n\t}\n}\n","import format from 'pg-format';\nimport { DynamicObject } from '../types/customExpressTypes.js';\n\n/**\n * This method does a couple of things:\n * 1. It escapes the column name to prevent SQL injection by removing any double quotes.\n * 2. It wraps the column name in double quotes to prevent any issues with reserved words or casing.\n * 3. It replaces any periods in the column name with a period wrapped in double quotes to prevent any issues with schema names.\n * NOTE: I looked into using pg-format ident() method but that will strip the double quotes when not needed.\n * @param columnName\n * @returns\n */\nexport function escapeColumnName(columnName: string | undefined): string {\n\tif (columnName === undefined) return '';\n\treturn `\"${columnName.replace(/\"/g, '')}\"`.replace('.', '\".\"');\n}\n\n/**\n * Converts a query with question marks to a query with numbered parameters,\n * however it ignores question marks inside single or double quotes.\n * @param query PostgreSQL query with question marks\n * @returns A string with numbered parameters such as $1, $2 in replacement of question marks\n */\nexport function questionMarksToOrderedParams(query: string) {\n\tlet count = 1;\n\tlet inSingleQuote = false;\n\tlet inDoubleQuote = false;\n\n\treturn query.replace(/('|\"|\\?)/g, (char) => {\n\t\tif (char === \"'\") {\n\t\t\tinSingleQuote = !inSingleQuote && !inDoubleQuote;\n\t\t\treturn char;\n\t\t}\n\t\tif (char === '\"') {\n\t\t\tinDoubleQuote = !inDoubleQuote && !inSingleQuote;\n\t\t\treturn char;\n\t\t}\n\t\tif (char === '?' && !inSingleQuote && !inDoubleQuote) {\n\t\t\treturn `$${count++}`;\n\t\t}\n\t\treturn char; // Return ? unchanged if inside quotes\n\t});\n}\n\n/**\n * Creates a query to insert an object into a table.\n * @param table Table name to insert the object into\n * @param obj Data to insert into the table\n * @returns the query to insert the object into the table\n */\nexport function insertObjectQuery(table: string, obj: DynamicObject): string {\n\tconst keys = Object.keys(obj);\n\tconst params = Object.values(obj);\n\n\tconst columns = keys.map((column) => escapeColumnName(column)).join(', ');\n\tconst values = params.map((value) => SQL`${value}`).join(', ');\n\n\tlet query = `\nINSERT INTO \"${table}\" (${columns})\n VALUES (${values})\n RETURNING *`;\n\n\tquery = query.replace(/'(\\?)'/, '?');\n\treturn query;\n}\n\n/**\n * Creates a query to update an object in a table.\n * @param table Table name to update the object in\n * @param obj Data to update in the table\n * @param whereStatement Where clause to determine which rows to update\n * @returns the query to update the object in the table\n */\nexport function updateObjectQuery(table: string, obj: DynamicObject, whereStatement: string): string {\n\tconst setArray = [];\n\tfor (const i in obj) {\n\t\tsetArray.push(`${escapeColumnName(i)} = ` + SQL`${obj[i]}`);\n\t}\n\n\treturn `\nUPDATE ${escapeColumnName(table)}\n SET ${setArray.join(', ')} ${whereStatement}\n RETURNING *`;\n}\n\n// Todo: Move this method into @redsky/core-utils package under NumberUtils\nexport function isValueNumber(value: unknown): value is number {\n\treturn !isNaN(Number(value));\n}\n\n/**\n * This method is used to format a query and escape user input.\n * Use this with the SQL tag to escape user input. For example:\n * SQL`UPDATE \"USER\" SET \"firstName\" = ${firstName}, \"isActive\" = ${isActive} WHERE \"id\" = ${id} RETURNING *`\n * @param strings template strings array\n * @param values values to escape\n * @returns An escaped query with user input\n */\nexport function SQL(strings: TemplateStringsArray, ...values: unknown[]) {\n\tlet query = strings[0];\n\tvalues.forEach((value: unknown, index: number) => {\n\t\tif (typeof value === 'boolean') {\n\t\t\tquery += value;\n\t\t} else if (typeof value === 'number') {\n\t\t\tquery += value;\n\t\t} else if (Array.isArray(value)) {\n\t\t\t// JSON arrays in the pg-format are stripped of their array brackets and used for grouped list conversions.\n\t\t\t// This is a workaround to fix this issue. Where we are expecting JSON arrays as the root element of the object.\n\t\t\tquery += format.literal(JSON.stringify(value)) + '::jsonb';\n\t\t} else {\n\t\t\tquery += format.literal(value as string); // escape input\n\t\t}\n\t\tquery += strings[index + 1];\n\t});\n\n\treturn query;\n}\n","import { ObjectUtils } from '@redskytech/core-utils';\nimport { RsError } from '../RsError.js';\nimport {\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tRouteData,\n\tStandardRouteData,\n\tTableData,\n\tWhereData\n} from '../schemas/resturaSchema.js';\nimport { DynamicObject, RsRequest } from '../types/customExpressTypes.js';\n\nexport default abstract class SqlEngine {\n\tasync runQueryForRoute(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t): Promise<DynamicObject | any[] | boolean> {\n\t\tif (\n\t\t\t!this.canRequesterAccessTable(\n\t\t\t\treq.requesterDetails.role,\n\t\t\t\treq.requesterDetails.scopes,\n\t\t\t\tschema,\n\t\t\t\trouteData.table\n\t\t\t)\n\t\t)\n\t\t\tthrow new RsError('FORBIDDEN', 'You do not have permission to access this table');\n\n\t\tswitch (routeData.method) {\n\t\t\tcase 'POST':\n\t\t\t\treturn this.executeCreateRequest(req, routeData, schema);\n\t\t\tcase 'GET':\n\t\t\t\treturn this.executeGetRequest(req, routeData, schema);\n\t\t\tcase 'PUT':\n\t\t\tcase 'PATCH':\n\t\t\t\treturn this.executeUpdateRequest(req, routeData, schema);\n\t\t\tcase 'DELETE':\n\t\t\t\treturn this.executeDeleteRequest(req, routeData, schema);\n\t\t}\n\t}\n\tprotected getTableSchema(schema: ResturaSchema, tableName: string): TableData {\n\t\tconst tableSchema = schema.database.find((item) => item.name === tableName);\n\t\tif (!tableSchema) throw new RsError('SCHEMA_ERROR', `Table ${tableName} not found in schema`);\n\t\treturn tableSchema;\n\t}\n\n\tprotected canRequesterAccessColumn(\n\t\trequesterRole: string | undefined | null,\n\t\trequesterScopes: string[] | undefined | null,\n\t\tschema: ResturaSchema,\n\t\titem: ResponseData,\n\t\tjoins: JoinData[]\n\t): boolean {\n\t\tif (item.type) return true;\n\t\tif (item.selector) {\n\t\t\tlet tableName = item.selector.split('.')[0];\n\t\t\tconst columnName = item.selector.split('.')[1];\n\t\t\tlet tableSchema = schema.database.find((item) => item.name === tableName);\n\t\t\tif (!tableSchema) {\n\t\t\t\t// check to see if this is an alias join table\n\t\t\t\tconst join = joins.find((join) => join.alias === tableName);\n\t\t\t\tif (!join) throw new RsError('SCHEMA_ERROR', `Table ${tableName} not found in schema`);\n\t\t\t\ttableName = join.table;\n\t\t\t\ttableSchema = schema.database.find((item) => item.name === tableName);\n\t\t\t}\n\t\t\tif (!tableSchema) throw new RsError('SCHEMA_ERROR', `Table ${tableName} not found in schema`);\n\t\t\tconst columnSchema = tableSchema.columns.find((item) => item.name === columnName);\n\t\t\tif (!columnSchema)\n\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Column ${columnName} not found in table ${tableName}`);\n\n\t\t\tif (ObjectUtils.isArrayWithData(columnSchema.roles)) {\n\t\t\t\tif (!requesterRole) return false;\n\t\t\t\treturn columnSchema.roles.includes(requesterRole);\n\t\t\t}\n\t\t\tif (ObjectUtils.isArrayWithData(columnSchema.scopes)) {\n\t\t\t\tif (!requesterScopes) return false;\n\t\t\t\treturn columnSchema.scopes.every((scope) => requesterScopes.includes(scope));\n\t\t\t}\n\t\t\treturn true; // Public column, any role can access\n\t\t}\n\t\tif (item.subquery) {\n\t\t\treturn ObjectUtils.isArrayWithData(\n\t\t\t\titem.subquery.properties.filter((nestedItem) => {\n\t\t\t\t\treturn this.canRequesterAccessColumn(requesterRole, requesterScopes, schema, nestedItem, joins);\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprotected canRequesterAccessTable(\n\t\trequesterRole: string | undefined,\n\t\trequesterScopes: string[] | undefined,\n\t\tschema: ResturaSchema,\n\t\ttableName: string\n\t): boolean {\n\t\tconst tableSchema = this.getTableSchema(schema, tableName);\n\t\tif (ObjectUtils.isArrayWithData(tableSchema.roles)) {\n\t\t\tif (!requesterRole) return false; // Table has roles, but no role provided (no access)\n\t\t\treturn tableSchema.roles.includes(requesterRole);\n\t\t}\n\t\tif (ObjectUtils.isArrayWithData(tableSchema.scopes)) {\n\t\t\tif (!requesterScopes) return false;\n\t\t\treturn tableSchema.scopes.some((scope) => requesterScopes.includes(scope));\n\t\t}\n\t\treturn true; // Public table, any role can access\n\t}\n\n\tprotected abstract generateJoinStatements(\n\t\treq: RsRequest<unknown>,\n\t\tjoins: JoinData[],\n\t\tbaseTable: string,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema,\n\t\tsqlParams: string[]\n\t): string;\n\n\tprotected abstract generateGroupBy(routeData: StandardRouteData): string;\n\n\tprotected abstract generateOrderBy(req: RsRequest<unknown>, routeData: StandardRouteData): string;\n\n\tprotected abstract generateWhereClause(\n\t\treq: RsRequest<unknown>,\n\t\twhere: WhereData[],\n\t\trouteData: StandardRouteData,\n\t\tsqlParams: string[]\n\t): string;\n\n\tprotected replaceParamKeywords(\n\t\tvalue: string | number,\n\t\trouteData: RouteData,\n\t\treq: RsRequest<unknown>,\n\t\tsqlParams: string[]\n\t): string | number {\n\t\tlet returnValue = value;\n\t\treturnValue = this.replaceLocalParamKeywords(returnValue, routeData, req, sqlParams);\n\t\treturnValue = this.replaceGlobalParamKeywords(returnValue, routeData, req, sqlParams);\n\t\treturn returnValue;\n\t}\n\n\tprotected replaceLocalParamKeywords(\n\t\tvalue: string | number,\n\t\trouteData: RouteData,\n\t\treq: RsRequest<unknown>,\n\t\tsqlParams: string[]\n\t): string | number {\n\t\tif (!routeData.request) return value;\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\tconst data = req.data as DynamicObject<any>;\n\t\tif (typeof value === 'string') {\n\t\t\t// Match any value that starts with a $\n\t\t\tvalue.match(/\\$[a-zA-Z][a-zA-Z0-9_]+/g)?.forEach((param) => {\n\t\t\t\tconst requestParam = routeData.request!.find((item) => {\n\t\t\t\t\treturn item.name === param.replace('$', '');\n\t\t\t\t});\n\t\t\t\tif (!requestParam)\n\t\t\t\t\tthrow new RsError('SCHEMA_ERROR', `Invalid route keyword in route ${routeData.name}`);\n\t\t\t\tsqlParams.push(data[requestParam.name]); // pass by reference\n\t\t\t});\n\t\t\treturn value.replace(new RegExp(/\\$[a-zA-Z][a-zA-Z0-9_]+/g), '?');\n\t\t}\n\t\treturn value;\n\t}\n\n\tprotected replaceGlobalParamKeywords(\n\t\tvalue: string | number,\n\t\trouteData: RouteData,\n\t\treq: RsRequest<unknown>,\n\t\tsqlParams: string[]\n\t): string | number {\n\t\tif (typeof value === 'string') {\n\t\t\t// Match any value that starts with a #\n\t\t\tvalue.match(/#[a-zA-Z][a-zA-Z0-9_]+/g)?.forEach((param) => {\n\t\t\t\tparam = param.replace('#', '');\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\tconst globalParamValue = (req.requesterDetails as any)[param];\n\t\t\t\tif (!globalParamValue)\n\t\t\t\t\tthrow new RsError(\n\t\t\t\t\t\t'SCHEMA_ERROR',\n\t\t\t\t\t\t`Invalid global keyword clause in route (${routeData.path}) when looking for (#${param})`\n\t\t\t\t\t);\n\t\t\t\tsqlParams.push(globalParamValue); // pass by reference\n\t\t\t});\n\t\t\treturn value.replace(new RegExp(/#[a-zA-Z][a-zA-Z0-9_]+/g), '?');\n\t\t}\n\t\treturn value;\n\t}\n\n\tabstract generateDatabaseSchemaFromSchema(schema: ResturaSchema): string;\n\tabstract diffDatabaseToSchema(schema: ResturaSchema): Promise<string>;\n\n\tprotected abstract createNestedSelect(\n\t\treq: RsRequest<unknown>,\n\t\tschema: ResturaSchema,\n\t\titem: ResponseData,\n\t\trouteData: StandardRouteData,\n\t\tsqlParams: string[]\n\t): string;\n\n\tprotected abstract executeCreateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject>;\n\n\tprotected abstract executeGetRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema // eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t): Promise<DynamicObject | any[]>;\n\tprotected abstract executeUpdateRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<DynamicObject>;\n\n\tprotected abstract executeDeleteRequest(\n\t\treq: RsRequest<unknown>,\n\t\trouteData: StandardRouteData,\n\t\tschema: ResturaSchema\n\t): Promise<boolean>;\n}\n","import peg, { ParserBuildOptions } from 'pegjs';\n\nconst filterSqlGrammar = `\n{\n// ported from pg-format but intentionally will add double quotes to every column\n function quoteSqlIdentity(value) {\n if (value === undefined || value === null) {\n throw new Error('SQL identifier cannot be null or undefined');\n } else if (value === false) {\n return '\"f\"';\n } else if (value === true) {\n return '\"t\"';\n } else if (value instanceof Date) {\n // return '\"' + formatDate(value.toISOString()) + '\"';\n } else if (value instanceof Buffer) {\n throw new Error('SQL identifier cannot be a buffer');\n } else if (Array.isArray(value) === true) {\n var temp = [];\n for (var i = 0; i < value.length; i++) {\n if (Array.isArray(value[i]) === true) {\n throw new Error('Nested array to grouped list conversion is not supported for SQL identifier');\n } else {\n // temp.push(quoteIdent(value[i]));\n }\n }\n return temp.toString();\n } else if (value === Object(value)) {\n throw new Error('SQL identifier cannot be an object');\n }\n\n var ident = value.toString().slice(0); // create copy\n\n // do not quote a valid, unquoted identifier\n // if (/^[a-z_][a-z0-9_$]*$/.test(ident) === true && isReserved(ident) === false) {\n // return ident;\n // }\n\n var quoted = '\"';\n\n for (var i = 0; i < ident.length; i++) {\n var c = ident[i];\n if (c === '\"') {\n quoted += c + c;\n } else {\n quoted += c;\n }\n }\n\n quoted += '\"';\n\n return quoted;\n};\n}\n\nstart = expressionList\n\n_ = [ \\\\t\\\\r\\\\n]* // Matches spaces, tabs, and line breaks\n\nexpressionList =\n leftExpression:expression _ operator:operator _ rightExpression:expressionList \n { return \\`\\${leftExpression} \\${operator} \\${rightExpression}\\`;}\n / expression\n\nexpression = \n negate:negate? _ \"(\" _ \"column\" _ \":\" column:column _ \",\"? _ value:value? \",\"? _ type:type? _ \")\"_\n {return \\`\\${negate? \" NOT \" : \"\"}(\\${type? type(column, value) : \\`\\${column\\} = \\${format.literal(value)}\\`})\\`;}\n /\n negate:negate?\"(\"expression:expressionList\")\" { return \\`\\${negate? \" NOT \" : \"\"}(\\${expression})\\`; }\n\nnegate = \"!\"\n \noperator = \"and\"i / \"or\"i\n\n\t \ncolumn = first:text rest:(\".\" text)* { \n const partsArray = [first];\n if (rest && rest.length > 0) {\n partsArray.push(...rest.map(item => item[1]));\n }\n \n if (partsArray.length > 3) {\n throw new SyntaxError('Column path cannot have more than 3 parts (table.column.jsonField)');\n }\n \n if (partsArray.length === 1) {\n return quoteSqlIdentity(partsArray[0]);\n }\n const tableName = quoteSqlIdentity(partsArray[0]);\n \n // If we only have two parts (table.column), use regular dot notation\n if (partsArray.length === 2) {\n return tableName + \".\" + quoteSqlIdentity(partsArray[1]);\n }\n \n // For JSON paths (more than 2 parts), first part is a column, last part uses ->>\n const jsonColumn = quoteSqlIdentity(partsArray[1]);\n const lastPart = partsArray[partsArray.length - 1];\n const result = tableName + \".\" + jsonColumn + \"->>'\" + lastPart + \"'\";\n return result;\n}\n\ntext = text:[a-z0-9 \\\\t\\\\r\\\\n\\\\-_:@']i+ { return text.join(\"\"); }\n\n\ntype = \"type\" _ \":\" _ type:typeString { return type; }\ntypeString = text:\"startsWith\" { return function(column, value) { return \\`\\${column} ILIKE '\\${format.literal(value).slice(1,-1)}%'\\`; } } /\n text:\"endsWith\" { return function(column, value) { return \\`\\${column} ILIKE '%\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"contains\" { return function(column, value) { return \\`\\${column} ILIKE '%\\${format.literal(value).slice(1,-1)}%'\\`; } } /\n text:\"exact\" { return function(column, value) { return \\`\\${column} = '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"greaterThanEqual\" { return function(column, value) { return \\`\\${column} >= '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"greaterThan\" { return function(column, value) { return \\`\\${column} > '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"lessThanEqual\" { return function(column, value) { return \\`\\${column} <= '\\${format.literal(value).slice(1,-1)}'\\`; } } /\n text:\"lessThan\" { return function(column, value) { return \\`\\${column} < '\\${format.literal(value).slice(1,-1)}'\\`; } } / \n text:\"isNull\" { return function(column, value) { return \\`isNull(\\${column})\\`; } } \n\nvalue = \"value\" _ \":\" value:text { return value; }\n\n\n`;\n\nconst filterPsqlParser = peg.generate(filterSqlGrammar, {\n\tformat: 'commonjs',\n\tdependencies: { format: 'pg-format' }\n} as ParserBuildOptions);\nexport default filterPsqlParser;\n","import fs from 'fs';\nimport path from 'path';\n\nimport { DateUtils } from '@redskytech/core-utils';\nimport { FileUtils } from '@restura/internal';\nimport Bluebird from 'bluebird';\nimport * as os from 'os';\nimport { logger } from '../../logger/logger.js';\n\nexport default class TempCache {\n\tlocation: string;\n\tprivate readonly maxDurationDays = 7;\n\n\tconstructor(location?: string) {\n\t\tthis.location = location || os.tmpdir();\n\t\tFileUtils.ensureDir(this.location).catch((e) => {\n\t\t\tthrow e;\n\t\t});\n\t}\n\n\tasync cleanup() {\n\t\tconst fileList = await fs.promises.readdir(this.location);\n\t\tawait Bluebird.map(\n\t\t\tfileList,\n\t\t\tasync (file) => {\n\t\t\t\tconst fullFilePath = path.join(this.location, file);\n\t\t\t\tconst fileStats = await fs.promises.stat(fullFilePath);\n\t\t\t\tif (\n\t\t\t\t\tDateUtils.daysBetweenStartAndEndDates(new Date(fileStats.mtimeMs), new Date()) >\n\t\t\t\t\tthis.maxDurationDays\n\t\t\t\t) {\n\t\t\t\t\tlogger.info(`Deleting old temp file: ${file}`);\n\t\t\t\t\tawait fs.promises.unlink(fullFilePath);\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ concurrency: 10 }\n\t\t);\n\t}\n}\n","import { UUID } from 'crypto';\nimport type { ClientConfig, Client as ClientType, QueryConfigValues, QueryResult, QueryResultRow } from 'pg';\nimport pg from 'pg';\nimport { PsqlConnection } from './PsqlConnection.js';\n\nconst { Client } = pg;\n\nexport class PsqlTransaction extends PsqlConnection {\n\tpublic client: ClientType;\n\tprivate beginTransactionPromise: Promise<QueryResult<QueryResultRow>>;\n\tprivate connectPromise: Promise<void>;\n\n\tconstructor(\n\t\tpublic clientConfig: ClientConfig,\n\t\tinstanceId?: UUID\n\t) {\n\t\tsuper(instanceId);\n\t\tthis.client = new Client(clientConfig);\n\t\tthis.connectPromise = this.client.connect();\n\t\tthis.beginTransactionPromise = this.beginTransaction();\n\t}\n\tasync close() {\n\t\tif (this.client) {\n\t\t\tawait this.client.end();\n\t\t}\n\t}\n\n\tprivate async beginTransaction() {\n\t\tawait this.connectPromise;\n\t\treturn this.client.query('BEGIN');\n\t}\n\n\tasync rollback() {\n\t\treturn this.query('ROLLBACK');\n\t}\n\n\tasync commit() {\n\t\treturn this.query('COMMIT');\n\t}\n\n\tasync release() {\n\t\treturn this.client.end();\n\t}\n\n\tprotected async query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(\n\t\tquery: string,\n\t\tvalues?: QueryConfigValues<T>\n\t): Promise<QueryResult<R>> {\n\t\tawait this.connectPromise;\n\t\tawait this.beginTransactionPromise;\n\t\treturn this.client.query(query, values);\n\t}\n}\n"],"mappings":"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","names":["HtmlStatusCodes","path","StringUtils","prettier","prettier","StringUtils","ObjectUtils","StringUtils","config","_typeof","obj","get","fs","path","prettier","path","original","Bluebird","isTsx","isTsNode","Bluebird","fs","path","fs","path","z","z","z","ObjectUtils","z","z","ObjectUtils","z","ObjectUtils","pg","format","z","format","isValueNumber","z","format","ObjectUtils","item","join","ObjectUtils","pg","resolve","ObjectUtils","column","fs","path","FileUtils","Bluebird","os","FileUtils","fs","Bluebird","path","config","fs","ObjectUtils","path","resolve","StringUtils","pg","Client","pg"]}
|