@contember/engine-actions 1.3.0-alpha.8 → 1.3.0-beta.2

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 (112) hide show
  1. package/dist/src/authorization/ActionsAuthorizationActions.d.ts +27 -0
  2. package/dist/src/authorization/ActionsAuthorizationActions.d.ts.map +1 -0
  3. package/dist/src/authorization/ActionsAuthorizationActions.js +17 -0
  4. package/dist/src/authorization/ActionsAuthorizationActions.js.map +1 -0
  5. package/dist/src/authorization/ActionsPermissionsFactory.d.ts +5 -0
  6. package/dist/src/authorization/ActionsPermissionsFactory.d.ts.map +1 -0
  7. package/dist/src/authorization/ActionsPermissionsFactory.js +17 -0
  8. package/dist/src/authorization/ActionsPermissionsFactory.js.map +1 -0
  9. package/dist/src/authorization/Identity.d.ts +5 -0
  10. package/dist/src/authorization/Identity.d.ts.map +1 -0
  11. package/dist/src/authorization/Identity.js +3 -0
  12. package/dist/src/authorization/Identity.js.map +1 -0
  13. package/dist/src/authorization/index.d.ts +4 -0
  14. package/dist/src/authorization/index.d.ts.map +1 -0
  15. package/dist/src/authorization/index.js +20 -0
  16. package/dist/src/authorization/index.js.map +1 -0
  17. package/dist/src/dispatch/EventDispatcher.d.ts +2 -2
  18. package/dist/src/dispatch/EventDispatcher.d.ts.map +1 -1
  19. package/dist/src/dispatch/EventsRepository.d.ts +1 -1
  20. package/dist/src/dispatch/EventsRepository.d.ts.map +1 -1
  21. package/dist/src/dispatch/EventsRepository.js +1 -1
  22. package/dist/src/dispatch/EventsRepository.js.map +1 -1
  23. package/dist/src/dispatch/WebhookFetcher.d.ts +14 -0
  24. package/dist/src/dispatch/WebhookFetcher.d.ts.map +1 -0
  25. package/dist/src/dispatch/WebhookFetcher.js +17 -0
  26. package/dist/src/dispatch/WebhookFetcher.js.map +1 -0
  27. package/dist/src/dispatch/WebhookTargetHandler.d.ts +8 -0
  28. package/dist/src/dispatch/WebhookTargetHandler.d.ts.map +1 -1
  29. package/dist/src/dispatch/WebhookTargetHandler.js +145 -44
  30. package/dist/src/dispatch/WebhookTargetHandler.js.map +1 -1
  31. package/dist/src/dispatch/types.d.ts +23 -2
  32. package/dist/src/dispatch/types.d.ts.map +1 -1
  33. package/dist/src/graphql/http/ActionsApiMiddlewareFactory.d.ts +4 -1
  34. package/dist/src/graphql/http/ActionsApiMiddlewareFactory.d.ts.map +1 -1
  35. package/dist/src/graphql/http/ActionsApiMiddlewareFactory.js +10 -2
  36. package/dist/src/graphql/http/ActionsApiMiddlewareFactory.js.map +1 -1
  37. package/dist/src/graphql/http/ActionsContextResolver.d.ts +8 -5
  38. package/dist/src/graphql/http/ActionsContextResolver.d.ts.map +1 -1
  39. package/dist/src/graphql/http/ActionsContextResolver.js +6 -4
  40. package/dist/src/graphql/http/ActionsContextResolver.js.map +1 -1
  41. package/dist/src/graphql/http/ActionsGraphQLHandlerFactory.d.ts +1 -1
  42. package/dist/src/graphql/http/ActionsGraphQLHandlerFactory.d.ts.map +1 -1
  43. package/dist/src/graphql/resolvers/ActionsContext.d.ts +2 -0
  44. package/dist/src/graphql/resolvers/ActionsContext.d.ts.map +1 -1
  45. package/dist/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.d.ts.map +1 -1
  46. package/dist/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.js +2 -0
  47. package/dist/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.js.map +1 -1
  48. package/dist/src/graphql/resolvers/mutation/SetVariablesMutationResolver.d.ts.map +1 -1
  49. package/dist/src/graphql/resolvers/mutation/SetVariablesMutationResolver.js +2 -0
  50. package/dist/src/graphql/resolvers/mutation/SetVariablesMutationResolver.js.map +1 -1
  51. package/dist/src/graphql/resolvers/query/EventsQueryResolver.d.ts.map +1 -1
  52. package/dist/src/graphql/resolvers/query/EventsQueryResolver.js +4 -0
  53. package/dist/src/graphql/resolvers/query/EventsQueryResolver.js.map +1 -1
  54. package/dist/src/graphql/resolvers/query/VariablesQueryResolver.d.ts.map +1 -1
  55. package/dist/src/graphql/resolvers/query/VariablesQueryResolver.js +2 -0
  56. package/dist/src/graphql/resolvers/query/VariablesQueryResolver.js.map +1 -1
  57. package/dist/src/graphql/schema/index.d.ts +43 -43
  58. package/dist/src/graphql/schema/index.d.ts.map +1 -1
  59. package/dist/src/index.d.ts.map +1 -1
  60. package/dist/src/index.js +9 -3
  61. package/dist/src/index.js.map +1 -1
  62. package/dist/src/model/VariablesManager.d.ts +1 -1
  63. package/dist/src/model/VariablesManager.d.ts.map +1 -1
  64. package/dist/src/model/VariablesQuery.d.ts +1 -1
  65. package/dist/src/model/VariablesQuery.d.ts.map +1 -1
  66. package/dist/src/model/types.d.ts +7 -4
  67. package/dist/src/model/types.d.ts.map +1 -1
  68. package/dist/src/triggers/Payload.d.ts +9 -14
  69. package/dist/src/triggers/Payload.d.ts.map +1 -1
  70. package/dist/src/triggers/TriggerHandler.d.ts +1 -1
  71. package/dist/src/triggers/TriggerHandler.d.ts.map +1 -1
  72. package/dist/src/triggers/TriggerListenersStore.d.ts +1 -1
  73. package/dist/src/triggers/TriggerListenersStore.d.ts.map +1 -1
  74. package/dist/src/triggers/TriggerPayloadBuilder.js +4 -4
  75. package/dist/src/triggers/TriggerPayloadBuilder.js.map +1 -1
  76. package/dist/src/triggers/TriggerPayloadManager.d.ts +1 -1
  77. package/dist/src/triggers/TriggerPayloadManager.d.ts.map +1 -1
  78. package/dist/src/triggers/TriggerPayloadPersister.d.ts.map +1 -1
  79. package/dist/src/triggers/TriggerPayloadPersister.js +3 -1
  80. package/dist/src/triggers/TriggerPayloadPersister.js.map +1 -1
  81. package/dist/src/tsconfig.tsbuildinfo +1 -1
  82. package/dist/tests/cases/integration/triggers.rootWatch.test.js +63 -0
  83. package/dist/tests/cases/integration/triggers.rootWatch.test.js.map +1 -1
  84. package/dist/tests/cases/unit/webhookHandler.test.d.ts +2 -0
  85. package/dist/tests/cases/unit/webhookHandler.test.d.ts.map +1 -0
  86. package/dist/tests/cases/unit/webhookHandler.test.js +248 -0
  87. package/dist/tests/cases/unit/webhookHandler.test.js.map +1 -0
  88. package/dist/tests/tsconfig.tsbuildinfo +1 -1
  89. package/package.json +18 -17
  90. package/src/authorization/ActionsAuthorizationActions.ts +14 -0
  91. package/src/authorization/ActionsPermissionsFactory.ts +14 -0
  92. package/src/authorization/Identity.ts +4 -0
  93. package/src/authorization/index.ts +3 -0
  94. package/src/dispatch/EventsRepository.ts +1 -1
  95. package/src/dispatch/WebhookFetcher.ts +24 -0
  96. package/src/dispatch/WebhookTargetHandler.ts +151 -46
  97. package/src/dispatch/types.ts +27 -0
  98. package/src/graphql/http/ActionsApiMiddlewareFactory.ts +10 -1
  99. package/src/graphql/http/ActionsContextResolver.ts +15 -6
  100. package/src/graphql/resolvers/ActionsContext.ts +2 -0
  101. package/src/graphql/resolvers/mutation/ProcessBatchMutationResolver.ts +3 -0
  102. package/src/graphql/resolvers/mutation/SetVariablesMutationResolver.ts +3 -0
  103. package/src/graphql/resolvers/query/EventsQueryResolver.ts +7 -0
  104. package/src/graphql/resolvers/query/VariablesQueryResolver.ts +3 -0
  105. package/src/index.ts +9 -3
  106. package/src/model/types.ts +7 -3
  107. package/src/triggers/Payload.ts +0 -8
  108. package/src/triggers/TriggerPayloadBuilder.ts +1 -1
  109. package/src/triggers/TriggerPayloadPersister.ts +10 -1
  110. package/src/tsconfig.json +1 -0
  111. package/tests/cases/integration/triggers.rootWatch.test.ts +64 -0
  112. package/tests/cases/unit/webhookHandler.test.ts +275 -0
@@ -2,8 +2,15 @@ import { Client, InsertBuilder } from '@contember/database'
2
2
  import { AnyEventPayload } from './Payload'
3
3
  import { Mapper } from '@contember/engine-content-api'
4
4
  import { Actions } from '@contember/schema'
5
+ import { EventRow } from '../model/types'
5
6
 
6
7
  export const NOTIFY_CHANNEL_NAME = 'actions_event'
8
+ type EventRowToInsert = Omit<EventRow, 'created_at' | 'visible_at' | 'last_state_change' | 'log'> & {
9
+ created_at: string | Date
10
+ visible_at: string | Date
11
+ last_state_change: string | Date
12
+ }
13
+
7
14
  export class TriggerPayloadPersister {
8
15
  constructor(
9
16
  private readonly mapper: Mapper,
@@ -21,7 +28,7 @@ export class TriggerPayloadPersister {
21
28
  const chunk = payloads.slice(i, i + chunkSize)
22
29
  await InsertBuilder.create()
23
30
  .into('actions_event')
24
- .values(chunk.map(it => ({
31
+ .values(chunk.map((it): EventRowToInsert => ({
25
32
  id: this.providers.uuid(),
26
33
  transaction_id: this.mapper.transactionId,
27
34
  created_at: 'now',
@@ -34,6 +41,8 @@ export class TriggerPayloadPersister {
34
41
  trigger: trigger.name,
35
42
  priority: trigger.priority ?? 0,
36
43
  payload: it,
44
+ resolved_at: null,
45
+ last_state_change: 'now',
37
46
  })))
38
47
  .execute(this.client)
39
48
  }
package/src/tsconfig.json CHANGED
@@ -4,6 +4,7 @@
4
4
  "outDir": "../dist/src"
5
5
  },
6
6
  "references": [
7
+ { "path": "../../../packages/authorization/src" },
7
8
  { "path": "../../../packages/database/src" },
8
9
  { "path": "../../../packages/database-migrations/src" },
9
10
  { "path": "../../../packages/engine-common/src" },
@@ -150,3 +150,67 @@ test('triggers: root watch - noop', async () => {
150
150
  })
151
151
 
152
152
 
153
+ test('triggers: root delete', async () => {
154
+ const schema = createSchema(ActionsModel)
155
+ await executeDbTest({
156
+ executionContainerFactoryFactory,
157
+ migrationGroups: { 'contember/actions': migrationsGroup },
158
+ schema: schema,
159
+ seed: [
160
+ {
161
+ query: gql`
162
+ mutation {
163
+ createArticle(data: {title: "Hello world"}) {
164
+ ok
165
+ }
166
+ }
167
+ `,
168
+ },
169
+ ],
170
+ query: gql`
171
+ mutation {
172
+ deleteArticle(by: {title: "Hello world"}) {
173
+ ok
174
+ }
175
+ }
176
+ `,
177
+ return: {
178
+ deleteArticle: {
179
+ ok: true,
180
+ },
181
+ },
182
+ expectSystemDatabase: {
183
+ actions_event: [{
184
+ payload: {
185
+ id: '123e4567-e89b-12d3-a456-000000000003',
186
+ entity: 'Article',
187
+ events: [{
188
+ id: '123e4567-e89b-12d3-a456-000000000003',
189
+ entity: 'Article',
190
+ values: { id: '123e4567-e89b-12d3-a456-000000000003', title: 'Hello world' },
191
+ operation: 'create',
192
+ }],
193
+ trigger: 'article_watch',
194
+ operation: 'watch',
195
+ selection: { id: '123e4567-e89b-12d3-a456-000000000003', title: 'Hello world' },
196
+ },
197
+ log: [],
198
+ }, {
199
+ payload: {
200
+ id: '123e4567-e89b-12d3-a456-000000000003',
201
+ entity: 'Article',
202
+ events: [{
203
+ id: '123e4567-e89b-12d3-a456-000000000003',
204
+ entity: 'Article',
205
+ operation: 'delete',
206
+ }],
207
+ trigger: 'article_watch',
208
+ operation: 'watch',
209
+ selection: { id: '123e4567-e89b-12d3-a456-000000000003', title: 'Hello world' },
210
+ },
211
+ log: [],
212
+ }],
213
+ },
214
+ })
215
+ })
216
+
@@ -0,0 +1,275 @@
1
+ import { assert, describe, expect, test } from 'vitest'
2
+ import { WebhookTargetHandler } from '../../../src/dispatch/WebhookTargetHandler'
3
+ import { FetcherResponse } from '../../../src/dispatch/WebhookFetcher'
4
+ import { createLogger, TestLoggerHandler } from '@contember/logger'
5
+ import { testUuid } from '@contember/engine-api-tester'
6
+ import { AnyEventPayload } from '../../../src/triggers/Payload'
7
+ import { EventRow } from '../../../src/model/types'
8
+ import { Actions } from '@contember/schema'
9
+ import { HandledEvent } from '../../../src/dispatch/types'
10
+
11
+
12
+ const now = new Date()
13
+ const createTestEvent = (i = 0, row: Partial<EventRow> = {}): EventRow => ({
14
+ created_at: now,
15
+ id: testUuid(i * 10 + 1),
16
+ trigger: 'test',
17
+ target: 'test_target',
18
+ last_state_change: now,
19
+ log: [],
20
+ num_retries: 0,
21
+ resolved_at: null,
22
+ transaction_id: testUuid(i * 10 + 2),
23
+ stage_id: testUuid(i * 10 + 3),
24
+ visible_at: now,
25
+ payload: { foo: 'bar' } as unknown as AnyEventPayload,
26
+ priority: 1,
27
+ schema_id: 1,
28
+ state: 'created',
29
+ ...row,
30
+ })
31
+
32
+ const dropDuration = (events: HandledEvent[]): HandledEvent[] => {
33
+ return events.map(it => ({ ...it, result: { ...it.result, durationMs: -1 } }))
34
+ }
35
+
36
+ describe('webhook handler', () => {
37
+ test('successful response', async () => {
38
+ const testLoggerHandler = new TestLoggerHandler()
39
+ const logger = createLogger(testLoggerHandler)
40
+
41
+ let fetchCalled = false
42
+ const webhookHandler = new WebhookTargetHandler({
43
+ fetch(url: string, init: RequestInit): Promise<FetcherResponse> {
44
+ fetchCalled = true
45
+ assert.equal(url, 'http://localhost')
46
+
47
+ return Promise.resolve({
48
+ ok: true,
49
+ headers: new Headers(),
50
+ responseText: '',
51
+ status: 200,
52
+ statusText: 'OK',
53
+ })
54
+ },
55
+ })
56
+
57
+ const target: Actions.AnyTarget = {
58
+ name: 'test_target',
59
+ type: 'webhook',
60
+ url: 'http://localhost',
61
+ }
62
+
63
+ const event1 = createTestEvent(0)
64
+ const event2 = createTestEvent(1)
65
+ const result = await webhookHandler.handle({
66
+ logger,
67
+ target: target,
68
+ events: [event1, event2],
69
+ variables: {},
70
+ })
71
+ assert.equal(fetchCalled, true)
72
+ assert.deepStrictEqual(dropDuration(result), [
73
+ {
74
+ row: event1,
75
+ target,
76
+ result: {
77
+ ok: true,
78
+ code: 200,
79
+ durationMs: -1,
80
+ },
81
+ },
82
+ {
83
+ row: event2,
84
+ target,
85
+ result: {
86
+ ok: true,
87
+ code: 200,
88
+ durationMs: -1,
89
+ },
90
+ },
91
+ ])
92
+ })
93
+
94
+ test('error response', async () => {
95
+ const testLoggerHandler = new TestLoggerHandler()
96
+ const logger = createLogger(testLoggerHandler)
97
+
98
+ let fetchCalled = false
99
+ const webhookHandler = new WebhookTargetHandler({
100
+ fetch(url: string, init: RequestInit): Promise<FetcherResponse> {
101
+ fetchCalled = true
102
+ assert.equal(url, 'http://localhost')
103
+
104
+ return Promise.resolve({
105
+ ok: false,
106
+ headers: new Headers(),
107
+ responseText: 'Failed to something',
108
+ status: 500,
109
+ statusText: 'Err',
110
+ })
111
+ },
112
+ })
113
+
114
+ const target: Actions.AnyTarget = {
115
+ name: 'test_target',
116
+ type: 'webhook',
117
+ url: 'http://localhost',
118
+ }
119
+
120
+ const event1 = createTestEvent(0)
121
+ const event2 = createTestEvent(1)
122
+ const result = await webhookHandler.handle({
123
+ logger,
124
+ target: target,
125
+ events: [event1, event2],
126
+ variables: {},
127
+ })
128
+ assert.equal(fetchCalled, true)
129
+ assert.deepStrictEqual(dropDuration(result), [
130
+ {
131
+ row: event1,
132
+ target,
133
+ result: {
134
+ ok: false,
135
+ code: 500,
136
+ durationMs: -1,
137
+ errorMessage: 'Err',
138
+ response: 'Failed to something',
139
+ },
140
+ },
141
+ {
142
+ row: event2,
143
+ target,
144
+ result: {
145
+ ok: false,
146
+ code: 500,
147
+ durationMs: -1,
148
+ errorMessage: 'Err',
149
+ response: 'Failed to something',
150
+ },
151
+ },
152
+ ])
153
+ })
154
+
155
+
156
+ test('invalid partial response', async () => {
157
+ const testLoggerHandler = new TestLoggerHandler()
158
+ const logger = createLogger(testLoggerHandler)
159
+
160
+ let fetchCalled = false
161
+ const webhookHandler = new WebhookTargetHandler({
162
+ fetch(url: string, init: RequestInit): Promise<FetcherResponse> {
163
+ fetchCalled = true
164
+ assert.equal(url, 'http://localhost')
165
+
166
+ return Promise.resolve({
167
+ ok: true,
168
+ headers: new Headers([['content-type', 'application/json']]),
169
+ responseText: `{"events": []}`,
170
+ status: 200,
171
+ statusText: 'OK',
172
+ })
173
+ },
174
+ })
175
+
176
+ const target: Actions.AnyTarget = {
177
+ name: 'test_target',
178
+ type: 'webhook',
179
+ url: 'http://localhost',
180
+ }
181
+
182
+ const event1 = createTestEvent(0)
183
+ const event2 = createTestEvent(1)
184
+ const result = await webhookHandler.handle({
185
+ logger,
186
+ target: target,
187
+ events: [event1, event2],
188
+ variables: {},
189
+ })
190
+ assert.equal(fetchCalled, true)
191
+ assert.deepStrictEqual(dropDuration(result), [
192
+ {
193
+ row: event1,
194
+ target,
195
+ result: {
196
+ ok: false,
197
+ code: 200,
198
+ durationMs: -1,
199
+ errorMessage: 'Invalid response: value at path /failures: must be array, undefined given',
200
+ response: '{"events": []}',
201
+ },
202
+ },
203
+ {
204
+ row: event2,
205
+ target,
206
+ result: {
207
+ ok: false,
208
+ code: 200,
209
+ durationMs: -1,
210
+ errorMessage: 'Invalid response: value at path /failures: must be array, undefined given',
211
+ response: '{"events": []}',
212
+ },
213
+ },
214
+ ])
215
+ })
216
+
217
+
218
+ test('partially successful response', async () => {
219
+ const testLoggerHandler = new TestLoggerHandler()
220
+ const logger = createLogger(testLoggerHandler)
221
+
222
+ let fetchCalled = false
223
+ const webhookHandler = new WebhookTargetHandler({
224
+ fetch(url: string, init: RequestInit): Promise<FetcherResponse> {
225
+ fetchCalled = true
226
+ assert.equal(url, 'http://localhost')
227
+
228
+ return Promise.resolve({
229
+ ok: true,
230
+ headers: new Headers([['content-type', 'application/json']]),
231
+ responseText: `{"failures": [{"eventId": "${testUuid(1)}", "error": "foo failure"}]}`,
232
+ status: 200,
233
+ statusText: 'OK',
234
+ })
235
+ },
236
+ })
237
+
238
+ const target: Actions.AnyTarget = {
239
+ name: 'test_target',
240
+ type: 'webhook',
241
+ url: 'http://localhost',
242
+ }
243
+
244
+ const event1 = createTestEvent(0)
245
+ const event2 = createTestEvent(1)
246
+ const result = await webhookHandler.handle({
247
+ logger,
248
+ target: target,
249
+ events: [event1, event2],
250
+ variables: {},
251
+ })
252
+ assert.equal(fetchCalled, true)
253
+ assert.deepStrictEqual(dropDuration(result), [
254
+ {
255
+ row: event1,
256
+ target,
257
+ result: {
258
+ ok: false,
259
+ code: 200,
260
+ durationMs: -1,
261
+ errorMessage: 'foo failure',
262
+ },
263
+ },
264
+ {
265
+ row: event2,
266
+ target,
267
+ result: {
268
+ ok: true,
269
+ code: 200,
270
+ durationMs: -1,
271
+ },
272
+ },
273
+ ])
274
+ })
275
+ })