@declaro/data 2.0.0-beta.12 → 2.0.0-beta.121
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/{LICENSE → LICENSE.md} +1 -1
- package/README.md +0 -0
- package/dist/browser/index.js +26 -0
- package/dist/browser/index.js.map +93 -0
- package/dist/node/index.cjs +13226 -0
- package/dist/node/index.cjs.map +93 -0
- package/dist/node/index.js +13205 -0
- package/dist/node/index.js.map +93 -0
- package/dist/ts/application/model-controller.d.ts +50 -0
- package/dist/ts/application/model-controller.d.ts.map +1 -0
- package/dist/ts/application/model-controller.test.d.ts +2 -0
- package/dist/ts/application/model-controller.test.d.ts.map +1 -0
- package/dist/ts/application/read-only-model-controller.d.ts +20 -0
- package/dist/ts/application/read-only-model-controller.d.ts.map +1 -0
- package/dist/ts/application/read-only-model-controller.test.d.ts +2 -0
- package/dist/ts/application/read-only-model-controller.test.d.ts.map +1 -0
- package/dist/ts/domain/events/domain-event.d.ts +41 -0
- package/dist/ts/domain/events/domain-event.d.ts.map +1 -0
- package/dist/ts/domain/events/domain-event.test.d.ts +2 -0
- package/dist/ts/domain/events/domain-event.test.d.ts.map +1 -0
- package/dist/ts/domain/events/event-types.d.ts +34 -0
- package/dist/ts/domain/events/event-types.d.ts.map +1 -0
- package/dist/ts/domain/events/mutation-event.d.ts +6 -0
- package/dist/ts/domain/events/mutation-event.d.ts.map +1 -0
- package/dist/ts/domain/events/mutation-event.test.d.ts +2 -0
- package/dist/ts/domain/events/mutation-event.test.d.ts.map +1 -0
- package/dist/ts/domain/events/query-event.d.ts +6 -0
- package/dist/ts/domain/events/query-event.d.ts.map +1 -0
- package/dist/ts/domain/events/query-event.test.d.ts +2 -0
- package/dist/ts/domain/events/query-event.test.d.ts.map +1 -0
- package/dist/ts/domain/events/request-event.d.ts +11 -0
- package/dist/ts/domain/events/request-event.d.ts.map +1 -0
- package/dist/ts/domain/events/request-event.test.d.ts +2 -0
- package/dist/ts/domain/events/request-event.test.d.ts.map +1 -0
- package/dist/ts/domain/interfaces/repository.d.ts +110 -0
- package/dist/ts/domain/interfaces/repository.d.ts.map +1 -0
- package/dist/ts/domain/models/pagination.d.ts +28 -0
- package/dist/ts/domain/models/pagination.d.ts.map +1 -0
- package/dist/ts/domain/services/base-model-service.d.ts +23 -0
- package/dist/ts/domain/services/base-model-service.d.ts.map +1 -0
- package/dist/ts/domain/services/model-service-args.d.ts +9 -0
- package/dist/ts/domain/services/model-service-args.d.ts.map +1 -0
- package/dist/ts/domain/services/model-service.d.ts +72 -0
- package/dist/ts/domain/services/model-service.d.ts.map +1 -0
- package/dist/ts/domain/services/model-service.normalization.test.d.ts +2 -0
- package/dist/ts/domain/services/model-service.normalization.test.d.ts.map +1 -0
- package/dist/ts/domain/services/model-service.test.d.ts +2 -0
- package/dist/ts/domain/services/model-service.test.d.ts.map +1 -0
- package/dist/ts/domain/services/read-only-model-service.d.ts +76 -0
- package/dist/ts/domain/services/read-only-model-service.d.ts.map +1 -0
- package/dist/ts/domain/services/read-only-model-service.test.d.ts +2 -0
- package/dist/ts/domain/services/read-only-model-service.test.d.ts.map +1 -0
- package/dist/ts/index.d.ts +18 -0
- package/dist/ts/index.d.ts.map +1 -0
- package/dist/ts/shared/utils/schema-inference.d.ts +23 -0
- package/dist/ts/shared/utils/schema-inference.d.ts.map +1 -0
- package/dist/ts/shared/utils/schema-inheritance.d.ts +24 -0
- package/dist/ts/shared/utils/schema-inheritance.d.ts.map +1 -0
- package/dist/ts/test/mock/models/mock-book-models.d.ts +42 -0
- package/dist/ts/test/mock/models/mock-book-models.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.assign.test.d.ts +2 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.assign.test.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.basic.test.d.ts +2 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.basic.test.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.bulk-upsert.test.d.ts +2 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.bulk-upsert.test.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.count.test.d.ts +2 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.count.test.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.custom-lookup.test.d.ts +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.custom-lookup.test.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts +62 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.search.test.d.ts +2 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.search.test.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.trash.test.d.ts +2 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.trash.test.d.ts.map +1 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.upsert.test.d.ts +2 -0
- package/dist/ts/test/mock/repositories/mock-memory-repository.upsert.test.d.ts.map +1 -0
- package/package.json +45 -42
- package/src/application/model-controller.test.ts +694 -0
- package/src/application/model-controller.ts +135 -0
- package/src/application/read-only-model-controller.test.ts +335 -0
- package/src/application/read-only-model-controller.ts +61 -0
- package/src/domain/events/domain-event.test.ts +82 -0
- package/src/domain/events/domain-event.ts +69 -0
- package/src/domain/events/event-types.ts +34 -0
- package/src/domain/events/mutation-event.test.ts +38 -0
- package/src/domain/events/mutation-event.ts +8 -0
- package/src/domain/events/query-event.test.ts +28 -0
- package/src/domain/events/query-event.ts +8 -0
- package/src/domain/events/request-event.test.ts +38 -0
- package/src/domain/events/request-event.ts +32 -0
- package/src/domain/interfaces/repository.ts +136 -0
- package/src/domain/models/pagination.ts +28 -0
- package/src/domain/services/base-model-service.ts +54 -0
- package/src/domain/services/model-service-args.ts +9 -0
- package/src/domain/services/model-service.normalization.test.ts +704 -0
- package/src/domain/services/model-service.test.ts +940 -0
- package/src/domain/services/model-service.ts +432 -0
- package/src/domain/services/read-only-model-service.test.ts +828 -0
- package/src/domain/services/read-only-model-service.ts +178 -0
- package/src/index.ts +17 -4
- package/src/shared/utils/schema-inference.ts +26 -0
- package/src/shared/utils/schema-inheritance.ts +28 -0
- package/src/test/mock/models/mock-book-models.ts +78 -0
- package/src/test/mock/repositories/mock-memory-repository.assign.test.ts +215 -0
- package/src/test/mock/repositories/mock-memory-repository.basic.test.ts +129 -0
- package/src/test/mock/repositories/mock-memory-repository.bulk-upsert.test.ts +159 -0
- package/src/test/mock/repositories/mock-memory-repository.count.test.ts +98 -0
- package/src/test/mock/repositories/mock-memory-repository.custom-lookup.test.ts +0 -0
- package/src/test/mock/repositories/mock-memory-repository.search.test.ts +265 -0
- package/src/test/mock/repositories/mock-memory-repository.trash.test.ts +736 -0
- package/src/test/mock/repositories/mock-memory-repository.ts +401 -0
- package/src/test/mock/repositories/mock-memory-repository.upsert.test.ts +108 -0
- package/dist/databaseConnection.d.ts +0 -24
- package/dist/datastoreAbstract.d.ts +0 -37
- package/dist/declaro-data.cjs +0 -1
- package/dist/declaro-data.mjs +0 -250
- package/dist/hydrateEntity.d.ts +0 -8
- package/dist/index.d.ts +0 -4
- package/dist/serverConnection.d.ts +0 -15
- package/dist/trackedStatus.d.ts +0 -15
- package/src/databaseConnection.ts +0 -137
- package/src/datastoreAbstract.ts +0 -190
- package/src/hydrateEntity.ts +0 -36
- package/src/placeholder.test.ts +0 -7
- package/src/serverConnection.ts +0 -74
- package/src/trackedStatus.ts +0 -35
- package/tsconfig.json +0 -10
- package/vite.config.ts +0 -23
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export enum ModelQueryEvent {
|
|
2
|
+
BeforeLoad = 'beforeLoad',
|
|
3
|
+
AfterLoad = 'afterLoad',
|
|
4
|
+
BeforeLoadMany = 'beforeLoadMany',
|
|
5
|
+
AfterLoadMany = 'afterLoadMany',
|
|
6
|
+
BeforeSearch = 'beforeSearch',
|
|
7
|
+
AfterSearch = 'afterSearch',
|
|
8
|
+
BeforeCount = 'beforeCount',
|
|
9
|
+
AfterCount = 'afterCount',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export enum ModelMutationAction {
|
|
13
|
+
Create = 'create',
|
|
14
|
+
BeforeCreate = 'beforeCreate',
|
|
15
|
+
AfterCreate = 'afterCreate',
|
|
16
|
+
Update = 'update',
|
|
17
|
+
BeforeUpdate = 'beforeUpdate',
|
|
18
|
+
AfterUpdate = 'afterUpdate',
|
|
19
|
+
Remove = 'remove',
|
|
20
|
+
BeforeRemove = 'beforeRemove',
|
|
21
|
+
AfterRemove = 'afterRemove',
|
|
22
|
+
Restore = 'restore',
|
|
23
|
+
BeforeRestore = 'beforeRestore',
|
|
24
|
+
AfterRestore = 'afterRestore',
|
|
25
|
+
EmptyTrash = 'emptyTrash',
|
|
26
|
+
BeforeEmptyTrash = 'beforeEmptyTrash',
|
|
27
|
+
AfterEmptyTrash = 'afterEmptyTrash',
|
|
28
|
+
PermanentlyDeleteFromTrash = 'permanentlyDeleteFromTrash',
|
|
29
|
+
BeforePermanentlyDeleteFromTrash = 'beforePermanentlyDeleteFromTrash',
|
|
30
|
+
AfterPermanentlyDeleteFromTrash = 'afterPermanentlyDeleteFromTrash',
|
|
31
|
+
PermanentlyDelete = 'permanentlyDelete',
|
|
32
|
+
BeforePermanentlyDelete = 'beforePermanentlyDelete',
|
|
33
|
+
AfterPermanentlyDelete = 'afterPermanentlyDelete',
|
|
34
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect } from 'bun:test'
|
|
2
|
+
import { MutationEvent } from './mutation-event'
|
|
3
|
+
|
|
4
|
+
describe('MutationEvent', () => {
|
|
5
|
+
it('should create a mutation event with input and descriptor', () => {
|
|
6
|
+
const input = { key: 'value' }
|
|
7
|
+
const descriptor = { namespace: 'test', action: 'create' }
|
|
8
|
+
const event = new MutationEvent(descriptor, input, {})
|
|
9
|
+
|
|
10
|
+
expect(event.descriptor.namespace).toBe('test')
|
|
11
|
+
expect(event.descriptor.action).toBe('create')
|
|
12
|
+
expect(event.meta.input).toEqual(input)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('should update meta correctly', () => {
|
|
16
|
+
const input = { key: 'value' }
|
|
17
|
+
const descriptor = { namespace: 'test', action: 'create' }
|
|
18
|
+
const event = new MutationEvent(descriptor, input, {
|
|
19
|
+
foo: 'bar',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
event.setMeta({
|
|
23
|
+
foo: 'baz',
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
expect(event.meta.foo).toBe('baz')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('should set result correctly', () => {
|
|
30
|
+
const input = { key: 'value' }
|
|
31
|
+
const descriptor = { namespace: 'test', action: 'create' }
|
|
32
|
+
const event = new MutationEvent(descriptor, input, {})
|
|
33
|
+
|
|
34
|
+
const result = { success: true }
|
|
35
|
+
event.setResult(result)
|
|
36
|
+
expect(event.data).toEqual(result)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IActionDescriptorInput } from '@declaro/core'
|
|
2
|
+
import { RequestEvent } from './request-event'
|
|
3
|
+
|
|
4
|
+
export class MutationEvent<TResult, TInput, TMeta = any> extends RequestEvent<TResult, TInput, TMeta> {
|
|
5
|
+
constructor(descriptor: IActionDescriptorInput, input: TInput, meta: TMeta = {} as TMeta) {
|
|
6
|
+
super(descriptor, input, meta)
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, it, expect } from 'bun:test'
|
|
2
|
+
import { QueryEvent } from './query-event'
|
|
3
|
+
|
|
4
|
+
describe('QueryEvent', () => {
|
|
5
|
+
describe('load action', () => {
|
|
6
|
+
it('should lookup a book with the given lookup', () => {
|
|
7
|
+
const params = { id: 42 }
|
|
8
|
+
const descriptor = { namespace: 'books', action: 'load' }
|
|
9
|
+
const query = new QueryEvent(descriptor, params, {})
|
|
10
|
+
|
|
11
|
+
expect(query.descriptor.namespace).toBe('books')
|
|
12
|
+
expect(query.descriptor.action).toBe('load')
|
|
13
|
+
expect(query.meta.input).toEqual(params)
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
describe('search action', () => {
|
|
18
|
+
it('should search for books with the given filters', () => {
|
|
19
|
+
const params = { text: '1984' }
|
|
20
|
+
const descriptor = { namespace: 'books', action: 'search' }
|
|
21
|
+
const query = new QueryEvent(descriptor, params, {})
|
|
22
|
+
|
|
23
|
+
expect(query.descriptor.namespace).toBe('books')
|
|
24
|
+
expect(query.descriptor.action).toBe('search')
|
|
25
|
+
expect(query.meta.input).toEqual(params)
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
})
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IActionDescriptorInput } from '@declaro/core'
|
|
2
|
+
import { RequestEvent } from './request-event'
|
|
3
|
+
|
|
4
|
+
export class QueryEvent<TResult, TParams, TMeta = any> extends RequestEvent<TResult, TParams, TMeta> {
|
|
5
|
+
constructor(descriptor: IActionDescriptorInput, params: TParams, meta: TMeta = {} as TMeta) {
|
|
6
|
+
super(descriptor, params, meta)
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { describe, it, expect } from 'bun:test'
|
|
2
|
+
import { RequestEvent } from './request-event'
|
|
3
|
+
|
|
4
|
+
describe('RequestEvent', () => {
|
|
5
|
+
it('should initialize meta correctly', () => {
|
|
6
|
+
const input = { key: 'value' }
|
|
7
|
+
const descriptor = { namespace: 'test', action: 'create' }
|
|
8
|
+
const event = new RequestEvent(descriptor, input, {
|
|
9
|
+
foo: 'bar',
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
expect(event.meta.foo).toBe('bar')
|
|
13
|
+
expect(event.meta.input?.key).toBe('value')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('should update meta correctly', () => {
|
|
17
|
+
const input = { key: 'value' }
|
|
18
|
+
const descriptor = { namespace: 'test', action: 'create' }
|
|
19
|
+
const event = new RequestEvent(descriptor, input, {
|
|
20
|
+
foo: 'bar',
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
event.setMeta({ foo: 'test' })
|
|
24
|
+
expect(event.meta.foo).toBe('test')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('should set result correctly', () => {
|
|
28
|
+
const input = { key: 'value' }
|
|
29
|
+
const descriptor = { namespace: 'test', action: 'create' }
|
|
30
|
+
const event = new RequestEvent(descriptor, input, {
|
|
31
|
+
foo: 'bar',
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
const result = { success: true }
|
|
35
|
+
event.setResult(result)
|
|
36
|
+
expect(event.data).toEqual(result)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { IActionDescriptorInput, Simplify } from '@declaro/core'
|
|
2
|
+
import { DomainEvent } from './domain-event'
|
|
3
|
+
|
|
4
|
+
export interface IRequestEventInput<TInput> {
|
|
5
|
+
input: TInput
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class RequestEvent<TResult, TInput, TMeta = any> extends DomainEvent<
|
|
9
|
+
TResult,
|
|
10
|
+
Simplify<IRequestEventInput<TInput> & TMeta>
|
|
11
|
+
> {
|
|
12
|
+
constructor(descriptor: IActionDescriptorInput, input: TInput, meta: TMeta = {} as TMeta) {
|
|
13
|
+
super({
|
|
14
|
+
meta: {
|
|
15
|
+
...meta,
|
|
16
|
+
input,
|
|
17
|
+
},
|
|
18
|
+
descriptor,
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setMeta(meta: Partial<TMeta>): this {
|
|
23
|
+
this.meta = { ...this.meta, ...meta }
|
|
24
|
+
return this
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
setResult(result: TResult): this {
|
|
28
|
+
this.data = result
|
|
29
|
+
|
|
30
|
+
return this
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { AnyModelSchema } from '@declaro/core'
|
|
2
|
+
import type {
|
|
3
|
+
InferDetail,
|
|
4
|
+
InferFilters,
|
|
5
|
+
InferInput,
|
|
6
|
+
InferLookup,
|
|
7
|
+
InferSearchResults,
|
|
8
|
+
InferSummary,
|
|
9
|
+
} from '../../shared/utils/schema-inference'
|
|
10
|
+
import type { ICreateOptions, IUpdateOptions } from '../services/model-service'
|
|
11
|
+
import type { ILoadOptions, ISearchOptions } from '../services/read-only-model-service'
|
|
12
|
+
|
|
13
|
+
export interface IRepository<TSchema extends AnyModelSchema> {
|
|
14
|
+
/**
|
|
15
|
+
* Loads a single element based on the provided lookup.
|
|
16
|
+
*
|
|
17
|
+
* @param input - The lookup criteria for the element.
|
|
18
|
+
* @returns A promise resolving to the detailed element or null if not found.
|
|
19
|
+
*/
|
|
20
|
+
load(input: InferLookup<TSchema>, options?: ILoadOptions): Promise<InferDetail<TSchema> | null>
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Loads multiple elements based on the provided lookups.
|
|
24
|
+
*
|
|
25
|
+
* @param inputs - The lookup criteria for the elements.
|
|
26
|
+
* @returns A promise resolving to an array of detailed elements.
|
|
27
|
+
*/
|
|
28
|
+
loadMany(inputs: InferLookup<TSchema>[], options?: ILoadOptions): Promise<InferDetail<TSchema>[]>
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Searches for elements based on filters and optional pagination.
|
|
32
|
+
*
|
|
33
|
+
* @param input - The filters to apply to the search.
|
|
34
|
+
* @param pagination - Optional pagination criteria.
|
|
35
|
+
* @returns A promise resolving to the search results.
|
|
36
|
+
*/
|
|
37
|
+
search(input: InferFilters<TSchema>, options?: ISearchOptions<TSchema>): Promise<InferSearchResults<TSchema>>
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Deletes elements based on the provided lookups.
|
|
41
|
+
*
|
|
42
|
+
* @param lookup - The lookup criteria for the element to delete.
|
|
43
|
+
* @returns A promise resolving to the deleted list item.
|
|
44
|
+
*/
|
|
45
|
+
remove(lookup: InferLookup<TSchema>, options?: ILoadOptions): Promise<InferSummary<TSchema>>
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Restores an element based on the provided lookups, if a soft-deleted copy exists.
|
|
49
|
+
*
|
|
50
|
+
* @param lookup - The lookup criteria for the element to restore.
|
|
51
|
+
* @returns A promise resolving to the restored list item.
|
|
52
|
+
*/
|
|
53
|
+
restore(lookup: InferLookup<TSchema>, options?: ILoadOptions): Promise<InferSummary<TSchema>>
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new element based on the provided input.
|
|
57
|
+
*
|
|
58
|
+
* @param input - The input data for the new element.
|
|
59
|
+
* @returns A promise resolving to the detailed created element.
|
|
60
|
+
*/
|
|
61
|
+
create(input: InferInput<TSchema>, options?: ICreateOptions): Promise<InferDetail<TSchema>>
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Updates elements based on filters.
|
|
65
|
+
*
|
|
66
|
+
* @param filters - The filters to apply to the update.
|
|
67
|
+
* @returns A promise resolving to the detailed updated element.
|
|
68
|
+
*/
|
|
69
|
+
update(
|
|
70
|
+
lookup: InferLookup<TSchema>,
|
|
71
|
+
input: InferInput<TSchema>,
|
|
72
|
+
options?: IUpdateOptions,
|
|
73
|
+
): Promise<InferDetail<TSchema>>
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Upserts an element based on the provided input.
|
|
77
|
+
* If the element exists, it will be updated; otherwise, a new element will be created.
|
|
78
|
+
*
|
|
79
|
+
* A load operation will be performed to check if the element exists. create/update related events will be dispatched accordingly.
|
|
80
|
+
*
|
|
81
|
+
* @param input - The input data for the new or existing element.
|
|
82
|
+
* @returns A promise resolving to the detailed created or updated element.
|
|
83
|
+
*/
|
|
84
|
+
upsert(input: InferInput<TSchema>, options?: ICreateOptions | IUpdateOptions): Promise<InferDetail<TSchema>>
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Upserts multiple elements based on the provided inputs.
|
|
88
|
+
* If an element exists, it will be updated; otherwise, a new element will be created.
|
|
89
|
+
*
|
|
90
|
+
* A loadMany operation will be performed to check if the elements exist. create/update related events will be dispatched accordingly.
|
|
91
|
+
*
|
|
92
|
+
* @param inputs - The input data for the upsert operation.
|
|
93
|
+
* @returns A promise resolving to an array of detailed upserted elements.
|
|
94
|
+
*/
|
|
95
|
+
bulkUpsert(
|
|
96
|
+
inputs: InferInput<TSchema>[],
|
|
97
|
+
options?: ICreateOptions | IUpdateOptions,
|
|
98
|
+
): Promise<InferDetail<TSchema>[]>
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Counts the number of elements matching the provided search criteria.
|
|
102
|
+
*
|
|
103
|
+
* @param search - The search criteria to apply.
|
|
104
|
+
* @returns A promise resolving to the count of matching elements.
|
|
105
|
+
*/
|
|
106
|
+
count(search: InferFilters<TSchema>, options?: ISearchOptions<TSchema>): Promise<number>
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Permanently deletes all items from trash, optionally filtered by the provided criteria.
|
|
110
|
+
* Items deleted via this method cannot be restored.
|
|
111
|
+
*
|
|
112
|
+
* @param filters - Optional filters to apply when selecting items to delete from trash.
|
|
113
|
+
* @returns A promise resolving to the count of permanently deleted items.
|
|
114
|
+
*/
|
|
115
|
+
emptyTrash(filters?: InferFilters<TSchema>): Promise<number>
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Permanently deletes a specific item from trash based on the provided lookup.
|
|
119
|
+
* The item must exist in trash (previously removed). Items deleted via this method cannot be restored.
|
|
120
|
+
*
|
|
121
|
+
* @param lookup - The lookup criteria for the item to permanently delete from trash.
|
|
122
|
+
* @returns A promise resolving to the permanently deleted item summary.
|
|
123
|
+
* @throws Error if the item is not found in trash.
|
|
124
|
+
*/
|
|
125
|
+
permanentlyDeleteFromTrash(lookup: InferLookup<TSchema>): Promise<InferSummary<TSchema>>
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Permanently deletes an item based on the provided lookup, regardless of whether it is active or in trash.
|
|
129
|
+
* Items deleted via this method cannot be restored.
|
|
130
|
+
*
|
|
131
|
+
* @param lookup - The lookup criteria for the item to permanently delete.
|
|
132
|
+
* @returns A promise resolving to the permanently deleted item summary.
|
|
133
|
+
* @throws Error if the item is not found in either active data or trash.
|
|
134
|
+
*/
|
|
135
|
+
permanentlyDelete(lookup: InferLookup<TSchema>): Promise<InferSummary<TSchema>>
|
|
136
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import z from 'zod/v4'
|
|
2
|
+
import { ZodModel } from '@declaro/zod'
|
|
3
|
+
import { ModelSchema } from '@declaro/core'
|
|
4
|
+
|
|
5
|
+
export const PaginationInput = new ZodModel(
|
|
6
|
+
'PaginationInput' as const,
|
|
7
|
+
z.object({
|
|
8
|
+
page: z.number().int().min(1).default(1).nullish(),
|
|
9
|
+
pageSize: z.number().int().min(1).default(25).nullish(),
|
|
10
|
+
}),
|
|
11
|
+
)
|
|
12
|
+
export type IPaginationInput = z.infer<typeof PaginationInput.schema>
|
|
13
|
+
|
|
14
|
+
export const PaginationOutput = new ZodModel(
|
|
15
|
+
'PaginationOutput' as const,
|
|
16
|
+
z.object({
|
|
17
|
+
page: z.number().int().min(1).default(1),
|
|
18
|
+
pageSize: z.number().int().min(1).default(25),
|
|
19
|
+
total: z.number().int().min(0).default(0),
|
|
20
|
+
totalPages: z.number().int().min(1).default(1),
|
|
21
|
+
}),
|
|
22
|
+
)
|
|
23
|
+
export type IPagination = z.infer<typeof PaginationOutput.schema>
|
|
24
|
+
|
|
25
|
+
export const PaginationSchema = ModelSchema.create('Pagination').custom({
|
|
26
|
+
input: () => PaginationInput,
|
|
27
|
+
output: () => PaginationOutput,
|
|
28
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { ActionDescriptor, type AnyModelSchema, type ModelSchema } from '@declaro/core'
|
|
2
|
+
import type { IModelServiceArgs } from './model-service-args'
|
|
3
|
+
import type { IRepository } from '../interfaces/repository'
|
|
4
|
+
import type {
|
|
5
|
+
InferEntityMetadata,
|
|
6
|
+
InferInput,
|
|
7
|
+
InferLookup,
|
|
8
|
+
InferPrimaryKeyType,
|
|
9
|
+
} from '../../shared/utils/schema-inference'
|
|
10
|
+
|
|
11
|
+
export interface IActionOptions {
|
|
12
|
+
/**
|
|
13
|
+
* The scope of the load operation, e.g., 'detail', 'list', etc.
|
|
14
|
+
*/
|
|
15
|
+
scope?: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class BaseModelService<TSchema extends AnyModelSchema> {
|
|
19
|
+
protected readonly namespace: string
|
|
20
|
+
protected readonly schema: TSchema
|
|
21
|
+
protected readonly entityMetadata: InferEntityMetadata<TSchema>
|
|
22
|
+
protected readonly emitter: IModelServiceArgs<TSchema>['emitter']
|
|
23
|
+
protected readonly repository: IRepository<TSchema>
|
|
24
|
+
|
|
25
|
+
constructor(args: IModelServiceArgs<TSchema>) {
|
|
26
|
+
this.schema = args.schema
|
|
27
|
+
this.namespace = args.namespace ?? 'global'
|
|
28
|
+
this.emitter = args.emitter
|
|
29
|
+
this.repository = args.repository
|
|
30
|
+
this.entityMetadata = this.schema.getEntityMetadata()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getDescriptor(action: string, scope?: string) {
|
|
34
|
+
return ActionDescriptor.fromJSON({
|
|
35
|
+
namespace: this.namespace,
|
|
36
|
+
resource: this.schema.name,
|
|
37
|
+
action,
|
|
38
|
+
scope,
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getPrimaryKeyValue(input: InferLookup<TSchema>): InferPrimaryKeyType<TSchema>
|
|
43
|
+
getPrimaryKeyValue(input: InferInput<TSchema>): InferPrimaryKeyType<TSchema>
|
|
44
|
+
getPrimaryKeyValue(input: any = {}): InferPrimaryKeyType<TSchema> {
|
|
45
|
+
if (!this.entityMetadata?.primaryKey) {
|
|
46
|
+
return undefined
|
|
47
|
+
}
|
|
48
|
+
return input[this.entityMetadata.primaryKey]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public getSchema() {
|
|
52
|
+
return this.schema
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AnyModelSchema, EventManager } from '@declaro/core'
|
|
2
|
+
import type { IRepository } from '../interfaces/repository'
|
|
3
|
+
|
|
4
|
+
export interface IModelServiceArgs<TSchema extends AnyModelSchema> {
|
|
5
|
+
schema: TSchema
|
|
6
|
+
namespace?: string
|
|
7
|
+
emitter: EventManager
|
|
8
|
+
repository: IRepository<TSchema>
|
|
9
|
+
}
|