@owlmeans/resource 0.1.0

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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +420 -0
  3. package/build/.gitkeep +0 -0
  4. package/build/consts.d.ts +4 -0
  5. package/build/consts.d.ts.map +1 -0
  6. package/build/consts.js +47 -0
  7. package/build/consts.js.map +1 -0
  8. package/build/errors.d.ts +32 -0
  9. package/build/errors.d.ts.map +1 -0
  10. package/build/errors.js +61 -0
  11. package/build/errors.js.map +1 -0
  12. package/build/helper.d.ts +4 -0
  13. package/build/helper.d.ts.map +1 -0
  14. package/build/helper.js +30 -0
  15. package/build/helper.js.map +1 -0
  16. package/build/index.d.ts +6 -0
  17. package/build/index.d.ts.map +1 -0
  18. package/build/index.js +5 -0
  19. package/build/index.js.map +1 -0
  20. package/build/service.d.ts +4 -0
  21. package/build/service.d.ts.map +1 -0
  22. package/build/service.js +67 -0
  23. package/build/service.js.map +1 -0
  24. package/build/types.d.ts +110 -0
  25. package/build/types.d.ts.map +1 -0
  26. package/build/types.js +2 -0
  27. package/build/types.js.map +1 -0
  28. package/build/utils/index.d.ts +2 -0
  29. package/build/utils/index.d.ts.map +1 -0
  30. package/build/utils/index.js +2 -0
  31. package/build/utils/index.js.map +1 -0
  32. package/build/utils/name.d.ts +3 -0
  33. package/build/utils/name.d.ts.map +1 -0
  34. package/build/utils/name.js +20 -0
  35. package/build/utils/name.js.map +1 -0
  36. package/package.json +40 -0
  37. package/src/consts.ts +49 -0
  38. package/src/errors.ts +78 -0
  39. package/src/helper.ts +33 -0
  40. package/src/index.ts +6 -0
  41. package/src/service.ts +93 -0
  42. package/src/types.ts +129 -0
  43. package/src/utils/index.ts +2 -0
  44. package/src/utils/name.ts +27 -0
  45. package/tsconfig.json +14 -0
  46. package/tsconfig.tsbuildinfo +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 OwlMeans Common — Fullstack typescript framework
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,420 @@
1
+ # @owlmeans/resource
2
+
3
+ A comprehensive data persistence and resource management library for OwlMeans Common applications. This package provides abstract interfaces and implementations for handling database operations, resource management, and data access patterns across different storage backends.
4
+
5
+ ## Overview
6
+
7
+ The `@owlmeans/resource` package is a foundational data access library in the OwlMeans Common ecosystem that provides:
8
+
9
+ - **Database Abstraction**: Generic interfaces for different database backends
10
+ - **CRUD Operations**: Complete Create, Read, Update, Delete functionality
11
+ - **Resource Management**: Advanced resource lifecycle management
12
+ - **Query System**: Flexible query and filtering capabilities
13
+ - **Pagination Support**: Built-in pagination and sorting functionality
14
+ - **Validation Integration**: Schema validation with JSON Schema support
15
+ - **Caching & TTL**: Time-to-live and caching mechanisms
16
+ - **Multi-Database Support**: Handle multiple database configurations
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @owlmeans/resource
22
+ ```
23
+
24
+ ## Core Concepts
25
+
26
+ ### Resource Interface
27
+
28
+ The `Resource<T>` interface provides the primary data access API for working with records that extend `ResourceRecord`.
29
+
30
+ ### Database Service
31
+
32
+ The `ResourceDbService` interface provides an abstraction for database-specific implementations, allowing different storage backends (MongoDB, Redis, etc.) to be used interchangeably.
33
+
34
+ ### Resource Records
35
+
36
+ All data entities extend `ResourceRecord`, which provides a basic structure with an optional `id` field.
37
+
38
+ ### List Operations
39
+
40
+ Advanced listing functionality with criteria-based filtering, pagination, and sorting capabilities.
41
+
42
+ ## API Reference
43
+
44
+ ### Types
45
+
46
+ #### `Resource<T extends ResourceRecord>`
47
+ Primary interface for resource operations.
48
+
49
+ ```typescript
50
+ interface Resource<T extends ResourceRecord> extends BasicResource {
51
+ get: <Type extends T>(id: string, field?: Getter, opts?: LifecycleOptions) => Promise<Type>
52
+ load: <Type extends T>(id: string, field?: Getter, opts?: LifecycleOptions) => Promise<Type | null>
53
+ list: <Type extends T>(criteria?: ListOptions | ListCriteria, opts?: ListOptions) => Promise<ListResult<Type>>
54
+ save: <Type extends T>(record: Partial<Type>, opts?: Getter) => Promise<Type>
55
+ create: <Type extends T>(record: Partial<Type>, opts?: LifecycleOptions) => Promise<Type>
56
+ update: <Type extends T>(record: Partial<Type>, opts?: Getter) => Promise<Type>
57
+ delete: <Type extends T>(id: string | T, opts?: Getter) => Promise<Type | null>
58
+ pick: <Type extends T>(id: string | T, opts?: Getter) => Promise<Type>
59
+ }
60
+ ```
61
+
62
+ #### `ResourceRecord`
63
+ Base interface for all resource entities.
64
+
65
+ ```typescript
66
+ interface ResourceRecord {
67
+ id?: string
68
+ }
69
+ ```
70
+
71
+ #### `ListOptions`
72
+ Configuration for list operations.
73
+
74
+ ```typescript
75
+ interface ListOptions {
76
+ pager?: ListPager
77
+ criteria?: ListCriteria
78
+ }
79
+ ```
80
+
81
+ #### `ListPager`
82
+ Pagination and sorting configuration.
83
+
84
+ ```typescript
85
+ interface ListPager {
86
+ sort?: ListSort[]
87
+ page?: number
88
+ size?: number
89
+ total?: number
90
+ }
91
+ ```
92
+
93
+ #### `ListResult<T>`
94
+ Result structure for list operations.
95
+
96
+ ```typescript
97
+ interface ListResult<T extends ResourceRecord> {
98
+ items: T[]
99
+ pager?: ListPager
100
+ }
101
+ ```
102
+
103
+ #### `DbConfig`
104
+ Database configuration structure.
105
+
106
+ ```typescript
107
+ interface DbConfig<P extends {} = {}> {
108
+ service: string
109
+ alias?: string
110
+ host: string | string[]
111
+ port?: number
112
+ user?: string
113
+ secret?: string
114
+ schema?: string
115
+ resourcePrefix?: string
116
+ entitySensitive?: boolean
117
+ serviceSensitive?: boolean
118
+ encryptionKey?: string
119
+ meta?: P
120
+ }
121
+ ```
122
+
123
+ ### Factory Functions
124
+
125
+ #### `createDbService<Db, Client, Service>(alias: string, override: Partial<Service>, init?: InitMethod<Service>): Service`
126
+ Creates a database service with the specified configuration.
127
+
128
+ **Parameters:**
129
+ - `alias`: Service alias for registration
130
+ - `override`: Partial service implementation
131
+ - `init`: Optional initialization method
132
+
133
+ **Returns:** Configured database service
134
+
135
+ ### Helper Functions
136
+
137
+ #### `createListSchema<T>(schema: JSONSchemaType<T>): JSONSchemaType<ListResult<T>>`
138
+ Creates a JSON Schema for list results based on a record schema.
139
+
140
+ #### `prepareListOptions(defPageSize?: number, criteria?: ListOptions | ListCriteria, opts?: ListOptions): ListOptions`
141
+ Prepares and normalizes list options with default pagination.
142
+
143
+ #### `filterObject<T>(obj: T, keep?: string[]): T`
144
+ Filters an object, removing null/undefined values except for specified keys.
145
+
146
+ ### CRUD Operations
147
+
148
+ #### `get(id: string, field?: Getter, opts?: LifecycleOptions): Promise<T>`
149
+ Retrieves a record by ID. Throws `UnknownRecordError` if not found.
150
+
151
+ #### `load(id: string, field?: Getter, opts?: LifecycleOptions): Promise<T | null>`
152
+ Loads a record by ID. Returns `null` if not found.
153
+
154
+ #### `save(record: Partial<T>, opts?: Getter): Promise<T>`
155
+ Saves a record (creates if new, updates if exists).
156
+
157
+ #### `create(record: Partial<T>, opts?: LifecycleOptions): Promise<T>`
158
+ Creates a new record. Throws `RecordExists` if record already exists.
159
+
160
+ #### `update(record: Partial<T>, opts?: Getter): Promise<T>`
161
+ Updates an existing record. Throws `UnknownRecordError` if not found.
162
+
163
+ #### `delete(id: string | T, opts?: Getter): Promise<T | null>`
164
+ Deletes a record by ID or record object.
165
+
166
+ #### `pick(id: string | T, opts?: Getter): Promise<T>`
167
+ Retrieves a record, throwing `UnknownRecordError` if not found.
168
+
169
+ #### `list(criteria?: ListOptions | ListCriteria, opts?: ListOptions): Promise<ListResult<T>>`
170
+ Lists records with optional filtering, pagination, and sorting.
171
+
172
+ ### Error Types
173
+
174
+ The package provides a comprehensive error hierarchy for resource operations:
175
+
176
+ #### `ResourceError`
177
+ Base error class for all resource-related errors.
178
+
179
+ #### `UnknownRecordError`
180
+ Error thrown when a requested record is not found.
181
+
182
+ ```typescript
183
+ class UnknownRecordError extends ResourceError {
184
+ constructor(id: string)
185
+ get id(): string // Extract the record ID from the error
186
+ }
187
+ ```
188
+
189
+ #### `MisshapedRecord`
190
+ Error for malformed or invalid record data.
191
+
192
+ #### `RecordExists`
193
+ Error thrown when attempting to create a record that already exists.
194
+
195
+ #### `RecordUpdateFailed`
196
+ Error for failed update operations.
197
+
198
+ #### `UnsupportedArgumentError`
199
+ Error for unsupported method arguments.
200
+
201
+ #### `UnsupportedMethodError`
202
+ Error for unsupported operations.
203
+
204
+ ## Usage Examples
205
+
206
+ ### Basic Resource Operations
207
+
208
+ ```typescript
209
+ interface User extends ResourceRecord {
210
+ id?: string
211
+ name: string
212
+ email: string
213
+ createdAt?: Date
214
+ }
215
+
216
+ // Create a new user
217
+ const newUser: User = await userResource.create({
218
+ name: 'John Doe',
219
+ email: 'john@example.com'
220
+ })
221
+
222
+ // Get a user by ID
223
+ const user = await userResource.get('user123')
224
+
225
+ // Update a user
226
+ const updatedUser = await userResource.update({
227
+ id: 'user123',
228
+ name: 'John Smith'
229
+ })
230
+
231
+ // Delete a user
232
+ await userResource.delete('user123')
233
+ ```
234
+
235
+ ### List Operations with Pagination
236
+
237
+ ```typescript
238
+ // Basic list
239
+ const users = await userResource.list()
240
+
241
+ // List with pagination
242
+ const pagedUsers = await userResource.list({
243
+ pager: {
244
+ page: 0,
245
+ size: 10,
246
+ sort: [['name', true], 'createdAt'] // Sort by name asc, then createdAt
247
+ }
248
+ })
249
+
250
+ // List with criteria
251
+ const filteredUsers = await userResource.list({
252
+ criteria: {
253
+ status: 'active',
254
+ role: ['admin', 'moderator']
255
+ },
256
+ pager: { size: 20 }
257
+ })
258
+ ```
259
+
260
+ ### Error Handling
261
+
262
+ ```typescript
263
+ import { UnknownRecordError, RecordExists } from '@owlmeans/resource'
264
+
265
+ try {
266
+ const user = await userResource.get('nonexistent')
267
+ } catch (error) {
268
+ if (error instanceof UnknownRecordError) {
269
+ console.log(`User not found: ${error.id}`)
270
+ }
271
+ }
272
+
273
+ try {
274
+ await userResource.create({ id: 'existing', name: 'Test' })
275
+ } catch (error) {
276
+ if (error instanceof RecordExists) {
277
+ console.log('User already exists')
278
+ }
279
+ }
280
+ ```
281
+
282
+ ### Database Configuration
283
+
284
+ ```typescript
285
+ import { createBasicContext } from '@owlmeans/context'
286
+
287
+ const context = createBasicContext({
288
+ dbs: [
289
+ {
290
+ service: 'mongo-db',
291
+ alias: 'primary',
292
+ host: 'localhost',
293
+ port: 27017,
294
+ schema: 'myapp',
295
+ user: 'dbuser',
296
+ secret: 'dbpass',
297
+ resourcePrefix: 'app_',
298
+ entitySensitive: true
299
+ },
300
+ {
301
+ service: 'redis-db',
302
+ alias: 'cache',
303
+ host: 'localhost',
304
+ port: 6379
305
+ }
306
+ ]
307
+ })
308
+ ```
309
+
310
+ ### Custom Resource Implementation
311
+
312
+ ```typescript
313
+ import { Resource, ResourceRecord } from '@owlmeans/resource'
314
+
315
+ interface Product extends ResourceRecord {
316
+ name: string
317
+ price: number
318
+ category: string
319
+ }
320
+
321
+ class ProductResource implements Resource<Product> {
322
+ // Implement all required methods
323
+ async get(id: string): Promise<Product> {
324
+ // Custom implementation
325
+ }
326
+
327
+ async list(criteria?: ListOptions): Promise<ListResult<Product>> {
328
+ // Custom implementation with business logic
329
+ }
330
+
331
+ // ... other methods
332
+ }
333
+ ```
334
+
335
+ ### TTL and Caching
336
+
337
+ ```typescript
338
+ // Load with TTL
339
+ const user = await userResource.load('user123', {
340
+ ttl: 300 // Cache for 5 minutes
341
+ })
342
+
343
+ // Load with expiration date
344
+ const user = await userResource.load('user123', {
345
+ ttl: new Date(Date.now() + 300000) // Expire in 5 minutes
346
+ })
347
+ ```
348
+
349
+ ## Advanced Features
350
+
351
+ ### Multi-Database Support
352
+
353
+ The package supports multiple database configurations within a single application:
354
+
355
+ ```typescript
356
+ // Different databases for different resource types
357
+ const userResource = makeUserResource('primary-db')
358
+ const cacheResource = makeCacheResource('redis-db')
359
+ const analyticsResource = makeAnalyticsResource('analytics-db')
360
+ ```
361
+
362
+ ### Schema Validation
363
+
364
+ Integration with JSON Schema for record validation:
365
+
366
+ ```typescript
367
+ import { createListSchema } from '@owlmeans/resource'
368
+
369
+ const userSchema: JSONSchemaType<User> = {
370
+ type: 'object',
371
+ properties: {
372
+ id: { type: 'string', nullable: true },
373
+ name: { type: 'string' },
374
+ email: { type: 'string', format: 'email' }
375
+ },
376
+ required: ['name', 'email'],
377
+ additionalProperties: false
378
+ }
379
+
380
+ const userListSchema = createListSchema(userSchema)
381
+ ```
382
+
383
+ ### Resource Locking
384
+
385
+ Support for record locking mechanisms:
386
+
387
+ ```typescript
388
+ interface ResourceLocker<T extends ResourceRecord> {
389
+ lock: (record: Partial<T>, fields?: string[]) => Promise<T>
390
+ unlock: (record: Partial<T>, fields?: string[]) => Promise<T>
391
+ }
392
+ ```
393
+
394
+ ## Integration with OwlMeans Ecosystem
395
+
396
+ The `@owlmeans/resource` package integrates with:
397
+
398
+ - **@owlmeans/context**: Service registration and configuration management
399
+ - **@owlmeans/error**: Resilient error handling system
400
+ - **@owlmeans/mongo-resource**: MongoDB-specific implementation
401
+ - **@owlmeans/redis-resource**: Redis-specific implementation
402
+ - **@owlmeans/client-resource**: Client-side resource management
403
+ - **@owlmeans/static-resource**: Static file resource management
404
+
405
+ ## Performance Considerations
406
+
407
+ - Use `load()` instead of `get()` when records might not exist
408
+ - Implement appropriate pagination for large datasets
409
+ - Use TTL for frequently accessed but rarely changed data
410
+ - Consider database-specific optimizations for complex queries
411
+ - Implement proper indexing strategies for list criteria
412
+
413
+ ## Security Features
414
+
415
+ - Entity-sensitive configurations for multi-tenant applications
416
+ - Service-sensitive configurations for microservice architectures
417
+ - Encryption key support for sensitive data
418
+ - Input validation through schema integration
419
+
420
+ Fixes #32.
package/build/.gitkeep ADDED
File without changes
@@ -0,0 +1,4 @@
1
+ import type { JSONSchemaType } from 'ajv';
2
+ import type { ListResult, ResourceRecord } from './types.js';
3
+ export declare const createListSchema: <T extends ResourceRecord>(schema: JSONSchemaType<T>) => JSONSchemaType<ListResult<T>>;
4
+ //# sourceMappingURL=consts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE5D,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,cAAc,UAAU,cAAc,CAAC,CAAC,CAAC,KAAG,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CA6CjH,CAAA"}
@@ -0,0 +1,47 @@
1
+ export const createListSchema = (schema) => ({
2
+ type: 'object',
3
+ properties: {
4
+ items: {
5
+ type: 'array',
6
+ items: {
7
+ ...schema,
8
+ type: 'object',
9
+ properties: {
10
+ id: { type: 'string', nullable: true },
11
+ ...schema.properties
12
+ },
13
+ ...(schema.required ? { required: [...schema.required] } : undefined),
14
+ additionalProperties: false,
15
+ }
16
+ },
17
+ pager: {
18
+ type: 'object',
19
+ properties: {
20
+ sort: {
21
+ type: 'array',
22
+ items: {
23
+ oneOf: [
24
+ { type: 'string' },
25
+ {
26
+ type: 'array', items: [
27
+ { type: 'string' },
28
+ { type: 'boolean', nullable: true }
29
+ ], minItems: 1, maxItems: 2
30
+ }
31
+ ]
32
+ },
33
+ nullable: true
34
+ },
35
+ page: { type: 'number', nullable: true },
36
+ size: { type: 'number', nullable: true },
37
+ total: { type: 'number', nullable: true }
38
+ },
39
+ required: [],
40
+ nullable: true,
41
+ additionalProperties: false,
42
+ }
43
+ },
44
+ required: ['items'],
45
+ additionalProperties: false,
46
+ });
47
+ //# sourceMappingURL=consts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAA2B,MAAyB,EAAiC,EAAE,CAAC,CAAC;IACvH,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,GAAG,MAAM;gBACT,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;oBACtC,GAAG,MAAM,CAAC,UAAU;iBACrB;gBACD,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBACrE,oBAAoB,EAAE,KAAK;aAC5B;SACF;QACD,KAAK,EAAE;YACL,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE;wBACL,KAAK,EAAE;4BACL,EAAE,IAAI,EAAE,QAAQ,EAAE;4BAClB;gCACE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE;oCACpB,EAAE,IAAI,EAAE,QAAQ,EAAE;oCAClB,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;iCACpC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;6BAC5B;yBACF;qBACF;oBACD,QAAQ,EAAE,IAAI;iBACf;gBACD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACxC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;gBACxC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;aAC1C;YACD,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,IAAI;YACd,oBAAoB,EAAE,KAAK;SAC5B;KACF;IACD,QAAQ,EAAE,CAAC,OAAO,CAAC;IACnB,oBAAoB,EAAE,KAAK;CAC5B,CAAC,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { ResilientError } from '@owlmeans/error';
2
+ export declare class ResourceError extends ResilientError {
3
+ static typeName: string;
4
+ constructor(message?: string);
5
+ }
6
+ export declare class UnknownRecordError extends ResourceError {
7
+ static typeName: string;
8
+ static readonly idSeparator: string;
9
+ constructor(id: string);
10
+ get id(): string;
11
+ }
12
+ export declare class MisshapedRecord extends ResourceError {
13
+ static typeName: string;
14
+ constructor(msg: string);
15
+ }
16
+ export declare class RecordExists extends ResourceError {
17
+ static typeName: string;
18
+ constructor(msg: string);
19
+ }
20
+ export declare class RecordUpdateFailed extends ResourceError {
21
+ static typeName: string;
22
+ constructor(msg: string);
23
+ }
24
+ export declare class UnsupportedArgumentError extends ResourceError {
25
+ static typeName: string;
26
+ constructor(argument: string);
27
+ }
28
+ export declare class UnsupportedMethodError extends ResourceError {
29
+ static typeName: string;
30
+ constructor(method: string);
31
+ }
32
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAG,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEjD,qBAAa,aAAc,SAAQ,cAAc;IAC/C,OAAuB,QAAQ,SAAkB;gBAErC,OAAO,GAAE,MAAgB;CAGtC;AAED,qBAAa,kBAAmB,SAAQ,aAAa;IACnD,OAAuB,QAAQ,SAAgD;IAE/E,gBAAuB,WAAW,EAAE,MAAM,CAAM;gBAEpC,EAAE,EAAE,MAAM;IAKtB,IAAI,EAAE,IAAI,MAAM,CAEf;CACF;AAED,qBAAa,eAAgB,SAAQ,aAAa;IAChD,OAAuB,QAAQ,SAA6C;gBAEhE,GAAG,EAAE,MAAM;CAIxB;AAED,qBAAa,YAAa,SAAQ,aAAa;IAC7C,OAAuB,QAAQ,SAA0C;gBAE7D,GAAG,EAAE,MAAM;CAIxB;AAED,qBAAa,kBAAmB,SAAQ,aAAa;IACnD,OAAuB,QAAQ,SAAgD;gBAEnE,GAAG,EAAE,MAAM;CAIxB;AAED,qBAAa,wBAAyB,SAAQ,aAAa;IACzD,OAAuB,QAAQ,SAAsD;gBAEzE,QAAQ,EAAE,MAAM;CAI7B;AAED,qBAAa,sBAAuB,SAAQ,aAAa;IACvD,OAAuB,QAAQ,SAAoD;gBAEvE,MAAM,EAAE,MAAM;CAI3B"}
@@ -0,0 +1,61 @@
1
+ import { ResilientError } from '@owlmeans/error';
2
+ export class ResourceError extends ResilientError {
3
+ static typeName = 'ResourceError';
4
+ constructor(message = 'error') {
5
+ super(ResourceError.typeName, `resource:${message}`);
6
+ }
7
+ }
8
+ export class UnknownRecordError extends ResourceError {
9
+ static typeName = `${ResourceError.typeName}UnknownRecordError`;
10
+ static idSeparator = '/';
11
+ constructor(id) {
12
+ super(`unknown-record${UnknownRecordError.idSeparator}${id}`);
13
+ this.type = UnknownRecordError.typeName;
14
+ }
15
+ get id() {
16
+ return this.message.split(UnknownRecordError.idSeparator)[1];
17
+ }
18
+ }
19
+ export class MisshapedRecord extends ResourceError {
20
+ static typeName = `${ResourceError.typeName}MisshapedRecord`;
21
+ constructor(msg) {
22
+ super(`misshaped-record:${msg}`);
23
+ this.type = MisshapedRecord.typeName;
24
+ }
25
+ }
26
+ export class RecordExists extends ResourceError {
27
+ static typeName = `${ResourceError.typeName}RecordExists`;
28
+ constructor(msg) {
29
+ super(`record-exists:${msg}`);
30
+ this.type = RecordExists.typeName;
31
+ }
32
+ }
33
+ export class RecordUpdateFailed extends ResourceError {
34
+ static typeName = `${ResourceError.typeName}RecordUpdateFailed`;
35
+ constructor(msg) {
36
+ super(`record-update-failed:${msg}`);
37
+ this.type = RecordUpdateFailed.typeName;
38
+ }
39
+ }
40
+ export class UnsupportedArgumentError extends ResourceError {
41
+ static typeName = `${ResourceError.typeName}UnsupportedArgumentError`;
42
+ constructor(argument) {
43
+ super(`unsupported-argument:${argument}`);
44
+ this.type = UnsupportedArgumentError.typeName;
45
+ }
46
+ }
47
+ export class UnsupportedMethodError extends ResourceError {
48
+ static typeName = `${ResourceError.typeName}UnsupportedMethodError`;
49
+ constructor(method) {
50
+ super(`unsupported-method:${method}`);
51
+ this.type = UnsupportedMethodError.typeName;
52
+ }
53
+ }
54
+ ResilientError.registerErrorClass(ResourceError);
55
+ ResilientError.registerErrorClass(UnknownRecordError);
56
+ ResilientError.registerErrorClass(MisshapedRecord);
57
+ ResilientError.registerErrorClass(RecordExists);
58
+ ResilientError.registerErrorClass(RecordUpdateFailed);
59
+ ResilientError.registerErrorClass(UnsupportedArgumentError);
60
+ ResilientError.registerErrorClass(UnsupportedMethodError);
61
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAG,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,OAAO,aAAc,SAAQ,cAAc;IACxC,MAAM,CAAU,QAAQ,GAAG,eAAe,CAAA;IAEjD,YAAY,UAAkB,OAAO;QACnC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,YAAY,OAAO,EAAE,CAAC,CAAA;IACtD,CAAC;;AAGH,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IAC5C,MAAM,CAAU,QAAQ,GAAG,GAAG,aAAa,CAAC,QAAQ,oBAAoB,CAAA;IAExE,MAAM,CAAU,WAAW,GAAW,GAAG,CAAA;IAEhD,YAAY,EAAU;QACpB,KAAK,CAAC,iBAAiB,kBAAkB,CAAC,WAAW,GAAG,EAAE,EAAE,CAAC,CAAA;QAC7D,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAA;IACzC,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9D,CAAC;;AAGH,MAAM,OAAO,eAAgB,SAAQ,aAAa;IACzC,MAAM,CAAU,QAAQ,GAAG,GAAG,aAAa,CAAC,QAAQ,iBAAiB,CAAA;IAE5E,YAAY,GAAW;QACrB,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAA;QAChC,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAA;IACtC,CAAC;;AAGH,MAAM,OAAO,YAAa,SAAQ,aAAa;IACtC,MAAM,CAAU,QAAQ,GAAG,GAAG,aAAa,CAAC,QAAQ,cAAc,CAAA;IAEzE,YAAY,GAAW;QACrB,KAAK,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAA;QAC7B,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAA;IACnC,CAAC;;AAGH,MAAM,OAAO,kBAAmB,SAAQ,aAAa;IAC5C,MAAM,CAAU,QAAQ,GAAG,GAAG,aAAa,CAAC,QAAQ,oBAAoB,CAAA;IAE/E,YAAY,GAAW;QACrB,KAAK,CAAC,wBAAwB,GAAG,EAAE,CAAC,CAAA;QACpC,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAA;IACzC,CAAC;;AAGH,MAAM,OAAO,wBAAyB,SAAQ,aAAa;IAClD,MAAM,CAAU,QAAQ,GAAG,GAAG,aAAa,CAAC,QAAQ,0BAA0B,CAAA;IAErF,YAAY,QAAgB;QAC1B,KAAK,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAA;QACzC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC,QAAQ,CAAA;IAC/C,CAAC;;AAGH,MAAM,OAAO,sBAAuB,SAAQ,aAAa;IAChD,MAAM,CAAU,QAAQ,GAAG,GAAG,aAAa,CAAC,QAAQ,wBAAwB,CAAA;IAEnF,YAAY,MAAc;QACxB,KAAK,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAA;QACrC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC,QAAQ,CAAA;IAC7C,CAAC;;AAGH,cAAc,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAA;AAChD,cAAc,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAA;AACrD,cAAc,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAA;AAClD,cAAc,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAA;AAC/C,cAAc,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAA;AACrD,cAAc,CAAC,kBAAkB,CAAC,wBAAwB,CAAC,CAAA;AAC3D,cAAc,CAAC,kBAAkB,CAAC,sBAAsB,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { ListCriteria, ListOptions } from './types.js';
2
+ export declare const prepareListOptions: (defPageSize?: number, criteria?: ListOptions | ListCriteria, opts?: ListOptions) => ListOptions;
3
+ export declare const filterObject: <T extends {}>(obj: T, keep?: string[]) => T;
4
+ //# sourceMappingURL=helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.d.ts","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAa,MAAM,YAAY,CAAA;AAEtE,eAAO,MAAM,kBAAkB,iBAAiB,MAAM,aAAkB,WAAW,GAAG,YAAY,SAAS,WAAW,KAAG,WAsBxH,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,MAAM,EAAE,KAAG,CAMxD,CAAA"}
@@ -0,0 +1,30 @@
1
+ export const prepareListOptions = (defPageSize = 10, criteria, opts) => {
2
+ if (opts == null) {
3
+ if (criteria == null) {
4
+ criteria = {};
5
+ opts = {};
6
+ }
7
+ else if ('criteria' in criteria) {
8
+ criteria = criteria.criteria;
9
+ opts = { pager: criteria.pager };
10
+ }
11
+ else if ('pager' in criteria) {
12
+ opts = { pager: criteria.pager };
13
+ criteria = {};
14
+ }
15
+ }
16
+ const size = (opts?.pager?.size ?? defPageSize);
17
+ const pager = {
18
+ sort: opts?.pager?.sort,
19
+ page: opts?.pager?.page ?? 0,
20
+ size, total: 0
21
+ };
22
+ return { criteria: criteria, pager };
23
+ };
24
+ export const filterObject = (obj, keep) => Object.entries(obj).reduce((obj, [key, value]) => {
25
+ if (value == null && !keep?.includes(key)) {
26
+ return obj;
27
+ }
28
+ return { ...obj, [key]: value };
29
+ }, {});
30
+ //# sourceMappingURL=helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helper.js","sourceRoot":"","sources":["../src/helper.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,cAAsB,EAAE,EAAE,QAAqC,EAAE,IAAkB,EAAe,EAAE;IACrI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;YACrB,QAAQ,GAAG,EAAE,CAAA;YACb,IAAI,GAAG,EAAE,CAAA;QACX,CAAC;aAAM,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;YAClC,QAAQ,GAAG,QAAQ,CAAC,QAAwB,CAAA;YAC5C,IAAI,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,KAA8B,EAAE,CAAA;QAC3D,CAAC;aAAM,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,KAA8B,EAAE,CAAA;YACzD,QAAQ,GAAG,EAAE,CAAA;QACf,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,WAAW,CAAC,CAAA;IAC/C,MAAM,KAAK,GAAc;QACvB,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI;QACvB,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;QAC5B,IAAI,EAAE,KAAK,EAAE,CAAC;KACf,CAAA;IAED,OAAO,EAAE,QAAQ,EAAE,QAAwB,EAAE,KAAK,EAAE,CAAA;AACtD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAe,GAAM,EAAE,IAAe,EAAK,EAAE,CACvE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;IAC/C,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,OAAO,GAAG,CAAA;IACZ,CAAC;IACD,OAAO,EAAE,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAA;AACjC,CAAC,EAAE,EAAO,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ export * from './errors.js';
2
+ export * from './consts.js';
3
+ export * from './service.js';
4
+ export * from './helper.js';
5
+ export type * from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,mBAAmB,YAAY,CAAA"}
package/build/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from './errors.js';
2
+ export * from './consts.js';
3
+ export * from './service.js';
4
+ export * from './helper.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { InitMethod } from '@owlmeans/context';
2
+ import type { ResourceDbService } from './types.js';
3
+ export declare const createDbService: <Db, Client, Service extends ResourceDbService<Db, Client> = ResourceDbService<Db, Client>>(alias: string, override: Partial<Service>, init?: InitMethod<Service>) => Service;
4
+ //# sourceMappingURL=service.d.ts.map