@fjell/express-router 4.4.23 → 4.4.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +205 -0
- package/dist/CItemRouter.d.ts +1 -1
- package/dist/CItemRouter.d.ts.map +1 -1
- package/dist/CItemRouter.js +23 -8
- package/dist/CItemRouter.js.map +2 -2
- package/dist/Instance.d.ts.map +1 -1
- package/dist/Instance.js.map +2 -2
- package/dist/InstanceFactory.d.ts.map +1 -1
- package/dist/InstanceFactory.js.map +2 -2
- package/dist/ItemRouter.d.ts +12 -3
- package/dist/ItemRouter.d.ts.map +1 -1
- package/dist/ItemRouter.js +91 -15
- package/dist/ItemRouter.js.map +2 -2
- package/dist/PItemRouter.d.ts +1 -1
- package/dist/PItemRouter.d.ts.map +1 -1
- package/dist/PItemRouter.js.map +2 -2
- package/dist/util/general.js.map +1 -1
- package/examples/README.md +47 -0
- package/examples/basic-router-example.ts +7 -6
- package/examples/full-application-example.ts +137 -12
- package/examples/nested-router-example.ts +154 -54
- package/examples/router-handlers-example.ts +370 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -110,6 +110,207 @@ This creates endpoints like:
|
|
|
110
110
|
|
|
111
111
|
## Advanced Usage
|
|
112
112
|
|
|
113
|
+
### Router-Level Handlers
|
|
114
|
+
|
|
115
|
+
Fjell Express Router supports router-level handlers for actions, facets, allActions, and allFacets. These handlers take precedence over library-level handlers and are ideal for implementing cross-system integrations, external service calls, or complex business logic that doesn't belong in the library layer.
|
|
116
|
+
|
|
117
|
+
#### When to Use Router-Level Handlers
|
|
118
|
+
|
|
119
|
+
- **Cross-system integrations**: When you need to call external services (APIs, databases, etc.)
|
|
120
|
+
- **Complex aggregations**: When you need to combine data from multiple sources
|
|
121
|
+
- **External notifications**: When you need to send emails, push notifications, etc.
|
|
122
|
+
- **Audit logging**: When you need to log actions to external systems
|
|
123
|
+
- **Caching strategies**: When you need custom caching logic
|
|
124
|
+
|
|
125
|
+
#### Example: Router-Level Handlers
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { PItemRouter, CItemRouter } from '@fjell/express-router';
|
|
129
|
+
import { Item, PriKey, ComKey } from '@fjell/core';
|
|
130
|
+
import { Request, Response } from 'express';
|
|
131
|
+
|
|
132
|
+
// Define your data models
|
|
133
|
+
interface User extends Item<'user'> {
|
|
134
|
+
id: string;
|
|
135
|
+
name: string;
|
|
136
|
+
email: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface Post extends Item<'post', 'user'> {
|
|
140
|
+
id: string;
|
|
141
|
+
title: string;
|
|
142
|
+
content: string;
|
|
143
|
+
authorId: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Create routers with router-level handlers
|
|
147
|
+
const userRouter = new PItemRouter(userInstance, 'user', {
|
|
148
|
+
// Router-level action handlers
|
|
149
|
+
actions: {
|
|
150
|
+
activate: async (req: Request, res: Response, ik: PriKey<'user'>) => {
|
|
151
|
+
// Custom logic: send activation email, update status, etc.
|
|
152
|
+
const user = await userInstance.operations.get(ik);
|
|
153
|
+
await emailService.sendActivationEmail(user.email);
|
|
154
|
+
await auditService.logAction('user_activated', ik.pk);
|
|
155
|
+
|
|
156
|
+
res.json({
|
|
157
|
+
message: 'User activated via router handler',
|
|
158
|
+
userId: ik.pk,
|
|
159
|
+
emailSent: true
|
|
160
|
+
});
|
|
161
|
+
},
|
|
162
|
+
deactivate: async (req: Request, res: Response, ik: PriKey<'user'>) => {
|
|
163
|
+
// Custom logic: send deactivation notification, update status, etc.
|
|
164
|
+
const user = await userInstance.operations.get(ik);
|
|
165
|
+
await notificationService.sendDeactivationNotification(user);
|
|
166
|
+
await auditService.logAction('user_deactivated', ik.pk);
|
|
167
|
+
|
|
168
|
+
res.json({
|
|
169
|
+
message: 'User deactivated via router handler',
|
|
170
|
+
userId: ik.pk,
|
|
171
|
+
notificationSent: true
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
// Router-level facet handlers
|
|
177
|
+
facets: {
|
|
178
|
+
profile: async (req: Request, res: Response, ik: PriKey<'user'>) => {
|
|
179
|
+
// Custom logic: aggregate data from multiple sources
|
|
180
|
+
const user = await userInstance.operations.get(ik);
|
|
181
|
+
const socialData = await socialService.getUserData(ik.pk);
|
|
182
|
+
const preferences = await preferenceService.getUserPreferences(ik.pk);
|
|
183
|
+
|
|
184
|
+
res.json({
|
|
185
|
+
userId: ik.pk,
|
|
186
|
+
basicInfo: user,
|
|
187
|
+
socialInfo: socialData,
|
|
188
|
+
preferences: preferences
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
stats: async (req: Request, res: Response, ik: PriKey<'user'>) => {
|
|
192
|
+
// Custom logic: calculate statistics from multiple data sources
|
|
193
|
+
const postsCount = await postService.getUserPostsCount(ik.pk);
|
|
194
|
+
const commentsCount = await commentService.getUserCommentsCount(ik.pk);
|
|
195
|
+
const likesReceived = await likeService.getUserLikesCount(ik.pk);
|
|
196
|
+
|
|
197
|
+
res.json({
|
|
198
|
+
userId: ik.pk,
|
|
199
|
+
postsCount,
|
|
200
|
+
commentsCount,
|
|
201
|
+
likesReceived,
|
|
202
|
+
lastActivity: new Date()
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// Router-level all action handlers
|
|
208
|
+
allActions: {
|
|
209
|
+
bulkActivate: async (req: Request, res: Response) => {
|
|
210
|
+
// Custom logic: batch processing, external service integration
|
|
211
|
+
const { userIds } = req.body;
|
|
212
|
+
const results = await Promise.all(
|
|
213
|
+
userIds.map(async (userId) => {
|
|
214
|
+
const user = await userInstance.operations.get({ kt: 'user', pk: userId });
|
|
215
|
+
await emailService.sendActivationEmail(user.email);
|
|
216
|
+
return { userId, emailSent: true };
|
|
217
|
+
})
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
res.json({
|
|
221
|
+
message: 'Bulk activation via router handler',
|
|
222
|
+
processedUsers: results.length,
|
|
223
|
+
results
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
// Router-level all facet handlers
|
|
229
|
+
allFacets: {
|
|
230
|
+
userStats: async (req: Request, res: Response) => {
|
|
231
|
+
// Custom logic: aggregate statistics from multiple systems
|
|
232
|
+
const totalUsers = await userInstance.operations.all().then(users => users.length);
|
|
233
|
+
const activeUsers = await analyticsService.getActiveUsersCount();
|
|
234
|
+
const newUsersThisMonth = await analyticsService.getNewUsersThisMonth();
|
|
235
|
+
|
|
236
|
+
res.json({
|
|
237
|
+
totalUsers,
|
|
238
|
+
activeUsers,
|
|
239
|
+
newUsersThisMonth,
|
|
240
|
+
systemHealth: 'excellent'
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Child router with router-level handlers
|
|
247
|
+
const postRouter = new CItemRouter(postInstance, 'post', userRouter, {
|
|
248
|
+
actions: {
|
|
249
|
+
publish: async (req: Request, res: Response, ik: ComKey<'post', 'user'>) => {
|
|
250
|
+
// Custom logic: publish to social media, send notifications
|
|
251
|
+
const post = await postInstance.operations.get(ik);
|
|
252
|
+
await socialMediaService.publishToTwitter(post);
|
|
253
|
+
await socialMediaService.publishToLinkedIn(post);
|
|
254
|
+
await notificationService.notifyFollowers(post.authorId, post);
|
|
255
|
+
|
|
256
|
+
res.json({
|
|
257
|
+
message: 'Post published via router handler',
|
|
258
|
+
postId: ik.pk,
|
|
259
|
+
socialMediaPosted: true,
|
|
260
|
+
notificationsSent: true
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
|
|
265
|
+
facets: {
|
|
266
|
+
analytics: async (req: Request, res: Response, ik: ComKey<'post', 'user'>) => {
|
|
267
|
+
// Custom logic: aggregate analytics from multiple sources
|
|
268
|
+
const views = await analyticsService.getPostViews(ik.pk);
|
|
269
|
+
const likes = await socialService.getPostLikes(ik.pk);
|
|
270
|
+
const shares = await socialService.getPostShares(ik.pk);
|
|
271
|
+
|
|
272
|
+
res.json({
|
|
273
|
+
postId: ik.pk,
|
|
274
|
+
views,
|
|
275
|
+
likes,
|
|
276
|
+
shares,
|
|
277
|
+
engagementRate: (likes + shares) / views
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### Handler Priority
|
|
285
|
+
|
|
286
|
+
Router-level handlers take precedence over library-level handlers:
|
|
287
|
+
|
|
288
|
+
1. **Router-level handler exists**: Use router handler
|
|
289
|
+
2. **Router-level handler doesn't exist**: Fallback to library handler
|
|
290
|
+
3. **No handlers exist**: Return error
|
|
291
|
+
|
|
292
|
+
This allows you to:
|
|
293
|
+
- Override specific handlers while keeping others at the library level
|
|
294
|
+
- Implement handlers only at the router level when needed
|
|
295
|
+
- Mix and match router and library handlers as appropriate
|
|
296
|
+
|
|
297
|
+
#### Handler Signatures
|
|
298
|
+
|
|
299
|
+
**Item Actions & Facets** (for PItemRouter):
|
|
300
|
+
```typescript
|
|
301
|
+
async (req: Request, res: Response, ik: PriKey<S>) => Promise<void>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Item Actions & Facets** (for CItemRouter):
|
|
305
|
+
```typescript
|
|
306
|
+
async (req: Request, res: Response, ik: ComKey<S, L1, L2, L3, L4, L5>) => Promise<void>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**All Actions & Facets** (for both router types):
|
|
310
|
+
```typescript
|
|
311
|
+
async (req: Request, res: Response) => Promise<void>
|
|
312
|
+
```
|
|
313
|
+
|
|
113
314
|
### Custom Business Logic
|
|
114
315
|
|
|
115
316
|
Add custom routes alongside automatic CRUD operations:
|
|
@@ -234,6 +435,7 @@ This package includes comprehensive examples in the `examples/` directory:
|
|
|
234
435
|
|
|
235
436
|
- **`basic-router-example.ts`** - Start here for fundamental usage patterns
|
|
236
437
|
- **`nested-router-example.ts`** - Hierarchical data management with organizations/departments/employees
|
|
438
|
+
- **`router-handlers-example.ts`** - Router-level handlers for cross-system integrations
|
|
237
439
|
- **`full-application-example.ts`** - Production-ready e-commerce application
|
|
238
440
|
|
|
239
441
|
Run examples:
|
|
@@ -245,6 +447,9 @@ npx tsx examples/basic-router-example.ts
|
|
|
245
447
|
# Nested routing example
|
|
246
448
|
npx tsx examples/nested-router-example.ts
|
|
247
449
|
|
|
450
|
+
# Router handlers example
|
|
451
|
+
npx tsx examples/router-handlers-example.ts
|
|
452
|
+
|
|
248
453
|
# Full application example
|
|
249
454
|
npx tsx examples/full-application-example.ts
|
|
250
455
|
```
|
package/dist/CItemRouter.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ItemRouter, ItemRouterOptions } from "./ItemRouter.js";
|
|
|
4
4
|
import { Instance } from "./Instance.js";
|
|
5
5
|
export declare class CItemRouter<T extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> extends ItemRouter<S, L1, L2, L3, L4, L5> {
|
|
6
6
|
private parentRoute;
|
|
7
|
-
constructor(lib: Instance<T, S, L1, L2, L3, L4, L5>, type: S, parentRoute: ItemRouter<L1, L2, L3, L4, L5, never>, options?: ItemRouterOptions);
|
|
7
|
+
constructor(lib: Instance<T, S, L1, L2, L3, L4, L5>, type: S, parentRoute: ItemRouter<L1, L2, L3, L4, L5, never>, options?: ItemRouterOptions<S, L1, L2, L3, L4, L5>);
|
|
8
8
|
hasParent(): boolean;
|
|
9
9
|
getIk(res: Response): ComKey<S, L1, L2, L3, L4, L5>;
|
|
10
10
|
getLKA(res: Response): LocKeyArray<S, L1, L2, L3, L4>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CItemRouter.d.ts","sourceRoot":"","sources":["../src/CItemRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAAE,IAAI,EAAqB,WAAW,EAC7C,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"CItemRouter.d.ts","sourceRoot":"","sources":["../src/CItemRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAAE,IAAI,EAAqB,WAAW,EAC7C,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAMzC,qBAAa,WAAW,CACtB,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,EACjB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,CACzB,SAAQ,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IAEzC,OAAO,CAAC,WAAW,CAAwC;gBAGzD,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACvC,IAAI,EAAE,CAAC,EACP,WAAW,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,EAClD,OAAO,GAAE,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAM;IAMjD,SAAS,IAAI,OAAO;IAIpB,KAAK,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IAMnD,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IAWrD,YAAY,CAAC,GAAG,EAAE,QAAQ,GAAG,WAAW,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IAInE,SAAS,CAAC,UAAU,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,mBAuBvD;IAEF,SAAS,CAAC,SAAS,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,mBA4BtD;CAEH"}
|
package/dist/CItemRouter.js
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
paramsToQuery,
|
|
3
3
|
validatePK
|
|
4
4
|
} from "@fjell/core";
|
|
5
|
+
import { NotFoundError } from "@fjell/lib";
|
|
5
6
|
import { ItemRouter } from "./ItemRouter.js";
|
|
6
7
|
class CItemRouter extends ItemRouter {
|
|
7
8
|
parentRoute;
|
|
@@ -28,14 +29,28 @@ class CItemRouter extends ItemRouter {
|
|
|
28
29
|
createItem = async (req, res) => {
|
|
29
30
|
const libOperations = this.lib.operations;
|
|
30
31
|
this.logger.default("Creating Item", { body: req?.body, query: req?.query, params: req?.params, locals: res?.locals });
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
try {
|
|
33
|
+
const itemToCreate = this.convertDates(req.body);
|
|
34
|
+
let item = validatePK(await libOperations.create(
|
|
35
|
+
itemToCreate,
|
|
36
|
+
{ locations: this.getLocations(res) }
|
|
37
|
+
), this.getPkType());
|
|
38
|
+
item = await this.postCreateItem(item);
|
|
39
|
+
this.logger.default("Created Item %j", item);
|
|
40
|
+
res.json(item);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
if (err instanceof NotFoundError) {
|
|
43
|
+
this.logger.error("Item Not Found for Create", { message: err?.message, stack: err?.stack });
|
|
44
|
+
res.status(404).json({
|
|
45
|
+
message: "Item Not Found"
|
|
46
|
+
});
|
|
47
|
+
} else {
|
|
48
|
+
this.logger.error("General Error in Create", { message: err?.message, stack: err?.stack });
|
|
49
|
+
res.status(500).json({
|
|
50
|
+
message: "General Error"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
39
54
|
};
|
|
40
55
|
findItems = async (req, res) => {
|
|
41
56
|
const libOperations = this.lib.operations;
|
package/dist/CItemRouter.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/CItemRouter.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n ComKey, Item, ItemQuery, LocKey, LocKeyArray, paramsToQuery, PriKey, QueryParams, validatePK\n} from \"@fjell/core\";\nimport { Request, Response } from \"express\";\nimport { ItemRouter, ItemRouterOptions } from \"./ItemRouter.js\";\nimport { Instance } from \"./Instance.js\";\n\ninterface ParsedQuery {\n [key: string]: undefined | string | string[] | ParsedQuery | ParsedQuery[];\n}\n\nexport class CItemRouter<\n T extends Item<S, L1, L2, L3, L4, L5>,\n S extends string,\n L1 extends string,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never\n> extends ItemRouter<S, L1, L2, L3, L4, L5> {\n\n private parentRoute: ItemRouter<L1, L2, L3, L4, L5, never>;\n\n constructor(\n lib: Instance<T, S, L1, L2, L3, L4, L5>,\n type: S,\n parentRoute: ItemRouter<L1, L2, L3, L4, L5, never>,\n options: ItemRouterOptions = {},\n ) {\n super(lib as any, type, options);\n this.parentRoute = parentRoute;\n }\n\n public hasParent(): boolean {\n return !!this.parentRoute;\n }\n\n public getIk(res: Response): ComKey<S, L1, L2, L3, L4, L5> {\n const pri = this.getPk(res) as PriKey<S>;\n const loc = this.getLocations(res) as LocKeyArray<L1, L2, L3, L4, L5>;\n return { kt: pri.kt, pk: pri.pk, loc }\n }\n\n public getLKA(res: Response): LocKeyArray<S, L1, L2, L3, L4> {\n /**\n * A location key array is passed to a child router to provide contextfor the items it will\n * be working with. It is always a concatenation of \"My LKA\" + \"Parent LKA\" which will\n * bubble all the way up to the root Primary.\n */\n let lka: LocKey<S | L1 | L2 | L3 | L4>[] = [this.getLk(res)];\n lka = lka.concat(this.parentRoute.getLKA(res) as LocKey<S | L1 | L2 | L3 | L4>[]);\n return lka as LocKeyArray<S, L1, L2, L3, L4>;\n }\n\n public getLocations(res: Response): LocKeyArray<L1, L2, L3, L4, L5> {\n return this.parentRoute.getLKA(res) as LocKeyArray<L1, L2, L3, L4, L5>;\n }\n\n protected createItem = async (req: Request, res: Response) => {\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 const itemToCreate = this.convertDates(req.body as Item<S, L1, L2, L3, L4, L5>);\n
|
|
5
|
-
"mappings": "AAAA;AAAA,EACgD;AAAA,EAAoC;AAAA,OAC7E;
|
|
4
|
+
"sourcesContent": ["import {\n ComKey, Item, ItemQuery, LocKey, LocKeyArray, paramsToQuery, PriKey, QueryParams, validatePK\n} from \"@fjell/core\";\nimport { NotFoundError } from \"@fjell/lib\";\nimport { Request, Response } from \"express\";\nimport { ItemRouter, ItemRouterOptions } from \"./ItemRouter.js\";\nimport { Instance } from \"./Instance.js\";\n\ninterface ParsedQuery {\n [key: string]: undefined | string | string[] | ParsedQuery | ParsedQuery[];\n}\n\nexport class CItemRouter<\n T extends Item<S, L1, L2, L3, L4, L5>,\n S extends string,\n L1 extends string,\n L2 extends string = never,\n L3 extends string = never,\n L4 extends string = never,\n L5 extends string = never\n> extends ItemRouter<S, L1, L2, L3, L4, L5> {\n\n private parentRoute: ItemRouter<L1, L2, L3, L4, L5, never>;\n\n constructor(\n lib: Instance<T, S, L1, L2, L3, L4, L5>,\n type: S,\n parentRoute: ItemRouter<L1, L2, L3, L4, L5, never>,\n options: ItemRouterOptions<S, L1, L2, L3, L4, L5> = {},\n ) {\n super(lib as any, type, options);\n this.parentRoute = parentRoute;\n }\n\n public hasParent(): boolean {\n return !!this.parentRoute;\n }\n\n public getIk(res: Response): ComKey<S, L1, L2, L3, L4, L5> {\n const pri = this.getPk(res) as PriKey<S>;\n const loc = this.getLocations(res) as LocKeyArray<L1, L2, L3, L4, L5>;\n return { kt: pri.kt, pk: pri.pk, loc }\n }\n\n public getLKA(res: Response): LocKeyArray<S, L1, L2, L3, L4> {\n /**\n * A location key array is passed to a child router to provide contextfor the items it will\n * be working with. It is always a concatenation of \"My LKA\" + \"Parent LKA\" which will\n * bubble all the way up to the root Primary.\n */\n let lka: LocKey<S | L1 | L2 | L3 | L4>[] = [this.getLk(res)];\n lka = lka.concat(this.parentRoute.getLKA(res) as LocKey<S | L1 | L2 | L3 | L4>[]);\n return lka as LocKeyArray<S, L1, L2, L3, L4>;\n }\n\n public getLocations(res: Response): LocKeyArray<L1, L2, L3, L4, L5> {\n return this.parentRoute.getLKA(res) as LocKeyArray<L1, L2, L3, L4, L5>;\n }\n\n protected createItem = async (req: Request, res: Response) => {\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 try {\n const itemToCreate = this.convertDates(req.body as Item<S, L1, L2, L3, L4, L5>);\n let item = validatePK(await libOperations.create(\n itemToCreate, { locations: this.getLocations(res) }), this.getPkType()) as Item<S, L1, L2, L3, L4, L5>;\n item = await this.postCreateItem(item);\n this.logger.default('Created Item %j', item);\n res.json(item);\n } catch (err: any) {\n if (err instanceof NotFoundError) {\n this.logger.error('Item Not Found for Create', { message: err?.message, stack: err?.stack });\n res.status(404).json({\n message: \"Item Not Found\",\n });\n } else {\n this.logger.error('General Error in Create', { message: err?.message, stack: err?.stack });\n res.status(500).json({\n message: \"General Error\",\n });\n }\n }\n };\n\n protected findItems = async (req: Request, res: Response) => {\n const libOperations = this.lib.operations;\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 let items: Item<S, L1, L2, L3, L4, L5>[] = [];\n\n if (finder) {\n // If finder is defined? Call a finder.\n this.logger.default('Finding Items with Finder', { finder, finderParams, one });\n\n if (one === 'true') {\n const item = await (this.lib as any).findOne(finder, JSON.parse(finderParams), this.getLocations(res));\n items = item ? [item] : [];\n } else {\n items = await libOperations.find(finder, JSON.parse(finderParams), this.getLocations(res));\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 Query: %j', itemQuery);\n items = await libOperations.all(itemQuery, this.getLocations(res));\n this.logger.default('Found %d Items with Query', items.length);\n }\n\n res.json(items.map((item: Item<S, L1, L2, L3, L4, L5>) => validatePK(item, this.getPkType())));\n };\n\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/Instance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Instance.d.ts","sourceRoot":"","sources":["../src/Instance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,UAAU,EAAwC,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ,CACvB,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,CACzB,SAAQ,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IAC3C,yEAAyE;IACzE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1C,sFAAsF;IACtF,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACjD,uFAAuF;IACvF,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3C,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;CACvB;AAED,eAAO,MAAM,cAAc,GACzB,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"Instance.d.ts","sourceRoot":"","sources":["../src/Instance.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,UAAU,EAAwC,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ,CACvB,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,CACzB,SAAQ,YAAY,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;IAC3C,yEAAyE;IACzE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC1C,sFAAsF;IACtF,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACjD,uFAAuF;IACvF,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3C,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;CACvB;AAED,eAAO,MAAM,cAAc,GACzB,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EAEvB,UAAU,QAAQ,EAClB,YAAY,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAC7C,QAAQ,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACzC,YAAY,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAChD,UAAU,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,KAC1C,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAIrC,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,UAAU,GAAG,KAAG,QAAQ,IAAI,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAQhG,CAAA"}
|
package/dist/Instance.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/Instance.ts"],
|
|
4
|
-
"sourcesContent": ["import LibLogger from \"./logger.js\";\nimport { Item } from \"@fjell/core\";\nimport { Instance as BaseInstance, Coordinate, createInstance as createBaseInstance, Registry } from \"@fjell/registry\";\nimport { Operations, Options } from \"@fjell/lib\";\nimport { ItemRouter } from \"./ItemRouter.js\";\n\nconst logger = LibLogger.get(\"Instance\");\n\n/**\n * The Express Router Instance interface represents a router model instance that extends the base Instance\n * from @fjell/registry and adds express router operations for handling HTTP requests.\n *\n * The interface extends the base Instance (which provides coordinate and registry) with:\n * - router: Provides methods for routing HTTP requests and handling CRUD operations\n * - operations: Provides methods for interacting with the data model (get, find, all, etc.)\n * - options: Provides hooks, validators, finders, actions, and facets\n *\n * @template V - The type of the data model item, extending Item\n * @template S - The string literal type representing the model's key type\n * @template L1-L5 - Optional string literal types for location hierarchy levels\n */\nexport interface Instance<\n V extends Item<S, L1, L2, L3, L4, L5>,\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> extends BaseInstance<S, L1, L2, L3, L4, L5> {\n /** The router object that provides methods for handling HTTP requests */\n router: ItemRouter<S, L1, L2, L3, L4, L5>;\n /** The operations object that provides methods for interacting with the data model */\n operations: Operations<V, S, L1, L2, L3, L4, L5>;\n /** The options object that provides hooks, validators, finders, actions, and facets */\n options: Options<V, S, L1, L2, L3, L4, L5>;\n /** The data model item type (for type safety) */\n readonly itemType?: V;\n}\n\nexport const createInstance = <\n V extends Item<S, L1, L2, L3, L4, L5>,\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
|
|
5
|
-
"mappings": "AAAA,OAAO,eAAe;AAEtB,SAA+C,kBAAkB,0BAAoC;AAIrG,MAAM,SAAS,UAAU,IAAI,UAAU;AAkChC,MAAM,iBAAiB,
|
|
4
|
+
"sourcesContent": ["import LibLogger from \"./logger.js\";\nimport { Item } from \"@fjell/core\";\nimport { Instance as BaseInstance, Coordinate, createInstance as createBaseInstance, Registry } from \"@fjell/registry\";\nimport { Operations, Options } from \"@fjell/lib\";\nimport { ItemRouter } from \"./ItemRouter.js\";\n\nconst logger = LibLogger.get(\"Instance\");\n\n/**\n * The Express Router Instance interface represents a router model instance that extends the base Instance\n * from @fjell/registry and adds express router operations for handling HTTP requests.\n *\n * The interface extends the base Instance (which provides coordinate and registry) with:\n * - router: Provides methods for routing HTTP requests and handling CRUD operations\n * - operations: Provides methods for interacting with the data model (get, find, all, etc.)\n * - options: Provides hooks, validators, finders, actions, and facets\n *\n * @template V - The type of the data model item, extending Item\n * @template S - The string literal type representing the model's key type\n * @template L1-L5 - Optional string literal types for location hierarchy levels\n */\nexport interface Instance<\n V extends Item<S, L1, L2, L3, L4, L5>,\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> extends BaseInstance<S, L1, L2, L3, L4, L5> {\n /** The router object that provides methods for handling HTTP requests */\n router: ItemRouter<S, L1, L2, L3, L4, L5>;\n /** The operations object that provides methods for interacting with the data model */\n operations: Operations<V, S, L1, L2, L3, L4, L5>;\n /** The options object that provides hooks, validators, finders, actions, and facets */\n options: Options<V, S, L1, L2, L3, L4, L5>;\n /** The data model item type (for type safety) */\n readonly itemType?: V;\n}\n\nexport const createInstance = <\n V extends Item<S, L1, L2, L3, L4, L5>,\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 registry: Registry,\n coordinate: Coordinate<S, L1, L2, L3, L4, L5>,\n router: ItemRouter<S, L1, L2, L3, L4, L5>,\n operations: Operations<V, S, L1, L2, L3, L4, L5>,\n options?: Options<V, S, L1, L2, L3, L4, L5>,\n ): Instance<V, S, L1, L2, L3, L4, L5> => {\n logger.debug(\"createInstance\", { coordinate, router, registry, operations, options });\n const baseInstance = createBaseInstance(registry, coordinate);\n return { ...baseInstance, router, operations, options: options || {} as Options<V, S, L1, L2, L3, L4, L5> };\n}\n\nexport const isInstance = (instance: any): instance is Instance<any, any, any, any, any, any, any> => {\n return instance != null &&\n typeof instance === 'object' &&\n instance.coordinate != null &&\n instance.router != null &&\n instance.registry != null &&\n instance.operations != null &&\n instance.options != null;\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,eAAe;AAEtB,SAA+C,kBAAkB,0BAAoC;AAIrG,MAAM,SAAS,UAAU,IAAI,UAAU;AAkChC,MAAM,iBAAiB,CAS1B,UACA,YACA,QACA,YACA,YACuC;AACzC,SAAO,MAAM,kBAAkB,EAAE,YAAY,QAAQ,UAAU,YAAY,QAAQ,CAAC;AACpF,QAAM,eAAe,mBAAmB,UAAU,UAAU;AAC5D,SAAO,EAAE,GAAG,cAAc,QAAQ,YAAY,SAAS,WAAW,CAAC,EAAuC;AAC5G;AAEO,MAAM,aAAa,CAAC,aAA2E;AACpG,SAAO,YAAY,QACjB,OAAO,aAAa,YACpB,SAAS,cAAc,QACvB,SAAS,UAAU,QACnB,SAAS,YAAY,QACrB,SAAS,cAAc,QACvB,SAAS,WAAW;AACxB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InstanceFactory.d.ts","sourceRoot":"","sources":["../src/InstanceFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,eAAe,IAAI,mBAAmB,EAAyB,MAAM,iBAAiB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAOjD,MAAM,MAAM,eAAe,CACzB,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,IACvB,CACF,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACzC,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAChD,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,KACxC,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAE7E;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAChC,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"InstanceFactory.d.ts","sourceRoot":"","sources":["../src/InstanceFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,eAAe,IAAI,mBAAmB,EAAyB,MAAM,iBAAiB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAOjD,MAAM,MAAM,eAAe,CACzB,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,IACvB,CACF,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACzC,UAAU,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAChD,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,KACxC,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAE7E;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAChC,CAAC,SAAS,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACrC,CAAC,SAAS,MAAM,EAChB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EACzB,EAAE,SAAS,MAAM,GAAG,KAAK,EAEvB,QAAQ,UAAU,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EACzC,YAAY,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAChD,UAAU,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,KAC1C,mBAAmB,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAM7C,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/InstanceFactory.ts"],
|
|
4
|
-
"sourcesContent": ["import { Item } from \"@fjell/core\";\nimport { ItemRouter } from \"./ItemRouter.js\";\nimport { InstanceFactory as BaseInstanceFactory, Registry, RegistryHub } from \"@fjell/registry\";\nimport { Operations, Options } from \"@fjell/lib\";\nimport { createInstance, Instance } from \"./Instance.js\";\nimport { Coordinate } from \"@fjell/registry\";\nimport LibLogger from \"./logger.js\";\n\nconst logger = LibLogger.get(\"InstanceFactory\");\n\nexport type InstanceFactory<\n V extends Item<S, L1, L2, L3, L4, L5>,\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 router: ItemRouter<S, L1, L2, L3, L4, L5>,\n operations: Operations<V, S, L1, L2, L3, L4, L5>,\n options?: Options<V, S, L1, L2, L3, L4, L5>\n) => BaseInstanceFactory<S, L1, L2, L3, L4, L5> & { readonly _itemType?: V };\n\n/**\n * Factory function for creating express-router instances\n */\nexport const createInstanceFactory = <\n V extends Item<S, L1, L2, L3, L4, L5>,\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
|
|
5
|
-
"mappings": "AAIA,SAAS,sBAAgC;AAEzC,OAAO,eAAe;AAEtB,MAAM,SAAS,UAAU,IAAI,iBAAiB;AAmBvC,MAAM,wBAAwB,
|
|
4
|
+
"sourcesContent": ["import { Item } from \"@fjell/core\";\nimport { ItemRouter } from \"./ItemRouter.js\";\nimport { InstanceFactory as BaseInstanceFactory, Registry, RegistryHub } from \"@fjell/registry\";\nimport { Operations, Options } from \"@fjell/lib\";\nimport { createInstance, Instance } from \"./Instance.js\";\nimport { Coordinate } from \"@fjell/registry\";\nimport LibLogger from \"./logger.js\";\n\nconst logger = LibLogger.get(\"InstanceFactory\");\n\nexport type InstanceFactory<\n V extends Item<S, L1, L2, L3, L4, L5>,\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 router: ItemRouter<S, L1, L2, L3, L4, L5>,\n operations: Operations<V, S, L1, L2, L3, L4, L5>,\n options?: Options<V, S, L1, L2, L3, L4, L5>\n) => BaseInstanceFactory<S, L1, L2, L3, L4, L5> & { readonly _itemType?: V };\n\n/**\n * Factory function for creating express-router instances\n */\nexport const createInstanceFactory = <\n V extends Item<S, L1, L2, L3, L4, L5>,\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 router: ItemRouter<S, L1, L2, L3, L4, L5>,\n operations: Operations<V, S, L1, L2, L3, L4, L5>,\n options?: Options<V, S, L1, L2, L3, L4, L5>\n ): BaseInstanceFactory<S, L1, L2, L3, L4, L5> => {\n return (coordinate: Coordinate<S, L1, L2, L3, L4, L5>, context: { registry: Registry, registryHub?: RegistryHub }) => {\n logger.debug(\"Creating express-router instance\", { coordinate, registry: context.registry, router, operations, options });\n\n return createInstance(context.registry, coordinate, router, operations, options) as Instance<V, S, L1, L2, L3, L4, L5>;\n };\n};\n"],
|
|
5
|
+
"mappings": "AAIA,SAAS,sBAAgC;AAEzC,OAAO,eAAe;AAEtB,MAAM,SAAS,UAAU,IAAI,iBAAiB;AAmBvC,MAAM,wBAAwB,CASjC,QACA,YACA,YAC+C;AACjD,SAAO,CAAC,YAA+C,YAA+D;AACpH,WAAO,MAAM,oCAAoC,EAAE,YAAY,UAAU,QAAQ,UAAU,QAAQ,YAAY,QAAQ,CAAC;AAExH,WAAO,eAAe,QAAQ,UAAU,YAAY,QAAQ,YAAY,OAAO;AAAA,EACjF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/ItemRouter.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import { ComKey, Item, LocKey, LocKeyArray, PriKey } from "@fjell/core";
|
|
2
2
|
import { Instance } from "./Instance.js";
|
|
3
3
|
import { Request, Response, Router } from "express";
|
|
4
|
-
export type ItemRouterOptions =
|
|
4
|
+
export type ItemRouterOptions<S extends string = string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> = {
|
|
5
|
+
/** Handlers for item actions */
|
|
6
|
+
actions?: Record<string, (req: Request, res: Response, ik: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>) => Promise<void>>;
|
|
7
|
+
/** Handlers for item facets */
|
|
8
|
+
facets?: Record<string, (req: Request, res: Response, ik: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>) => Promise<void>>;
|
|
9
|
+
/** Handlers for all actions */
|
|
10
|
+
allActions?: Record<string, (req: Request, res: Response) => Promise<void>>;
|
|
11
|
+
/** Handlers for all facets */
|
|
12
|
+
allFacets?: Record<string, (req: Request, res: Response) => Promise<void>>;
|
|
13
|
+
};
|
|
5
14
|
export declare class ItemRouter<S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
|
|
6
15
|
protected lib: Instance<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>;
|
|
7
16
|
private keyType;
|
|
8
|
-
protected options: ItemRouterOptions
|
|
17
|
+
protected options: ItemRouterOptions<S, L1, L2, L3, L4, L5>;
|
|
9
18
|
private childRouters;
|
|
10
19
|
protected logger: import("@fjell/logging").Logger;
|
|
11
|
-
constructor(lib: Instance<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>, keyType: S, options?: ItemRouterOptions);
|
|
20
|
+
constructor(lib: Instance<Item<S, L1, L2, L3, L4, L5>, S, L1, L2, L3, L4, L5>, keyType: S, options?: ItemRouterOptions<S, L1, L2, L3, L4, L5>);
|
|
12
21
|
getPkType: () => S;
|
|
13
22
|
protected getPkParam: () => string;
|
|
14
23
|
protected getLk(res: Response): LocKey<S>;
|
package/dist/ItemRouter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ItemRouter.d.ts","sourceRoot":"","sources":["../src/ItemRouter.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAEN,IAAI,EAEJ,MAAM,EACN,WAAW,EACX,MAAM,EAEP,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGpD,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ItemRouter.d.ts","sourceRoot":"","sources":["../src/ItemRouter.ts"],"names":[],"mappings":"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"}
|
package/dist/ItemRouter.js
CHANGED
|
@@ -49,15 +49,26 @@ class ItemRouter {
|
|
|
49
49
|
const libOperations = this.lib.operations;
|
|
50
50
|
this.logger.debug("Posting All Action", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
51
51
|
const allActionKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
52
|
+
if (this.options.allActions && this.options.allActions[allActionKey]) {
|
|
53
|
+
this.logger.debug("Using router-level all action handler", { allActionKey });
|
|
54
|
+
try {
|
|
55
|
+
await this.options.allActions[allActionKey](req, res);
|
|
56
|
+
return;
|
|
57
|
+
} catch (err) {
|
|
58
|
+
this.logger.error("Error in router-level all action", { message: err?.message, stack: err?.stack });
|
|
59
|
+
res.status(500).json(err);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
52
63
|
if (!libOptions.allActions) {
|
|
53
|
-
this.logger.error("
|
|
54
|
-
res.status(500).json({ error: "
|
|
64
|
+
this.logger.error("All Actions are not configured");
|
|
65
|
+
res.status(500).json({ error: "All Actions are not configured" });
|
|
55
66
|
return;
|
|
56
67
|
}
|
|
57
68
|
const allAction = libOptions.allActions[allActionKey];
|
|
58
69
|
if (!allAction) {
|
|
59
70
|
this.logger.error("All Action is not configured", { allActionKey });
|
|
60
|
-
res.status(500).json({ error: "
|
|
71
|
+
res.status(500).json({ error: "All Action is not configured" });
|
|
61
72
|
return;
|
|
62
73
|
}
|
|
63
74
|
try {
|
|
@@ -72,15 +83,26 @@ class ItemRouter {
|
|
|
72
83
|
const libOperations = this.lib.operations;
|
|
73
84
|
this.logger.debug("Getting All Facet", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
74
85
|
const facetKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
86
|
+
if (this.options.allFacets && this.options.allFacets[facetKey]) {
|
|
87
|
+
this.logger.debug("Using router-level all facet handler", { facetKey });
|
|
88
|
+
try {
|
|
89
|
+
await this.options.allFacets[facetKey](req, res);
|
|
90
|
+
return;
|
|
91
|
+
} catch (err) {
|
|
92
|
+
this.logger.error("Error in router-level all facet", { message: err?.message, stack: err?.stack });
|
|
93
|
+
res.status(500).json(err);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
75
97
|
if (!libOptions.allFacets) {
|
|
76
|
-
this.logger.error("
|
|
77
|
-
res.status(500).json({ error: "
|
|
98
|
+
this.logger.error("All Facets are not configured");
|
|
99
|
+
res.status(500).json({ error: "All Facets are not configured" });
|
|
78
100
|
return;
|
|
79
101
|
}
|
|
80
102
|
const facet = libOptions.allFacets[facetKey];
|
|
81
103
|
if (!facet) {
|
|
82
|
-
this.logger.error("
|
|
83
|
-
res.status(500).json({ error: "
|
|
104
|
+
this.logger.error("All Facet is not configured", { facetKey });
|
|
105
|
+
res.status(500).json({ error: "All Facet is not configured" });
|
|
84
106
|
return;
|
|
85
107
|
}
|
|
86
108
|
try {
|
|
@@ -94,9 +116,20 @@ class ItemRouter {
|
|
|
94
116
|
postItemAction = async (req, res) => {
|
|
95
117
|
const libOptions = this.lib.options;
|
|
96
118
|
const libOperations = this.lib.operations;
|
|
97
|
-
this.logger.debug("
|
|
119
|
+
this.logger.debug("Posting Item Action", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
98
120
|
const ik = this.getIk(res);
|
|
99
121
|
const actionKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
122
|
+
if (this.options.actions && this.options.actions[actionKey]) {
|
|
123
|
+
this.logger.debug("Using router-level action handler", { actionKey });
|
|
124
|
+
try {
|
|
125
|
+
await this.options.actions[actionKey](req, res, ik);
|
|
126
|
+
return;
|
|
127
|
+
} catch (err) {
|
|
128
|
+
this.logger.error("Error in router-level action", { message: err?.message, stack: err?.stack });
|
|
129
|
+
res.status(500).json(err);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
100
133
|
if (!libOptions.actions) {
|
|
101
134
|
this.logger.error("Item Actions are not configured");
|
|
102
135
|
res.status(500).json({ error: "Item Actions are not configured" });
|
|
@@ -118,9 +151,20 @@ class ItemRouter {
|
|
|
118
151
|
getItemFacet = async (req, res) => {
|
|
119
152
|
const libOptions = this.lib.options;
|
|
120
153
|
const libOperations = this.lib.operations;
|
|
121
|
-
this.logger.debug("Getting Item", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
154
|
+
this.logger.debug("Getting Item Facet", { query: req?.query, params: req?.params, locals: res?.locals });
|
|
122
155
|
const ik = this.getIk(res);
|
|
123
156
|
const facetKey = req.path.substring(req.path.lastIndexOf("/") + 1);
|
|
157
|
+
if (this.options.facets && this.options.facets[facetKey]) {
|
|
158
|
+
this.logger.debug("Using router-level facet handler", { facetKey });
|
|
159
|
+
try {
|
|
160
|
+
await this.options.facets[facetKey](req, res, ik);
|
|
161
|
+
return;
|
|
162
|
+
} catch (err) {
|
|
163
|
+
this.logger.error("Error in router-level facet", { message: err?.message, stack: err?.stack });
|
|
164
|
+
res.status(500).json(err);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
124
168
|
if (!libOptions.facets) {
|
|
125
169
|
this.logger.error("Item Facets are not configured");
|
|
126
170
|
res.status(500).json({ error: "Item Facets are not configured" });
|
|
@@ -225,9 +269,25 @@ class ItemRouter {
|
|
|
225
269
|
const libOperations = this.lib.operations;
|
|
226
270
|
this.logger.debug("Deleting Item", { query: req.query, params: req.params, locals: res.locals });
|
|
227
271
|
const ik = this.getIk(res);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
272
|
+
try {
|
|
273
|
+
const removedItem = await libOperations.remove(ik);
|
|
274
|
+
const item = validatePK(removedItem, this.getPkType());
|
|
275
|
+
res.json(item);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
if (err instanceof NotFoundError) {
|
|
278
|
+
this.logger.error("Item Not Found for Delete", { ik, message: err?.message, stack: err?.stack });
|
|
279
|
+
res.status(404).json({
|
|
280
|
+
ik,
|
|
281
|
+
message: "Item Not Found"
|
|
282
|
+
});
|
|
283
|
+
} else {
|
|
284
|
+
this.logger.error("General Error in Delete", { ik, message: err?.message, stack: err?.stack });
|
|
285
|
+
res.status(500).json({
|
|
286
|
+
ik,
|
|
287
|
+
message: "General Error"
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
231
291
|
};
|
|
232
292
|
/* eslint-disable */
|
|
233
293
|
/* istanbul ignore next */
|
|
@@ -265,9 +325,25 @@ class ItemRouter {
|
|
|
265
325
|
{ body: req?.body, query: req?.query, params: req?.params, locals: res?.locals }
|
|
266
326
|
);
|
|
267
327
|
const ik = this.getIk(res);
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
328
|
+
try {
|
|
329
|
+
const itemToUpdate = this.convertDates(req.body);
|
|
330
|
+
const retItem = validatePK(await libOperations.update(ik, itemToUpdate), this.getPkType());
|
|
331
|
+
res.json(retItem);
|
|
332
|
+
} catch (err) {
|
|
333
|
+
if (err instanceof NotFoundError) {
|
|
334
|
+
this.logger.error("Item Not Found for Update", { ik, message: err?.message, stack: err?.stack });
|
|
335
|
+
res.status(404).json({
|
|
336
|
+
ik,
|
|
337
|
+
message: "Item Not Found"
|
|
338
|
+
});
|
|
339
|
+
} else {
|
|
340
|
+
this.logger.error("General Error in Update", { ik, message: err?.message, stack: err?.stack });
|
|
341
|
+
res.status(500).json({
|
|
342
|
+
ik,
|
|
343
|
+
message: "General Error"
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
271
347
|
};
|
|
272
348
|
convertDates = (item) => {
|
|
273
349
|
const events = item.events;
|