interaqt 2.0.4 → 3.0.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.
Files changed (69) hide show
  1. package/README.md +1 -1
  2. package/agent/agentspace/knowledge/generator/api-reference.md +2 -9
  3. package/agent/agentspace/knowledge/generator/permission-test-implementation.md +18 -0
  4. package/agent/agentspace/knowledge/generator/test-implementation.md +6 -5
  5. package/agent/agentspace/knowledge/usage/02-define-entities-properties.md +11 -6
  6. package/agent/agentspace/knowledge/usage/04-reactive-computations.md +6 -1
  7. package/agent/agentspace/knowledge/usage/05-interactions.md +51 -60
  8. package/agent/agentspace/knowledge/usage/06-attributive-permissions.md +54 -7
  9. package/agent/agentspace/knowledge/usage/07-payload-parameters.md +95 -72
  10. package/agent/agentspace/knowledge/usage/11-global-dictionaries.md +13 -14
  11. package/agent/agentspace/knowledge/usage/13-testing.md +2 -2
  12. package/agent/agentspace/knowledge/usage/14-api-reference.md +24 -66
  13. package/agent/agentspace/knowledge/usage/16-frontend-page-design-guide.md +3 -3
  14. package/agent/agentspace/knowledge/usage/18-api-exports-reference.md +2 -5
  15. package/agent/agentspace/knowledge/usage/README.md +2 -2
  16. package/agent/skill/interaqt-reference.md +6 -18
  17. package/dist/builtins/interaction/Condition.d.ts.map +1 -1
  18. package/dist/builtins/interaction/Interaction.d.ts +1 -22
  19. package/dist/builtins/interaction/Interaction.d.ts.map +1 -1
  20. package/dist/builtins/interaction/PayloadItem.d.ts +5 -14
  21. package/dist/builtins/interaction/PayloadItem.d.ts.map +1 -1
  22. package/dist/builtins/interaction/activity/ActivityCall.d.ts +2 -5
  23. package/dist/builtins/interaction/activity/ActivityCall.d.ts.map +1 -1
  24. package/dist/builtins/interaction/activity/ActivityManager.d.ts.map +1 -1
  25. package/dist/builtins/interaction/index.d.ts +0 -2
  26. package/dist/builtins/interaction/index.d.ts.map +1 -1
  27. package/dist/core/interfaces.d.ts +0 -12
  28. package/dist/core/interfaces.d.ts.map +1 -1
  29. package/dist/drivers/Mysql.d.ts +1 -0
  30. package/dist/drivers/Mysql.d.ts.map +1 -1
  31. package/dist/drivers/PGLite.d.ts +1 -0
  32. package/dist/drivers/PGLite.d.ts.map +1 -1
  33. package/dist/drivers/PostgreSQL.d.ts +1 -0
  34. package/dist/drivers/PostgreSQL.d.ts.map +1 -1
  35. package/dist/drivers/SQLite.d.ts +1 -0
  36. package/dist/drivers/SQLite.d.ts.map +1 -1
  37. package/dist/drivers.js +15 -5
  38. package/dist/drivers.js.map +1 -1
  39. package/dist/index.js +2464 -2606
  40. package/dist/index.js.map +1 -1
  41. package/dist/runtime/Controller.d.ts +12 -0
  42. package/dist/runtime/Controller.d.ts.map +1 -1
  43. package/dist/runtime/MonoSystem.d.ts.map +1 -1
  44. package/dist/runtime/Scheduler.d.ts +16 -0
  45. package/dist/runtime/Scheduler.d.ts.map +1 -1
  46. package/dist/runtime/System.d.ts +1 -0
  47. package/dist/runtime/System.d.ts.map +1 -1
  48. package/dist/runtime/computations/Custom.d.ts.map +1 -1
  49. package/dist/runtime/computations/StateMachine.d.ts +2 -0
  50. package/dist/runtime/computations/StateMachine.d.ts.map +1 -1
  51. package/dist/runtime/computations/Transform.d.ts.map +1 -1
  52. package/dist/runtime/computations/TransitionFinder.d.ts.map +1 -1
  53. package/dist/runtime/computations/aggregationTemplate.d.ts.map +1 -1
  54. package/dist/runtime/errors/ConditionErrors.d.ts +2 -5
  55. package/dist/runtime/errors/ConditionErrors.d.ts.map +1 -1
  56. package/dist/runtime/migration.d.ts.map +1 -1
  57. package/dist/runtime/transaction.d.ts.map +1 -1
  58. package/dist/storage/erstorage/EntityToTableMap.d.ts.map +1 -1
  59. package/dist/storage/erstorage/MatchExp.d.ts.map +1 -1
  60. package/dist/storage/erstorage/Modifier.d.ts.map +1 -1
  61. package/dist/storage/erstorage/QueryExecutor.d.ts.map +1 -1
  62. package/dist/storage/erstorage/SchemaDialect.d.ts +1 -0
  63. package/dist/storage/erstorage/SchemaDialect.d.ts.map +1 -1
  64. package/dist/storage/erstorage/Setup.d.ts.map +1 -1
  65. package/package.json +1 -1
  66. package/dist/builtins/interaction/Attributive.d.ts +0 -91
  67. package/dist/builtins/interaction/Attributive.d.ts.map +0 -1
  68. package/dist/builtins/interaction/User.d.ts +0 -10
  69. package/dist/builtins/interaction/User.d.ts.map +0 -1
@@ -27,15 +27,16 @@ const CreatePost = Interaction.create({
27
27
  ```javascript
28
28
  PayloadItem.create({
29
29
  name: 'itemName', // Parameter name (required)
30
+ type: 'string', // Primitive type check (optional)
30
31
  base: Entity, // Reference to Entity/Relation (optional)
31
32
  isRef: true, // Whether it's a reference with id (default: false)
32
33
  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)
34
+ isCollection: true // Whether it's an array (default: false)
36
35
  })
37
36
  ```
38
37
 
38
+ To validate payload **contents** (e.g. "only published posts can be shared"), write the check as a `Condition` on the Interaction — see [Payload Validation with Conditions](#payload-validation-with-conditions) below.
39
+
39
40
  ## Basic Payload Usage
40
41
 
41
42
  ### Simple Parameters Without Entity Reference
@@ -82,7 +83,7 @@ await controller.callInteraction('SendMessage', {
82
83
  **Important**: When `base` is not specified, the framework only checks:
83
84
  - Whether required parameters are present
84
85
  - Whether collection parameters are arrays
85
- - No concept validation or attributive checks are performed
86
+ - No concept validation is performed
86
87
 
87
88
  ### Parameters with Entity Reference
88
89
 
@@ -242,18 +243,23 @@ await controller.callInteraction('TagPosts', {
242
243
  });
243
244
  ```
244
245
 
245
- ## Payload Validation with Attributives
246
+ ## Payload Validation with Conditions
246
247
 
247
- ### Basic Attributive Validation
248
+ Payload content checks are written as `Condition`s on the Interaction. A condition callback receives the full event args (`user`, `payload`, `query`, `activityId`) with the Controller as `this`, so it can read the payload and query storage. It must return a strict boolean — any non-boolean result fails the check (fail-closed).
248
249
 
249
- When PayloadItem has both `base` and `attributives`, the framework validates the payload data:
250
+ ### Basic Condition Validation
250
251
 
251
252
  ```javascript
252
- // Define validation attributive
253
- const PublishedPost = Attributive.create({
254
- name: 'PublishedPost',
255
- content: function(post, eventArgs) {
256
- return post.status === 'published';
253
+ // Define validation condition
254
+ const PublishedPostOnly = Condition.create({
255
+ name: 'PublishedPostOnly',
256
+ content: async function(event) {
257
+ const post = await this.system.storage.findOne('Post',
258
+ MatchExp.atom({ key: 'id', value: ['=', event.payload.post.id] }),
259
+ undefined,
260
+ ['status']
261
+ );
262
+ return post?.status === 'published';
257
263
  }
258
264
  });
259
265
 
@@ -266,11 +272,11 @@ const SharePost = Interaction.create({
266
272
  name: 'post',
267
273
  base: Post,
268
274
  isRef: true,
269
- required: true,
270
- attributives: PublishedPost // Only published posts can be shared
275
+ required: true
271
276
  })
272
277
  ]
273
- })
278
+ }),
279
+ conditions: PublishedPostOnly // Only published posts can be shared
274
280
  });
275
281
 
276
282
  // This will succeed:
@@ -292,20 +298,30 @@ await controller.callInteraction('SharePost', {
292
298
 
293
299
  ### Complex Validation with BoolExp
294
300
 
295
- You can combine multiple attributives using BoolExp:
301
+ You can combine multiple conditions using `Conditions.create` and BoolExp:
296
302
 
297
303
  ```javascript
298
- const ActiveTag = Attributive.create({
299
- name: 'ActiveTag',
300
- content: function(tag, eventArgs) {
301
- return tag.isActive === true;
304
+ const TagsAreActive = Condition.create({
305
+ name: 'TagsAreActive',
306
+ content: async function(event) {
307
+ const tags = await this.system.storage.find('Tag',
308
+ MatchExp.atom({ key: 'id', value: ['in', event.payload.tags.map(tag => tag.id)] }),
309
+ undefined,
310
+ ['isActive']
311
+ );
312
+ return tags.every(tag => tag.isActive === true);
302
313
  }
303
314
  });
304
315
 
305
- const PopularTag = Attributive.create({
306
- name: 'PopularTag',
307
- content: function(tag, eventArgs) {
308
- return tag.usageCount > 100;
316
+ const TagsArePopular = Condition.create({
317
+ name: 'TagsArePopular',
318
+ content: async function(event) {
319
+ const tags = await this.system.storage.find('Tag',
320
+ MatchExp.atom({ key: 'id', value: ['in', event.payload.tags.map(tag => tag.id)] }),
321
+ undefined,
322
+ ['usageCount']
323
+ );
324
+ return tags.every(tag => tag.usageCount > 100);
309
325
  }
310
326
  });
311
327
 
@@ -318,26 +334,32 @@ const AddTags = Interaction.create({
318
334
  name: 'tags',
319
335
  base: Tag,
320
336
  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
- })
337
+ isCollection: true
326
338
  })
327
339
  ]
340
+ }),
341
+ // Tags must be both active AND popular
342
+ conditions: Conditions.create({
343
+ content: BoolExp.atom(TagsAreActive).and(TagsArePopular)
328
344
  })
329
345
  });
330
346
  ```
331
347
 
332
348
  ### Validation for Collections
333
349
 
334
- When `isCollection` is true, attributives are checked for **every item** in the array:
350
+ When a payload item is a collection, write the condition to check **every item** in the array:
335
351
 
336
352
  ```javascript
337
- const VerifiedUser = Attributive.create({
338
- name: 'VerifiedUser',
339
- content: function(user, eventArgs) {
340
- return user.isVerified === true;
353
+ const AllUsersVerified = Condition.create({
354
+ name: 'AllUsersVerified',
355
+ content: async function(event) {
356
+ const users = await this.system.storage.find('User',
357
+ MatchExp.atom({ key: 'id', value: ['in', event.payload.users.map(user => user.id)] }),
358
+ undefined,
359
+ ['isVerified']
360
+ );
361
+ return users.length === event.payload.users.length &&
362
+ users.every(user => user.isVerified === true);
341
363
  }
342
364
  });
343
365
 
@@ -350,11 +372,11 @@ const InviteUsers = Interaction.create({
350
372
  name: 'users',
351
373
  base: User,
352
374
  isRef: true,
353
- isCollection: true,
354
- attributives: VerifiedUser // ALL users must be verified
375
+ isCollection: true
355
376
  })
356
377
  ]
357
- })
378
+ }),
379
+ conditions: AllUsersVerified // ALL users must be verified
358
380
  });
359
381
 
360
382
  // This will fail if ANY user in the array is not verified
@@ -386,9 +408,8 @@ Framework behavior:
386
408
  - ✅ Checks if required parameter is present
387
409
  - ✅ Checks if collection parameter is an array (when isCollection: true)
388
410
  - ❌ Does NOT perform concept validation
389
- - ❌ Does NOT check attributives
390
411
  - ❌ Does NOT validate data structure
391
- - **You must handle validation in your own logic**
412
+ - **You must handle validation in your own logic (e.g. through conditions)**
392
413
 
393
414
  ### When base IS specified
394
415
 
@@ -396,8 +417,7 @@ Framework behavior:
396
417
  PayloadItem.create({
397
418
  name: 'post',
398
419
  base: Post, // Entity reference
399
- isRef: true,
400
- attributives: PublishedPost
420
+ isRef: true
401
421
  })
402
422
  ```
403
423
 
@@ -405,8 +425,8 @@ Framework behavior:
405
425
  - ✅ Checks if required parameter is present
406
426
  - ✅ Validates the data matches the concept (Entity/Relation)
407
427
  - ✅ 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
428
+ - ✅ For collections, validates every item against the concept
429
+ - Content-level rules (e.g. "post must be published") are expressed as conditions on the Interaction
410
430
 
411
431
  ### Payload Storage Behavior
412
432
 
@@ -436,11 +456,11 @@ const CreateArticle = Interaction.create({
436
456
 
437
457
  ```javascript
438
458
  // ✅ Good: Use base for entity-related data
459
+ // (content rules like "user must be active" go into the interaction's conditions)
439
460
  PayloadItem.create({
440
461
  name: 'targetUser',
441
462
  base: User,
442
- isRef: true,
443
- attributives: ActiveUser
463
+ isRef: true
444
464
  })
445
465
 
446
466
  // ✅ Good: Simple parameters without base
@@ -490,12 +510,17 @@ const UpdateUserProfile = Interaction.create({
490
510
  ### 3. Consistent Validation Patterns
491
511
 
492
512
  ```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;
513
+ // Define a reusable condition factory
514
+ const canBeEdited = (entityName, payloadKey) => Condition.create({
515
+ name: `${entityName}CanBeEdited`,
516
+ content: async function(event) {
517
+ const item = await this.system.storage.findOne(entityName,
518
+ MatchExp.atom({ key: 'id', value: ['=', event.payload[payloadKey].id] }),
519
+ undefined,
520
+ ['status', 'createdBy']
521
+ );
522
+ return !!item && item.status !== 'locked' &&
523
+ item.createdBy === event.user.id;
499
524
  }
500
525
  });
501
526
 
@@ -506,11 +531,11 @@ const EditPost = Interaction.create({
506
531
  PayloadItem.create({
507
532
  name: 'post',
508
533
  base: Post,
509
- isRef: true,
510
- attributives: CanBeEdited
534
+ isRef: true
511
535
  })
512
536
  ]
513
- })
537
+ }),
538
+ conditions: canBeEdited('Post', 'post')
514
539
  });
515
540
 
516
541
  const EditComment = Interaction.create({
@@ -519,11 +544,11 @@ const EditComment = Interaction.create({
519
544
  PayloadItem.create({
520
545
  name: 'comment',
521
546
  base: Comment,
522
- isRef: true,
523
- attributives: CanBeEdited
547
+ isRef: true
524
548
  })
525
549
  ]
526
- })
550
+ }),
551
+ conditions: canBeEdited('Comment', 'comment')
527
552
  });
528
553
  ```
529
554
 
@@ -531,17 +556,15 @@ const EditComment = Interaction.create({
531
556
 
532
557
  ```javascript
533
558
  // 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
- }
559
+ const result = await controller.callInteraction('SharePost', {
560
+ user: currentUser,
561
+ payload: { post: { id: postId } }
562
+ });
563
+
564
+ if (result.error) {
565
+ if (result.error.type === 'condition check failed') {
566
+ // Handle validation failure; result.error.error.data.name is the failing condition
567
+ console.error('Cannot share: Post is not published');
545
568
  }
546
569
  }
547
570
  ```
@@ -579,15 +602,15 @@ NOT setting base property maintains the same functionality but avoids the resolu
579
602
 
580
603
  The Payload system in interaqt provides a powerful way to:
581
604
  - Define structured interaction parameters
582
- - Enforce validation rules through attributives
605
+ - Enforce content validation rules through conditions
583
606
  - Ensure type safety with entity references
584
607
  - Handle both simple data and complex entity relationships
585
608
 
586
609
  Key points to remember:
587
- - **With base**: Framework handles validation and attributive checks
610
+ - **With base**: Framework handles concept validation and reference resolution
588
611
  - **Without base**: You handle validation in your own logic
589
612
  - **isRef**: Distinguishes between references and new data
590
- - **attributives**: Only work when base is specified
591
- - **isCollection**: Validates every item in arrays
613
+ - **conditions**: Payload content rules live on the Interaction, not on PayloadItem
614
+ - **isCollection**: Validates every item in arrays against the concept
592
615
 
593
616
  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.
@@ -470,6 +470,16 @@ async function setDefaultConfig() {
470
470
  ### 10.4.3 Conditional Logic Based on Dictionaries
471
471
 
472
472
  ```typescript
473
+ // Use Condition to control permissions based on dictionary values
474
+ const MaxUsersNotReached = Condition.create({
475
+ name: 'MaxUsersNotReached',
476
+ content: async function(this: Controller, event) {
477
+ const currentUserCount = await this.system.storage.get('state', 'totalUsers');
478
+ const maxUsers = await this.system.storage.get('state', 'maxUsers');
479
+ return currentUserCount < maxUsers;
480
+ }
481
+ });
482
+
473
483
  // Using dictionary values for conditional logic in interactions
474
484
  const createUserInteraction = Interaction.create({
475
485
  name: 'createUser',
@@ -481,21 +491,10 @@ const createUserInteraction = Interaction.create({
481
491
  base: userEntity
482
492
  })
483
493
  ]
484
- })
494
+ }),
495
+ // Dictionary-based permission control
496
+ conditions: MaxUsersNotReached
485
497
  });
486
-
487
- // Use Attributive to control permissions based on dictionary values
488
- const MaxUsersReachedAttributive = Attributive.create({
489
- name: 'MaxUsersNotReached',
490
- content: async function(context: any) {
491
- const currentUserCount = await context.system.storage.get('state', 'totalUsers');
492
- const maxUsers = await context.system.storage.get('state', 'maxUsers');
493
- return currentUserCount < maxUsers;
494
- }
495
- });
496
-
497
- // Add dictionary-based permission control to interaction
498
- createUserInteraction.attributives = [MaxUsersReachedAttributive];
499
498
  ```
500
499
 
501
500
  ### 10.4.4 Combining Dictionaries with Computations
@@ -645,11 +645,11 @@ describe('Approval Process Activity', () => {
645
645
  });
646
646
  ```
647
647
 
648
- ## 12.3 Testing Permissions and Attributives
648
+ ## 12.3 Testing Permissions (Conditions)
649
649
 
650
650
  > **Important: Correct Error Handling Approach**
651
651
  >
652
- > The interaqt framework automatically catches all errors (including Attributive validation failures, insufficient permissions, etc.) and returns error information through the `error` field in the return value. The framework **does not throw uncaught exceptions**.
652
+ > The interaqt framework automatically catches all errors (including condition check failures, insufficient permissions, etc.) and returns error information through the `error` field in the return value. The framework **does not throw uncaught exceptions**.
653
653
  >
654
654
  > Therefore, when writing tests:
655
655
  > - ✅ **Correct approach**: Check the `error` field in the return value
@@ -1124,17 +1124,18 @@ PayloadItem.create(config: PayloadItemConfig): KlassInstance<typeof PayloadItem>
1124
1124
 
1125
1125
  **Parameters**
1126
1126
  - `config.name` (string, required): Parameter name
1127
- - `config.base` (Entity, optional): Parameter entity type, only needed when isRef is true
1127
+ - `config.type` (string, optional): Primitive type check ('string', 'number', 'boolean', 'object')
1128
+ - `config.base` (Entity|Relation, optional): Parameter entity type, only needed when isRef is true
1128
1129
  - `config.isRef` (boolean, optional): Whether it's a reference type, defaults to false
1129
1130
  - `config.required` (boolean, optional): Whether it's required, defaults to false
1130
1131
  - `config.isCollection` (boolean, optional): Whether it's a collection type, defaults to false
1131
- - `config.attributives` (Attributive|Attributives, optional): Parameter permission attributives
1132
- - `config.itemRef` (Attributive|Entity, optional): Used to reference entities defined in other interactions within Activity
1132
+
1133
+ Payload **content** validation (e.g. "post must have title and content") is expressed as `conditions` on the Interaction see Condition.create().
1133
1134
 
1134
1135
  **Examples**
1135
1136
  ```typescript
1136
1137
  // Reference existing user
1137
- const userRef = PayloadItem.create({
1138
+ const userItem = PayloadItem.create({
1138
1139
  name: 'user',
1139
1140
  base: User,
1140
1141
  isRef: true,
@@ -1145,13 +1146,15 @@ const userRef = PayloadItem.create({
1145
1146
  const postData = PayloadItem.create({
1146
1147
  name: 'postData',
1147
1148
  base: Post,
1148
- required: true,
1149
- attributives: Attributive.create({
1150
- name: 'ValidPost',
1151
- content: function(post) {
1152
- return post.title && post.content
1153
- }
1154
- })
1149
+ required: true
1150
+ })
1151
+
1152
+ // Content validation goes on the Interaction's conditions
1153
+ const ValidPost = Condition.create({
1154
+ name: 'ValidPost',
1155
+ content: async function(event) {
1156
+ return !!(event.payload.postData.title && event.payload.postData.content)
1157
+ }
1155
1158
  })
1156
1159
 
1157
1160
  // Collection type reference
@@ -1159,19 +1162,7 @@ const reviewersItem = PayloadItem.create({
1159
1162
  name: 'reviewers',
1160
1163
  base: User,
1161
1164
  isRef: true,
1162
- isCollection: true,
1163
- attributives: Attributives.create({
1164
- content: BoolAtomData.create({data: ReviewerAttr, type: 'atom'})
1165
- })
1166
- })
1167
-
1168
- // Activity item reference
1169
- const activityItem = PayloadItem.create({
1170
- name: 'to',
1171
- base: User,
1172
- isRef: true,
1173
- attributives: boolExpToAttributives(BoolExp.atom(OtherAttr)),
1174
- itemRef: userRefB
1165
+ isCollection: true
1175
1166
  })
1176
1167
  ```
1177
1168
 
@@ -1244,7 +1235,7 @@ const ApprovalTransfer = Transfer.create({
1244
1235
 
1245
1236
  ### Condition.create()
1246
1237
 
1247
- Create activity execution condition.
1238
+ Create an execution condition — the single guard concept for interactions (permission checks, payload content checks, activity user binding).
1248
1239
 
1249
1240
  **Syntax**
1250
1241
  ```typescript
@@ -1253,16 +1244,21 @@ Condition.create(config: ConditionConfig): KlassInstance<typeof Condition>
1253
1244
 
1254
1245
  **Parameters**
1255
1246
  - `config.name` (string, required): Condition name
1256
- - `config.content` (function, required): Condition judgment function
1247
+ - `config.content` (function, required): Condition judgment function. Called with the Controller as `this` and the full event args (`user`, `payload`, `query`, `activityId`). Must return a strict boolean — any non-boolean result fails the check (fail-closed).
1257
1248
 
1258
1249
  **Examples**
1259
1250
  ```typescript
1260
1251
  const OrderValueCondition = Condition.create({
1261
1252
  name: 'highValueOrder',
1262
- content: function(order) {
1263
- return order.totalAmount > 1000
1253
+ content: async function(event) {
1254
+ return event.payload.order.totalAmount > 1000
1264
1255
  }
1265
1256
  })
1257
+
1258
+ // Combine multiple conditions with Conditions.create + BoolExp
1259
+ const AdminHighValueOrder = Conditions.create({
1260
+ content: BoolExp.atom(AdminOnly).and(OrderValueCondition)
1261
+ })
1266
1262
  ```
1267
1263
 
1268
1264
  ## 13.5 System-Related APIs
@@ -1476,44 +1472,6 @@ const condition = MatchExp.fromObject({
1476
1472
  // Equivalent to: status='active' AND age=25 AND city='Beijing'
1477
1473
  ```
1478
1474
 
1479
- ### Attributive.create()
1480
-
1481
- Create permission attributive for access control.
1482
-
1483
- **Syntax**
1484
- ```typescript
1485
- Attributive.create(config: AttributiveConfig): KlassInstance<typeof Attributive>
1486
- ```
1487
-
1488
- **Parameters**
1489
- - `config.name` (string, optional): Attributive name
1490
- - `config.content` (function, required): Permission judgment function
1491
- - `config.isRef` (boolean, optional): Whether it's a reference
1492
-
1493
- **Examples**
1494
- ```typescript
1495
- // Admin permission
1496
- const AdminAttributive = Attributive.create({
1497
- name: 'Admin',
1498
- content: function(target, { user }) {
1499
- return user.role === 'admin'
1500
- }
1501
- })
1502
-
1503
- // Resource owner permission
1504
- const OwnerAttributive = Attributive.create({
1505
- name: 'Owner',
1506
- content: function(target, { user }) {
1507
- return target.userId === user.id
1508
- }
1509
- })
1510
-
1511
- // Combined permissions (using BoolExp)
1512
- const AdminOrOwnerAttributives = boolExpToAttributives(
1513
- BoolExp.atom(AdminAttributive).or(OwnerAttributive)
1514
- )
1515
- ```
1516
-
1517
1475
  ### BoolExp
1518
1476
 
1519
1477
  Boolean expression builder for constructing complex logical expressions.
@@ -14,7 +14,7 @@ This document guides how to systematically design frontend page architecture and
14
14
  ### 2. Reactive Data Display
15
15
  - **Reactive Computations**: All properties with `computation` should be displayed in real-time in the interface
16
16
  - **State-Aware**: Dynamically display different operation options based on entity state
17
- - **Permission Control**: Control interface element visibility based on Attributive definitions
17
+ - **Permission Control**: Control interface element visibility based on Condition definitions
18
18
 
19
19
  ### 3. User Experience Consistency
20
20
  - **Operation Feedback**: Every interaction operation should have clear feedback
@@ -191,7 +191,7 @@ Operation History Area (Optional)
191
191
  ```
192
192
 
193
193
  #### 2.2 Design Points
194
- - **Permission Control**: Dynamically display action buttons based on Attributive
194
+ - **Permission Control**: Dynamically display action buttons based on Condition
195
195
  - **State Awareness**: Display different operation options based on entity state
196
196
  - **Association Display**: Reasonably display associated entities, avoid information overload
197
197
  - **Operation Feedback**: Clear operation result notifications
@@ -340,7 +340,7 @@ For properties containing `computation`:
340
340
  - **Transition Hints**: Display possible state transition operations
341
341
 
342
342
  #### 2.2 Conditional Operation Display
343
- Based on permission control defined by Attributive:
343
+ Based on permission control defined by Condition:
344
344
  - **Dynamic Buttons**: Dynamically display action buttons based on permissions
345
345
  - **Disabled States**: Show disabled operations when conditions aren't met
346
346
  - **Permission Hints**: Explain why certain operations are unavailable
@@ -40,9 +40,7 @@ import {
40
40
  RealTime,
41
41
  MathResolver,
42
42
 
43
- // Attributive and Conditions
44
- Attributive,
45
- Attributives,
43
+ // Conditions
46
44
  Condition,
47
45
  Conditions,
48
46
 
@@ -95,8 +93,7 @@ import {
95
93
  RelationBasedEvery, // Only 'Every' exists
96
94
  InteractionEvent, // Correct name is 'InteractionEventEntity'
97
95
  FilteredEntity, // Created via Entity.create with baseEntity
98
- SideEffect, // Not a direct export
99
- DataAttributive // Use Attributive for all purposes
96
+ SideEffect // Not a direct export
100
97
  } from 'interaqt';
101
98
  ```
102
99
 
@@ -22,7 +22,7 @@ Master declarative data computation.
22
22
  ### 6. 🎮 [Interactions](./05-interactions.md)
23
23
  Learn how to define user interactions (Remember: Action is just an identifier!).
24
24
 
25
- ### 7. 🔐 [Attributive Permissions](./06-attributive-permissions.md)
25
+ ### 7. 🔐 [Permission Control (Conditions)](./06-attributive-permissions.md)
26
26
  Understand how to control access permissions.
27
27
 
28
28
  ### 8. 📦 [Payload Parameters](./07-payload-parameters.md)
@@ -124,7 +124,7 @@ Remember: **Stop thinking "how to do", start thinking "what is"**!
124
124
  ### Reactive System
125
125
  5. [Reactive Computations](./04-reactive-computations.md) - Declarative data computation
126
126
  6. [Interactions](./05-interactions.md) - User interaction definition
127
- 7. [Attributive Permissions](./06-attributive-permissions.md) - Access control
127
+ 7. [Permission Control (Conditions)](./06-attributive-permissions.md) - Access control
128
128
  8. [Payload Parameters](./07-payload-parameters.md) - Interaction parameter validation
129
129
  9. [Activities](./08-activities.md) - Complex business processes
130
130
 
@@ -125,14 +125,15 @@ Payload.create(args: {
125
125
  PayloadItem.create(args: {
126
126
  name: string // Parameter name
127
127
  type: string // Required: data type
128
- base?: EntityInstance // Entity reference for validation
128
+ base?: EntityInstance | RelationInstance // Entity/Relation reference for validation
129
129
  isRef?: boolean // true = reference by ID to existing entity
130
130
  required?: boolean // true = mandatory parameter
131
131
  isCollection?: boolean // true = array of items
132
- itemRef?: AttributiveInstance | EntityInstance // Reference to entities defined in other interactions (for Activity)
133
132
  }): PayloadItemInstance
134
133
  ```
135
134
 
135
+ Payload content validation is expressed as `conditions` on the Interaction (see Condition.create).
136
+
136
137
  ---
137
138
 
138
139
  ## Count.create
@@ -530,19 +531,6 @@ MatchExp.atom({ key: 'author.name', value: ['=', 'Alice'] })
530
531
 
531
532
  ---
532
533
 
533
- ## Attributive.create
534
-
535
- ```typescript
536
- Attributive.create(args: {
537
- name?: string
538
- content: (record: any, eventArgs: any) => boolean
539
- }): AttributiveInstance
540
- ```
541
-
542
- Used on Interaction `userAttributives` to validate user context.
543
-
544
- ---
545
-
546
534
  ## BoolExp
547
535
 
548
536
  ```typescript
@@ -551,7 +539,7 @@ boolExp.and(other: BoolExp | T): BoolExp
551
539
  boolExp.or(other: BoolExp | T): BoolExp
552
540
  ```
553
541
 
554
- Combines multiple Attributives, Conditions, or other expressions for complex logic.
542
+ Combines multiple Conditions, match atoms, or other expressions for complex logic.
555
543
 
556
544
  ---
557
545
 
@@ -568,8 +556,9 @@ Conditions.create(args: {
568
556
  }): ConditionsInstance
569
557
  ```
570
558
 
571
- - `content` returns `true` to allow, `false` to reject
559
+ - `content` returns `true` to allow, `false` to reject; any non-boolean result fails the check (fail-closed)
572
560
  - `this` is bound to Controller — can access `this.system.storage`
561
+ - `event` contains `user`, `payload`, `query`, `activityId` — use it for user checks, payload content checks, and activity user binding
573
562
  - Failed conditions return `{ error: { type: 'condition check failed' } }`
574
563
 
575
564
  ---
@@ -652,7 +641,6 @@ import {
652
641
  Expression, Inequality, Equation, MathResolver,
653
642
 
654
643
  // Validation & conditions
655
- Attributive, Attributives,
656
644
  Condition, Conditions,
657
645
 
658
646
  // Data policy
@@ -1 +1 @@
1
- {"version":3,"file":"Condition.d.ts","sourceRoot":"","sources":["../../../src/builtins/interaction/Condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiJ,MAAM,OAAO,CAAC;AAGjL,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,SAAU,YAAW,iBAAiB;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,SAAe;IACpB,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;gBAET,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAQlE,MAAM,CAAC,OAAO,EAAG,IAAI,CAAU;IAC/B,MAAM,CAAC,WAAW,SAAe;IACjC,MAAM,CAAC,SAAS,EAAE,iBAAiB,EAAE,CAAM;IAE3C,MAAM,CAAC,MAAM;;;;;;;;;MASX;IAEF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,iBAAiB;IAaxF,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM;IAerD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,GAAG,iBAAiB;IASzE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,iBAAiB;IAIjD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAItC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB;CAI9C"}
1
+ {"version":3,"file":"Condition.d.ts","sourceRoot":"","sources":["../../../src/builtins/interaction/Condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAiJ,MAAM,OAAO,CAAC;AAGjL,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,SAAU,YAAW,iBAAiB;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,SAAe;IACpB,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;gBAET,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAQlE,MAAM,CAAC,OAAO,EAAG,IAAI,CAAU;IAC/B,MAAM,CAAC,WAAW,SAAe;IACjC,MAAM,CAAC,SAAS,EAAE,iBAAiB,EAAE,CAAM;IAE3C,MAAM,CAAC,MAAM;;;;;;;;;MASX;IAEF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,iBAAiB;IAsBxF,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM;IAerD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,OAAO,GAAG,iBAAiB;IASzE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,iBAAiB;IAIjD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO;IAItC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB;CAI9C"}