interaqt 0.3.0 → 0.3.1
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/agent/.claude/agents/code-generation-handler.md +2 -0
- package/agent/.claude/agents/computation-generation-handler.md +1 -0
- package/agent/.claude/agents/implement-design-handler.md +4 -13
- package/agent/.claude/agents/requirements-analysis-handler.md +46 -14
- package/agent/agentspace/knowledge/generator/api-reference.md +3378 -0
- package/agent/agentspace/knowledge/generator/basic-interaction-generation.md +377 -0
- package/agent/agentspace/knowledge/generator/computation-analysis.md +307 -0
- package/agent/agentspace/knowledge/generator/computation-implementation.md +959 -0
- package/agent/agentspace/knowledge/generator/data-analysis.md +463 -0
- package/agent/agentspace/knowledge/generator/entity-relation-generation.md +395 -0
- package/agent/agentspace/knowledge/generator/permission-implementation.md +460 -0
- package/agent/agentspace/knowledge/generator/permission-test-implementation.md +870 -0
- package/agent/agentspace/knowledge/generator/test-implementation.md +674 -0
- package/agent/agentspace/knowledge/usage/00-mindset-shift.md +322 -0
- package/agent/agentspace/knowledge/usage/01-core-concepts.md +131 -0
- package/agent/agentspace/knowledge/usage/02-define-entities-properties.md +407 -0
- package/agent/agentspace/knowledge/usage/03-entity-relations.md +599 -0
- package/agent/agentspace/knowledge/usage/04-reactive-computations.md +2186 -0
- package/agent/agentspace/knowledge/usage/05-interactions.md +1411 -0
- package/agent/agentspace/knowledge/usage/06-attributive-permissions.md +10 -0
- package/agent/agentspace/knowledge/usage/07-payload-parameters.md +593 -0
- package/agent/agentspace/knowledge/usage/08-activities.md +863 -0
- package/agent/agentspace/knowledge/usage/09-filtered-entities.md +784 -0
- package/agent/agentspace/knowledge/usage/10-async-computations.md +734 -0
- package/agent/agentspace/knowledge/usage/11-global-dictionaries.md +942 -0
- package/agent/agentspace/knowledge/usage/12-data-querying.md +1033 -0
- package/agent/agentspace/knowledge/usage/13-testing.md +1201 -0
- package/agent/agentspace/knowledge/usage/14-api-reference.md +1606 -0
- package/agent/agentspace/knowledge/usage/15-entity-crud-patterns.md +1122 -0
- package/agent/agentspace/knowledge/usage/16-frontend-page-design-guide.md +485 -0
- package/agent/agentspace/knowledge/usage/17-performance-optimization.md +283 -0
- package/agent/agentspace/knowledge/usage/18-api-exports-reference.md +176 -0
- package/agent/agentspace/knowledge/usage/19-common-anti-patterns.md +563 -0
- package/agent/agentspace/knowledge/usage/README.md +148 -0
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Permission Control (Deprecated)
|
|
2
|
+
|
|
3
|
+
The `userAttributives` and `dataAttributives` permission control features have been removed from the interaqt framework.
|
|
4
|
+
|
|
5
|
+
For controlling access to interactions and data, please use:
|
|
6
|
+
- `conditions` parameter in Interaction.create() for execution conditions
|
|
7
|
+
- Application-level authentication and authorization (e.g., JWT, OAuth)
|
|
8
|
+
- Custom business logic in your interactions
|
|
9
|
+
|
|
10
|
+
The framework now focuses on reactive business logic rather than built-in permission control.
|
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
# How to Use Payload for Interaction Parameters
|
|
2
|
+
|
|
3
|
+
Payload is the core mechanism for defining and validating interaction parameters in interaqt. It allows you to declare what data an interaction accepts, enforce validation rules, and ensure type safety through the framework's reactive system.
|
|
4
|
+
|
|
5
|
+
## Understanding Payload and PayloadItem
|
|
6
|
+
|
|
7
|
+
### What is Payload
|
|
8
|
+
|
|
9
|
+
Payload defines the structure and validation rules for data that users pass to interactions. It consists of one or more PayloadItems, each representing a specific parameter.
|
|
10
|
+
|
|
11
|
+
```javascript
|
|
12
|
+
const CreatePost = Interaction.create({
|
|
13
|
+
name: 'CreatePost',
|
|
14
|
+
action: Action.create({ name: 'create' }),
|
|
15
|
+
payload: Payload.create({
|
|
16
|
+
items: [
|
|
17
|
+
PayloadItem.create({ name: 'title', required: true }),
|
|
18
|
+
PayloadItem.create({ name: 'content', required: true }),
|
|
19
|
+
PayloadItem.create({ name: 'tags', isCollection: true })
|
|
20
|
+
]
|
|
21
|
+
})
|
|
22
|
+
});
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### PayloadItem Structure
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
PayloadItem.create({
|
|
29
|
+
name: 'itemName', // Parameter name (required)
|
|
30
|
+
base: Entity, // Reference to Entity/Relation (optional)
|
|
31
|
+
isRef: true, // Whether it's a reference with id (default: false)
|
|
32
|
+
required: true, // Whether this parameter is required (default: false)
|
|
33
|
+
isCollection: true, // Whether it's an array (default: false)
|
|
34
|
+
attributives: Attributive, // Validation rules (optional)
|
|
35
|
+
itemRef: Entity // Reference to other concepts (optional)
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Basic Payload Usage
|
|
40
|
+
|
|
41
|
+
### Simple Parameters Without Entity Reference
|
|
42
|
+
|
|
43
|
+
When PayloadItem doesn't have a `base` property, the framework treats it as simple data without concept validation:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
const SendMessage = Interaction.create({
|
|
47
|
+
name: 'SendMessage',
|
|
48
|
+
action: Action.create({ name: 'send' }),
|
|
49
|
+
payload: Payload.create({
|
|
50
|
+
items: [
|
|
51
|
+
// Simple string parameter
|
|
52
|
+
PayloadItem.create({
|
|
53
|
+
name: 'message',
|
|
54
|
+
required: true
|
|
55
|
+
}),
|
|
56
|
+
// Simple number parameter
|
|
57
|
+
PayloadItem.create({
|
|
58
|
+
name: 'priority',
|
|
59
|
+
required: false
|
|
60
|
+
}),
|
|
61
|
+
// Array of strings
|
|
62
|
+
PayloadItem.create({
|
|
63
|
+
name: 'recipients',
|
|
64
|
+
isCollection: true,
|
|
65
|
+
required: true
|
|
66
|
+
})
|
|
67
|
+
]
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Usage:
|
|
72
|
+
await controller.callInteraction('SendMessage', {
|
|
73
|
+
user: currentUser,
|
|
74
|
+
payload: {
|
|
75
|
+
message: 'Hello World',
|
|
76
|
+
priority: 1,
|
|
77
|
+
recipients: ['user1@example.com', 'user2@example.com']
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Important**: When `base` is not specified, the framework only checks:
|
|
83
|
+
- Whether required parameters are present
|
|
84
|
+
- Whether collection parameters are arrays
|
|
85
|
+
- No concept validation or attributive checks are performed
|
|
86
|
+
|
|
87
|
+
### Parameters with Entity Reference
|
|
88
|
+
|
|
89
|
+
When PayloadItem has a `base` property pointing to an Entity, the framework provides additional validation:
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
const User = Entity.create({
|
|
93
|
+
name: 'User',
|
|
94
|
+
properties: [
|
|
95
|
+
Property.create({ name: 'name', type: 'string' }),
|
|
96
|
+
Property.create({ name: 'email', type: 'string' }),
|
|
97
|
+
Property.create({ name: 'status', type: 'string' })
|
|
98
|
+
]
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const Post = Entity.create({
|
|
102
|
+
name: 'Post',
|
|
103
|
+
properties: [
|
|
104
|
+
Property.create({ name: 'title', type: 'string' }),
|
|
105
|
+
Property.create({ name: 'content', type: 'string' }),
|
|
106
|
+
Property.create({ name: 'status', type: 'string' })
|
|
107
|
+
]
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const UpdatePost = Interaction.create({
|
|
111
|
+
name: 'UpdatePost',
|
|
112
|
+
action: Action.create({ name: 'update' }),
|
|
113
|
+
payload: Payload.create({
|
|
114
|
+
items: [
|
|
115
|
+
// Reference to existing post
|
|
116
|
+
PayloadItem.create({
|
|
117
|
+
name: 'post',
|
|
118
|
+
base: Post,
|
|
119
|
+
isRef: true, // Must have an id
|
|
120
|
+
required: true
|
|
121
|
+
}),
|
|
122
|
+
// New data (not a reference)
|
|
123
|
+
PayloadItem.create({
|
|
124
|
+
name: 'updates',
|
|
125
|
+
base: Post,
|
|
126
|
+
isRef: false, // New data without id
|
|
127
|
+
required: true
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
})
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Using isRef for Entity References
|
|
135
|
+
|
|
136
|
+
### isRef: true - Reference to Existing Entity
|
|
137
|
+
|
|
138
|
+
When `isRef` is true, the payload item must contain an `id` pointing to an existing entity:
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
const DeleteComment = Interaction.create({
|
|
142
|
+
name: 'DeleteComment',
|
|
143
|
+
action: Action.create({ name: 'delete' }),
|
|
144
|
+
payload: Payload.create({
|
|
145
|
+
items: [
|
|
146
|
+
PayloadItem.create({
|
|
147
|
+
name: 'comment',
|
|
148
|
+
base: Comment,
|
|
149
|
+
isRef: true, // Must reference existing comment
|
|
150
|
+
required: true
|
|
151
|
+
})
|
|
152
|
+
]
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Usage:
|
|
157
|
+
await controller.callInteraction('DeleteComment', {
|
|
158
|
+
user: currentUser,
|
|
159
|
+
payload: {
|
|
160
|
+
comment: { id: 'comment-123' } // Only id is required
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### isRef: false - Creating New Entity Data
|
|
166
|
+
|
|
167
|
+
When `isRef` is false and `base` is specified, the payload contains new entity data:
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
const CreateProduct = Interaction.create({
|
|
171
|
+
name: 'CreateProduct',
|
|
172
|
+
action: Action.create({ name: 'create' }),
|
|
173
|
+
payload: Payload.create({
|
|
174
|
+
items: [
|
|
175
|
+
PayloadItem.create({
|
|
176
|
+
name: 'product',
|
|
177
|
+
base: Product,
|
|
178
|
+
isRef: false, // New product data
|
|
179
|
+
required: true
|
|
180
|
+
})
|
|
181
|
+
]
|
|
182
|
+
})
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Usage:
|
|
186
|
+
await controller.callInteraction('CreateProduct', {
|
|
187
|
+
user: currentUser,
|
|
188
|
+
payload: {
|
|
189
|
+
product: {
|
|
190
|
+
name: 'New Product',
|
|
191
|
+
price: 99.99,
|
|
192
|
+
category: 'Electronics'
|
|
193
|
+
// No id - this is new data
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Collection Parameters
|
|
200
|
+
|
|
201
|
+
Use `isCollection: true` for array parameters:
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
const TagPosts = Interaction.create({
|
|
205
|
+
name: 'TagPosts',
|
|
206
|
+
action: Action.create({ name: 'tag' }),
|
|
207
|
+
payload: Payload.create({
|
|
208
|
+
items: [
|
|
209
|
+
// Array of post references
|
|
210
|
+
PayloadItem.create({
|
|
211
|
+
name: 'posts',
|
|
212
|
+
base: Post,
|
|
213
|
+
isRef: true,
|
|
214
|
+
isCollection: true,
|
|
215
|
+
required: true
|
|
216
|
+
}),
|
|
217
|
+
// Array of tag references
|
|
218
|
+
PayloadItem.create({
|
|
219
|
+
name: 'tags',
|
|
220
|
+
base: Tag,
|
|
221
|
+
isRef: true,
|
|
222
|
+
isCollection: true,
|
|
223
|
+
required: true
|
|
224
|
+
})
|
|
225
|
+
]
|
|
226
|
+
})
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Usage:
|
|
230
|
+
await controller.callInteraction('TagPosts', {
|
|
231
|
+
user: currentUser,
|
|
232
|
+
payload: {
|
|
233
|
+
posts: [
|
|
234
|
+
{ id: 'post-1' },
|
|
235
|
+
{ id: 'post-2' }
|
|
236
|
+
],
|
|
237
|
+
tags: [
|
|
238
|
+
{ id: 'tag-javascript' },
|
|
239
|
+
{ id: 'tag-react' }
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Payload Validation with Attributives
|
|
246
|
+
|
|
247
|
+
### Basic Attributive Validation
|
|
248
|
+
|
|
249
|
+
When PayloadItem has both `base` and `attributives`, the framework validates the payload data:
|
|
250
|
+
|
|
251
|
+
```javascript
|
|
252
|
+
// Define validation attributive
|
|
253
|
+
const PublishedPost = Attributive.create({
|
|
254
|
+
name: 'PublishedPost',
|
|
255
|
+
content: function(post, eventArgs) {
|
|
256
|
+
return post.status === 'published';
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
const SharePost = Interaction.create({
|
|
261
|
+
name: 'SharePost',
|
|
262
|
+
action: Action.create({ name: 'share' }),
|
|
263
|
+
payload: Payload.create({
|
|
264
|
+
items: [
|
|
265
|
+
PayloadItem.create({
|
|
266
|
+
name: 'post',
|
|
267
|
+
base: Post,
|
|
268
|
+
isRef: true,
|
|
269
|
+
required: true,
|
|
270
|
+
attributives: PublishedPost // Only published posts can be shared
|
|
271
|
+
})
|
|
272
|
+
]
|
|
273
|
+
})
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// This will succeed:
|
|
277
|
+
await controller.callInteraction('SharePost', {
|
|
278
|
+
user: currentUser,
|
|
279
|
+
payload: {
|
|
280
|
+
post: { id: 'published-post-id' }
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// This will fail validation:
|
|
285
|
+
await controller.callInteraction('SharePost', {
|
|
286
|
+
user: currentUser,
|
|
287
|
+
payload: {
|
|
288
|
+
post: { id: 'draft-post-id' } // Assuming this post has status: 'draft'
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Complex Validation with BoolExp
|
|
294
|
+
|
|
295
|
+
You can combine multiple attributives using BoolExp:
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
const ActiveTag = Attributive.create({
|
|
299
|
+
name: 'ActiveTag',
|
|
300
|
+
content: function(tag, eventArgs) {
|
|
301
|
+
return tag.isActive === true;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
const PopularTag = Attributive.create({
|
|
306
|
+
name: 'PopularTag',
|
|
307
|
+
content: function(tag, eventArgs) {
|
|
308
|
+
return tag.usageCount > 100;
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const AddTags = Interaction.create({
|
|
313
|
+
name: 'AddTags',
|
|
314
|
+
action: Action.create({ name: 'addTags' }),
|
|
315
|
+
payload: Payload.create({
|
|
316
|
+
items: [
|
|
317
|
+
PayloadItem.create({
|
|
318
|
+
name: 'tags',
|
|
319
|
+
base: Tag,
|
|
320
|
+
isRef: true,
|
|
321
|
+
isCollection: true,
|
|
322
|
+
// Tags must be both active AND popular
|
|
323
|
+
attributives: Attributives.create({
|
|
324
|
+
content: BoolExp.atom(ActiveTag).and(BoolExp.atom(PopularTag))
|
|
325
|
+
})
|
|
326
|
+
})
|
|
327
|
+
]
|
|
328
|
+
})
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Validation for Collections
|
|
333
|
+
|
|
334
|
+
When `isCollection` is true, attributives are checked for **every item** in the array:
|
|
335
|
+
|
|
336
|
+
```javascript
|
|
337
|
+
const VerifiedUser = Attributive.create({
|
|
338
|
+
name: 'VerifiedUser',
|
|
339
|
+
content: function(user, eventArgs) {
|
|
340
|
+
return user.isVerified === true;
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const InviteUsers = Interaction.create({
|
|
345
|
+
name: 'InviteUsers',
|
|
346
|
+
action: Action.create({ name: 'invite' }),
|
|
347
|
+
payload: Payload.create({
|
|
348
|
+
items: [
|
|
349
|
+
PayloadItem.create({
|
|
350
|
+
name: 'users',
|
|
351
|
+
base: User,
|
|
352
|
+
isRef: true,
|
|
353
|
+
isCollection: true,
|
|
354
|
+
attributives: VerifiedUser // ALL users must be verified
|
|
355
|
+
})
|
|
356
|
+
]
|
|
357
|
+
})
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// This will fail if ANY user in the array is not verified
|
|
361
|
+
await controller.callInteraction('InviteUsers', {
|
|
362
|
+
user: currentUser,
|
|
363
|
+
payload: {
|
|
364
|
+
users: [
|
|
365
|
+
{ id: 'verified-user-1' },
|
|
366
|
+
{ id: 'unverified-user' }, // This will cause validation to fail
|
|
367
|
+
{ id: 'verified-user-2' }
|
|
368
|
+
]
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Important Framework Behaviors
|
|
374
|
+
|
|
375
|
+
### When base is NOT specified
|
|
376
|
+
|
|
377
|
+
```javascript
|
|
378
|
+
PayloadItem.create({
|
|
379
|
+
name: 'customData',
|
|
380
|
+
required: true
|
|
381
|
+
// No base property
|
|
382
|
+
})
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Framework behavior:
|
|
386
|
+
- ✅ Checks if required parameter is present
|
|
387
|
+
- ✅ Checks if collection parameter is an array (when isCollection: true)
|
|
388
|
+
- ❌ Does NOT perform concept validation
|
|
389
|
+
- ❌ Does NOT check attributives
|
|
390
|
+
- ❌ Does NOT validate data structure
|
|
391
|
+
- **You must handle validation in your own logic**
|
|
392
|
+
|
|
393
|
+
### When base IS specified
|
|
394
|
+
|
|
395
|
+
```javascript
|
|
396
|
+
PayloadItem.create({
|
|
397
|
+
name: 'post',
|
|
398
|
+
base: Post, // Entity reference
|
|
399
|
+
isRef: true,
|
|
400
|
+
attributives: PublishedPost
|
|
401
|
+
})
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Framework behavior:
|
|
405
|
+
- ✅ Checks if required parameter is present
|
|
406
|
+
- ✅ Validates the data matches the concept (Entity/Relation)
|
|
407
|
+
- ✅ If isRef: true, verifies id exists and fetches full record
|
|
408
|
+
- ✅ If attributives exist, validates the data against them
|
|
409
|
+
- ✅ For collections, validates every item
|
|
410
|
+
|
|
411
|
+
### Payload Storage Behavior
|
|
412
|
+
|
|
413
|
+
When `isRef: false` and `base` is specified, the framework automatically stores the payload data:
|
|
414
|
+
|
|
415
|
+
```javascript
|
|
416
|
+
const CreateArticle = Interaction.create({
|
|
417
|
+
name: 'CreateArticle',
|
|
418
|
+
payload: Payload.create({
|
|
419
|
+
items: [
|
|
420
|
+
PayloadItem.create({
|
|
421
|
+
name: 'article',
|
|
422
|
+
base: Article,
|
|
423
|
+
isRef: false // New data will be stored
|
|
424
|
+
})
|
|
425
|
+
]
|
|
426
|
+
})
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// The article data will be automatically saved to storage
|
|
430
|
+
// and the saved record (with id) will be available in the interaction event
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Best Practices
|
|
434
|
+
|
|
435
|
+
### 1. Use Appropriate Validation Level
|
|
436
|
+
|
|
437
|
+
```javascript
|
|
438
|
+
// ✅ Good: Use base for entity-related data
|
|
439
|
+
PayloadItem.create({
|
|
440
|
+
name: 'targetUser',
|
|
441
|
+
base: User,
|
|
442
|
+
isRef: true,
|
|
443
|
+
attributives: ActiveUser
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
// ✅ Good: Simple parameters without base
|
|
447
|
+
PayloadItem.create({
|
|
448
|
+
name: 'searchQuery',
|
|
449
|
+
required: true
|
|
450
|
+
// No base needed for simple strings
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
// ❌ Bad: Over-engineering simple parameters
|
|
454
|
+
PayloadItem.create({
|
|
455
|
+
name: 'pageNumber',
|
|
456
|
+
base: SomeNumberEntity, // Unnecessary
|
|
457
|
+
isRef: false
|
|
458
|
+
})
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### 2. Clear Naming and Documentation
|
|
462
|
+
|
|
463
|
+
```javascript
|
|
464
|
+
const UpdateUserProfile = Interaction.create({
|
|
465
|
+
name: 'UpdateUserProfile',
|
|
466
|
+
payload: Payload.create({
|
|
467
|
+
items: [
|
|
468
|
+
PayloadItem.create({
|
|
469
|
+
name: 'user', // Clear: which user
|
|
470
|
+
base: User,
|
|
471
|
+
isRef: true,
|
|
472
|
+
required: true
|
|
473
|
+
}),
|
|
474
|
+
PayloadItem.create({
|
|
475
|
+
name: 'profileData', // Clear: what data
|
|
476
|
+
base: UserProfile,
|
|
477
|
+
isRef: false,
|
|
478
|
+
required: true
|
|
479
|
+
}),
|
|
480
|
+
PayloadItem.create({
|
|
481
|
+
name: 'notifyFollowers', // Clear: simple flag
|
|
482
|
+
required: false
|
|
483
|
+
// Boolean flag, no base needed
|
|
484
|
+
})
|
|
485
|
+
]
|
|
486
|
+
})
|
|
487
|
+
});
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### 3. Consistent Validation Patterns
|
|
491
|
+
|
|
492
|
+
```javascript
|
|
493
|
+
// Define reusable attributives
|
|
494
|
+
const CanBeEdited = Attributive.create({
|
|
495
|
+
name: 'CanBeEdited',
|
|
496
|
+
content: function(item, eventArgs) {
|
|
497
|
+
return item.status !== 'locked' &&
|
|
498
|
+
item.createdBy === eventArgs.user.id;
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
// Use consistently across interactions
|
|
503
|
+
const EditPost = Interaction.create({
|
|
504
|
+
payload: Payload.create({
|
|
505
|
+
items: [
|
|
506
|
+
PayloadItem.create({
|
|
507
|
+
name: 'post',
|
|
508
|
+
base: Post,
|
|
509
|
+
isRef: true,
|
|
510
|
+
attributives: CanBeEdited
|
|
511
|
+
})
|
|
512
|
+
]
|
|
513
|
+
})
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
const EditComment = Interaction.create({
|
|
517
|
+
payload: Payload.create({
|
|
518
|
+
items: [
|
|
519
|
+
PayloadItem.create({
|
|
520
|
+
name: 'comment',
|
|
521
|
+
base: Comment,
|
|
522
|
+
isRef: true,
|
|
523
|
+
attributives: CanBeEdited
|
|
524
|
+
})
|
|
525
|
+
]
|
|
526
|
+
})
|
|
527
|
+
});
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### 4. Handle Validation Errors Gracefully
|
|
531
|
+
|
|
532
|
+
```javascript
|
|
533
|
+
// In your application code
|
|
534
|
+
try {
|
|
535
|
+
const result = await controller.callInteraction('SharePost', {
|
|
536
|
+
user: currentUser,
|
|
537
|
+
payload: { post: { id: postId } }
|
|
538
|
+
});
|
|
539
|
+
} catch (error) {
|
|
540
|
+
if (error instanceof AttributeError) {
|
|
541
|
+
if (error.type === 'post not match attributive') {
|
|
542
|
+
// Handle validation failure
|
|
543
|
+
console.error('Cannot share: Post is not published');
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
## Known Issues and Workarounds
|
|
550
|
+
|
|
551
|
+
### Entity Resolution with Circular Dependencies
|
|
552
|
+
|
|
553
|
+
In some cases, using entity references in PayloadItem can cause resolution issues, particularly when entities have circular dependencies:
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
// May cause "entity undefined not found" error
|
|
557
|
+
PayloadItem.create({
|
|
558
|
+
name: 'version',
|
|
559
|
+
base: Version, // Entity with circular dependencies
|
|
560
|
+
isRef: false
|
|
561
|
+
})
|
|
562
|
+
|
|
563
|
+
// Workaround: Use generic object type
|
|
564
|
+
// do not set base property to avoids resolution issues
|
|
565
|
+
PayloadItem.create({
|
|
566
|
+
name: 'version',
|
|
567
|
+
isRef: false
|
|
568
|
+
})
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
This issue typically occurs when:
|
|
572
|
+
- Entities reference each other in complex ways
|
|
573
|
+
- The entity being referenced has forward references
|
|
574
|
+
- The interaction is defined before all entities are fully initialized
|
|
575
|
+
|
|
576
|
+
NOT setting base property maintains the same functionality but avoids the resolution problem, though you lose framework-level validation.
|
|
577
|
+
|
|
578
|
+
## Summary
|
|
579
|
+
|
|
580
|
+
The Payload system in interaqt provides a powerful way to:
|
|
581
|
+
- Define structured interaction parameters
|
|
582
|
+
- Enforce validation rules through attributives
|
|
583
|
+
- Ensure type safety with entity references
|
|
584
|
+
- Handle both simple data and complex entity relationships
|
|
585
|
+
|
|
586
|
+
Key points to remember:
|
|
587
|
+
- **With base**: Framework handles validation and attributive checks
|
|
588
|
+
- **Without base**: You handle validation in your own logic
|
|
589
|
+
- **isRef**: Distinguishes between references and new data
|
|
590
|
+
- **attributives**: Only work when base is specified
|
|
591
|
+
- **isCollection**: Validates every item in arrays
|
|
592
|
+
|
|
593
|
+
By properly using Payload and PayloadItem, you can build robust, type-safe interactions that validate data at the framework level, reducing the need for manual validation code and improving system reliability.
|