@topolo/sdk 0.2.7 → 0.2.9
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/index.cjs +347 -71
- package/dist/index.d.cts +311 -66
- package/dist/index.d.ts +311 -66
- package/dist/index.js +346 -71
- package/package.json +1 -1
- package/src/applications.generated.ts +114 -59
- package/src/index.ts +17 -0
- package/src/modules/p2p.test.ts +218 -0
- package/src/modules/p2p.ts +451 -0
- package/src/services.generated.ts +15 -12
- package/src/services.test.ts +2 -1
- package/src/widgets.test.ts +2 -2
- package/src/widgets.ts +1 -0
package/package.json
CHANGED
|
@@ -15,7 +15,9 @@ export const APPLICATIONS = {
|
|
|
15
15
|
"name": "topoloadmin",
|
|
16
16
|
"kind": "pages",
|
|
17
17
|
"apiUrl": null,
|
|
18
|
-
"domains": [
|
|
18
|
+
"domains": [
|
|
19
|
+
"admin.topolo.app"
|
|
20
|
+
],
|
|
19
21
|
"routes": [],
|
|
20
22
|
"serviceId": null
|
|
21
23
|
}
|
|
@@ -35,15 +37,19 @@ export const APPLICATIONS = {
|
|
|
35
37
|
"name": "topolo-agent",
|
|
36
38
|
"kind": "pages",
|
|
37
39
|
"apiUrl": null,
|
|
38
|
-
"domains": [
|
|
40
|
+
"domains": [
|
|
41
|
+
"agent.topolo.app"
|
|
42
|
+
],
|
|
39
43
|
"routes": [],
|
|
40
44
|
"serviceId": null
|
|
41
45
|
},
|
|
42
46
|
{
|
|
43
47
|
"name": "topolo-agent-worker",
|
|
44
48
|
"kind": "worker",
|
|
45
|
-
"apiUrl": "https://
|
|
46
|
-
"domains": [
|
|
49
|
+
"apiUrl": "https://agent-api.topolo.app",
|
|
50
|
+
"domains": [
|
|
51
|
+
"agent-api.topolo.app"
|
|
52
|
+
],
|
|
47
53
|
"routes": [],
|
|
48
54
|
"serviceId": "agent"
|
|
49
55
|
}
|
|
@@ -135,15 +141,19 @@ export const APPLICATIONS = {
|
|
|
135
141
|
"name": "bytes",
|
|
136
142
|
"kind": "pages",
|
|
137
143
|
"apiUrl": null,
|
|
138
|
-
"domains": [
|
|
144
|
+
"domains": [
|
|
145
|
+
"bytes.topolo.app"
|
|
146
|
+
],
|
|
139
147
|
"routes": [],
|
|
140
148
|
"serviceId": null
|
|
141
149
|
},
|
|
142
150
|
{
|
|
143
151
|
"name": "r2-media-manager-worker",
|
|
144
152
|
"kind": "worker",
|
|
145
|
-
"apiUrl": "https://
|
|
146
|
-
"domains": [
|
|
153
|
+
"apiUrl": "https://bytes-api.topolo.app",
|
|
154
|
+
"domains": [
|
|
155
|
+
"bytes-api.topolo.app"
|
|
156
|
+
],
|
|
147
157
|
"routes": [],
|
|
148
158
|
"serviceId": "bytes"
|
|
149
159
|
}
|
|
@@ -186,10 +196,9 @@ export const APPLICATIONS = {
|
|
|
186
196
|
{
|
|
187
197
|
"name": "topolo-capacity",
|
|
188
198
|
"kind": "worker",
|
|
189
|
-
"apiUrl": "https://
|
|
199
|
+
"apiUrl": "https://capacity.topolo.app",
|
|
190
200
|
"domains": [
|
|
191
|
-
"capacity.topolo.app"
|
|
192
|
-
"topolo-capacity.topolo.workers.dev"
|
|
201
|
+
"capacity.topolo.app"
|
|
193
202
|
],
|
|
194
203
|
"routes": [],
|
|
195
204
|
"serviceId": "capacity"
|
|
@@ -251,9 +260,9 @@ export const APPLICATIONS = {
|
|
|
251
260
|
{
|
|
252
261
|
"name": "topolo-commerce-api",
|
|
253
262
|
"kind": "worker",
|
|
254
|
-
"apiUrl": "https://
|
|
263
|
+
"apiUrl": "https://commerce-api.topolo.app",
|
|
255
264
|
"domains": [
|
|
256
|
-
"
|
|
265
|
+
"commerce-api.topolo.app"
|
|
257
266
|
],
|
|
258
267
|
"routes": [],
|
|
259
268
|
"serviceId": "commerce"
|
|
@@ -263,8 +272,7 @@ export const APPLICATIONS = {
|
|
|
263
272
|
"kind": "pages",
|
|
264
273
|
"apiUrl": null,
|
|
265
274
|
"domains": [
|
|
266
|
-
"guest.topolo.app"
|
|
267
|
-
"topolo-commerce-guest-web.pages.dev"
|
|
275
|
+
"guest.topolo.app"
|
|
268
276
|
],
|
|
269
277
|
"routes": [],
|
|
270
278
|
"serviceId": null
|
|
@@ -274,8 +282,7 @@ export const APPLICATIONS = {
|
|
|
274
282
|
"kind": "pages",
|
|
275
283
|
"apiUrl": null,
|
|
276
284
|
"domains": [
|
|
277
|
-
"commerce.topolo.app"
|
|
278
|
-
"topolo-commerce-ops-web.pages.dev"
|
|
285
|
+
"commerce.topolo.app"
|
|
279
286
|
],
|
|
280
287
|
"routes": [],
|
|
281
288
|
"serviceId": null
|
|
@@ -285,8 +292,7 @@ export const APPLICATIONS = {
|
|
|
285
292
|
"kind": "pages",
|
|
286
293
|
"apiUrl": null,
|
|
287
294
|
"domains": [
|
|
288
|
-
"station-commerce.topolo.app"
|
|
289
|
-
"topolo-commerce-station-web.pages.dev"
|
|
295
|
+
"station-commerce.topolo.app"
|
|
290
296
|
],
|
|
291
297
|
"routes": [],
|
|
292
298
|
"serviceId": null
|
|
@@ -331,7 +337,9 @@ export const APPLICATIONS = {
|
|
|
331
337
|
"name": "topolo-crm-frontend",
|
|
332
338
|
"kind": "pages",
|
|
333
339
|
"apiUrl": null,
|
|
334
|
-
"domains": [
|
|
340
|
+
"domains": [
|
|
341
|
+
"crm.topolo.app"
|
|
342
|
+
],
|
|
335
343
|
"routes": [],
|
|
336
344
|
"serviceId": null
|
|
337
345
|
},
|
|
@@ -339,7 +347,9 @@ export const APPLICATIONS = {
|
|
|
339
347
|
"name": "topolo-crm-worker",
|
|
340
348
|
"kind": "worker",
|
|
341
349
|
"apiUrl": "https://crm-api.topolo.app",
|
|
342
|
-
"domains": [
|
|
350
|
+
"domains": [
|
|
351
|
+
"crm-api.topolo.app"
|
|
352
|
+
],
|
|
343
353
|
"routes": [],
|
|
344
354
|
"serviceId": "crm"
|
|
345
355
|
}
|
|
@@ -413,8 +423,8 @@ export const APPLICATIONS = {
|
|
|
413
423
|
"id": "feed",
|
|
414
424
|
"appDir": "TopoloFeed",
|
|
415
425
|
"name": "TopoloFeed",
|
|
416
|
-
"packageName":
|
|
417
|
-
"productionUrl": "https://
|
|
426
|
+
"packageName": "topolo-feed",
|
|
427
|
+
"productionUrl": "https://feed-api.topolo.app",
|
|
418
428
|
"services": [
|
|
419
429
|
"feed"
|
|
420
430
|
],
|
|
@@ -422,24 +432,24 @@ export const APPLICATIONS = {
|
|
|
422
432
|
{
|
|
423
433
|
"name": "topolo-feed-analytics-api",
|
|
424
434
|
"kind": "worker",
|
|
425
|
-
"apiUrl": "https://
|
|
435
|
+
"apiUrl": "https://feed-analytics-api.topolo.app",
|
|
426
436
|
"domains": [
|
|
427
|
-
"
|
|
437
|
+
"feed-analytics-api.topolo.app"
|
|
428
438
|
],
|
|
429
439
|
"routes": [
|
|
430
|
-
"
|
|
440
|
+
"feed-analytics-api.topolo.app"
|
|
431
441
|
],
|
|
432
442
|
"serviceId": null
|
|
433
443
|
},
|
|
434
444
|
{
|
|
435
445
|
"name": "topolo-feed-api",
|
|
436
446
|
"kind": "worker",
|
|
437
|
-
"apiUrl": "https://
|
|
447
|
+
"apiUrl": "https://feed-api.topolo.app",
|
|
438
448
|
"domains": [
|
|
439
|
-
"
|
|
449
|
+
"feed-api.topolo.app"
|
|
440
450
|
],
|
|
441
451
|
"routes": [
|
|
442
|
-
"
|
|
452
|
+
"feed-api.topolo.app"
|
|
443
453
|
],
|
|
444
454
|
"serviceId": "feed"
|
|
445
455
|
}
|
|
@@ -483,15 +493,19 @@ export const APPLICATIONS = {
|
|
|
483
493
|
"name": "forecast",
|
|
484
494
|
"kind": "pages",
|
|
485
495
|
"apiUrl": null,
|
|
486
|
-
"domains": [
|
|
496
|
+
"domains": [
|
|
497
|
+
"forecast.topolo.app"
|
|
498
|
+
],
|
|
487
499
|
"routes": [],
|
|
488
500
|
"serviceId": null
|
|
489
501
|
},
|
|
490
502
|
{
|
|
491
503
|
"name": "forecast-worker-production",
|
|
492
504
|
"kind": "worker",
|
|
493
|
-
"apiUrl": "https://forecast-
|
|
494
|
-
"domains": [
|
|
505
|
+
"apiUrl": "https://forecast-api.topolo.app",
|
|
506
|
+
"domains": [
|
|
507
|
+
"forecast-api.topolo.app"
|
|
508
|
+
],
|
|
495
509
|
"routes": [],
|
|
496
510
|
"serviceId": "forecast"
|
|
497
511
|
}
|
|
@@ -592,9 +606,9 @@ export const APPLICATIONS = {
|
|
|
592
606
|
{
|
|
593
607
|
"name": "topololearn-api",
|
|
594
608
|
"kind": "worker",
|
|
595
|
-
"apiUrl": "https://
|
|
609
|
+
"apiUrl": "https://learn-api.topolo.app",
|
|
596
610
|
"domains": [
|
|
597
|
-
"
|
|
611
|
+
"learn-api.topolo.app"
|
|
598
612
|
],
|
|
599
613
|
"routes": [],
|
|
600
614
|
"serviceId": "learn"
|
|
@@ -647,12 +661,12 @@ export const APPLICATIONS = {
|
|
|
647
661
|
{
|
|
648
662
|
"name": "topolo-mdm-api",
|
|
649
663
|
"kind": "worker",
|
|
650
|
-
"apiUrl": "https://
|
|
664
|
+
"apiUrl": "https://mdm-api.topolo.app",
|
|
651
665
|
"domains": [
|
|
652
|
-
"
|
|
666
|
+
"mdm-api.topolo.app"
|
|
653
667
|
],
|
|
654
668
|
"routes": [
|
|
655
|
-
"
|
|
669
|
+
"mdm-api.topolo.app"
|
|
656
670
|
],
|
|
657
671
|
"serviceId": "mdm"
|
|
658
672
|
},
|
|
@@ -661,8 +675,7 @@ export const APPLICATIONS = {
|
|
|
661
675
|
"kind": "pages",
|
|
662
676
|
"apiUrl": null,
|
|
663
677
|
"domains": [
|
|
664
|
-
"mdm.topolo.app"
|
|
665
|
-
"topolo-mdm-console.pages.dev"
|
|
678
|
+
"mdm.topolo.app"
|
|
666
679
|
],
|
|
667
680
|
"routes": [
|
|
668
681
|
"mdm.topolo.app"
|
|
@@ -716,8 +729,7 @@ export const APPLICATIONS = {
|
|
|
716
729
|
"kind": "pages",
|
|
717
730
|
"apiUrl": null,
|
|
718
731
|
"domains": [
|
|
719
|
-
"nexus.topolo.app"
|
|
720
|
-
"topolo-nexus-dashboard.pages.dev"
|
|
732
|
+
"nexus.topolo.app"
|
|
721
733
|
],
|
|
722
734
|
"routes": [],
|
|
723
735
|
"serviceId": null
|
|
@@ -725,9 +737,9 @@ export const APPLICATIONS = {
|
|
|
725
737
|
{
|
|
726
738
|
"name": "topolo-nexus-gateway",
|
|
727
739
|
"kind": "worker",
|
|
728
|
-
"apiUrl": "https://
|
|
740
|
+
"apiUrl": "https://nexus-api.topolo.app",
|
|
729
741
|
"domains": [
|
|
730
|
-
"
|
|
742
|
+
"nexus-api.topolo.app"
|
|
731
743
|
],
|
|
732
744
|
"routes": [],
|
|
733
745
|
"serviceId": "nexus"
|
|
@@ -765,25 +777,26 @@ export const APPLICATIONS = {
|
|
|
765
777
|
"packageName": "topolo-oneclick-sso",
|
|
766
778
|
"productionUrl": "https://one.topolo.app",
|
|
767
779
|
"services": [
|
|
768
|
-
"one"
|
|
780
|
+
"one",
|
|
781
|
+
"one.ai"
|
|
769
782
|
],
|
|
770
783
|
"deployTargets": [
|
|
771
784
|
{
|
|
772
785
|
"name": "ai-chat-rag",
|
|
773
786
|
"kind": "worker",
|
|
774
|
-
"apiUrl":
|
|
787
|
+
"apiUrl": "https://ai.one.topolo.app",
|
|
775
788
|
"domains": [
|
|
776
|
-
"ai
|
|
789
|
+
"ai.one.topolo.app"
|
|
777
790
|
],
|
|
778
791
|
"routes": [],
|
|
779
|
-
"serviceId":
|
|
792
|
+
"serviceId": "one.ai"
|
|
780
793
|
},
|
|
781
794
|
{
|
|
782
795
|
"name": "topoloone",
|
|
783
796
|
"kind": "pages",
|
|
784
797
|
"apiUrl": null,
|
|
785
798
|
"domains": [
|
|
786
|
-
"
|
|
799
|
+
"one.topolo.app"
|
|
787
800
|
],
|
|
788
801
|
"routes": [],
|
|
789
802
|
"serviceId": null
|
|
@@ -804,7 +817,9 @@ export const APPLICATIONS = {
|
|
|
804
817
|
"name": "topoloone-worker",
|
|
805
818
|
"kind": "worker",
|
|
806
819
|
"apiUrl": "https://one.topolo.app",
|
|
807
|
-
"domains": [
|
|
820
|
+
"domains": [
|
|
821
|
+
"one.topolo.app"
|
|
822
|
+
],
|
|
808
823
|
"routes": [
|
|
809
824
|
"one.topolo.app/*"
|
|
810
825
|
],
|
|
@@ -812,6 +827,30 @@ export const APPLICATIONS = {
|
|
|
812
827
|
}
|
|
813
828
|
]
|
|
814
829
|
},
|
|
830
|
+
"p2p": {
|
|
831
|
+
"id": "p2p",
|
|
832
|
+
"appDir": "TopoloP2P",
|
|
833
|
+
"name": "topolo-p2p",
|
|
834
|
+
"packageName": "topolo-p2p",
|
|
835
|
+
"productionUrl": "https://p2p.topolo.app",
|
|
836
|
+
"services": [
|
|
837
|
+
"p2p"
|
|
838
|
+
],
|
|
839
|
+
"deployTargets": [
|
|
840
|
+
{
|
|
841
|
+
"name": "topolo-p2p",
|
|
842
|
+
"kind": "worker",
|
|
843
|
+
"apiUrl": "https://p2p.topolo.app",
|
|
844
|
+
"domains": [
|
|
845
|
+
"p2p.topolo.app"
|
|
846
|
+
],
|
|
847
|
+
"routes": [
|
|
848
|
+
"p2p.topolo.app"
|
|
849
|
+
],
|
|
850
|
+
"serviceId": "p2p"
|
|
851
|
+
}
|
|
852
|
+
]
|
|
853
|
+
},
|
|
815
854
|
"pay": {
|
|
816
855
|
"id": "pay",
|
|
817
856
|
"appDir": "TopoloPay",
|
|
@@ -825,8 +864,10 @@ export const APPLICATIONS = {
|
|
|
825
864
|
{
|
|
826
865
|
"name": "topolo-pay",
|
|
827
866
|
"kind": "worker",
|
|
828
|
-
"apiUrl": "https://
|
|
829
|
-
"domains": [
|
|
867
|
+
"apiUrl": "https://pay.topolo.app",
|
|
868
|
+
"domains": [
|
|
869
|
+
"pay.topolo.app"
|
|
870
|
+
],
|
|
830
871
|
"routes": [],
|
|
831
872
|
"serviceId": "pay"
|
|
832
873
|
}
|
|
@@ -871,7 +912,9 @@ export const APPLICATIONS = {
|
|
|
871
912
|
"name": "quro-api",
|
|
872
913
|
"kind": "worker",
|
|
873
914
|
"apiUrl": "https://api.ol0.me",
|
|
874
|
-
"domains": [
|
|
915
|
+
"domains": [
|
|
916
|
+
"api.ol0.me"
|
|
917
|
+
],
|
|
875
918
|
"routes": [],
|
|
876
919
|
"serviceId": "quro.api"
|
|
877
920
|
},
|
|
@@ -879,7 +922,9 @@ export const APPLICATIONS = {
|
|
|
879
922
|
"name": "quro-redirect-system",
|
|
880
923
|
"kind": "worker",
|
|
881
924
|
"apiUrl": "https://ol0.me",
|
|
882
|
-
"domains": [
|
|
925
|
+
"domains": [
|
|
926
|
+
"ol0.me"
|
|
927
|
+
],
|
|
883
928
|
"routes": [
|
|
884
929
|
"ol0.me/*"
|
|
885
930
|
],
|
|
@@ -889,7 +934,9 @@ export const APPLICATIONS = {
|
|
|
889
934
|
"name": "quro-ui",
|
|
890
935
|
"kind": "pages",
|
|
891
936
|
"apiUrl": null,
|
|
892
|
-
"domains": [
|
|
937
|
+
"domains": [
|
|
938
|
+
"quro.topolo.app"
|
|
939
|
+
],
|
|
893
940
|
"routes": [],
|
|
894
941
|
"serviceId": null
|
|
895
942
|
}
|
|
@@ -965,15 +1012,19 @@ export const APPLICATIONS = {
|
|
|
965
1012
|
"name": "topolo-social-studio",
|
|
966
1013
|
"kind": "pages",
|
|
967
1014
|
"apiUrl": null,
|
|
968
|
-
"domains": [
|
|
1015
|
+
"domains": [
|
|
1016
|
+
"studio.topolo.app"
|
|
1017
|
+
],
|
|
969
1018
|
"routes": [],
|
|
970
1019
|
"serviceId": null
|
|
971
1020
|
},
|
|
972
1021
|
{
|
|
973
1022
|
"name": "topolo-social-studio-api",
|
|
974
1023
|
"kind": "worker",
|
|
975
|
-
"apiUrl": "https://
|
|
976
|
-
"domains": [
|
|
1024
|
+
"apiUrl": "https://studio-api.topolo.app",
|
|
1025
|
+
"domains": [
|
|
1026
|
+
"studio-api.topolo.app"
|
|
1027
|
+
],
|
|
977
1028
|
"routes": [],
|
|
978
1029
|
"serviceId": "social_studio"
|
|
979
1030
|
},
|
|
@@ -1001,15 +1052,19 @@ export const APPLICATIONS = {
|
|
|
1001
1052
|
"name": "socialize",
|
|
1002
1053
|
"kind": "pages",
|
|
1003
1054
|
"apiUrl": null,
|
|
1004
|
-
"domains": [
|
|
1055
|
+
"domains": [
|
|
1056
|
+
"socialize.topolo.app"
|
|
1057
|
+
],
|
|
1005
1058
|
"routes": [],
|
|
1006
1059
|
"serviceId": null
|
|
1007
1060
|
},
|
|
1008
1061
|
{
|
|
1009
1062
|
"name": "socialize-prod-api",
|
|
1010
1063
|
"kind": "worker",
|
|
1011
|
-
"apiUrl": "https://socialize-
|
|
1012
|
-
"domains": [
|
|
1064
|
+
"apiUrl": "https://socialize-api.topolo.app",
|
|
1065
|
+
"domains": [
|
|
1066
|
+
"socialize-api.topolo.app"
|
|
1067
|
+
],
|
|
1013
1068
|
"routes": [],
|
|
1014
1069
|
"serviceId": "socialize"
|
|
1015
1070
|
},
|
package/src/index.ts
CHANGED
|
@@ -43,6 +43,23 @@ export {
|
|
|
43
43
|
type ListContactsResult,
|
|
44
44
|
} from "./modules/crm.js";
|
|
45
45
|
export { IdentityModule } from "./modules/identity.js";
|
|
46
|
+
export {
|
|
47
|
+
P2PModule,
|
|
48
|
+
type P2PCapability,
|
|
49
|
+
type P2PPricingModel,
|
|
50
|
+
type PublishCapabilityInput,
|
|
51
|
+
type P2PActionRow,
|
|
52
|
+
type P2PActionRun,
|
|
53
|
+
type P2PActionRequestInput,
|
|
54
|
+
type P2PActionRequestResult,
|
|
55
|
+
type P2PActionDetail,
|
|
56
|
+
type P2PHold,
|
|
57
|
+
type P2PLedgerEntry,
|
|
58
|
+
type P2PPolicy,
|
|
59
|
+
type P2PConnection,
|
|
60
|
+
type P2PSettlementGroup,
|
|
61
|
+
type P2PSettlementBatch,
|
|
62
|
+
} from "./modules/p2p.js";
|
|
46
63
|
export {
|
|
47
64
|
TopoloOAuth,
|
|
48
65
|
type OAuthHelperOptions,
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { TopoloClient } from '../client.js';
|
|
3
|
+
import { P2PModule } from './p2p.js';
|
|
4
|
+
|
|
5
|
+
const AGENT = { clientName: 'topolo-sdk-test', clientVersion: '0.0.0' };
|
|
6
|
+
|
|
7
|
+
function stubFetch(responses: Array<{ status?: number; body?: unknown }>) {
|
|
8
|
+
const calls: Array<{ url: string; init: RequestInit }> = [];
|
|
9
|
+
const impl = vi.fn(async (url: string, init: RequestInit) => {
|
|
10
|
+
calls.push({ url, init });
|
|
11
|
+
const next = responses.shift() ?? { status: 200, body: { success: true, data: {} } };
|
|
12
|
+
return new Response(JSON.stringify(next.body ?? { success: true, data: {} }), {
|
|
13
|
+
status: next.status ?? 200,
|
|
14
|
+
headers: { 'Content-Type': 'application/json' },
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
return { impl: impl as unknown as typeof fetch, calls };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function clientWith(impl: typeof fetch) {
|
|
21
|
+
return new TopoloClient({
|
|
22
|
+
credential: { kind: 'access_token', accessToken: 'tok_test' },
|
|
23
|
+
agent: AGENT,
|
|
24
|
+
fetch: impl,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('P2PModule.listDirectory', () => {
|
|
29
|
+
it('GETs /api/directory/capabilities and unwraps the envelope', async () => {
|
|
30
|
+
const { impl, calls } = stubFetch([
|
|
31
|
+
{
|
|
32
|
+
body: {
|
|
33
|
+
success: true,
|
|
34
|
+
data: {
|
|
35
|
+
capabilities: [
|
|
36
|
+
{
|
|
37
|
+
capability_id: 'cap_1',
|
|
38
|
+
publisher_org_id: 'org_a',
|
|
39
|
+
app_id: 'app_x',
|
|
40
|
+
service_id: 'srv_x',
|
|
41
|
+
name: 'Demo',
|
|
42
|
+
description: 'A capability',
|
|
43
|
+
category: 'other',
|
|
44
|
+
pricing_model: 'free',
|
|
45
|
+
pricing_amount_minor: null,
|
|
46
|
+
currency: null,
|
|
47
|
+
requires_human_approval: false,
|
|
48
|
+
supported_contexts: ['agent'],
|
|
49
|
+
trust_level: 'standard',
|
|
50
|
+
source_revision: 'rev_1',
|
|
51
|
+
synced_at: 1,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
]);
|
|
58
|
+
const p2p = new P2PModule(clientWith(impl));
|
|
59
|
+
|
|
60
|
+
const capabilities = await p2p.listDirectory({ limit: 10 });
|
|
61
|
+
expect(capabilities).toHaveLength(1);
|
|
62
|
+
expect(capabilities[0]!.capability_id).toBe('cap_1');
|
|
63
|
+
const url = new URL(calls[0]!.url);
|
|
64
|
+
expect(url.pathname).toBe('/api/directory/capabilities');
|
|
65
|
+
expect(url.searchParams.get('limit')).toBe('10');
|
|
66
|
+
expect((calls[0]!.init.method ?? 'GET').toUpperCase()).toBe('GET');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('P2PModule.publishCapability', () => {
|
|
71
|
+
it('POSTs to the internal sync route with the publisher_org_id and acting_for_org_id default', async () => {
|
|
72
|
+
const { impl, calls } = stubFetch([
|
|
73
|
+
{
|
|
74
|
+
body: {
|
|
75
|
+
success: true,
|
|
76
|
+
data: {
|
|
77
|
+
capability: {
|
|
78
|
+
capability_id: 'cap_z',
|
|
79
|
+
publisher_org_id: 'org_p',
|
|
80
|
+
app_id: 'app_x',
|
|
81
|
+
service_id: 'srv_x',
|
|
82
|
+
name: 'Demo',
|
|
83
|
+
description: 'A capability',
|
|
84
|
+
category: 'other',
|
|
85
|
+
pricing_model: 'fixed',
|
|
86
|
+
pricing_amount_minor: 500,
|
|
87
|
+
currency: 'USD',
|
|
88
|
+
requires_human_approval: false,
|
|
89
|
+
supported_contexts: ['agent'],
|
|
90
|
+
trust_level: 'standard',
|
|
91
|
+
source_revision: 'rev_2',
|
|
92
|
+
synced_at: 1,
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
]);
|
|
98
|
+
const p2p = new P2PModule(clientWith(impl));
|
|
99
|
+
|
|
100
|
+
const capability = await p2p.publishCapability({
|
|
101
|
+
capability_id: 'cap_z',
|
|
102
|
+
publisher_org_id: 'org_p',
|
|
103
|
+
app_id: 'app_x',
|
|
104
|
+
service_id: 'srv_x',
|
|
105
|
+
name: 'Demo',
|
|
106
|
+
description: 'A capability',
|
|
107
|
+
category: 'other',
|
|
108
|
+
pricing_model: 'fixed',
|
|
109
|
+
pricing_amount_minor: 500,
|
|
110
|
+
currency: 'USD',
|
|
111
|
+
supported_contexts: ['agent'],
|
|
112
|
+
public_directory_visible: true,
|
|
113
|
+
source_revision: 'rev_2',
|
|
114
|
+
});
|
|
115
|
+
expect(capability.capability_id).toBe('cap_z');
|
|
116
|
+
|
|
117
|
+
const sent = JSON.parse(String(calls[0]!.init.body));
|
|
118
|
+
expect(sent.publisher_org_id).toBe('org_p');
|
|
119
|
+
expect(sent.acting_for_org_id).toBe('org_p');
|
|
120
|
+
expect(sent.public_directory_visible).toBe(true);
|
|
121
|
+
expect(sent.requires_human_approval).toBe(false);
|
|
122
|
+
expect(sent.trust_level).toBe('standard');
|
|
123
|
+
const url = new URL(calls[0]!.url);
|
|
124
|
+
expect(url.pathname).toBe('/api/p2p/internal/capabilities/sync');
|
|
125
|
+
expect((calls[0]!.init.method ?? '').toUpperCase()).toBe('POST');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('honours an explicit acting_for_org_id when the platform key is publishing for another org', async () => {
|
|
129
|
+
const { impl, calls } = stubFetch([
|
|
130
|
+
{ body: { success: true, data: { capability: null } } },
|
|
131
|
+
]);
|
|
132
|
+
const p2p = new P2PModule(clientWith(impl));
|
|
133
|
+
await p2p.publishCapability({
|
|
134
|
+
capability_id: 'cap_other',
|
|
135
|
+
publisher_org_id: 'org_target',
|
|
136
|
+
app_id: 'app_x',
|
|
137
|
+
service_id: 'srv_x',
|
|
138
|
+
name: 'Demo',
|
|
139
|
+
description: '...',
|
|
140
|
+
category: 'other',
|
|
141
|
+
pricing_model: 'free',
|
|
142
|
+
supported_contexts: ['agent'],
|
|
143
|
+
public_directory_visible: true,
|
|
144
|
+
source_revision: 'rev_1',
|
|
145
|
+
acting_for_org_id: 'org_target',
|
|
146
|
+
});
|
|
147
|
+
const sent = JSON.parse(String(calls[0]!.init.body));
|
|
148
|
+
expect(sent.acting_for_org_id).toBe('org_target');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe('P2PModule.requestAction', () => {
|
|
153
|
+
it('rejects without an idempotency_key', async () => {
|
|
154
|
+
const { impl } = stubFetch([]);
|
|
155
|
+
const p2p = new P2PModule(clientWith(impl));
|
|
156
|
+
await expect(
|
|
157
|
+
p2p.requestAction({ capability_id: 'cap_1', idempotency_key: '', inputs: {} }),
|
|
158
|
+
).rejects.toThrow(/idempotency_key/);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('returns the worker decision payload', async () => {
|
|
162
|
+
const { impl } = stubFetch([
|
|
163
|
+
{
|
|
164
|
+
body: {
|
|
165
|
+
success: true,
|
|
166
|
+
data: {
|
|
167
|
+
decision: 'auto_accepted',
|
|
168
|
+
idempotent: false,
|
|
169
|
+
request: { request_id: 'req_1', state: 'auto_accepted' },
|
|
170
|
+
run: null,
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
]);
|
|
175
|
+
const p2p = new P2PModule(clientWith(impl));
|
|
176
|
+
const result = await p2p.requestAction({
|
|
177
|
+
capability_id: 'cap_1',
|
|
178
|
+
idempotency_key: 'key_1',
|
|
179
|
+
inputs: { foo: 'bar' },
|
|
180
|
+
});
|
|
181
|
+
expect(result.decision).toBe('auto_accepted');
|
|
182
|
+
expect(result.idempotent).toBe(false);
|
|
183
|
+
expect(result.request.request_id).toBe('req_1');
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe('P2PModule.getCapability', () => {
|
|
188
|
+
it('returns null on a 404 from the worker', async () => {
|
|
189
|
+
const { impl } = stubFetch([{ status: 404, body: { success: false, error: 'capability_not_found' } }]);
|
|
190
|
+
const p2p = new P2PModule(clientWith(impl));
|
|
191
|
+
const capability = await p2p.getCapability('cap_missing');
|
|
192
|
+
expect(capability).toBeNull();
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('P2PModule.releaseHold', () => {
|
|
197
|
+
it('POSTs the resolution + reason and returns hold + cancel entries', async () => {
|
|
198
|
+
const { impl, calls } = stubFetch([
|
|
199
|
+
{
|
|
200
|
+
body: {
|
|
201
|
+
success: true,
|
|
202
|
+
data: {
|
|
203
|
+
hold: { hold_id: 'hold_1', status: 'released' },
|
|
204
|
+
resolution: 'seller',
|
|
205
|
+
cancel_entries: [{ entry_id: 'led_1', amount_minor: 500 }],
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
]);
|
|
210
|
+
const p2p = new P2PModule(clientWith(impl));
|
|
211
|
+
const result = await p2p.releaseHold('hold_1', 'seller', { reason: 'arbitration' });
|
|
212
|
+
expect(result.resolution).toBe('seller');
|
|
213
|
+
expect(result.cancel_entries[0]!.entry_id).toBe('led_1');
|
|
214
|
+
const sent = JSON.parse(String(calls[0]!.init.body));
|
|
215
|
+
expect(sent.resolution).toBe('seller');
|
|
216
|
+
expect(sent.reason).toBe('arbitration');
|
|
217
|
+
});
|
|
218
|
+
});
|