@declaro/data 2.0.0-beta.121 → 2.0.0-beta.125
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/dist/browser/index.js +10 -10
- package/dist/browser/index.js.map +6 -6
- package/dist/node/index.cjs +14 -5
- package/dist/node/index.cjs.map +6 -6
- package/dist/node/index.js +14 -5
- package/dist/node/index.js.map +6 -6
- package/dist/ts/domain/events/domain-event.d.ts +1 -1
- package/dist/ts/domain/events/domain-event.d.ts.map +1 -1
- package/dist/ts/domain/events/mutation-event.d.ts +5 -2
- package/dist/ts/domain/events/mutation-event.d.ts.map +1 -1
- package/dist/ts/domain/events/query-event.d.ts +4 -2
- package/dist/ts/domain/events/query-event.d.ts.map +1 -1
- package/dist/ts/domain/events/request-event.d.ts +17 -2
- package/dist/ts/domain/events/request-event.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/domain/events/domain-event.ts +1 -1
- package/src/domain/events/mutation-event.test.ts +369 -17
- package/src/domain/events/mutation-event.ts +10 -2
- package/src/domain/events/query-event.test.ts +218 -18
- package/src/domain/events/query-event.ts +8 -2
- package/src/domain/events/request-event.test.ts +1 -1
- package/src/domain/events/request-event.ts +22 -7
- package/src/domain/services/model-service.normalization.test.ts +6 -6
- package/src/domain/services/model-service.test.ts +4 -7
|
@@ -1,28 +1,228 @@
|
|
|
1
1
|
import { describe, it, expect } from 'bun:test'
|
|
2
2
|
import { QueryEvent } from './query-event'
|
|
3
|
+
import { ActionDescriptor, type IActionDescriptorInput } from '@declaro/core'
|
|
4
|
+
|
|
5
|
+
interface IBookResult {
|
|
6
|
+
id: string
|
|
7
|
+
title: string
|
|
8
|
+
description: string
|
|
9
|
+
author: string
|
|
10
|
+
year: number
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ILoadParams {
|
|
14
|
+
id: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ISearchParams {
|
|
18
|
+
text?: string
|
|
19
|
+
author?: string
|
|
20
|
+
year?: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface ICustomMeta {
|
|
24
|
+
customField?: string
|
|
25
|
+
anotherField?: number
|
|
26
|
+
}
|
|
3
27
|
|
|
4
28
|
describe('QueryEvent', () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
29
|
+
it('should create a query event with params and descriptor', () => {
|
|
30
|
+
const params: ILoadParams = { id: '1' }
|
|
31
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'load' }
|
|
32
|
+
const event = new QueryEvent<IBookResult, ILoadParams>(descriptor, params)
|
|
33
|
+
|
|
34
|
+
expect(event.input).toEqual(params)
|
|
35
|
+
expect(event.descriptor.toString()).toEqual(new ActionDescriptor(descriptor).toString())
|
|
36
|
+
expect(event.meta).toEqual({})
|
|
37
|
+
expect(event.data).toBeUndefined()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('should set result correctly', () => {
|
|
41
|
+
const params: ILoadParams = { id: '1' }
|
|
42
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'load' }
|
|
43
|
+
const event = new QueryEvent<IBookResult, ILoadParams>(descriptor, params)
|
|
44
|
+
|
|
45
|
+
expect(event.data).toBeUndefined()
|
|
46
|
+
|
|
47
|
+
const result: IBookResult = {
|
|
48
|
+
id: '1',
|
|
49
|
+
title: 'Test Book',
|
|
50
|
+
description: 'A book for testing',
|
|
51
|
+
author: 'Author Name',
|
|
52
|
+
year: 2024,
|
|
53
|
+
}
|
|
54
|
+
event.setResult(result)
|
|
55
|
+
|
|
56
|
+
expect(event.data).toEqual(result)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should update meta correctly', () => {
|
|
60
|
+
const params: ISearchParams = { text: '1984' }
|
|
61
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'search' }
|
|
62
|
+
const event = new QueryEvent<IBookResult[], ISearchParams, ICustomMeta>(descriptor, params)
|
|
63
|
+
|
|
64
|
+
event.setMeta({ customField: 'custom value' })
|
|
65
|
+
|
|
66
|
+
expect(event.meta.customField).toBe('custom value')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('should serialize to JSON with eventId and timestamp', () => {
|
|
70
|
+
const params: ILoadParams = { id: '1' }
|
|
71
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'load' }
|
|
72
|
+
const event = new QueryEvent<IBookResult, ILoadParams>(descriptor, params)
|
|
73
|
+
|
|
74
|
+
const result: IBookResult = {
|
|
75
|
+
id: '1',
|
|
76
|
+
title: 'Test Book',
|
|
77
|
+
description: 'A book for testing',
|
|
78
|
+
author: 'Author Name',
|
|
79
|
+
year: 2024,
|
|
80
|
+
}
|
|
81
|
+
event.setResult(result)
|
|
82
|
+
|
|
83
|
+
const json = event.toJSON()
|
|
84
|
+
|
|
85
|
+
expect(json.eventId).toBeDefined()
|
|
86
|
+
expect(json.timestamp).toBeDefined()
|
|
87
|
+
expect(json.type).toBe('books::book.load')
|
|
88
|
+
expect(json.input).toEqual(params)
|
|
89
|
+
expect(json.data).toEqual(result)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('should handle chaining of setter methods', () => {
|
|
93
|
+
const params: ILoadParams = { id: '1' }
|
|
94
|
+
const result: IBookResult = {
|
|
95
|
+
id: '1',
|
|
96
|
+
title: 'Test Book',
|
|
97
|
+
description: 'A book for testing',
|
|
98
|
+
author: 'Author Name',
|
|
99
|
+
year: 2024,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'load' }
|
|
103
|
+
const event = new QueryEvent<IBookResult, ILoadParams, ICustomMeta>(descriptor, params)
|
|
104
|
+
.setMeta({ customField: 'value' })
|
|
105
|
+
.setResult(result)
|
|
106
|
+
|
|
107
|
+
expect(event.input).toEqual(params)
|
|
108
|
+
expect(event.meta.customField).toBe('value')
|
|
109
|
+
expect(event.data).toEqual(result)
|
|
15
110
|
})
|
|
16
111
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const query = new QueryEvent(descriptor, params, {})
|
|
112
|
+
it('should update input after initialization', () => {
|
|
113
|
+
const params: ISearchParams = { text: '1984' }
|
|
114
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'search' }
|
|
115
|
+
const event = new QueryEvent<IBookResult[], ISearchParams>(descriptor, params)
|
|
22
116
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
117
|
+
const newParams: ISearchParams = {
|
|
118
|
+
text: 'Brave New World',
|
|
119
|
+
author: 'Aldous Huxley',
|
|
120
|
+
}
|
|
121
|
+
event.setInput(newParams)
|
|
122
|
+
|
|
123
|
+
expect(event.input).toEqual(newParams)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('should maintain type throughout lifecycle', () => {
|
|
127
|
+
const params: ILoadParams = { id: '1' }
|
|
128
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'load' }
|
|
129
|
+
const event = new QueryEvent<IBookResult, ILoadParams>(descriptor, params)
|
|
130
|
+
|
|
131
|
+
expect(event.type).toBe('books::book.load')
|
|
132
|
+
|
|
133
|
+
event.setInput({ id: '2' })
|
|
134
|
+
expect(event.type).toBe('books::book.load')
|
|
135
|
+
|
|
136
|
+
const result: IBookResult = {
|
|
137
|
+
id: '2',
|
|
138
|
+
title: 'Another Book',
|
|
139
|
+
description: 'Another description',
|
|
140
|
+
author: 'Another Author',
|
|
141
|
+
year: 2025,
|
|
142
|
+
}
|
|
143
|
+
event.setResult(result)
|
|
144
|
+
expect(event.type).toBe('books::book.load')
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('should handle search action with multiple filters', () => {
|
|
148
|
+
const params: ISearchParams = {
|
|
149
|
+
text: 'science fiction',
|
|
150
|
+
author: 'Isaac Asimov',
|
|
151
|
+
year: 1950,
|
|
152
|
+
}
|
|
153
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'search' }
|
|
154
|
+
const event = new QueryEvent<IBookResult[], ISearchParams>(descriptor, params)
|
|
155
|
+
|
|
156
|
+
expect(event.descriptor.action).toBe('search')
|
|
157
|
+
expect(event.input).toEqual(params)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('should handle search results as array', () => {
|
|
161
|
+
const params: ISearchParams = { text: 'Foundation' }
|
|
162
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'search' }
|
|
163
|
+
const event = new QueryEvent<IBookResult[], ISearchParams>(descriptor, params)
|
|
164
|
+
|
|
165
|
+
const results: IBookResult[] = [
|
|
166
|
+
{
|
|
167
|
+
id: '1',
|
|
168
|
+
title: 'Foundation',
|
|
169
|
+
description: 'First book',
|
|
170
|
+
author: 'Isaac Asimov',
|
|
171
|
+
year: 1951,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: '2',
|
|
175
|
+
title: 'Foundation and Empire',
|
|
176
|
+
description: 'Second book',
|
|
177
|
+
author: 'Isaac Asimov',
|
|
178
|
+
year: 1952,
|
|
179
|
+
},
|
|
180
|
+
]
|
|
181
|
+
event.setResult(results)
|
|
182
|
+
|
|
183
|
+
expect(event.data).toEqual(results)
|
|
184
|
+
expect(event.data?.length).toBe(2)
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('should handle load action with single result', () => {
|
|
188
|
+
const params: ILoadParams = { id: '42' }
|
|
189
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'load' }
|
|
190
|
+
const event = new QueryEvent<IBookResult, ILoadParams>(descriptor, params)
|
|
191
|
+
|
|
192
|
+
const result: IBookResult = {
|
|
193
|
+
id: '42',
|
|
194
|
+
title: "The Hitchhiker's Guide to the Galaxy",
|
|
195
|
+
description: "Don't Panic",
|
|
196
|
+
author: 'Douglas Adams',
|
|
197
|
+
year: 1979,
|
|
198
|
+
}
|
|
199
|
+
event.setResult(result)
|
|
200
|
+
|
|
201
|
+
expect(event.data).toEqual(result)
|
|
202
|
+
expect(event.descriptor.action).toBe('load')
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
it('should serialize meta to JSON', () => {
|
|
206
|
+
const params: ISearchParams = { text: 'test' }
|
|
207
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'search' }
|
|
208
|
+
const event = new QueryEvent<IBookResult[], ISearchParams, ICustomMeta>(descriptor, params, {
|
|
209
|
+
customField: 'custom value',
|
|
210
|
+
anotherField: 123,
|
|
26
211
|
})
|
|
212
|
+
|
|
213
|
+
const json = event.toJSON()
|
|
214
|
+
|
|
215
|
+
expect(json.meta.customField).toBe('custom value')
|
|
216
|
+
expect(json.meta.anotherField).toBe(123)
|
|
217
|
+
expect(json.input).toEqual(params)
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it('should handle empty search params', () => {
|
|
221
|
+
const params: ISearchParams = {}
|
|
222
|
+
const descriptor: IActionDescriptorInput = { namespace: 'books', resource: 'book', action: 'search' }
|
|
223
|
+
const event = new QueryEvent<IBookResult[], ISearchParams>(descriptor, params)
|
|
224
|
+
|
|
225
|
+
expect(event.input).toEqual({})
|
|
226
|
+
expect(event.descriptor.action).toBe('search')
|
|
27
227
|
})
|
|
28
228
|
})
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { IActionDescriptorInput } from '@declaro/core'
|
|
2
|
-
import { RequestEvent } from './request-event'
|
|
2
|
+
import { RequestEvent, type IRequestEventMeta } from './request-event'
|
|
3
3
|
|
|
4
|
-
export
|
|
4
|
+
export interface IQueryEventMeta<TResult> extends IRequestEventMeta {}
|
|
5
|
+
|
|
6
|
+
export class QueryEvent<
|
|
7
|
+
TResult,
|
|
8
|
+
TParams,
|
|
9
|
+
TMeta extends IQueryEventMeta<TResult> = IQueryEventMeta<TResult>,
|
|
10
|
+
> extends RequestEvent<TResult, TParams, TMeta> {
|
|
5
11
|
constructor(descriptor: IActionDescriptorInput, params: TParams, meta: TMeta = {} as TMeta) {
|
|
6
12
|
super(descriptor, params, meta)
|
|
7
13
|
}
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
import type { IActionDescriptorInput, Simplify } from '@declaro/core'
|
|
2
2
|
import { DomainEvent } from './domain-event'
|
|
3
3
|
|
|
4
|
-
export interface
|
|
4
|
+
export interface IRequestEventMeta {}
|
|
5
|
+
|
|
6
|
+
export interface IRequestEventJSON<TInput, TMeta = IRequestEventMeta> extends Simplify<DomainEvent<TInput, TMeta>> {
|
|
5
7
|
input: TInput
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
export class RequestEvent<TResult, TInput, TMeta =
|
|
10
|
+
export class RequestEvent<TResult, TInput, TMeta extends IRequestEventMeta = IRequestEventMeta> extends DomainEvent<
|
|
9
11
|
TResult,
|
|
10
|
-
|
|
12
|
+
TMeta
|
|
11
13
|
> {
|
|
14
|
+
input: TInput
|
|
15
|
+
|
|
12
16
|
constructor(descriptor: IActionDescriptorInput, input: TInput, meta: TMeta = {} as TMeta) {
|
|
13
17
|
super({
|
|
14
|
-
meta
|
|
15
|
-
...meta,
|
|
16
|
-
input,
|
|
17
|
-
},
|
|
18
|
+
meta,
|
|
18
19
|
descriptor,
|
|
19
20
|
})
|
|
21
|
+
|
|
22
|
+
this.input = input
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setInput(input: TInput): this {
|
|
26
|
+
this.input = input
|
|
27
|
+
return this
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
setMeta(meta: Partial<TMeta>): this {
|
|
@@ -29,4 +37,11 @@ export class RequestEvent<TResult, TInput, TMeta = any> extends DomainEvent<
|
|
|
29
37
|
|
|
30
38
|
return this
|
|
31
39
|
}
|
|
40
|
+
|
|
41
|
+
toJSON() {
|
|
42
|
+
return {
|
|
43
|
+
...super.toJSON(),
|
|
44
|
+
input: this.input,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
32
47
|
}
|
|
@@ -138,13 +138,13 @@ describe('ModelService - Normalization', () => {
|
|
|
138
138
|
const beforeCreateCall = beforeCreateSpy.mock.calls[0][0]
|
|
139
139
|
const afterCreateCall = afterCreateSpy.mock.calls[0][0]
|
|
140
140
|
|
|
141
|
-
expect(beforeCreateCall.
|
|
142
|
-
expect(beforeCreateCall.
|
|
143
|
-
expect(beforeCreateCall.
|
|
141
|
+
expect(beforeCreateCall.input.title).toBe('Test Book')
|
|
142
|
+
expect(beforeCreateCall.input.author).toBe('Author Name')
|
|
143
|
+
expect(beforeCreateCall.input.publishedDate).toEqual(new Date('2023-01-01'))
|
|
144
144
|
|
|
145
|
-
expect(afterCreateCall.
|
|
146
|
-
expect(afterCreateCall.
|
|
147
|
-
expect(afterCreateCall.
|
|
145
|
+
expect(afterCreateCall.input.title).toBe('Test Book')
|
|
146
|
+
expect(afterCreateCall.input.author).toBe('Author Name')
|
|
147
|
+
expect(afterCreateCall.input.publishedDate).toEqual(new Date('2023-01-01'))
|
|
148
148
|
})
|
|
149
149
|
|
|
150
150
|
it('should call normalizeInput method exactly once per input during bulkUpsert with Promise.all', async () => {
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach } from 'bun:test'
|
|
2
|
-
import { ModelService } from './model-service'
|
|
3
|
-
import { MockMemoryRepository } from '../../test/mock/repositories/mock-memory-repository'
|
|
4
|
-
import { MockBookSchema, type MockBookInput } from '../../test/mock/models/mock-book-models'
|
|
5
1
|
import { EventManager } from '@declaro/core'
|
|
6
|
-
import { mock } from 'bun:test'
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
2
|
+
import { beforeEach, describe, expect, it, mock } from 'bun:test'
|
|
3
|
+
import { MockBookSchema } from '../../test/mock/models/mock-book-models'
|
|
4
|
+
import { MockMemoryRepository } from '../../test/mock/repositories/mock-memory-repository'
|
|
5
|
+
import { ModelService } from './model-service'
|
|
9
6
|
|
|
10
7
|
describe('ModelService', () => {
|
|
11
8
|
const namespace = 'books'
|