@restura/core 0.1.0-alpha.7 → 0.1.0-alpha.8

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/logger/logger.ts","../src/config.schema.ts","../src/restura/restura.ts","../../../node_modules/.pnpm/autobind-decorator@2.4.0/node_modules/autobind-decorator/lib/esm/index.js","../src/restura/errors.ts","../src/restura/SqlUtils.ts","../src/restura/ResponseValidator.ts","../src/restura/apiGenerator.ts","../src/restura/middleware/addApiResponseFunctions.ts","../src/restura/validateRequestParams.ts","../src/restura/restura.schema.ts","../src/restura/middleware/schemaValidation.ts","../src/restura/modelGenerator.ts","../src/restura/middleware/authenticateUser.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 '../config.schema.js';\n\nconst loggerConfig = 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\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\t//defaultMeta: { service: 'user-service' },\n\ttransports: [\n\t\t//\n\t\t// - Write to all logs with level `info` and below to `combined.log`\n\t\t// - Write all logs error (and below) to `error.log`.\n\t\t// - Write all logs to standard out.\n\t\t//\n\t\t// new winston.transports.File({ filename: 'error.log', level: 'error' }),\n\t\t// new winston.transports.File({ filename: 'combined.log' }),\n\t\tnew winston.transports.Console({ format: consoleFormat })\n\t]\n});\n\nexport { logger };\n","import { z } from 'zod';\n\nexport const loggerConfigSchema = z.object({\n\tlevel: z.enum(['info', 'warn', 'error', 'debug']).default('info')\n});\nexport type LoggerConfigSchema = z.infer<typeof loggerConfigSchema>;\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\tgeneratedTypesPath: z.string().default(process.cwd() + '/src/@types')\n});\nexport type ResturaConfigSchema = z.infer<typeof resturaConfigSchema>;\n","import { ObjectUtils } 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 { createHash } from 'crypto';\nimport * as express from 'express';\nimport fs from 'fs';\nimport path from 'path';\nimport * as prettier from 'prettier';\nimport { resturaConfigSchema, type ResturaConfigSchema } from '../config.schema.js';\nimport { logger } from '../logger/logger.js';\nimport ResponseValidator from './ResponseValidator.js';\nimport apiGenerator from './apiGenerator.js';\nimport { RsError } from './errors.js';\nimport addApiResponseFunctions from './middleware/addApiResponseFunctions.js';\nimport { schemaValidation } from './middleware/schemaValidation.js';\nimport modelGenerator from './modelGenerator.js';\nimport { isSchemaValid, type CustomRouteData, type ResturaSchema, type RouteData } from './restura.schema.js';\nimport type { RsRequest, RsResponse } from './types/expressCustom.js';\nimport type { AuthenticateHandler } from './types/restura.types.js';\nimport { authenticateUser } from './middleware/authenticateUser.js';\n\nclass ResturaEngine {\n\t// Make public so other modules can access without re-parsing the config\n\tresturaConfig!: ResturaConfigSchema;\n\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\t// private customTypeValidation!: ValidationDictionary;\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(app: express.Application, authenticationHandler: AuthenticateHandler): Promise<void> {\n\t\tthis.resturaConfig = config.validate('restura', resturaConfigSchema) as ResturaConfigSchema;\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/', authenticateUser 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\tthis.validateGeneratedTypesFolder();\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 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(\n\t\t\toutputFile,\n\t\t\tawait apiGenerator(providedSchema, await this.generateHashForSchema(providedSchema))\n\t\t);\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(\n\t\t\toutputFile,\n\t\t\tawait modelGenerator(providedSchema, await this.generateHashForSchema(providedSchema))\n\t\t);\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\t/**\n\t * Asynchronously generates and retrieves hashes for the provided schema and related generated files.\n\t *\n\t * @param providedSchema - The schema for which hashes need to be generated.\n\t * @returns A promise that resolves to an object containing:\n\t * - `schemaHash`: The hash of the provided schema.\n\t * - `apiCreatedSchemaHash`: The hash extracted from the generated `api.d.ts` file.\n\t * - `modelCreatedSchemaHash`: The hash extracted from the generated `models.d.ts` file.\n\t */\n\tasync getHashes(providedSchema: ResturaSchema): Promise<{\n\t\tschemaHash: string;\n\t\tapiCreatedSchemaHash: string;\n\t\tmodelCreatedSchemaHash: string;\n\t}> {\n\t\tconst schemaHash = await this.generateHashForSchema(providedSchema);\n\t\tconst apiFile = fs.readFileSync(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'));\n\t\tconst apiCreatedSchemaHash = apiFile.toString().match(/\\((.*)\\)/)?.[1] ?? '';\n\t\tconst modelFile = fs.readFileSync(path.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'));\n\t\tconst modelCreatedSchemaHash = modelFile.toString().match(/\\((.*)\\)/)?.[1] ?? '';\n\t\treturn {\n\t\t\tschemaHash,\n\t\t\tapiCreatedSchemaHash,\n\t\t\tmodelCreatedSchemaHash\n\t\t};\n\t}\n\n\tprivate async reloadEndpoints() {\n\t\tthis.schema = await this.getLatestFileSystemSchema();\n\t\t// this.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) this.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 validateGeneratedTypesFolder() {\n\t\tif (!fs.existsSync(this.resturaConfig.generatedTypesPath)) {\n\t\t\tfs.mkdirSync(this.resturaConfig.generatedTypesPath, { recursive: true });\n\t\t}\n\n\t\tconst hasApiFile = fs.existsSync(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'));\n\t\tconst hasModelsFile = fs.existsSync(path.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'));\n\n\t\tif (!hasApiFile) {\n\t\t\tawait this.generateApiFromSchema(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'), this.schema);\n\t\t}\n\t\tif (!hasModelsFile) {\n\t\t\tawait this.generateModelFromSchema(\n\t\t\t\tpath.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\t\tthis.schema\n\t\t\t);\n\t\t}\n\n\t\t// Now get the hashes for the schema and the generated files and regenerate if needed\n\t\tconst hashes = await this.getHashes(this.schema);\n\t\tif (hashes.schemaHash !== hashes.apiCreatedSchemaHash) {\n\t\t\tawait this.generateApiFromSchema(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'), this.schema);\n\t\t}\n\t\tif (hashes.schemaHash !== hashes.modelCreatedSchemaHash) {\n\t\t\tawait this.generateModelFromSchema(\n\t\t\t\tpath.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\t\tthis.schema\n\t\t\t);\n\t\t}\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\t// const schemaDiff = await compareSchema.diffSchema(req.data, this.schema);\n\t\t\tconst schemaDiff = { commands: '', endPoints: [], globalParams: [], roles: [], customTypes: false }; // todo remove this line\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 = 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}\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 schemaHash = await this.generateHashForSchema(schema);\n\t\t\tconst apiText = await apiGenerator(schema, schemaHash);\n\t\t\tconst modelsText = await modelGenerator(schema, schemaHash);\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\t// private 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 =\n\t// \t\trouteData.fileUploadType === 'MULTIPLE'\n\t// \t\t\t? multerCommonUpload.array('files')\n\t// \t\t\t: 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 user has access to the endpoint\n\t\t\tthis.validateAuthorization(req, routeData);\n\n\t\t\t// Check for file uploads\n\t\t\t// await this.getMulterFilesIfAny(req, res, routeData);\n\n\t\t\t// Validate the request and assign to req.data\n\t\t\t// validateRequestParams(req as RsRequest<DynamicObject>, routeData, this.customTypeValidation);\n\n\t\t\t// Check for custom logic\n\t\t\t// if (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\t// const data = await sqlEngine.runQueryForRoute(req as RsRequest<DynamicObject>, routeData, this.schema);\n\n\t\t\t// Validate the response\n\t\t\t// this.responseValidator.validateResponseParams(data, req.baseUrl, routeData);\n\n\t\t\t// Send response\n\t\t\t// if (routeData.type === 'PAGED') res.sendNoWrap(data as T);\n\t\t\t// else 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\t// private 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 = apiFactory.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) throw new RsError('NOT_FOUND', `API path ${routeData.path} not implemented`);\n\t// \tawait customFunction(req, res, routeData);\n\t// }\n\n\tprivate async generateHashForSchema(providedSchema: ResturaSchema): Promise<string> {\n\t\tconst schemaPrettyStr = await prettier.format(JSON.stringify(providedSchema), {\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\treturn createHash('sha256').update(schemaPrettyStr).digest('hex');\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 role = req.requesterDetails.role;\n\t\tif (routeData.roles.length === 0 || !role) return;\n\t\tif (!routeData.roles.includes(role))\n\t\t\tthrow new RsError('UNAUTHORIZED', 'Not authorized to access this endpoint');\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}","/* 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\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\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\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};\n","import type { ValidatorString } from './types/restura.types.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 (\n\t\t\ttype.indexOf('int') > -1 ||\n\t\t\ttype.startsWith('decimal') ||\n\t\t\ttype.startsWith('double') ||\n\t\t\ttype.startsWith('float')\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","import { RsError } from './errors.js';\nimport { SqlUtils } from './SqlUtils.js';\nimport type {\n\tCustomRouteData,\n\tResponseData,\n\tResponseType,\n\tResponseTypeMap,\n\tResturaSchema,\n\tRouteData,\n\tStandardRouteData,\n\tTableData,\n\tValidatorString\n} from './types/restura.types.js';\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);\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): ResponseType {\n\t\tif (field.selector) {\n\t\t\treturn this.getTypeFromTable(field.selector, tableName);\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 isOptional = table.roles.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);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tisArray: true,\n\t\t\t\tisOptional,\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): ResponseType {\n\t\tconst path = selector.split('.');\n\t\tif (path.length === 0 || path.length > 2 || path[0] === '') return { validator: 'any', isOptional: false };\n\n\t\tconst tableName = path.length == 2 ? path[0] : name,\n\t\t\tcolumnName = path.length == 2 ? path[1] : path[0];\n\t\tconst table = this.database.find((t) => t.name == tableName);\n\t\tconst column = table?.columns.find((c) => c.name == columnName);\n\t\tif (!table || !column) return { validator: 'any', isOptional: false };\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\tisOptional: column.roles.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{ isOptional, 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 (isOptional) 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 { ObjectUtils, StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport ResponseValidator from './ResponseValidator.js';\nimport type { EndpointData, ResponseData, ResturaSchema, RouteData, TableData } from './restura.schema.js';\nimport { SqlUtils } from './SqlUtils.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}`;\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)}`;\n\t}\n\n\tgetFields(fields: ReadonlyArray<ResponseData>): string {\n\t\tconst nameFields = fields.map((f) => this.getNameAndType(f));\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): string {\n\t\tlet responseType = 'any',\n\t\t\toptional = false,\n\t\t\tarray = false;\n\t\tif (p.selector) {\n\t\t\t({ responseType, optional } = this.getTypeFromTable(p.selector, p.name));\n\t\t} else if (p.subquery) {\n\t\t\tresponseType = this.getFields(p.subquery.properties);\n\t\t\tarray = true;\n\t\t}\n\t\treturn `${p.name}${optional ? '?' : ''}:${responseType}${array ? '[]' : ''}`;\n\t}\n\n\tgetTypeFromTable(selector: string, name: string): { responseType: string; optional: boolean } {\n\t\tconst path = selector.split('.');\n\t\tif (path.length === 0 || path.length > 2 || path[0] === '') return { responseType: 'any', optional: 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', optional: false };\n\n\t\treturn {\n\t\t\tresponseType: SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value),\n\t\t\toptional: column.roles.length > 0 || column.isNullable\n\t\t};\n\t}\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, schemaHash: string): Promise<string> {\n\tlet apiString = `/** Auto generated file from Schema Hash (${schemaHash}). DO NOT MODIFY **/`;\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\tif (schema.customTypes.length > 0) {\n\t\tapiString += `\\n\n\t\tdeclare namespace CustomTypes {\n\t\t\t${schema.customTypes}\n\t\t}`;\n\t}\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 { NextFunction } from 'express';\nimport { RsError, type ErrorCode, type HtmlStatusCodes } from '../errors.js';\nimport { restura } from '../restura.js';\nimport type { RsRequest, RsResponse } from '../types/expressCustom.js';\nimport type { RsErrorData, RsPagedResponseData } from '../types/restura.types.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 { ObjectUtils } from '@redskytech/core-utils';\nimport jsonschema, { Schema } from 'jsonschema';\nimport type { DynamicObject, RsRequest } from './types/expressCustom.js';\nimport { Definition } from 'typescript-json-schema';\n\nimport { RequestData, RouteData, ValidatorData } from './restura.schema';\nimport { RsError } from './errors';\n\nexport interface ValidationDictionary {\n\t[Key: string]: Definition;\n}\n\nexport default function validateRequestParams(\n\treq: RsRequest<DynamicObject>,\n\trouteData: RouteData,\n\tvalidationSchema: ValidationDictionary\n) {\n\tconst requestData = getRequestData(req as RsRequest<DynamicObject>);\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\t\tconst executeValidation = validator.validate(req.data, currentInterface 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).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\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 performTypeCheck(requestValue: unknown, validator: ValidatorData, requestParamName: string) {\n\tif (validator.value === 'number' || validator.value === 'string' || validator.value === 'boolean') {\n\t\tif (typeof requestValue !== validator.value) {\n\t\t\tthrow new RsError(\n\t\t\t\t'BAD_REQUEST',\n\t\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not of type (${validator.value})`\n\t\t\t);\n\t\t}\n\t} else if (validator.value === 'string[]' || validator.value === 'number[]' || validator.value === 'any[]') {\n\t\tif (!Array.isArray(requestValue)) {\n\t\t\tthrow new RsError(\n\t\t\t\t'BAD_REQUEST',\n\t\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not of type (${validator.value})`\n\t\t\t);\n\t\t}\n\t\tif (validator.value === 'any[]') return;\n\t\trequestValue.forEach((value: unknown) => {\n\t\t\tif (typeof value !== (validator.value as string).replace('[]', '')) {\n\t\t\t\tthrow new RsError(\n\t\t\t\t\t'BAD_REQUEST',\n\t\t\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not of type (${validator.value})`\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t} else if (validator.value === 'object') {\n\t\tif (typeof requestValue !== 'object') {\n\t\t\tthrow new RsError(\n\t\t\t\t'BAD_REQUEST',\n\t\t\t\t`Request param (${requestParamName}) with value (${requestValue}) is not of type (${validator.value})`\n\t\t\t);\n\t\t}\n\t} else {\n\t\tthrow new RsError('SCHEMA_ERROR', `Schema validator value (${validator.value}) is not a valid type`);\n\t}\n}\n\nfunction performMinCheck(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\tif (requestValue < validator.value)\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\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\tif (requestValue > validator.value)\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<DynamicObject>): 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) {\n\t\tfor (const attr in bodyData) {\n\t\t\tif (attr === 'token') {\n\t\t\t\tdelete bodyData[attr];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (bodyData[attr] instanceof Array) {\n\t\t\t\tconst attrList = [];\n\t\t\t\tfor (const value of bodyData[attr]) {\n\t\t\t\t\tif (isNaN(Number(value))) continue;\n\t\t\t\t\tattrList.push(Number(value));\n\t\t\t\t}\n\t\t\t\tif (ObjectUtils.isArrayWithData(attrList)) {\n\t\t\t\t\tbodyData[attr] = attrList;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tbodyData[attr] = ObjectUtils.safeParse(bodyData[attr]);\n\t\t\t\tif (isNaN(Number(bodyData[attr]))) continue;\n\t\t\t\tbodyData[attr] = Number(bodyData[attr]);\n\t\t\t}\n\t\t}\n\t}\n\treturn bodyData;\n}\n","import { z } from 'zod';\nimport { logger } from '../logger/logger.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(['=', '<', '>', '<=', '>=', '!=', 'LIKE', 'IN', 'NOT IN', 'STARTS WITH', 'ENDS WITH'])\n\t\t\t.optional(),\n\t\tvalue: z.string().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\tlocalColumnName: z.string().optional(),\n\t\tforeignColumnName: z.string().optional(),\n\t\tcustom: z.string().optional(),\n\t\ttype: z.enum(['LEFT', 'INNER']),\n\t\talias: z.string().optional()\n\t})\n\t.strict();\n\nexport type JoinData = z.infer<typeof joinDataSchema>;\n\nconst validatorDataSchema = z\n\t.object({\n\t\ttype: z.enum(['TYPE_CHECK', 'MIN', 'MAX', 'ONE_OF']),\n\t\tvalue: z.union([z.string(), z.array(z.string()), z.number(), z.array(z.number())])\n\t})\n\t.strict();\n\nexport type ValidatorData = z.infer<typeof validatorDataSchema>;\n\nconst requestDataSchema = z\n\t.object({\n\t\tname: z.string(),\n\t\trequired: z.boolean(),\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\tproperties: z.array(z.lazy((): z.ZodSchema => responseDataSchema)), // Explicit type for the lazy schema\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})\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})\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\n// PostgresColumnNumericTypes Zod enum with PascalCase values and comments\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\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\n// PostgresColumnStringTypes Zod enum with PascalCase values and comments\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\n// PostgresColumnDateTypes Zod enum with PascalCase values and comments\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\n// MariaDbColumnNumericTypes Zod enum with PascalCase values and comments\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\n// MariaDbColumnStringTypes Zod enum with PascalCase values and comments\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\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\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})\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 resturaZodSchema = 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\tcustomTypes: z.string()\n\t})\n\t.strict();\n\nexport type ResturaSchema = z.infer<typeof resturaZodSchema>;\n\nexport async function isSchemaValid(schemaToCheck: unknown): Promise<boolean> {\n\ttry {\n\t\tresturaZodSchema.parse(schemaToCheck);\n\t\treturn true;\n\t} catch (error) {\n\t\tlogger.error(error);\n\t\treturn false;\n\t}\n}\n","import type { NextFunction } from 'express';\nimport type { DynamicObject, RsRequest, RsResponse } from '../types/expressCustom.js';\nimport { getRequestData } from '../validateRequestParams.js';\nimport { logger } from '../../logger/logger.js';\nimport { HtmlStatusCodes } from '../errors.js';\nimport { resturaZodSchema } from '../restura.schema.js';\n\nexport async function schemaValidation(req: RsRequest<unknown>, res: RsResponse<unknown>, next: NextFunction) {\n\treq.data = getRequestData(req as RsRequest<DynamicObject>);\n\n\ttry {\n\t\tresturaZodSchema.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 { StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport { SqlUtils } from './SqlUtils.js';\nimport type { ResturaSchema, TableData } from './restura.schema.js';\n\nexport default function modelGenerator(schema: ResturaSchema, schemaHash: string): Promise<string> {\n\tlet modelString = `/** Auto generated file from Schema Hash (${schemaHash}). DO NOT MODIFY **/\\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}${column.isNullable ? '?' : ''}: ${SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value)};\\n`;\n\t}\n\tmodelString += `\\t}\\n`;\n\treturn modelString;\n}\n","import type { NextFunction } from 'express';\nimport type { RsRequest, RsResponse } from '../types/expressCustom.js';\nimport type { AuthenticateHandler, RoleWithOptionalUserDetails } from '../types/restura.types.js';\n\nexport async function authenticateUser(applicationAuthenticateHandler: AuthenticateHandler) {\n\treturn (req: RsRequest, res: RsResponse, next: NextFunction) => {\n\t\t// Call the custom function\n\t\tapplicationAuthenticateHandler(\n\t\t\treq,\n\t\t\t(userDetails: RoleWithOptionalUserDetails) => {\n\t\t\t\treq.requesterDetails = { ...req.requesterDetails, ...userDetails };\n\t\t\t\tnext();\n\t\t\t},\n\t\t\t(errorMessage: string) => {\n\t\t\t\tres.sendError('UNAUTHORIZED', errorMessage);\n\t\t\t}\n\t\t);\n\t};\n}\n"],"mappings":"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","names":["ObjectUtils","config","_typeof","obj","get","prettier","path","path","ObjectUtils","ObjectUtils","z","z","StringUtils","prettier","prettier","StringUtils","config","ObjectUtils","path"]}
1
+ {"version":3,"sources":["../src/logger/logger.ts","../src/config.schema.ts","../src/restura/restura.ts","../../../node_modules/.pnpm/autobind-decorator@2.4.0/node_modules/autobind-decorator/lib/esm/index.js","../src/restura/errors.ts","../src/restura/sql/SqlUtils.ts","../src/restura/ResponseValidator.ts","../src/restura/apiGenerator.ts","../src/restura/middleware/addApiResponseFunctions.ts","../src/restura/validateRequestParams.ts","../src/restura/types/validation.types.ts","../src/restura/utils/addQuotesToStrings.ts","../src/restura/restura.schema.ts","../src/restura/middleware/schemaValidation.ts","../src/restura/modelGenerator.ts","../src/restura/middleware/authenticateUser.ts","../src/restura/customTypeValidationGenerator.ts","../src/restura/sql/SqlEngine.ts","../src/restura/sql/filterSqlParser.ts","../src/restura/sql/PsqlEngine.ts","../src/restura/sql/PsqlUtils.ts","../src/restura/sql/PsqlPool.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 '../config.schema.js';\n\nconst loggerConfig = 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\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\t//defaultMeta: { service: 'user-service' },\n\ttransports: [\n\t\t//\n\t\t// - Write to all logs with level `info` and below to `combined.log`\n\t\t// - Write all logs error (and below) to `error.log`.\n\t\t// - Write all logs to standard out.\n\t\t//\n\t\t// new winston.transports.File({ filename: 'error.log', level: 'error' }),\n\t\t// new winston.transports.File({ filename: 'combined.log' }),\n\t\tnew winston.transports.Console({ format: consoleFormat })\n\t]\n});\n\nexport { logger };\n","import { z } from 'zod';\n\nexport const loggerConfigSchema = z.object({\n\tlevel: z.enum(['info', 'warn', 'error', 'debug']).default('info')\n});\nexport type LoggerConfigSchema = z.infer<typeof loggerConfigSchema>;\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\tgeneratedTypesPath: z.string().default(process.cwd() + '/src/@types')\n});\nexport type ResturaConfigSchema = z.infer<typeof resturaConfigSchema>;\n","import { ObjectUtils } 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 { createHash } from 'crypto';\nimport * as express from 'express';\nimport fs from 'fs';\nimport path from 'path';\nimport * as prettier from 'prettier';\nimport { resturaConfigSchema, type ResturaConfigSchema } from '../config.schema.js';\nimport { logger } from '../logger/logger.js';\nimport ResponseValidator from './ResponseValidator.js';\nimport apiGenerator from './apiGenerator.js';\nimport { RsError } from './errors.js';\nimport addApiResponseFunctions from './middleware/addApiResponseFunctions.js';\nimport { schemaValidation } from './middleware/schemaValidation.js';\nimport modelGenerator from './modelGenerator.js';\nimport {\n\tisSchemaValid,\n\ttype CustomRouteData,\n\ttype ResturaSchema,\n\ttype RouteData,\n\tStandardRouteData\n} from './restura.schema.js';\nimport type { RsRequest, RsResponse } from './types/expressCustom.js';\nimport type { AuthenticateHandler } from './types/restura.types.js';\nimport { authenticateUser } from './middleware/authenticateUser.js';\nimport validateRequestParams, { ValidationDictionary } from './validateRequestParams.js';\nimport customTypeValidationGenerator from './customTypeValidationGenerator.js';\nimport PsqlEngine from './sql/PsqlEngine.js';\nimport { types } from 'pg';\nimport { PsqlPool } from './sql/PsqlPool.js';\n\nclass ResturaEngine {\n\t// Make public so other modules can access without re-parsing the config\n\tresturaConfig!: ResturaConfigSchema;\n\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\tthis.psqlConnectionPool = psqlConnectionPool;\n\t\tthis.psqlEngine = new PsqlEngine(this.psqlConnectionPool);\n\t\tsetupPgReturnTypes();\n\t\tthis.resturaConfig = config.validate('restura', resturaConfigSchema) as ResturaConfigSchema;\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/', authenticateUser(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.validateGeneratedTypesFolder();\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 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(\n\t\t\toutputFile,\n\t\t\tawait apiGenerator(providedSchema, await this.generateHashForSchema(providedSchema))\n\t\t);\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(\n\t\t\toutputFile,\n\t\t\tawait modelGenerator(providedSchema, await this.generateHashForSchema(providedSchema))\n\t\t);\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\t/**\n\t * Asynchronously generates and retrieves hashes for the provided schema and related generated files.\n\t *\n\t * @param providedSchema - The schema for which hashes need to be generated.\n\t * @returns A promise that resolves to an object containing:\n\t * - `schemaHash`: The hash of the provided schema.\n\t * - `apiCreatedSchemaHash`: The hash extracted from the generated `api.d.ts` file.\n\t * - `modelCreatedSchemaHash`: The hash extracted from the generated `models.d.ts` file.\n\t */\n\tasync getHashes(providedSchema: ResturaSchema): Promise<{\n\t\tschemaHash: string;\n\t\tapiCreatedSchemaHash: string;\n\t\tmodelCreatedSchemaHash: string;\n\t}> {\n\t\tconst schemaHash = await this.generateHashForSchema(providedSchema);\n\t\tconst apiFile = fs.readFileSync(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'));\n\t\tconst apiCreatedSchemaHash = apiFile.toString().match(/\\((.*)\\)/)?.[1] ?? '';\n\t\tconst modelFile = fs.readFileSync(path.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'));\n\t\tconst modelCreatedSchemaHash = modelFile.toString().match(/\\((.*)\\)/)?.[1] ?? '';\n\t\treturn {\n\t\t\tschemaHash,\n\t\t\tapiCreatedSchemaHash,\n\t\t\tmodelCreatedSchemaHash\n\t\t};\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) this.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 validateGeneratedTypesFolder() {\n\t\tif (!fs.existsSync(this.resturaConfig.generatedTypesPath)) {\n\t\t\tfs.mkdirSync(this.resturaConfig.generatedTypesPath, { recursive: true });\n\t\t}\n\n\t\tconst hasApiFile = fs.existsSync(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'));\n\t\tconst hasModelsFile = fs.existsSync(path.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'));\n\n\t\tif (!hasApiFile) {\n\t\t\tawait this.generateApiFromSchema(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'), this.schema);\n\t\t}\n\t\tif (!hasModelsFile) {\n\t\t\tawait this.generateModelFromSchema(\n\t\t\t\tpath.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\t\tthis.schema\n\t\t\t);\n\t\t}\n\n\t\t// Now get the hashes for the schema and the generated files and regenerate if needed\n\t\tconst hashes = await this.getHashes(this.schema);\n\t\tif (hashes.schemaHash !== hashes.apiCreatedSchemaHash) {\n\t\t\tawait this.generateApiFromSchema(path.join(this.resturaConfig.generatedTypesPath, 'api.d.ts'), this.schema);\n\t\t}\n\t\tif (hashes.schemaHash !== hashes.modelCreatedSchemaHash) {\n\t\t\tawait this.generateModelFromSchema(\n\t\t\t\tpath.join(this.resturaConfig.generatedTypesPath, 'models.d.ts'),\n\t\t\t\tthis.schema\n\t\t\t);\n\t\t}\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\t// const schemaDiff = await compareSchema.diffSchema(req.data, this.schema);\n\t\t\tconst schemaDiff = { commands: '', endPoints: [], globalParams: [], roles: [], customTypes: false }; // todo remove this line\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 = 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}\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 schemaHash = await this.generateHashForSchema(schema);\n\t\t\tconst apiText = await apiGenerator(schema, schemaHash);\n\t\t\tconst modelsText = await modelGenerator(schema, schemaHash);\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\t// private 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 =\n\t// \t\trouteData.fileUploadType === 'MULTIPLE'\n\t// \t\t\t? multerCommonUpload.array('files')\n\t// \t\t\t: 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 user has access to the endpoint\n\t\t\tthis.validateAuthorization(req, routeData);\n\n\t\t\t// Check for file uploads\n\t\t\t// await this.getMulterFilesIfAny(req, res, routeData);\n\n\t\t\t// Validate the request and assign to req.data\n\t\t\tvalidateRequestParams(req as RsRequest<unknown>, routeData, this.customTypeValidation);\n\n\t\t\t// Check for custom logic\n\t\t\t// if (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\t// this.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\t// private 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 = apiFactory.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) throw new RsError('NOT_FOUND', `API path ${routeData.path} not implemented`);\n\t// \tawait customFunction(req, res, routeData);\n\t// }\n\n\tprivate async generateHashForSchema(providedSchema: ResturaSchema): Promise<string> {\n\t\tconst schemaPrettyStr = await prettier.format(JSON.stringify(providedSchema), {\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\treturn createHash('sha256').update(schemaPrettyStr).digest('hex');\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 role = req.requesterDetails.role;\n\t\tif (routeData.roles.length === 0 || !role) return;\n\t\tif (!routeData.roles.includes(role))\n\t\t\tthrow new RsError('UNAUTHORIZED', 'Not authorized to access this endpoint');\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}\nconst setupPgReturnTypes = () => {\n\t// OID for timestamptz in Postgres\n\tconst TIMESTAMPTZ_OID = 1184;\n\t// Set a custom parser for timestamptz to return an ISO string\n\ttypes.setTypeParser(TIMESTAMPTZ_OID, (val) => {\n\t\treturn val === null ? null : new Date(val).toISOString();\n\t});\n\tconst BIGINT_OID = 20;\n\t// Set a custom parser for BIGINT to return a JavaScript Number\n\ttypes.setTypeParser(BIGINT_OID, (val) => {\n\t\treturn val === null ? null : Number(val);\n\t});\n};\nsetupPgReturnTypes();\n\nconst restura = new ResturaEngine();\nexport { restura, PsqlPool };\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}","/* 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\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\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\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};\n","import { ValidatorString } from '../types/restura.types.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 (\n\t\t\ttype.indexOf('int') > -1 ||\n\t\t\ttype.startsWith('decimal') ||\n\t\t\ttype.startsWith('double') ||\n\t\t\ttype.startsWith('float')\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","import { RsError } from './errors.js';\n\nimport type {\n\tCustomRouteData,\n\tResponseData,\n\tResponseType,\n\tResponseTypeMap,\n\tResturaSchema,\n\tRouteData,\n\tStandardRouteData,\n\tTableData,\n\tValidatorString\n} from './types/restura.types.js';\nimport { SqlUtils } from './sql/SqlUtils.js';\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);\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): ResponseType {\n\t\tif (field.selector) {\n\t\t\treturn this.getTypeFromTable(field.selector, tableName);\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 isOptional = table.roles.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);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tisArray: true,\n\t\t\t\tisOptional,\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): ResponseType {\n\t\tconst path = selector.split('.');\n\t\tif (path.length === 0 || path.length > 2 || path[0] === '') return { validator: 'any', isOptional: false };\n\n\t\tconst tableName = path.length == 2 ? path[0] : name,\n\t\t\tcolumnName = path.length == 2 ? path[1] : path[0];\n\t\tconst table = this.database.find((t) => t.name == tableName);\n\t\tconst column = table?.columns.find((c) => c.name == columnName);\n\t\tif (!table || !column) return { validator: 'any', isOptional: false };\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\tisOptional: column.roles.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{ isOptional, 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 (isOptional) 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 { ObjectUtils, StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport ResponseValidator from './ResponseValidator.js';\nimport type { EndpointData, ResponseData, ResturaSchema, RouteData, TableData } from './restura.schema.js';\nimport { SqlUtils } from './sql/SqlUtils.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}`;\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)}`;\n\t}\n\n\tgetFields(fields: ReadonlyArray<ResponseData>): string {\n\t\tconst nameFields = fields.map((f) => this.getNameAndType(f));\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): string {\n\t\tlet responseType = 'any',\n\t\t\toptional = false,\n\t\t\tarray = false;\n\t\tif (p.selector) {\n\t\t\t({ responseType, optional } = this.getTypeFromTable(p.selector, p.name));\n\t\t} else if (p.subquery) {\n\t\t\tresponseType = this.getFields(p.subquery.properties);\n\t\t\tarray = true;\n\t\t}\n\t\treturn `${p.name}${optional ? '?' : ''}:${responseType}${array ? '[]' : ''}`;\n\t}\n\n\tgetTypeFromTable(selector: string, name: string): { responseType: string; optional: boolean } {\n\t\tconst path = selector.split('.');\n\t\tif (path.length === 0 || path.length > 2 || path[0] === '') return { responseType: 'any', optional: 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', optional: false };\n\n\t\treturn {\n\t\t\tresponseType: SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value),\n\t\t\toptional: column.roles.length > 0 || column.isNullable\n\t\t};\n\t}\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, schemaHash: string): Promise<string> {\n\tlet apiString = `/** Auto generated file from Schema Hash (${schemaHash}). DO NOT MODIFY **/`;\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\tif (schema.customTypes.length > 0) {\n\t\tapiString += `\\n\n\t\tdeclare namespace CustomTypes {\n\t\t\t${schema.customTypes}\n\t\t}`;\n\t}\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 { NextFunction } from 'express';\nimport { RsError, type ErrorCode, type HtmlStatusCodes } from '../errors.js';\nimport { restura } from '../restura.js';\nimport type { RsRequest, RsResponse } from '../types/expressCustom.js';\nimport type { RsErrorData, RsPagedResponseData } from '../types/restura.types.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 { ObjectUtils } from '@redskytech/core-utils';\nimport jsonschema, { Schema } from 'jsonschema';\nimport type { DynamicObject, RsRequest } from './types/expressCustom.js';\nimport { Definition } from 'typescript-json-schema';\nimport { RequestData, RouteData } from './restura.schema.js';\nimport { RsError } from './errors';\nimport { z } from 'zod';\nimport { ValidatorData, ValidatorDataSchemeValue, validatorDataSchemeValue } from './types/validation.types';\nimport addQuotesToStrings from './utils/addQuotesToStrings';\n\nexport interface ValidationDictionary {\n\t[Key: string]: Definition;\n}\n\nexport default function validateRequestParams(\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\t\tconst executeValidation = validator.validate(req.data, currentInterface 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\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tObject.keys(req.data as any[]).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\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) {\n\t\tfor (const attr in bodyData) {\n\t\t\tif (attr === 'token') {\n\t\t\t\tdelete bodyData[attr];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (bodyData[attr] instanceof Array) {\n\t\t\t\tconst attrList = [];\n\t\t\t\tfor (const value of bodyData[attr]) {\n\t\t\t\t\tif (isNaN(Number(value))) continue;\n\t\t\t\t\tattrList.push(Number(value));\n\t\t\t\t}\n\t\t\t\tif (ObjectUtils.isArrayWithData(attrList)) {\n\t\t\t\t\tbodyData[attr] = attrList;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tbodyData[attr] = ObjectUtils.safeParse(bodyData[attr]);\n\t\t\t\tif (isNaN(Number(bodyData[attr]))) continue;\n\t\t\t\tbodyData[attr] = Number(bodyData[attr]);\n\t\t\t}\n\t\t}\n\t}\n\treturn bodyData;\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","// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport default function addQuotesToStrings(variable: any): any {\n\tif (typeof variable === 'string') {\n\t\treturn `'${variable}'`; // Add quotes around strings\n\t} else if (Array.isArray(variable)) {\n\t\t// For arrays, iterate through each element and handle accordingly\n\t\tconst arrayWithQuotes = variable.map(addQuotesToStrings);\n\t\treturn arrayWithQuotes;\n\t\t// return `[${arrayWithQuotes.join(', ')}]`;\n\t} else {\n\t\treturn variable; // Print other types as is\n\t}\n}\n","import { z } from 'zod';\nimport { logger } from '../logger/logger';\nimport { validatorDataSchema } from './types/validation.types';\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(['=', '<', '>', '<=', '>=', '!=', 'LIKE', 'IN', 'NOT IN', 'STARTS WITH', 'ENDS WITH'])\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\tlocalColumnName: z.string().optional(),\n\t\tforeignColumnName: z.string().optional(),\n\t\tcustom: z.string().optional(),\n\t\ttype: z.enum(['LEFT', 'INNER']),\n\t\talias: z.string().optional()\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\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\tproperties: z.array(z.lazy((): z.ZodSchema => responseDataSchema)), // Explicit type for the lazy schema\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})\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})\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\ttable: z.undefined(),\n\t\tjoins: z.undefined(),\n\t\tassignments: z.undefined(),\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\n// PostgresColumnNumericTypes Zod enum with PascalCase values and comments\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\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\n// PostgresColumnStringTypes Zod enum with PascalCase values and comments\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\n// PostgresColumnDateTypes Zod enum with PascalCase values and comments\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\n// MariaDbColumnNumericTypes Zod enum with PascalCase values and comments\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\n// MariaDbColumnStringTypes Zod enum with PascalCase values and comments\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\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\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})\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 resturaZodSchema = 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\tcustomTypes: z.string()\n\t})\n\t.strict();\n\nexport type ResturaSchema = z.infer<typeof resturaZodSchema>;\n\nexport async function isSchemaValid(schemaToCheck: unknown): Promise<boolean> {\n\ttry {\n\t\tresturaZodSchema.parse(schemaToCheck);\n\t\treturn true;\n\t} catch (error) {\n\t\tlogger.error(error);\n\t\treturn false;\n\t}\n}\n","import type { NextFunction } from 'express';\nimport type { RsRequest, RsResponse } from '../types/expressCustom.js';\nimport { getRequestData } from '../validateRequestParams.js';\nimport { logger } from '../../logger/logger.js';\nimport { HtmlStatusCodes } from '../errors.js';\nimport { resturaZodSchema } from '../restura.schema.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\tresturaZodSchema.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 { StringUtils } from '@redskytech/core-utils';\nimport prettier from 'prettier';\nimport type { ResturaSchema, TableData } from './restura.schema.js';\nimport { SqlUtils } from './sql/SqlUtils';\n\nexport default function modelGenerator(schema: ResturaSchema, schemaHash: string): Promise<string> {\n\tlet modelString = `/** Auto generated file from Schema Hash (${schemaHash}). DO NOT MODIFY **/\\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}${column.isNullable ? '?' : ''}: ${SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value)};\\n`;\n\t}\n\tmodelString += `\\t}\\n`;\n\treturn modelString;\n}\n","import type { NextFunction } from 'express';\nimport type { RsRequest, RsResponse } from '../types/expressCustom.js';\nimport type { AuthenticateHandler, RoleWithOptionalUserDetails } from '../types/restura.types.js';\n\nexport function authenticateUser(applicationAuthenticateHandler: AuthenticateHandler) {\n\treturn (req: RsRequest, res: RsResponse, next: NextFunction) => {\n\t\t// Call the custom function\n\t\tapplicationAuthenticateHandler(\n\t\t\treq,\n\t\t\t(userDetails: RoleWithOptionalUserDetails) => {\n\t\t\t\treq.requesterDetails = { ...req.requesterDetails, ...userDetails };\n\t\t\t\tnext();\n\t\t\t},\n\t\t\t(errorMessage: string) => {\n\t\t\t\tres.sendError('UNAUTHORIZED', errorMessage);\n\t\t\t}\n\t\t);\n\t};\n}\n","import fs from 'fs';\nimport * as TJS from 'typescript-json-schema';\nimport path, { resolve } from 'path';\nimport { Definition } from 'typescript-json-schema';\nimport tmp from 'tmp';\nimport * as process from 'process';\nimport { ResturaSchema } from './restura.schema.js';\n\nexport interface ValidationDictionary {\n\t[Key: string]: Definition;\n}\n\nexport default function customTypeValidationGenerator(currentSchema: ResturaSchema): ValidationDictionary {\n\tconst schemaObject: ValidationDictionary = {};\n\tconst customInterfaceNames = currentSchema.customTypes.match(/(?<=interface\\s)(\\w+)|(?<=type\\s)(\\w+)/g);\n\tif (!customInterfaceNames) return {};\n\n\tconst temporaryFile = tmp.fileSync({ mode: 0o644, prefix: 'prefix-', postfix: '.ts' });\n\tfs.writeFileSync(temporaryFile.name, currentSchema.customTypes);\n\n\t// optionally pass ts compiler options\n\tconst compilerOptions: TJS.CompilerOptions = {\n\t\tstrictNullChecks: true,\n\t\tskipLibCheck: true\n\t};\n\n\tconst program = TJS.getProgramFromFiles(\n\t\t[\n\t\t\tresolve(temporaryFile.name), // find a way to remove\n\t\t\tpath.join(process.cwd(), 'src/@types/models.d.ts'),\n\t\t\tpath.join(process.cwd(), 'src/@types/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 { RsError } from '../errors';\nimport {\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tRouteData,\n\tStandardRouteData,\n\tTableData,\n\tWhereData\n} from '../restura.schema.js';\nimport { DynamicObject, RsRequest } from '../types/expressCustom.js';\nimport { ObjectUtils } from '@redskytech/core-utils';\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 (!this.doesRoleHavePermissionToTable(req.requesterDetails.role, schema, routeData.table))\n\t\t\tthrow new RsError('UNAUTHORIZED', '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 doesRoleHavePermissionToColumn(\n\t\trole: string | undefined | null,\n\t\tschema: ResturaSchema,\n\t\titem: ResponseData,\n\t\tjoins: JoinData[]\n\t): boolean {\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\tconst doesColumnHaveRoles = ObjectUtils.isArrayWithData(columnSchema.roles);\n\t\t\tif (!doesColumnHaveRoles) return true; // Public column, any role can access\n\n\t\t\tif (!role) return false; // Column has roles, but no role provided (no access)\n\n\t\t\treturn columnSchema.roles.includes(role!);\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.doesRoleHavePermissionToColumn(role, schema, nestedItem, joins);\n\t\t\t\t})\n\t\t\t);\n\t\t}\n\t\treturn false;\n\t}\n\n\tprotected doesRoleHavePermissionToTable(\n\t\tuserRole: string | undefined,\n\t\tschema: ResturaSchema,\n\t\ttableName: string\n\t): boolean {\n\t\tconst tableSchema = this.getTableSchema(schema, tableName);\n\t\tconst doesTableHaveRoles = ObjectUtils.isArrayWithData(tableSchema.roles);\n\t\tif (!doesTableHaveRoles) return true; // Public table, any role can access\n\n\t\tif (!userRole) return false; // Table has roles, but no role provided (no access)\n\n\t\treturn tableSchema.roles.includes(userRole);\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\tuserRole: string | undefined,\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('SCHEMA_ERROR', `Invalid global keyword clause in route ${routeData.name}`);\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\tuserRole: string | undefined,\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 = `\nstart = expressionList\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? \"!\" : \"\"}(\\${type? type(column, value) : \\`\\${column\\} = \\${mysql.escape(value)}\\`})\\`;}\n /\n negate:negate?\"(\"expression:expressionList\")\" { return \\`\\${negate? \"!\" : \"\"}(\\${expression})\\`; }\n\nnegate = \"!\"\n \noperator = \"and\"i / \"or\"i\n\ncolumn = left:text \".\" right:text { return \\`\\${mysql.escapeId(left)}.\\${mysql.escapeId(right)}\\`; }\n\t /\n\t text:text { return mysql.escapeId(text); }\n\n\ntext = text:[ a-z0-9-_:.@]i+ { return text.join(\"\");}\n\ntype = \"type:\" type:typeString { return type; }\ntypeString = text:\"startsWith\" { return function(column, value) { return \\`\\${column} LIKE '\\${mysql.escape(value).slice(1,-1)}%'\\`; } } /\n text:\"endsWith\" { return function(column, value) { return \\`\\${column} LIKE '%\\${mysql.escape(value).slice(1,-1)}'\\`; } } /\n text:\"contains\" { return function(column, value) { return \\`\\${column} LIKE '%\\${mysql.escape(value).slice(1,-1)}%'\\`; } } /\n text:\"exact\" { return function(column, value) { return \\`\\${column} = '\\${mysql.escape(value).slice(1,-1)}'\\`; } } /\n text:\"greaterThanEqual\" { return function(column, value) { return \\`\\${column} >= '\\${mysql.escape(value).slice(1,-1)}'\\`; } } /\n text:\"greaterThan\" { return function(column, value) { return \\`\\${column} > '\\${mysql.escape(value).slice(1,-1)}'\\`; } } /\n text:\"lessThanEqual\" { return function(column, value) { return \\`\\${column} <= '\\${mysql.escape(value).slice(1,-1)}'\\`; } } /\n text:\"lessThan\" { return function(column, value) { return \\`\\${column} < '\\${mysql.escape(value).slice(1,-1)}'\\`; } } / \n text:\"isNull\" { return function(column, value) { return \\`isNull(\\${column})\\`; } } \n \nvalue = \"value:\" value:text { return value; } \n\n`;\n\nconst filterSqlParser = peg.generate(filterSqlGrammar, {\n\tformat: 'commonjs'\n\t// dependencies: { mysql: 'mysql' } // todo: figure out a better way to escape values depending on the database type\n} as ParserBuildOptions);\nexport default filterSqlParser;\n","import SqlEngine from './SqlEngine';\nimport { DynamicObject, RsRequest } from '../types/expressCustom.js';\nimport {\n\tCustomRouteData,\n\tJoinData,\n\tResponseData,\n\tResturaSchema,\n\tStandardRouteData,\n\tTableData,\n\tWhereData\n} from '../restura.schema.js';\nimport { RsError } from '../errors';\nimport filterSqlParser from './filterSqlParser';\nimport { ObjectUtils } from '@redskytech/core-utils';\nimport { SqlUtils } from './SqlUtils';\nimport { escapeColumnName, insertObjectQuery, SQL, updateObjectQuery } from './PsqlUtils.js';\nimport { PageQuery } from '../types/restura.types.js';\nimport { PsqlPool } from './PsqlPool.js';\n\nexport default class PsqlEngine extends SqlEngine {\n\tconstructor(private psqlConnectionPool: PsqlPool) {\n\t\tsuper();\n\t}\n\n\tasync diffDatabaseToSchema(schema: ResturaSchema): Promise<string> {\n\t\tconsole.log(schema);\n\t\treturn Promise.resolve('');\n\t}\n\n\tgenerateDatabaseSchemaFromSchema(schema: ResturaSchema): string {\n\t\tconsole.log(schema);\n\t\treturn '';\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\tuserRole: string | undefined,\n\t\tsqlParams: string[]\n\t): string {\n\t\tconsole.log(req, schema, item, routeData, userRole, sqlParams);\n\t\treturn '';\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(query, sqlParams);\n\t\tconst insertId = createdItem?.id;\n\t\tconst whereData: WhereData[] = [\n\t\t\t{\n\t\t\t\ttableName: routeData.table,\n\t\t\t\tvalue: insertId,\n\t\t\t\tcolumnName: 'id',\n\t\t\t\toperator: '='\n\t\t\t}\n\t\t];\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\tconst userRole = req.requesterDetails.role;\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 (item.subquery || this.doesRoleHavePermissionToColumn(userRole, schema, item, routeData.joins))\n\t\t\t\tselectColumns.push(item);\n\t\t});\n\t\tif (!selectColumns.length) throw new RsError('UNAUTHORIZED', `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, userRole, sqlParams)} AS ${\n\t\t\t\t\t\titem.name\n\t\t\t\t\t}`;\n\t\t\t\t}\n\t\t\t\treturn `${escapeColumnName(item.selector)} AS ${escapeColumnName(item.name)}`;\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\tuserRole,\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);\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);\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 pageResults = await this.psqlConnectionPool.runQuery(\n\t\t\t\t`${selectStatement}${sqlStatement}${groupByOrderByStatement} LIMIT ? OFFSET ?;SELECT COUNT(${\n\t\t\t\t\trouteData.groupBy ? `DISTINCT ${routeData.groupBy.tableName}.${routeData.groupBy.columnName}` : '*'\n\t\t\t\t}) AS total\\n${sqlStatement};`,\n\t\t\t\t[\n\t\t\t\t\t...sqlParams,\n\t\t\t\t\tdata.perPage || DEFAULT_PAGED_PER_PAGE_NUMBER,\n\t\t\t\t\t(data.page - 1) * data.perPage || DEFAULT_PAGED_PAGE_NUMBER,\n\t\t\t\t\t...sqlParams\n\t\t\t\t]\n\t\t\t);\n\t\t\tlet total = 0;\n\t\t\tif (ObjectUtils.isArrayWithData(pageResults)) {\n\t\t\t\ttotal = pageResults[1][0].total;\n\t\t\t}\n\t\t\treturn { data: pageResults[0], 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\t// In order remove ambiguity, we need to add the table name to the column names when the table is joined\n\t\t// for (let i in bodyNoId) {\n\t\t// \tif (i.includes('.')) continue;\n\t\t// \tbodyNoId[escapeColumnName(`${routeData.table}.${i}`)] = bodyNoId[i];\n\t\t// \tdelete bodyNoId[i];\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 assignmentWithPrefix = escapeColumnName(`${routeData.table}.${assignment.name}`);\n\n\t\t\tif (SqlUtils.convertDatabaseTypeToTypescript(column.type!) === 'number')\n\t\t\t\tbodyNoId[assignmentWithPrefix] = Number(assignment.value);\n\t\t\telse bodyNoId[assignmentWithPrefix] = assignment.value;\n\t\t}\n\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]);\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\treq.requesterDetails.role,\n\t\t\tsqlParams\n\t\t);\n\n\t\tlet deleteStatement = `DELETE\n FROM \"${routeData.table}\" ${joinStatement}`;\n\t\tdeleteStatement += this.generateWhereClause(req, routeData.where, routeData, sqlParams);\n\t\tdeleteStatement += ';';\n\t\tawait this.psqlConnectionPool.runQuery(deleteStatement, sqlParams);\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\tuserRole: string | undefined,\n\t\tsqlParams: string[]\n\t): string {\n\t\tconsole.log(req, joins, baseTable, routeData, schema, userRole, sqlParams);\n\t\treturn '';\n\t}\n\n\tprotected getTableSchema(schema: ResturaSchema, tableName: string): TableData {\n\t\tconsole.log(schema, tableName);\n\t\treturn {} as TableData;\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\twhereClause += this.replaceParamKeywords(item.custom, routeData, req, sqlParams);\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\tif (operator === 'LIKE') {\n\t\t\t\tsqlParams[sqlParams.length - 1] = `%${sqlParams[sqlParams.length - 1]}%`;\n\t\t\t} else if (operator === 'STARTS WITH') {\n\t\t\t\toperator = 'LIKE';\n\t\t\t\tsqlParams[sqlParams.length - 1] = `${sqlParams[sqlParams.length - 1]}%`;\n\t\t\t} else if (operator === 'ENDS WITH') {\n\t\t\t\toperator = 'LIKE';\n\t\t\t\tsqlParams[sqlParams.length - 1] = `%${sqlParams[sqlParams.length - 1]}`;\n\t\t\t}\n\n\t\t\tconst replacedValue = this.replaceParamKeywords(item.value, routeData, req, sqlParams);\n\t\t\tconst escapedValue = SQL`${replacedValue}`;\n\t\t\twhereClause += `\\t${item.conjunction || ''} \"${item.tableName}\".\"${item.columnName}\" ${operator} ${\n\t\t\t\t['IN', 'NOT IN'].includes(operator) ? `(${escapedValue})` : escapedValue\n\t\t\t}\\n`;\n\t\t});\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];\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];\n\t\t\t});\n\n\t\t\tstatement = filterSqlParser.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","import format from 'pg-format';\nimport { DynamicObject } from '../types/expressCustom.js';\n\nexport function escapeColumnName(columnName: string | undefined): string {\n\t// consider using an existing library\n\tif (columnName === undefined) return '';\n\treturn `\"${columnName.replace(/\"/g, '')}\"`.replace('.', '\".\"');\n}\n\nexport function questionMarksToOrderedParams(query: string) {\n\tlet count = 1;\n\n\treturn query.replace(/'\\?'/g, () => `$${count++}`);\n}\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\tconst query = `INSERT INTO \"${table}\" (${columns})\n VALUES (${values})\n RETURNING *`;\n\treturn query;\n}\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 `UPDATE ${escapeColumnName(table)}\n SET ${setArray.join(', ')} ${whereStatement}\n RETURNING *`;\n}\n\nfunction isValueNumber(value: unknown): value is number {\n\treturn !isNaN(Number(value));\n}\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function SQL(strings: any, ...values: any) {\n\tlet query = strings[0];\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tvalues.forEach((value: any, index: number) => {\n\t\tif (isValueNumber(value)) {\n\t\t\tquery += value;\n\t\t} else {\n\t\t\tquery += format.literal(value); // escape input\n\t\t}\n\t\tquery += strings[index + 1];\n\t});\n\n\treturn query;\n}\n","import { Pool, PoolConfig, QueryConfigValues } from 'pg';\nimport { questionMarksToOrderedParams } from './PsqlUtils.js';\nimport { RsError } from '../errors.js';\n\nexport class PsqlPool {\n\tpublic pool: Pool;\n\tconstructor(public poolConfig: PoolConfig) {\n\t\tthis.pool = new Pool(poolConfig);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tasync queryOne(query: string, options: Array<any>) {\n\t\tconst formattedQuery = questionMarksToOrderedParams(query);\n\t\ttry {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst response = await this.pool.query(formattedQuery, options as QueryConfigValues<any>);\n\t\t\treturn response.rows[0];\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tconsole.error(error, query, options);\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\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tasync runQuery(query: string, options: any[]) {\n\t\tconst formattedQuery = questionMarksToOrderedParams(query);\n\t\tconst queryUpdated = query.replace(/[\\t\\n]/g, ' ');\n\t\tconsole.log(queryUpdated, options);\n\t\ttry {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tconst response = await this.pool.query(formattedQuery, options as QueryConfigValues<any>);\n\t\t\treturn response.rows;\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t} catch (error: any) {\n\t\t\tconsole.error(error, query, options);\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"],"mappings":"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","names":["ObjectUtils","config","_typeof","obj","get","fs","path","prettier","path","path","ObjectUtils","z","z","z","ObjectUtils","z","z","StringUtils","prettier","prettier","StringUtils","process","ObjectUtils","item","join","ObjectUtils","format","isValueNumber","ObjectUtils","column","config","fs","ObjectUtils","path"]}