@fjell/express-router 4.4.53 → 4.4.55

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,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/ItemRouter.ts"],
4
- "sourcesContent": ["import {\n ComKey,\n cPK,\n Item,\n ItemEvent,\n LocKey,\n LocKeyArray,\n PriKey,\n validatePK\n} from \"@fjell/core\";\nimport { NotFoundError } from \"@fjell/lib\";\nimport { Instance } from \"./Instance.js\";\nimport deepmerge from \"deepmerge\";\nimport { Request, Response, Router } from \"express\";\nimport LibLogger from \"./logger.js\";\n\n/**\n * Router-level action method signature - aligned with library ActionMethod pattern\n * Takes the resolved item key, action parameters, and HTTP context\n */\nexport interface RouterActionMethod<\n S extends string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n ik: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>,\n actionParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\n/**\n * Router-level facet method signature - aligned with library FacetMethod pattern\n * Takes the resolved item key, facet parameters, and HTTP context\n */\nexport interface RouterFacetMethod<\n S extends string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n ik: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>,\n facetParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\n/**\n * Router-level all action method signature - aligned with library AllActionMethod pattern\n * Takes action parameters, optional locations, and HTTP context\n */\nexport interface RouterAllActionMethod<\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n allActionParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n locations: LocKeyArray<L1, L2, L3, L4, L5> | [],\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\n/**\n * Router-level all facet method signature - aligned with library AllFacetMethod pattern\n * Takes facet parameters, optional locations, and HTTP context\n */\nexport interface RouterAllFacetMethod<\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n allFacetParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n locations: LocKeyArray<L1, L2, L3, L4, L5> | [],\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\nexport type ItemRouterOptions<\n S extends string = string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never\n> = {\n /**\n * Handlers for item actions - aligned with library operation signatures\n * The key in the Record is the action name, method receives resolved item key and parameters\n */\n actions?: Record<string, RouterActionMethod<S, L1, L2, L3, L4, L5>>;\n\n /**\n * Handlers for item facets - aligned with library operation signatures\n * The key in the Record is the facet name, method receives resolved item key and parameters\n */\n facets?: Record<string, RouterFacetMethod<S, L1, L2, L3, L4, L5>>;\n\n /**\n * Handlers for all actions - aligned with library operation signatures\n * The key in the Record is the action name, method receives parameters and optional locations\n */\n allActions?: Record<string, RouterAllActionMethod<L1, L2, L3, L4, L5>>;\n\n /**\n * Handlers for all facets - aligned with library operation signatures\n * The key in the Record is the facet name, method receives parameters and optional locations\n */\n allFacets?: Record<string, RouterAllFacetMethod<L1, L2, L3, L4, L5>>;\n};\n\nexport class ItemRouter<\n S extends string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never\n> {\n\n protected lib: Instance<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>;\n private keyType: S;\n protected options: ItemRouterOptions<S, L1, L2, L3, L4, L5>;\n private childRouters: Record<string, Router> = {};\n protected logger;\n protected parentRoute?: ItemRouter<L1, L2, L3, L4, L5, never>;\n\n constructor(\n lib: Instance<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>,\n keyType: S,\n options: ItemRouterOptions<S, L1, L2, L3, L4, L5> = {},\n parentRoute?: ItemRouter<L1, L2, L3, L4, L5, never>\n ) {\n this.lib = lib;\n this.keyType = keyType;\n this.options = options;\n this.parentRoute = parentRoute;\n this.logger = LibLogger.get(\"ItemRouter\", keyType);\n }\n\n public getPkType = (): S => {\n return this.keyType;\n }\n\n protected getPkParam = (): string => {\n return `${this.getPkType()}Pk`;\n }\n\n protected getLk(res: Response): LocKey<S> {\n const pkParam = this.getPkParam();\n const lkValue = res.locals[pkParam];\n this.logger.debug('Getting location key', {\n keyType: this.keyType,\n pkParam: pkParam,\n lkValue: lkValue,\n allLocals: res.locals\n });\n return { kt: this.keyType, lk: lkValue };\n }\n\n // this is meant to be consumed by children routers\n public getLKA(res: Response): LocKeyArray<S, L1, L2, L3, L4> {\n return [this.getLk(res)] as LocKeyArray<S, L1, L2, L3, L4>;\n }\n\n public getPk(res: Response): PriKey<S> {\n return cPK<S>(res.locals[this.getPkParam()], this.getPkType());\n }\n\n // Unless this is a contained router, the locations will always be an empty array.\n protected getLocations(res: Response): LocKeyArray<L1, L2, L3, L4, L5> | [] {\n return this.parentRoute ? this.parentRoute.getLKA(res) as LocKeyArray<L1, L2, L3, L4, L5> : [];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected getIk(res: Response): PriKey<S> | ComKey<S, L1, L2, L3, L4, L5> {\n throw new Error('Method not implemented in an abstract router');\n }\n\n protected postAllAction = async (req: Request, res: Response) => {\n const libOptions = this.lib.options;\n const libOperations = this.lib.operations;\n this.logger.debug('Posting All Action', { query: req?.query, params: req?.params, locals: res?.locals });\n const allActionKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n // Check for router-level handler first\n if (this.options.allActions && this.options.allActions[allActionKey]) {\n this.logger.debug('Using router-level all action handler', { allActionKey });\n try {\n const result = await this.options.allActions[allActionKey](\n req.body as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n this.getLocations(res),\n { req, res }\n );\n if (result != null) res.json(result);\n return;\n } catch (err: any) {\n this.logger.error('Error in router-level all action', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n return;\n }\n }\n\n // Fallback to library handler\n if (!libOptions.allActions) {\n this.logger.error('All Actions are not configured');\n res.status(500).json({ error: 'All Actions are not configured' });\n return;\n }\n const allAction = libOptions.allActions[allActionKey];\n if (!allAction) {\n this.logger.error('All Action is not configured', { allActionKey });\n res.status(500).json({ error: 'All Action is not configured' });\n return;\n }\n try {\n const [result, affectedItems] = await libOperations.allAction(allActionKey, req.body, this.getLocations(res));\n res.json([result, affectedItems]);\n } catch (err: any) {\n this.logger.error('Error in All Action', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n }\n }\n\n protected getAllFacet = async (req: Request, res: Response) => {\n const libOptions = this.lib.options;\n const libOperations = this.lib.operations;\n this.logger.debug('Getting All Facet', { query: req?.query, params: req?.params, locals: res?.locals });\n const facetKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n // Check for router-level handler first\n if (this.options.allFacets && this.options.allFacets[facetKey]) {\n this.logger.debug('Using router-level all facet handler', { facetKey });\n try {\n const result = await this.options.allFacets[facetKey](\n req.query as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n this.getLocations(res),\n { req, res }\n );\n if (result != null) res.json(result);\n return;\n } catch (err: any) {\n this.logger.error('Error in router-level all facet', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n return;\n }\n }\n\n // Fallback to library handler\n if (!libOptions.allFacets) {\n this.logger.error('All Facets are not configured');\n res.status(500).json({ error: 'All Facets are not configured' });\n return;\n }\n const facet = libOptions.allFacets[facetKey];\n if (!facet) {\n this.logger.error('All Facet is not configured', { facetKey });\n res.status(500).json({ error: 'All Facet is not configured' });\n return;\n }\n try {\n const combinedQueryParams = { ...(req.query || {}), ...(req.params || {}) } as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>;\n res.json(await libOperations.allFacet(facetKey, combinedQueryParams, this.getLocations(res)));\n } catch (err: any) {\n this.logger.error('Error in All Facet', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n }\n }\n\n protected postItemAction = async (req: Request, res: Response) => {\n const libOptions = this.lib.options;\n const libOperations = this.lib.operations;\n this.logger.debug('Posting Item Action', { query: req?.query, params: req?.params, locals: res?.locals });\n const ik = this.getIk(res);\n const actionKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n // Check for router-level handler first\n if (this.options.actions && this.options.actions[actionKey]) {\n this.logger.debug('Using router-level action handler', { actionKey });\n try {\n const result = await this.options.actions[actionKey](\n ik,\n req.body as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n { req, res }\n );\n if (result != null) res.json(result);\n return;\n } catch (err: any) {\n this.logger.error('Error in router-level action', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n return;\n }\n }\n\n // Fallback to library handler\n if (!libOptions.actions) {\n this.logger.error('Item Actions are not configured');\n res.status(500).json({ error: 'Item Actions are not configured' });\n return;\n }\n const action = libOptions.actions[actionKey];\n if (!action) {\n this.logger.error('Item Action is not configured', { actionKey });\n res.status(500).json({ error: 'Item Action is not configured' });\n return;\n }\n try {\n const [result, affectedItems] = await libOperations.action(ik, actionKey, req.body);\n res.json([result, affectedItems]);\n } catch (err: any) {\n this.logger.error('Error in Item Action', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n }\n }\n\n protected getItemFacet = async (req: Request, res: Response) => {\n const libOptions = this.lib.options;\n const libOperations = this.lib.operations;\n this.logger.debug('Getting Item Facet', { query: req?.query, params: req?.params, locals: res?.locals });\n const ik = this.getIk(res);\n const facetKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n // Check for router-level handler first\n if (this.options.facets && this.options.facets[facetKey]) {\n this.logger.debug('Using router-level facet handler', { facetKey });\n try {\n const result = await this.options.facets[facetKey](\n ik,\n req.query as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n { req, res }\n );\n if (result != null) res.json(result);\n return;\n } catch (err: any) {\n this.logger.error('Error in router-level facet', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n return;\n }\n }\n\n // Fallback to library handler\n if (!libOptions.facets) {\n this.logger.error('Item Facets are not configured');\n res.status(500).json({ error: 'Item Facets are not configured' });\n return;\n }\n const facet = libOptions.facets[facetKey];\n if (!facet) {\n this.logger.error('Item Facet is not configured', { facetKey });\n res.status(500).json({ error: 'Item Facet is not configured' });\n return;\n }\n try {\n const combinedQueryParams = { ...(req.query || {}), ...(req.params || {}) } as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>;\n res.json(await libOperations.facet(ik, facetKey, combinedQueryParams));\n } catch (err: any) {\n this.logger.error('Error in Item Facet', { message: err?.message, stack: err?.stack });\n res.status(500).json(err);\n }\n }\n\n private configure = (router: Router) => {\n const libOptions = this.lib.options;\n this.logger.debug('Configuring Router', { pkType: this.getPkType() });\n router.get('/', this.findItems);\n router.post('/', this.createItem);\n\n // Track registered routes to detect collisions\n const registeredAllActions = new Set<string>();\n const registeredAllFacets = new Set<string>();\n const registeredItemActions = new Set<string>();\n const registeredItemFacets = new Set<string>();\n\n // Configure router-level allActions first (highest precedence)\n this.logger.default('Router All Actions', { allActions: this.options.allActions });\n if (this.options.allActions) {\n Object.keys(this.options.allActions).forEach((actionKey) => {\n this.logger.debug('Configuring Router All Action %s', actionKey);\n router.post(`/${actionKey}`, this.postAllAction);\n registeredAllActions.add(actionKey);\n });\n }\n\n // Configure library allActions, warn on conflicts\n this.logger.default('Library All Actions', { allActions: libOptions.allActions });\n if (libOptions.allActions) {\n Object.keys(libOptions.allActions).forEach((actionKey) => {\n if (registeredAllActions.has(actionKey)) {\n this.logger.warning('All Action name collision - router-level handler takes precedence', { actionKey });\n } else {\n this.logger.debug('Configuring Library All Action %s', actionKey);\n router.post(`/${actionKey}`, this.postAllAction);\n registeredAllActions.add(actionKey);\n }\n });\n }\n\n // Configure router-level allFacets first (highest precedence)\n this.logger.default('Router All Facets', { allFacets: this.options.allFacets });\n if (this.options.allFacets) {\n Object.keys(this.options.allFacets).forEach((facetKey) => {\n this.logger.debug('Configuring Router All Facet %s', facetKey);\n router.get(`/${facetKey}`, this.getAllFacet);\n registeredAllFacets.add(facetKey);\n });\n }\n\n // Configure library allFacets, warn on conflicts\n this.logger.default('Library All Facets', { allFacets: libOptions.allFacets });\n if (libOptions.allFacets) {\n Object.keys(libOptions.allFacets).forEach((facetKey) => {\n if (registeredAllFacets.has(facetKey)) {\n this.logger.warning('All Facet name collision - router-level handler takes precedence', { facetKey });\n } else {\n this.logger.debug('Configuring Library All Facet %s', facetKey);\n router.get(`/${facetKey}`, this.getAllFacet);\n registeredAllFacets.add(facetKey);\n }\n });\n }\n\n const itemRouter = Router();\n itemRouter.get('/', this.getItem);\n itemRouter.put('/', this.updateItem);\n itemRouter.delete('/', this.deleteItem);\n\n // Configure router-level item actions first (highest precedence)\n this.logger.default('Router Item Actions', { itemActions: this.options.actions });\n if (this.options.actions) {\n Object.keys(this.options.actions).forEach((actionKey) => {\n this.logger.debug('Configuring Router Item Action %s', actionKey);\n itemRouter.post(`/${actionKey}`, this.postItemAction);\n registeredItemActions.add(actionKey);\n });\n }\n\n // Configure library item actions, warn on conflicts\n this.logger.default('Library Item Actions', { itemActions: libOptions.actions });\n if (libOptions.actions) {\n Object.keys(libOptions.actions).forEach((actionKey) => {\n if (registeredItemActions.has(actionKey)) {\n this.logger.warning('Item Action name collision - router-level handler takes precedence', { actionKey });\n } else {\n this.logger.debug('Configuring Library Item Action %s', actionKey);\n itemRouter.post(`/${actionKey}`, this.postItemAction);\n registeredItemActions.add(actionKey);\n }\n });\n }\n\n // Configure router-level item facets first (highest precedence)\n this.logger.default('Router Item Facets', { itemFacets: this.options.facets });\n if (this.options.facets) {\n Object.keys(this.options.facets).forEach((facetKey) => {\n this.logger.debug('Configuring Router Item Facet %s', facetKey);\n itemRouter.get(`/${facetKey}`, this.getItemFacet);\n registeredItemFacets.add(facetKey);\n });\n }\n\n // Configure library item facets, warn on conflicts\n this.logger.default('Library Item Facets', { itemFacets: libOptions.facets });\n if (libOptions.facets) {\n Object.keys(libOptions.facets).forEach((facetKey) => {\n if (registeredItemFacets.has(facetKey)) {\n this.logger.warning('Item Facet name collision - router-level handler takes precedence', { facetKey });\n } else {\n this.logger.debug('Configuring Library Item Facet %s', facetKey);\n itemRouter.get(`/${facetKey}`, this.getItemFacet);\n registeredItemFacets.add(facetKey);\n }\n });\n }\n\n this.logger.debug('Configuring Item Operations under PK Param %s', this.getPkParam());\n router.use(`/:${this.getPkParam()}`, this.validatePrimaryKeyValue, itemRouter);\n\n if (this.childRouters) {\n this.configureChildRouters(itemRouter, this.childRouters);\n }\n return router;\n }\n\n private validatePrimaryKeyValue = (req: Request, res: Response, next: any) => {\n const pkParamValue = req.params[this.getPkParam()];\n if (this.validatePKParam(pkParamValue)) {\n res.locals[this.getPkParam()] = pkParamValue;\n next();\n } else {\n this.logger.error('Invalid Primary Key', { pkParamValue, path: req?.originalUrl });\n res.status(400).json({ error: 'Invalid Primary Key', path: req?.originalUrl });\n }\n }\n\n private configureChildRouters = (router: Router, childRouters: Record<string, Router>) => {\n for (const path in childRouters) {\n this.logger.debug('Configuring Child Router at Path %s', path);\n\n router.use(`/${path}`, childRouters[path]);\n }\n return router;\n }\n\n public addChildRouter = (path: string, router: Router) => {\n this.childRouters[path] = router;\n }\n\n /* istanbul ignore next */\n public getRouter(): Router {\n const router = Router();\n this.configure(router);\n return router;\n }\n\n /* istanbul ignore next */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected createItem = async (req: Request, res: Response): Promise<void> => {\n throw new Error('Method not implemented in an abstract router');\n };\n\n // TODO: Probably a better way to do this, but this postCreate hook only needs the item.\n /* istanbul ignore next */\n public postCreateItem = async (item: Item<S, L1, L2, L3, L4, L5>): Promise<Item<S, L1, L2, L3, L4, L5>> => {\n this.logger.debug('Post Create Item', { item });\n return item;\n };\n\n protected deleteItem = async (req: Request, res: Response): Promise<void> => {\n const libOperations = this.lib.operations;\n\n this.logger.debug('Deleting Item', { query: req.query, params: req.params, locals: res.locals });\n const ik = this.getIk(res);\n try {\n const removedItem = await libOperations.remove(ik);\n const item = validatePK(removedItem, this.getPkType());\n res.json(item);\n } catch (err: any) {\n if (err instanceof NotFoundError) {\n this.logger.error('Item Not Found for Delete', { ik, message: err?.message, stack: err?.stack });\n res.status(404).json({\n ik,\n message: \"Item Not Found\",\n });\n } else {\n this.logger.error('General Error in Delete', { ik, message: err?.message, stack: err?.stack });\n res.status(500).json({\n ik,\n message: \"General Error\",\n });\n }\n }\n };\n\n /* eslint-disable */\n /* istanbul ignore next */\n protected findItems = async (req: Request, res: Response): Promise<void> => {\n throw new Error('Method not implemented in an abstract router');\n };\n /* eslint-enable */\n\n protected getItem = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Getting Item', { query: req.query, params: req.params, locals: res.locals });\n const ik = this.getIk(res);\n try {\n // TODO: What error does validate PK throw, when can that fail?\n const item = validatePK(await libOperations.get(ik), this.getPkType());\n res.json(item);\n } catch (err: any) {\n if (err instanceof NotFoundError) {\n this.logger.error('Item Not Found', { ik, message: err?.message, stack: err?.stack });\n res.status(404).json({\n ik,\n message: \"Item Not Found\",\n });\n } else {\n this.logger.error('General Error', { ik, message: err?.message, stack: err?.stack });\n res.status(500).json({\n ik,\n message: \"General Error\",\n });\n }\n }\n }\n\n protected updateItem = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Updating Item',\n { body: req?.body, query: req?.query, params: req?.params, locals: res?.locals });\n const ik = this.getIk(res);\n try {\n const itemToUpdate = this.convertDates(req.body as Partial<Item<S, L1, L2, L3, L4, L5>>);\n const retItem = validatePK(await libOperations.update(ik, itemToUpdate), this.getPkType());\n res.json(retItem);\n } catch (err: any) {\n if (err instanceof NotFoundError) {\n this.logger.error('Item Not Found for Update', { ik, message: err?.message, stack: err?.stack });\n res.status(404).json({\n ik,\n message: \"Item Not Found\",\n });\n } else {\n this.logger.error('General Error in Update', { ik, message: err?.message, stack: err?.stack });\n res.status(500).json({\n ik,\n message: \"General Error\",\n });\n }\n }\n };\n\n public convertDates = (item: Partial<Item<S, L1, L2, L3, L4, L5>>): Partial<Item<S, L1, L2, L3, L4, L5>> => {\n this.logger.debug('Converting Dates', { item });\n const events = item.events as Record<string, ItemEvent> | undefined;\n if (events) {\n Object.keys(events).forEach((key: string) => {\n Object.assign(events, {\n [key]: deepmerge(events[key], { at: events[key].at ? new Date(events[key].at) : null })\n });\n });\n }\n Object.assign(item, { events });\n return item;\n };\n\n // TODO: Maybe just simplify this and require that everything is a UUID?\n /**\n * This method might be an annoyance, but we need to capture a few cases where someone passes\n * a PK parameter that has an odd string in it.\n *\n * @param pkParamValue The value of the primary key parameter\n * @returns if the value is valid.\n */\n protected validatePKParam = (pkParamValue: string): boolean => {\n let validPkParam = true;\n if (pkParamValue.length <= 0) {\n this.logger.error('Primary Key is an Empty String', { pkParamValue });\n validPkParam = false;\n } else if (pkParamValue === 'undefined') {\n this.logger.error('Primary Key is the string \\'undefined\\'', { pkParamValue });\n validPkParam = false;\n }\n return validPkParam;\n }\n\n}\n"],
5
- "mappings": "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",
6
- "names": []
4
+ "sourcesContent": ["import {\n ActionError,\n ComKey,\n cPK,\n Item,\n ItemEvent,\n LocKey,\n LocKeyArray,\n PriKey,\n validatePK\n} from \"@fjell/core\";\nimport { NotFoundError } from \"@fjell/lib\";\nimport { Instance } from \"./Instance.js\";\nimport deepmerge from \"deepmerge\";\nimport { NextFunction, Request, Response, Router } from \"express\";\nimport LibLogger from \"./logger.js\";\nimport { createErrorHandler, ErrorHandlerOptions } from \"./errorHandler.js\";\n\n/**\n * Router-level action method signature - aligned with library ActionMethod pattern\n * Takes the resolved item key, action parameters, and HTTP context\n */\nexport interface RouterActionMethod<\n S extends string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n ik: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>,\n actionParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\n/**\n * Router-level facet method signature - aligned with library FacetMethod pattern\n * Takes the resolved item key, facet parameters, and HTTP context\n */\nexport interface RouterFacetMethod<\n S extends string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n ik: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>,\n facetParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\n/**\n * Router-level all action method signature - aligned with library AllActionMethod pattern\n * Takes action parameters, optional locations, and HTTP context\n */\nexport interface RouterAllActionMethod<\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n allActionParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n locations: LocKeyArray<L1, L2, L3, L4, L5> | [],\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\n/**\n * Router-level all facet method signature - aligned with library AllFacetMethod pattern\n * Takes facet parameters, optional locations, and HTTP context\n */\nexport interface RouterAllFacetMethod<\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never,\n> {\n (\n allFacetParams: Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n locations: LocKeyArray<L1, L2, L3, L4, L5> | [],\n context: { req: Request, res: Response }\n ): Promise<any>;\n}\n\nexport type ItemRouterOptions<\n S extends string = string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never\n> = {\n /**\n * Handlers for item actions - aligned with library operation signatures\n * The key in the Record is the action name, method receives resolved item key and parameters\n */\n actions?: Record<string, RouterActionMethod<S, L1, L2, L3, L4, L5>>;\n\n /**\n * Handlers for item facets - aligned with library operation signatures\n * The key in the Record is the facet name, method receives resolved item key and parameters\n */\n facets?: Record<string, RouterFacetMethod<S, L1, L2, L3, L4, L5>>;\n\n /**\n * Handlers for all actions - aligned with library operation signatures\n * The key in the Record is the action name, method receives parameters and optional locations\n */\n allActions?: Record<string, RouterAllActionMethod<L1, L2, L3, L4, L5>>;\n\n /**\n * Handlers for all facets - aligned with library operation signatures\n * The key in the Record is the facet name, method receives parameters and optional locations\n */\n allFacets?: Record<string, RouterAllFacetMethod<L1, L2, L3, L4, L5>>;\n\n /**\n * Error handler configuration\n */\n errorHandler?: ErrorHandlerOptions;\n};\n\nexport class ItemRouter<\n S extends string,\n L1 extends string = never,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never\n> {\n\n protected lib: Instance<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>;\n private keyType: S;\n protected options: ItemRouterOptions<S, L1, L2, L3, L4, L5>;\n private childRouters: Record<string, Router> = {};\n protected logger;\n protected parentRoute?: ItemRouter<L1, L2, L3, L4, L5, never>;\n protected errorHandler: (err: any, req: Request, res: Response, next: NextFunction) => void;\n\n constructor(\n lib: Instance<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>,\n keyType: S,\n options: ItemRouterOptions<S, L1, L2, L3, L4, L5> = {},\n parentRoute?: ItemRouter<L1, L2, L3, L4, L5, never>\n ) {\n this.lib = lib;\n this.keyType = keyType;\n this.options = options;\n this.parentRoute = parentRoute;\n this.logger = LibLogger.get(\"ItemRouter\", keyType);\n this.errorHandler = createErrorHandler(options.errorHandler);\n }\n\n /**\n * Wrap async route handlers to catch errors and pass to error handler\n */\n protected wrapAsync(fn: (req: Request, res: Response, next: NextFunction) => Promise<any>) {\n return (req: Request, res: Response, next: NextFunction) => {\n Promise.resolve(fn.call(this, req, res, next)).catch(next);\n };\n }\n\n public getPkType = (): S => {\n return this.keyType;\n }\n\n protected getPkParam = (): string => {\n return `${this.getPkType()}Pk`;\n }\n\n protected getLk(res: Response): LocKey<S> {\n const pkParam = this.getPkParam();\n const lkValue = res.locals[pkParam];\n this.logger.debug('Getting location key', {\n keyType: this.keyType,\n pkParam: pkParam,\n lkValue: lkValue,\n allLocals: res.locals\n });\n return { kt: this.keyType, lk: lkValue };\n }\n\n // this is meant to be consumed by children routers\n public getLKA(res: Response): LocKeyArray<S, L1, L2, L3, L4> {\n return [this.getLk(res)] as LocKeyArray<S, L1, L2, L3, L4>;\n }\n\n public getPk(res: Response): PriKey<S> {\n return cPK<S>(res.locals[this.getPkParam()], this.getPkType());\n }\n\n // Unless this is a contained router, the locations will always be an empty array.\n protected getLocations(res: Response): LocKeyArray<L1, L2, L3, L4, L5> | [] {\n return this.parentRoute ? this.parentRoute.getLKA(res) as LocKeyArray<L1, L2, L3, L4, L5> : [];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected getIk(res: Response): PriKey<S> | ComKey<S, L1, L2, L3, L4, L5> {\n throw new Error('Method not implemented in an abstract router');\n }\n\n protected postAllAction = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Posting All Action', { query: req?.query, params: req?.params, locals: res?.locals });\n const allActionKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n try {\n // Check for router-level handler first\n if (this.options.allActions && this.options.allActions[allActionKey]) {\n this.logger.debug('Using router-level all action handler', { allActionKey });\n const result = await this.options.allActions[allActionKey](\n req.body as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n this.getLocations(res),\n { req, res }\n );\n if (result != null) {\n res.json(result);\n }\n return;\n }\n\n // Check if allAction operation exists\n if (!libOperations.allAction) {\n res.status(500).json({ error: 'All Actions are not configured' });\n return;\n }\n\n // Fallback to library handler\n const [result] = await libOperations.allAction(allActionKey, req.body, this.getLocations(res));\n res.json(result);\n } catch (error: any) {\n this.logger.error('Error in postAllAction', { error });\n // Check if it's a validation error or action not found error\n if ((error.name === 'ValidationError' || error.message?.includes('not found')) && error.message) {\n res.status(500).json({ error: 'All Action is not configured' });\n } else {\n res.status(500).json(error);\n }\n }\n }\n\n protected getAllFacet = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Getting All Facet', { query: req?.query, params: req?.params, locals: res?.locals });\n const facetKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n try {\n // Check for router-level handler first\n if (this.options.allFacets && this.options.allFacets[facetKey]) {\n this.logger.debug('Using router-level all facet handler', { facetKey });\n const result = await this.options.allFacets[facetKey](\n req.query as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n this.getLocations(res),\n { req, res }\n );\n if (result != null) {\n res.json(result);\n }\n return;\n }\n\n // Check if allFacet operation exists\n if (!libOperations.allFacet) {\n res.status(500).json({ error: 'All Facets are not configured' });\n return;\n }\n\n // Fallback to library handler\n const combinedQueryParams = { ...(req.query || {}), ...(req.params || {}) } as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>;\n const result = await libOperations.allFacet(facetKey, combinedQueryParams, this.getLocations(res));\n res.json(result);\n } catch (error: any) {\n this.logger.error('Error in getAllFacet', { error });\n // Check if it's a validation error or facet not found error\n if ((error.name === 'ValidationError' || error.message?.includes('not found')) && error.message) {\n res.status(500).json({ error: 'All Facet is not configured' });\n } else {\n res.status(500).json(error);\n }\n }\n }\n\n protected postItemAction = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Posting Item Action', { query: req?.query, params: req?.params, locals: res?.locals });\n const ik = this.getIk(res);\n const actionKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n try {\n // Check for router-level handler first\n if (this.options.actions && this.options.actions[actionKey]) {\n this.logger.debug('Using router-level action handler', { actionKey });\n const result = await this.options.actions[actionKey](\n ik,\n req.body as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n { req, res }\n );\n if (result != null) {\n res.json(result);\n }\n return;\n }\n\n // Check if actions operation exists\n if (!libOperations.action) {\n res.status(500).json({ error: 'Item Actions are not configured' });\n return;\n }\n\n // Fallback to library handler\n const [result] = await libOperations.action(ik, actionKey, req.body);\n res.json(result);\n } catch (error: any) {\n this.logger.error('Error in postItemAction', { error });\n // Check if it's a validation error or action not found error\n if ((error.name === 'ValidationError' || error.message?.includes('not found')) && error.message) {\n res.status(500).json({ error: 'Item Action is not configured' });\n } else {\n res.status(500).json(error);\n }\n }\n }\n\n protected getItemFacet = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Getting Item Facet', { query: req?.query, params: req?.params, locals: res?.locals });\n const ik = this.getIk(res);\n const facetKey = req.path.substring(req.path.lastIndexOf('/') + 1);\n\n try {\n // Check for router-level handler first\n if (this.options.facets && this.options.facets[facetKey]) {\n this.logger.debug('Using router-level facet handler', { facetKey });\n const result = await this.options.facets[facetKey](\n ik,\n req.query as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>,\n { req, res }\n );\n if (result != null) {\n res.json(result);\n }\n return;\n }\n\n // Check if facets operation exists\n if (!libOperations.facet) {\n res.status(500).json({ error: 'Item Facets are not configured' });\n return;\n }\n\n // Fallback to library handler\n const combinedQueryParams = { ...(req.query || {}), ...(req.params || {}) } as Record<string, string | number | boolean | Date | Array<string | number | boolean | Date>>;\n const result = await libOperations.facet(ik, facetKey, combinedQueryParams);\n res.json(result);\n } catch (error: any) {\n this.logger.error('Error in getItemFacet', { error });\n // Check if it's a validation error or facet not found error\n if ((error.name === 'ValidationError' || error.message?.includes('not found')) && error.message) {\n res.status(500).json({ error: 'Item Facet is not configured' });\n } else {\n res.status(500).json(error);\n }\n }\n }\n\n private configure = (router: Router) => {\n const libOptions = this.lib.options;\n this.logger.debug('Configuring Router', { pkType: this.getPkType() });\n router.get('/', this.wrapAsync(this.findItems));\n router.post('/', this.wrapAsync(this.createItem));\n\n // Track registered routes to detect collisions\n const registeredAllActions = new Set<string>();\n const registeredAllFacets = new Set<string>();\n const registeredItemActions = new Set<string>();\n const registeredItemFacets = new Set<string>();\n\n // Configure router-level allActions first (highest precedence)\n this.logger.default('Router All Actions', { allActions: this.options.allActions });\n if (this.options.allActions) {\n Object.keys(this.options.allActions).forEach((actionKey) => {\n this.logger.debug('Configuring Router All Action %s', actionKey);\n router.post(`/${actionKey}`, this.wrapAsync(this.postAllAction));\n registeredAllActions.add(actionKey);\n });\n }\n\n // Configure library allActions, warn on conflicts\n this.logger.default('Library All Actions', { allActions: libOptions.allActions });\n if (libOptions.allActions) {\n Object.keys(libOptions.allActions).forEach((actionKey) => {\n if (registeredAllActions.has(actionKey)) {\n this.logger.warning('All Action name collision - router-level handler takes precedence', { actionKey });\n } else {\n this.logger.debug('Configuring Library All Action %s', actionKey);\n router.post(`/${actionKey}`, this.wrapAsync(this.postAllAction));\n registeredAllActions.add(actionKey);\n }\n });\n }\n\n // Configure router-level allFacets first (highest precedence)\n this.logger.default('Router All Facets', { allFacets: this.options.allFacets });\n if (this.options.allFacets) {\n Object.keys(this.options.allFacets).forEach((facetKey) => {\n this.logger.debug('Configuring Router All Facet %s', facetKey);\n router.get(`/${facetKey}`, this.wrapAsync(this.getAllFacet));\n registeredAllFacets.add(facetKey);\n });\n }\n\n // Configure library allFacets, warn on conflicts\n this.logger.default('Library All Facets', { allFacets: libOptions.allFacets });\n if (libOptions.allFacets) {\n Object.keys(libOptions.allFacets).forEach((facetKey) => {\n if (registeredAllFacets.has(facetKey)) {\n this.logger.warning('All Facet name collision - router-level handler takes precedence', { facetKey });\n } else {\n this.logger.debug('Configuring Library All Facet %s', facetKey);\n router.get(`/${facetKey}`, this.wrapAsync(this.getAllFacet));\n registeredAllFacets.add(facetKey);\n }\n });\n }\n\n const itemRouter = Router();\n itemRouter.get('/', this.wrapAsync(this.getItem));\n itemRouter.put('/', this.wrapAsync(this.updateItem));\n itemRouter.delete('/', this.wrapAsync(this.deleteItem));\n\n // Configure router-level item actions first (highest precedence)\n this.logger.default('Router Item Actions', { itemActions: this.options.actions });\n if (this.options.actions) {\n Object.keys(this.options.actions).forEach((actionKey) => {\n this.logger.debug('Configuring Router Item Action %s', actionKey);\n itemRouter.post(`/${actionKey}`, this.wrapAsync(this.postItemAction));\n registeredItemActions.add(actionKey);\n });\n }\n\n // Configure library item actions, warn on conflicts\n this.logger.default('Library Item Actions', { itemActions: libOptions.actions });\n if (libOptions.actions) {\n Object.keys(libOptions.actions).forEach((actionKey) => {\n if (registeredItemActions.has(actionKey)) {\n this.logger.warning('Item Action name collision - router-level handler takes precedence', { actionKey });\n } else {\n this.logger.debug('Configuring Library Item Action %s', actionKey);\n itemRouter.post(`/${actionKey}`, this.wrapAsync(this.postItemAction));\n registeredItemActions.add(actionKey);\n }\n });\n }\n\n // Configure router-level item facets first (highest precedence)\n this.logger.default('Router Item Facets', { itemFacets: this.options.facets });\n if (this.options.facets) {\n Object.keys(this.options.facets).forEach((facetKey) => {\n this.logger.debug('Configuring Router Item Facet %s', facetKey);\n itemRouter.get(`/${facetKey}`, this.wrapAsync(this.getItemFacet));\n registeredItemFacets.add(facetKey);\n });\n }\n\n // Configure library item facets, warn on conflicts\n this.logger.default('Library Item Facets', { itemFacets: libOptions.facets });\n if (libOptions.facets) {\n Object.keys(libOptions.facets).forEach((facetKey) => {\n if (registeredItemFacets.has(facetKey)) {\n this.logger.warning('Item Facet name collision - router-level handler takes precedence', { facetKey });\n } else {\n this.logger.debug('Configuring Library Item Facet %s', facetKey);\n itemRouter.get(`/${facetKey}`, this.wrapAsync(this.getItemFacet));\n registeredItemFacets.add(facetKey);\n }\n });\n }\n\n this.logger.debug('Configuring Item Operations under PK Param %s', this.getPkParam());\n router.use(`/:${this.getPkParam()}`, this.validatePrimaryKeyValue, itemRouter);\n\n if (this.childRouters) {\n this.configureChildRouters(itemRouter, this.childRouters);\n }\n\n // Apply error handler as last middleware\n router.use(this.errorHandler);\n \n return router;\n }\n\n private validatePrimaryKeyValue = (req: Request, res: Response, next: any) => {\n const pkParamValue = req.params[this.getPkParam()];\n if (this.validatePKParam(pkParamValue)) {\n res.locals[this.getPkParam()] = pkParamValue;\n next();\n } else {\n this.logger.error('Invalid Primary Key', { pkParamValue, path: req?.originalUrl });\n res.status(400).json({ error: 'Invalid Primary Key', path: req?.originalUrl });\n }\n }\n\n private configureChildRouters = (router: Router, childRouters: Record<string, Router>) => {\n for (const path in childRouters) {\n this.logger.debug('Configuring Child Router at Path %s', path);\n\n router.use(`/${path}`, childRouters[path]);\n }\n return router;\n }\n\n public addChildRouter = (path: string, router: Router) => {\n this.childRouters[path] = router;\n }\n\n /* istanbul ignore next */\n public getRouter(): Router {\n const router = Router();\n this.configure(router);\n return router;\n }\n\n /* istanbul ignore next */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected createItem = async (req: Request, res: Response): Promise<void> => {\n throw new Error('Method not implemented in an abstract router');\n };\n\n // TODO: Probably a better way to do this, but this postCreate hook only needs the item.\n /* istanbul ignore next */\n public postCreateItem = async (item: Item<S, L1, L2, L3, L4, L5>): Promise<Item<S, L1, L2, L3, L4, L5>> => {\n this.logger.debug('Post Create Item', { item });\n return item;\n };\n\n protected deleteItem = async (req: Request, res: Response): Promise<void> => {\n const libOperations = this.lib.operations;\n\n this.logger.debug('Deleting Item', { query: req.query, params: req.params, locals: res.locals });\n const ik = this.getIk(res);\n \n try {\n const removedItem = await libOperations.remove(ik);\n if (removedItem) {\n const item = validatePK(removedItem, this.getPkType());\n res.json(item);\n } else {\n res.status(204).send();\n }\n } catch (error) {\n if (error instanceof NotFoundError || (error as any).name === 'NotFoundError') {\n res.status(404).json({ ik, message: \"Item Not Found\" });\n } else {\n this.logger.error('Error in deleteItem', { error });\n res.status(500).json({ ik, message: \"General Error\" });\n }\n }\n };\n\n /* eslint-disable */\n /* istanbul ignore next */\n protected findItems = async (req: Request, res: Response): Promise<void> => {\n throw new Error('Method not implemented in an abstract router');\n };\n /* eslint-enable */\n\n protected getItem = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Getting Item', { query: req.query, params: req.params, locals: res.locals });\n const ik = this.getIk(res);\n \n try {\n const fetchedItem = await libOperations.get(ik);\n if (!fetchedItem) {\n throw new ActionError({\n code: 'NOT_FOUND',\n message: `${this.keyType} not found`,\n operation: {\n type: 'get',\n name: 'get',\n params: { key: ik }\n },\n context: {\n itemType: this.keyType\n },\n details: { retryable: false },\n technical: {\n timestamp: new Date().toISOString()\n }\n });\n }\n \n const item = validatePK(fetchedItem, this.getPkType());\n res.json(item);\n } catch (error) {\n if (error instanceof NotFoundError || (error as any).name === 'NotFoundError') {\n res.status(404).json({ ik, message: \"Item Not Found\" });\n } else {\n this.logger.error('Error in getItem', { error });\n res.status(500).json({ ik, message: \"General Error\" });\n }\n }\n }\n\n protected updateItem = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.debug('Updating Item',\n { body: req?.body, query: req?.query, params: req?.params, locals: res?.locals });\n const ik = this.getIk(res);\n \n try {\n const itemToUpdate = this.convertDates(req.body as Partial<Item<S, L1, L2, L3, L4, L5>>);\n const retItem = validatePK(await libOperations.update(ik, itemToUpdate), this.getPkType());\n res.json(retItem);\n } catch (error) {\n if (error instanceof NotFoundError || (error as any).name === 'NotFoundError') {\n res.status(404).json({ ik, message: \"Item Not Found\" });\n } else {\n this.logger.error('Error in updateItem', { error });\n res.status(500).json({ ik, message: \"General Error\" });\n }\n }\n };\n\n public convertDates = (item: Partial<Item<S, L1, L2, L3, L4, L5>>): Partial<Item<S, L1, L2, L3, L4, L5>> => {\n this.logger.debug('Converting Dates', { item });\n const events = item.events as Record<string, ItemEvent> | undefined;\n if (events) {\n Object.keys(events).forEach((key: string) => {\n Object.assign(events, {\n [key]: deepmerge(events[key], { at: events[key].at ? new Date(events[key].at) : null })\n });\n });\n }\n Object.assign(item, { events });\n return item;\n };\n\n // TODO: Maybe just simplify this and require that everything is a UUID?\n /**\n * This method might be an annoyance, but we need to capture a few cases where someone passes\n * a PK parameter that has an odd string in it.\n *\n * @param pkParamValue The value of the primary key parameter\n * @returns if the value is valid.\n */\n protected validatePKParam = (pkParamValue: string): boolean => {\n let validPkParam = true;\n if (pkParamValue.length <= 0) {\n this.logger.error('Primary Key is an Empty String', { pkParamValue });\n validPkParam = false;\n } else if (pkParamValue === 'undefined') {\n this.logger.error('Primary Key is the string \\'undefined\\'', { pkParamValue });\n validPkParam = false;\n }\n return validPkParam;\n }\n\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["result"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PItemRouter.d.ts","sourceRoot":"","sources":["../src/PItemRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA4B,MAAM,EAA2B,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAMrC,qBAAa,WAAW,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;gBAErE,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAE,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAM;IAI1G,KAAK,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC;IAM/B,UAAU,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,OAAO,GAAG,mBAiDhE;IAEF,SAAS,CAAC,SAAS,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,mBAuCtD;CAEH"}
1
+ {"version":3,"file":"PItemRouter.d.ts","sourceRoot":"","sources":["../src/PItemRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA4B,MAAM,EAA2B,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,OAAO,EAAiB,MAAM,YAAY,CAAC;AAMpD,qBAAa,WAAW,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAC;gBAErE,GAAG,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAE,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAM;IAI1G,KAAK,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC;IAM/B,UAAU,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,OAAO,GAAG,mBAwBhE;IAEF,SAAS,CAAC,SAAS,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,mBAkDtD;CAEH"}
@@ -1,5 +1,6 @@
1
1
  import { paramsToQuery, validatePK } from "@fjell/core";
2
2
  import { ItemRouter } from "./ItemRouter.js";
3
+ import { NotFoundError } from "@fjell/lib";
3
4
  class PItemRouter extends ItemRouter {
4
5
  constructor(lib, keyType, options = {}) {
5
6
  super(lib, keyType, options);
@@ -19,65 +20,56 @@ class PItemRouter extends ItemRouter {
19
20
  this.logger.default("Created Item %j", item);
20
21
  res.status(201).json(item);
21
22
  } catch (error) {
22
- this.logger.error("Error caught in createItem", {
23
- errorName: error.name,
24
- errorMessage: error.message,
25
- body: req.body
26
- });
27
- if (error.name === "CreateValidationError" || error.name === "ValidationError" || error.name === "SequelizeValidationError" || error.message?.includes("validation") || error.message?.includes("Validation failed") || error.message?.includes("required") || error.message?.includes("must be") || error.message?.includes("cannot be") || error.message?.includes("notNull Violation") || error.message?.includes("cannot be null") || error.message?.includes("Required field")) {
28
- this.logger.error("Validation error in createItem", {
29
- error: error.message,
30
- body: req.body
31
- });
32
- res.status(400).json({
33
- success: false,
34
- error: error.message || "Validation failed"
35
- });
23
+ this.logger.error("Error in createItem", { error });
24
+ if (error.name === "CreateValidationError" || error.name === "ValidationError" || error.name === "SequelizeValidationError" || error.message && (error.message.includes("validation") || error.message.includes("required") || error.message.includes("cannot be null") || error.message.includes("notNull Violation"))) {
25
+ res.status(400).json({ success: false, error: error.message || "Validation failed" });
36
26
  } else {
37
- this.logger.error("General error in createItem", {
38
- error: error.message,
39
- stack: error.stack,
40
- body: req.body
41
- });
42
- res.status(500).json({
43
- success: false,
44
- error: "Internal server error"
45
- });
27
+ res.status(500).json({ success: false, error: error.message || "Internal server error" });
46
28
  }
47
29
  }
48
30
  };
49
31
  findItems = async (req, res) => {
50
32
  const libOperations = this.lib.operations;
51
33
  this.logger.default("Finding Items", { query: req.query, params: req.params, locals: res.locals });
52
- let items = [];
53
- const query = req.query;
54
- const finder = query["finder"];
55
- const finderParams = query["finderParams"];
56
- const one = query["one"];
57
- if (finder) {
58
- this.logger.default("Finding Items with Finder %s %j one:%s", finder, finderParams, one);
59
- try {
60
- const parsedParams = finderParams ? JSON.parse(finderParams) : {};
34
+ try {
35
+ let items = [];
36
+ const query = req.query;
37
+ const finder = query["finder"];
38
+ const finderParams = query["finderParams"];
39
+ const one = query["one"];
40
+ if (finder) {
41
+ this.logger.default("Finding Items with Finder %s %j one:%s", finder, finderParams, one);
42
+ let parsedParams;
43
+ try {
44
+ parsedParams = finderParams ? JSON.parse(finderParams) : {};
45
+ } catch (parseError) {
46
+ res.status(400).json({
47
+ error: "Invalid JSON in finderParams",
48
+ message: parseError.message
49
+ });
50
+ return;
51
+ }
61
52
  if (one === "true") {
62
53
  const item = await this.lib.findOne(finder, parsedParams);
63
54
  items = item ? [item] : [];
64
55
  } else {
65
56
  items = await libOperations.find(finder, parsedParams);
66
57
  }
67
- } catch (parseError) {
68
- this.logger.error("Error parsing finderParams JSON", { finder, finderParams, error: parseError.message });
69
- res.status(400).json({
70
- error: "Invalid JSON in finderParams",
71
- message: parseError.message
72
- });
73
- return;
58
+ } else {
59
+ const itemQuery = paramsToQuery(req.query);
60
+ this.logger.default("Finding Items with a query %j", itemQuery);
61
+ items = await libOperations.all(itemQuery);
62
+ }
63
+ const validatedItems = items.map((item) => validatePK(item, this.getPkType()));
64
+ res.json(validatedItems);
65
+ } catch (error) {
66
+ this.logger.error("Error in findItems", { error });
67
+ if (error instanceof NotFoundError || error?.name === "NotFoundError") {
68
+ res.status(404).json({ error: error.message || "Item not found" });
69
+ } else {
70
+ res.status(500).json({ error: error.message || "Internal server error" });
74
71
  }
75
- } else {
76
- const itemQuery = paramsToQuery(req.query);
77
- this.logger.default("Finding Items with a query %j", itemQuery);
78
- items = await libOperations.all(itemQuery);
79
72
  }
80
- res.json(items.map((item) => validatePK(item, this.getPkType())));
81
73
  };
82
74
  }
83
75
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/PItemRouter.ts"],
4
- "sourcesContent": ["import { Item, ItemQuery, paramsToQuery, PriKey, QueryParams, validatePK } from \"@fjell/core\";\nimport { Request, Response } from \"express\";\nimport { ItemRouter, ItemRouterOptions } from \"./ItemRouter.js\";\nimport { Library } from \"@fjell/lib\";\n\ninterface ParsedQuery {\n [key: string]: undefined | string | string[] | ParsedQuery | ParsedQuery[];\n}\n\nexport class PItemRouter<T extends Item<S>, S extends string> extends ItemRouter<S> {\n\n constructor(lib: Library<T, S>, keyType: S, options: ItemRouterOptions<S, never, never, never, never, never> = {}) {\n super(lib as any, keyType, options);\n }\n\n public getIk(res: Response): PriKey<S> {\n const pri = this.getPk(res) as PriKey<S>;\n return pri\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public createItem = async (req: Request, res: Response, next?: any) => {\n const libOperations = this.lib.operations;\n this.logger.default('Creating Item', { body: req.body, query: req.query, params: req.params, locals: res.locals });\n\n try {\n const itemToCreate = this.convertDates(req.body as Item<S>);\n let item = validatePK(await libOperations.create(itemToCreate), this.getPkType()) as Item<S>;\n item = await this.postCreateItem(item);\n this.logger.default('Created Item %j', item);\n res.status(201).json(item);\n } catch (error: any) {\n this.logger.error('Error caught in createItem', {\n errorName: error.name,\n errorMessage: error.message,\n body: req.body\n });\n\n // Check if this is a validation error (from fjell-lib, custom validators, or database constraints)\n if (error.name === 'CreateValidationError' ||\n error.name === 'ValidationError' ||\n error.name === 'SequelizeValidationError' ||\n error.message?.includes('validation') ||\n error.message?.includes('Validation failed') ||\n error.message?.includes('required') ||\n error.message?.includes('must be') ||\n error.message?.includes('cannot be') ||\n error.message?.includes('notNull Violation') ||\n error.message?.includes('cannot be null') ||\n error.message?.includes('Required field')) {\n this.logger.error('Validation error in createItem', {\n error: error.message,\n body: req.body\n });\n res.status(400).json({\n success: false,\n error: error.message || 'Validation failed'\n });\n } else {\n this.logger.error('General error in createItem', {\n error: error.message,\n stack: error.stack,\n body: req.body\n });\n res.status(500).json({\n success: false,\n error: 'Internal server error'\n });\n }\n }\n };\n\n protected findItems = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.default('Finding Items', { query: req.query, params: req.params, locals: res.locals });\n\n let items: Item<S>[] = [];\n\n const query: ParsedQuery = req.query as unknown as ParsedQuery;\n const finder = query['finder'] as string;\n const finderParams = query['finderParams'] as string;\n const one = query['one'] as string;\n\n if (finder) {\n // If finder is defined? Call a finder.\n this.logger.default('Finding Items with Finder %s %j one:%s', finder, finderParams, one);\n\n try {\n const parsedParams = finderParams ? JSON.parse(finderParams) : {};\n if (one === 'true') {\n const item = await (this.lib as any).findOne(finder, parsedParams);\n items = item ? [item] : [];\n } else {\n items = await libOperations.find(finder, parsedParams);\n }\n } catch (parseError: any) {\n this.logger.error('Error parsing finderParams JSON', { finder, finderParams, error: parseError.message });\n res.status(400).json({\n error: 'Invalid JSON in finderParams',\n message: parseError.message\n });\n return;\n }\n } else {\n // TODO: This is once of the more important places to perform some validaation and feedback\n const itemQuery: ItemQuery = paramsToQuery(req.query as QueryParams);\n this.logger.default('Finding Items with a query %j', itemQuery);\n items = await libOperations.all(itemQuery);\n }\n\n res.json(items.map((item: Item<S>) => validatePK(item, this.getPkType())));\n };\n\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Item, ItemQuery, paramsToQuery, PriKey, QueryParams, validatePK } from \"@fjell/core\";\nimport { Request, Response } from \"express\";\nimport { ItemRouter, ItemRouterOptions } from \"./ItemRouter.js\";\nimport { Library, NotFoundError } from \"@fjell/lib\";\n\ninterface ParsedQuery {\n [key: string]: undefined | string | string[] | ParsedQuery | ParsedQuery[];\n}\n\nexport class PItemRouter<T extends Item<S>, S extends string> extends ItemRouter<S> {\n\n constructor(lib: Library<T, S>, keyType: S, options: ItemRouterOptions<S, never, never, never, never, never> = {}) {\n super(lib as any, keyType, options);\n }\n\n public getIk(res: Response): PriKey<S> {\n const pri = this.getPk(res) as PriKey<S>;\n return pri\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n public createItem = async (req: Request, res: Response, next?: any) => {\n const libOperations = this.lib.operations;\n this.logger.default('Creating Item', { body: req.body, query: req.query, params: req.params, locals: res.locals });\n\n try {\n const itemToCreate = this.convertDates(req.body as Item<S>);\n let item = validatePK(await libOperations.create(itemToCreate), this.getPkType()) as Item<S>;\n item = await this.postCreateItem(item);\n this.logger.default('Created Item %j', item);\n res.status(201).json(item);\n } catch (error: any) {\n this.logger.error('Error in createItem', { error });\n // Check for validation errors\n if (error.name === 'CreateValidationError' || error.name === 'ValidationError' ||\n error.name === 'SequelizeValidationError' ||\n (error.message && (error.message.includes('validation') ||\n error.message.includes('required') ||\n error.message.includes('cannot be null') ||\n error.message.includes('notNull Violation')))) {\n res.status(400).json({ success: false, error: error.message || \"Validation failed\" });\n } else {\n res.status(500).json({ success: false, error: error.message || \"Internal server error\" });\n }\n }\n };\n\n protected findItems = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\n this.logger.default('Finding Items', { query: req.query, params: req.params, locals: res.locals });\n\n try {\n let items: Item<S>[] = [];\n\n const query: ParsedQuery = req.query as unknown as ParsedQuery;\n const finder = query['finder'] as string;\n const finderParams = query['finderParams'] as string;\n const one = query['one'] as string;\n\n if (finder) {\n // If finder is defined? Call a finder.\n this.logger.default('Finding Items with Finder %s %j one:%s', finder, finderParams, one);\n\n let parsedParams: any;\n try {\n parsedParams = finderParams ? JSON.parse(finderParams) : {};\n } catch (parseError: any) {\n res.status(400).json({\n error: 'Invalid JSON in finderParams',\n message: parseError.message\n });\n return;\n }\n\n if (one === 'true') {\n const item = await (this.lib as any).findOne(finder, parsedParams);\n items = item ? [item] : [];\n } else {\n items = await libOperations.find(finder, parsedParams);\n }\n } else {\n // TODO: This is once of the more important places to perform some validaation and feedback\n const itemQuery: ItemQuery = paramsToQuery(req.query as QueryParams);\n this.logger.default('Finding Items with a query %j', itemQuery);\n items = await libOperations.all(itemQuery);\n }\n\n const validatedItems = items.map((item: Item<S>) => validatePK(item, this.getPkType()));\n res.json(validatedItems);\n } catch (error: any) {\n this.logger.error('Error in findItems', { error });\n if (error instanceof NotFoundError || error?.name === 'NotFoundError') {\n res.status(404).json({ error: error.message || 'Item not found' });\n } else {\n res.status(500).json({ error: error.message || 'Internal server error' });\n }\n }\n };\n\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,13 @@
1
+ import { Express } from 'express';
2
+ import { ErrorHandlerOptions } from './errorHandler.js';
3
+ export interface FjellAppOptions {
4
+ errorHandler?: ErrorHandlerOptions;
5
+ jsonLimit?: string;
6
+ urlencoded?: boolean;
7
+ cors?: boolean | any;
8
+ }
9
+ /**
10
+ * Create an Express app configured for Fjell with standard middleware
11
+ */
12
+ export declare function createFjellApp(options?: FjellAppOptions): Express;
13
+ //# sourceMappingURL=createApp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createApp.d.ts","sourceRoot":"","sources":["../src/createApp.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,GAAG,GAAG,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,eAAoB,GAAG,OAAO,CA8BrE"}
@@ -0,0 +1,27 @@
1
+ import express from "express";
2
+ function createFjellApp(options = {}) {
3
+ const app = express();
4
+ app.use(express.json({ limit: options.jsonLimit || "10mb" }));
5
+ if (options.urlencoded !== false) {
6
+ app.use(express.urlencoded({ extended: true }));
7
+ }
8
+ if (options.cors) {
9
+ try {
10
+ const cors = require("cors");
11
+ app.use(cors(options.cors === true ? {} : options.cors));
12
+ } catch {
13
+ console.warn("CORS requested but cors package not installed. Run: npm install cors");
14
+ }
15
+ }
16
+ app.use((req, res, next) => {
17
+ if (!req.headers["x-request-id"]) {
18
+ req.headers["x-request-id"] = `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
19
+ }
20
+ next();
21
+ });
22
+ return app;
23
+ }
24
+ export {
25
+ createFjellApp
26
+ };
27
+ //# sourceMappingURL=createApp.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/createApp.ts"],
4
+ "sourcesContent": ["import express, { Express } from 'express';\nimport { ErrorHandlerOptions } from './errorHandler.js';\n\nexport interface FjellAppOptions {\n errorHandler?: ErrorHandlerOptions;\n jsonLimit?: string;\n urlencoded?: boolean;\n cors?: boolean | any;\n}\n\n/**\n * Create an Express app configured for Fjell with standard middleware\n */\nexport function createFjellApp(options: FjellAppOptions = {}): Express {\n const app = express();\n\n // Standard middleware\n app.use(express.json({ limit: options.jsonLimit || '10mb' }));\n \n if (options.urlencoded !== false) {\n app.use(express.urlencoded({ extended: true }));\n }\n\n if (options.cors) {\n // Dynamic import for optional CORS dependency\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const cors = require('cors');\n app.use(cors(options.cors === true ? {} : options.cors));\n } catch {\n console.warn('CORS requested but cors package not installed. Run: npm install cors');\n }\n }\n\n // Add request ID middleware\n app.use((req, res, next) => {\n if (!req.headers['x-request-id']) {\n req.headers['x-request-id'] = `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n next();\n });\n\n return app;\n}\n\n"],
5
+ "mappings": "AAAA,OAAO,aAA0B;AAa1B,SAAS,eAAe,UAA2B,CAAC,GAAY;AACrE,QAAM,MAAM,QAAQ;AAGpB,MAAI,IAAI,QAAQ,KAAK,EAAE,OAAO,QAAQ,aAAa,OAAO,CAAC,CAAC;AAE5D,MAAI,QAAQ,eAAe,OAAO;AAChC,QAAI,IAAI,QAAQ,WAAW,EAAE,UAAU,KAAK,CAAC,CAAC;AAAA,EAChD;AAEA,MAAI,QAAQ,MAAM;AAEhB,QAAI;AAEF,YAAM,OAAO,QAAQ,MAAM;AAC3B,UAAI,IAAI,KAAK,QAAQ,SAAS,OAAO,CAAC,IAAI,QAAQ,IAAI,CAAC;AAAA,IACzD,QAAQ;AACN,cAAQ,KAAK,sEAAsE;AAAA,IACrF;AAAA,EACF;AAGA,MAAI,IAAI,CAAC,KAAK,KAAK,SAAS;AAC1B,QAAI,CAAC,IAAI,QAAQ,cAAc,GAAG;AAChC,UAAI,QAAQ,cAAc,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,IAC5F;AACA,SAAK;AAAA,EACP,CAAC;AAED,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,52 @@
1
+ import { NextFunction, Request, Response } from 'express';
2
+ import { ErrorInfo } from '@fjell/core';
3
+ export interface ErrorHandlerOptions {
4
+ includeStackTrace?: boolean;
5
+ logErrors?: boolean;
6
+ customErrorMapper?: (error: any) => ErrorInfo | null;
7
+ }
8
+ export declare class FjellErrorHandler {
9
+ private options;
10
+ constructor(options?: ErrorHandlerOptions);
11
+ /**
12
+ * Get appropriate HTTP status code for error
13
+ */
14
+ private getHttpStatusForError;
15
+ /**
16
+ * Convert generic errors to ErrorInfo structure
17
+ */
18
+ private convertToErrorInfo;
19
+ /**
20
+ * Enhance error info with request context
21
+ */
22
+ private enhanceErrorInfo;
23
+ /**
24
+ * Extract operation type from request
25
+ */
26
+ private getOperationTypeFromRequest;
27
+ /**
28
+ * Extract item type from path
29
+ */
30
+ private extractItemType;
31
+ /**
32
+ * Get request ID from headers or generate one
33
+ */
34
+ private getRequestId;
35
+ /**
36
+ * Get error code for HTTP status
37
+ */
38
+ private getErrorCodeForStatus;
39
+ /**
40
+ * Get default message for HTTP status
41
+ */
42
+ private getDefaultMessageForStatus;
43
+ /**
44
+ * Express error handler middleware
45
+ */
46
+ handle: (err: any, req: Request, res: Response, next: NextFunction) => void;
47
+ }
48
+ /**
49
+ * Export convenience function
50
+ */
51
+ export declare function createErrorHandler(options?: ErrorHandlerOptions): (err: any, req: Request, res: Response, next: NextFunction) => void;
52
+ //# sourceMappingURL=errorHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../src/errorHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAiB,MAAM,aAAa,CAAC;AAKvD,MAAM,WAAW,mBAAmB;IAClC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,SAAS,GAAG,IAAI,CAAC;CACtD;AAED,qBAAa,iBAAiB;IAChB,OAAO,CAAC,OAAO;gBAAP,OAAO,GAAE,mBAAwB;IAQrD;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiE1B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAoBxB;;OAEG;IACH,OAAO,CAAC,2BAA2B;IA4BnC;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,OAAO,CAAC,0BAA0B;IAclC;;OAEG;IACH,MAAM,GAAI,KAAK,GAAG,EAAE,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAsCxE;CACH;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,mBAAmB,SA5C/C,GAAG,OAAO,OAAO,OAAO,QAAQ,QAAQ,YAAY,KAAG,IAAI,CA+C3E"}