@topolo/sdk 0.4.7 → 0.4.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 +163 -137
- package/dist/index.d.cts +83 -91
- package/dist/index.d.ts +83 -91
- package/dist/index.js +163 -137
- package/package.json +1 -1
- package/src/application-requirements.ts +9 -5
- package/src/applications.generated.ts +50 -102
- package/src/client.test.ts +108 -19
- package/src/client.ts +137 -4
- package/src/index.test.ts +69 -0
- package/src/index.ts +1 -0
- package/src/modules/crm.test.ts +208 -0
- package/src/modules/identity.test.ts +165 -0
- package/src/modules/p2p.test.ts +286 -0
- package/src/oauth.test.ts +103 -0
- package/src/services.generated.ts +14 -15
- package/src/services.test.ts +18 -7
- package/src/widgets.test.ts +216 -0
package/dist/index.js
CHANGED
|
@@ -58,54 +58,53 @@ var TopoloHttpError = class extends TopoloSdkError {
|
|
|
58
58
|
|
|
59
59
|
// src/services.generated.ts
|
|
60
60
|
var SERVICES = {
|
|
61
|
-
agent: "https://agent
|
|
61
|
+
agent: "https://agent.topolo.app",
|
|
62
62
|
auth: "https://auth.topolo.app",
|
|
63
63
|
backup: "https://backup.topolo.app",
|
|
64
64
|
books: "https://books.topolo.app",
|
|
65
65
|
bugfix: "https://bugfix.topolo.app",
|
|
66
|
-
bytes: "https://bytes
|
|
66
|
+
bytes: "https://bytes.topolo.app",
|
|
67
67
|
calendar: "https://calendar.topolo.app",
|
|
68
68
|
capacity: "https://capacity.topolo.app",
|
|
69
69
|
chat: "https://chat.topolo.app",
|
|
70
|
-
commerce: "https://commerce
|
|
70
|
+
commerce: "https://commerce.topolo.app",
|
|
71
71
|
compose: "https://compose.topolo.app",
|
|
72
72
|
consent: "https://consent.topolo.app",
|
|
73
|
-
crm: "https://crm
|
|
73
|
+
crm: "https://crm.topolo.app",
|
|
74
74
|
developers: "https://developers.topolo.app",
|
|
75
75
|
director: "https://director.topolo.app",
|
|
76
|
-
feed: "https://feed
|
|
76
|
+
feed: "https://feed.topolo.app",
|
|
77
77
|
flow: "https://flow.topolo.app",
|
|
78
|
-
forecast: "https://forecast
|
|
78
|
+
forecast: "https://forecast.topolo.app",
|
|
79
79
|
forms: "https://forms.topolo.app",
|
|
80
80
|
home: "https://home.topolo.app",
|
|
81
81
|
insights: "https://insights.topolo.app",
|
|
82
82
|
inventory: "https://inventory.topolo.app",
|
|
83
|
-
learn: "https://learn
|
|
83
|
+
learn: "https://learn.topolo.app",
|
|
84
84
|
localize: "https://localize.topolo.app",
|
|
85
|
-
mail: "https://mail
|
|
86
|
-
mdm: "https://mdm
|
|
85
|
+
mail: "https://mail.topolo.app",
|
|
86
|
+
mdm: "https://mdm.topolo.app",
|
|
87
87
|
messages: "https://messages.topolo.app",
|
|
88
|
-
nexus: "https://nexus
|
|
88
|
+
nexus: "https://nexus.topolo.app",
|
|
89
89
|
notify: "https://notify.topolo.app",
|
|
90
90
|
observability_watch: "https://observability-watch.topolo.app",
|
|
91
91
|
one: "https://www.topolo.app",
|
|
92
92
|
p2p: "https://p2p.topolo.app",
|
|
93
93
|
pay: "https://pay.topolo.app",
|
|
94
94
|
people: "https://people.topolo.app",
|
|
95
|
-
pulse: "https://pulse.topolo.app",
|
|
96
95
|
"quro.api": "https://api.ol0.me",
|
|
97
96
|
"quro.redirect": "https://ol0.me",
|
|
98
|
-
roadmapper: "https://roadmapper
|
|
97
|
+
roadmapper: "https://roadmapper.topolo.app",
|
|
99
98
|
sign: "https://sign.topolo.app",
|
|
100
|
-
social_studio: "https://studio
|
|
101
|
-
socialize: "https://socialize
|
|
99
|
+
social_studio: "https://studio.topolo.app",
|
|
100
|
+
socialize: "https://socialize.topolo.app",
|
|
102
101
|
spaces: "https://spaces.topolo.app",
|
|
103
102
|
status: "https://status.topolo.app",
|
|
104
103
|
success: "https://success.topolo.app",
|
|
105
104
|
support: "https://support.topolo.app",
|
|
106
105
|
survey: "https://survey.topolo.app",
|
|
107
106
|
voice: "https://voice.topolo.app",
|
|
108
|
-
web: "https://web
|
|
107
|
+
web: "https://web.topolo.app"
|
|
109
108
|
};
|
|
110
109
|
|
|
111
110
|
// src/applications.generated.ts
|
|
@@ -156,17 +155,15 @@ var APPLICATIONS = {
|
|
|
156
155
|
"agent.topolo.app"
|
|
157
156
|
],
|
|
158
157
|
"routes": [],
|
|
159
|
-
"serviceId":
|
|
158
|
+
"serviceId": "agent"
|
|
160
159
|
},
|
|
161
160
|
{
|
|
162
161
|
"name": "topolo-agent-api",
|
|
163
162
|
"kind": "worker",
|
|
164
|
-
"apiUrl":
|
|
165
|
-
"domains": [
|
|
166
|
-
"agent-api.topolo.app"
|
|
167
|
-
],
|
|
163
|
+
"apiUrl": null,
|
|
164
|
+
"domains": [],
|
|
168
165
|
"routes": [],
|
|
169
|
-
"serviceId":
|
|
166
|
+
"serviceId": null
|
|
170
167
|
}
|
|
171
168
|
]
|
|
172
169
|
},
|
|
@@ -286,17 +283,15 @@ var APPLICATIONS = {
|
|
|
286
283
|
"bytes.topolo.app"
|
|
287
284
|
],
|
|
288
285
|
"routes": [],
|
|
289
|
-
"serviceId":
|
|
286
|
+
"serviceId": "bytes"
|
|
290
287
|
},
|
|
291
288
|
{
|
|
292
289
|
"name": "topolo-bytes-api",
|
|
293
290
|
"kind": "worker",
|
|
294
|
-
"apiUrl":
|
|
295
|
-
"domains": [
|
|
296
|
-
"bytes-api.topolo.app"
|
|
297
|
-
],
|
|
291
|
+
"apiUrl": null,
|
|
292
|
+
"domains": [],
|
|
298
293
|
"routes": [],
|
|
299
|
-
"serviceId":
|
|
294
|
+
"serviceId": null
|
|
300
295
|
}
|
|
301
296
|
]
|
|
302
297
|
},
|
|
@@ -395,12 +390,10 @@ var APPLICATIONS = {
|
|
|
395
390
|
{
|
|
396
391
|
"name": "topolo-commerce-api",
|
|
397
392
|
"kind": "worker",
|
|
398
|
-
"apiUrl":
|
|
399
|
-
"domains": [
|
|
400
|
-
"commerce-api.topolo.app"
|
|
401
|
-
],
|
|
393
|
+
"apiUrl": null,
|
|
394
|
+
"domains": [],
|
|
402
395
|
"routes": [],
|
|
403
|
-
"serviceId":
|
|
396
|
+
"serviceId": null
|
|
404
397
|
},
|
|
405
398
|
{
|
|
406
399
|
"name": "topolo-commerce-guest-web",
|
|
@@ -420,7 +413,7 @@ var APPLICATIONS = {
|
|
|
420
413
|
"commerce.topolo.app"
|
|
421
414
|
],
|
|
422
415
|
"routes": [],
|
|
423
|
-
"serviceId":
|
|
416
|
+
"serviceId": "commerce"
|
|
424
417
|
},
|
|
425
418
|
{
|
|
426
419
|
"name": "topolo-commerce-station-web",
|
|
@@ -507,12 +500,10 @@ var APPLICATIONS = {
|
|
|
507
500
|
{
|
|
508
501
|
"name": "topolo-crm-api",
|
|
509
502
|
"kind": "worker",
|
|
510
|
-
"apiUrl":
|
|
511
|
-
"domains": [
|
|
512
|
-
"crm-api.topolo.app"
|
|
513
|
-
],
|
|
503
|
+
"apiUrl": null,
|
|
504
|
+
"domains": [],
|
|
514
505
|
"routes": [],
|
|
515
|
-
"serviceId":
|
|
506
|
+
"serviceId": null
|
|
516
507
|
},
|
|
517
508
|
{
|
|
518
509
|
"name": "topolo-crm-app",
|
|
@@ -522,7 +513,7 @@ var APPLICATIONS = {
|
|
|
522
513
|
"crm.topolo.app"
|
|
523
514
|
],
|
|
524
515
|
"routes": [],
|
|
525
|
-
"serviceId":
|
|
516
|
+
"serviceId": "crm"
|
|
526
517
|
}
|
|
527
518
|
]
|
|
528
519
|
},
|
|
@@ -650,7 +641,7 @@ var APPLICATIONS = {
|
|
|
650
641
|
"feed-api.topolo.app"
|
|
651
642
|
],
|
|
652
643
|
"routes": [],
|
|
653
|
-
"serviceId":
|
|
644
|
+
"serviceId": null
|
|
654
645
|
},
|
|
655
646
|
{
|
|
656
647
|
"name": "topolo-feed-web",
|
|
@@ -660,7 +651,7 @@ var APPLICATIONS = {
|
|
|
660
651
|
"feed.topolo.app"
|
|
661
652
|
],
|
|
662
653
|
"routes": [],
|
|
663
|
-
"serviceId":
|
|
654
|
+
"serviceId": "feed"
|
|
664
655
|
}
|
|
665
656
|
]
|
|
666
657
|
},
|
|
@@ -712,17 +703,15 @@ var APPLICATIONS = {
|
|
|
712
703
|
"forecast.topolo.app"
|
|
713
704
|
],
|
|
714
705
|
"routes": [],
|
|
715
|
-
"serviceId":
|
|
706
|
+
"serviceId": "forecast"
|
|
716
707
|
},
|
|
717
708
|
{
|
|
718
709
|
"name": "topolo-forecast-api",
|
|
719
710
|
"kind": "worker",
|
|
720
|
-
"apiUrl":
|
|
721
|
-
"domains": [
|
|
722
|
-
"forecast-api.topolo.app"
|
|
723
|
-
],
|
|
711
|
+
"apiUrl": null,
|
|
712
|
+
"domains": [],
|
|
724
713
|
"routes": [],
|
|
725
|
-
"serviceId":
|
|
714
|
+
"serviceId": null
|
|
726
715
|
}
|
|
727
716
|
]
|
|
728
717
|
},
|
|
@@ -864,17 +853,15 @@ var APPLICATIONS = {
|
|
|
864
853
|
"learn.topolo.app"
|
|
865
854
|
],
|
|
866
855
|
"routes": [],
|
|
867
|
-
"serviceId":
|
|
856
|
+
"serviceId": "learn"
|
|
868
857
|
},
|
|
869
858
|
{
|
|
870
859
|
"name": "topolo-learn-api",
|
|
871
860
|
"kind": "worker",
|
|
872
|
-
"apiUrl":
|
|
873
|
-
"domains": [
|
|
874
|
-
"learn-api.topolo.app"
|
|
875
|
-
],
|
|
861
|
+
"apiUrl": null,
|
|
862
|
+
"domains": [],
|
|
876
863
|
"routes": [],
|
|
877
|
-
"serviceId":
|
|
864
|
+
"serviceId": null
|
|
878
865
|
}
|
|
879
866
|
]
|
|
880
867
|
},
|
|
@@ -920,17 +907,15 @@ var APPLICATIONS = {
|
|
|
920
907
|
"mail.topolo.app"
|
|
921
908
|
],
|
|
922
909
|
"routes": [],
|
|
923
|
-
"serviceId":
|
|
910
|
+
"serviceId": "mail"
|
|
924
911
|
},
|
|
925
912
|
{
|
|
926
913
|
"name": "topolo-mail-api",
|
|
927
914
|
"kind": "worker",
|
|
928
|
-
"apiUrl":
|
|
929
|
-
"domains": [
|
|
930
|
-
"mail-api.topolo.app"
|
|
931
|
-
],
|
|
915
|
+
"apiUrl": null,
|
|
916
|
+
"domains": [],
|
|
932
917
|
"routes": [],
|
|
933
|
-
"serviceId":
|
|
918
|
+
"serviceId": null
|
|
934
919
|
}
|
|
935
920
|
]
|
|
936
921
|
},
|
|
@@ -947,12 +932,10 @@ var APPLICATIONS = {
|
|
|
947
932
|
{
|
|
948
933
|
"name": "topolo-mdm-api",
|
|
949
934
|
"kind": "worker",
|
|
950
|
-
"apiUrl":
|
|
951
|
-
"domains": [
|
|
952
|
-
"mdm-api.topolo.app"
|
|
953
|
-
],
|
|
935
|
+
"apiUrl": null,
|
|
936
|
+
"domains": [],
|
|
954
937
|
"routes": [],
|
|
955
|
-
"serviceId":
|
|
938
|
+
"serviceId": null
|
|
956
939
|
},
|
|
957
940
|
{
|
|
958
941
|
"name": "topolo-mdm-console",
|
|
@@ -962,7 +945,7 @@ var APPLICATIONS = {
|
|
|
962
945
|
"mdm.topolo.app"
|
|
963
946
|
],
|
|
964
947
|
"routes": [],
|
|
965
|
-
"serviceId":
|
|
948
|
+
"serviceId": "mdm"
|
|
966
949
|
}
|
|
967
950
|
]
|
|
968
951
|
},
|
|
@@ -1027,9 +1010,9 @@ var APPLICATIONS = {
|
|
|
1027
1010
|
{
|
|
1028
1011
|
"name": "topolo-nexus-gateway",
|
|
1029
1012
|
"kind": "worker",
|
|
1030
|
-
"apiUrl": "https://nexus
|
|
1013
|
+
"apiUrl": "https://nexus.topolo.app",
|
|
1031
1014
|
"domains": [
|
|
1032
|
-
"nexus
|
|
1015
|
+
"nexus.topolo.app"
|
|
1033
1016
|
],
|
|
1034
1017
|
"routes": [],
|
|
1035
1018
|
"serviceId": "nexus"
|
|
@@ -1221,36 +1204,6 @@ var APPLICATIONS = {
|
|
|
1221
1204
|
}
|
|
1222
1205
|
]
|
|
1223
1206
|
},
|
|
1224
|
-
"pulse": {
|
|
1225
|
-
"id": "pulse",
|
|
1226
|
-
"appDir": "TopoloPulse",
|
|
1227
|
-
"name": "topolo-pulse",
|
|
1228
|
-
"packageName": "topolo-pulse",
|
|
1229
|
-
"productionUrl": "https://pulse.topolo.app",
|
|
1230
|
-
"services": [
|
|
1231
|
-
"pulse"
|
|
1232
|
-
],
|
|
1233
|
-
"deployTargets": [
|
|
1234
|
-
{
|
|
1235
|
-
"name": "topolo-pulse",
|
|
1236
|
-
"kind": "worker",
|
|
1237
|
-
"apiUrl": "https://pulse.topolo.app",
|
|
1238
|
-
"domains": [
|
|
1239
|
-
"pulse.topolo.app"
|
|
1240
|
-
],
|
|
1241
|
-
"routes": [],
|
|
1242
|
-
"serviceId": "pulse"
|
|
1243
|
-
},
|
|
1244
|
-
{
|
|
1245
|
-
"name": "topolo-pulse-api",
|
|
1246
|
-
"kind": "worker",
|
|
1247
|
-
"apiUrl": null,
|
|
1248
|
-
"domains": [],
|
|
1249
|
-
"routes": [],
|
|
1250
|
-
"serviceId": null
|
|
1251
|
-
}
|
|
1252
|
-
]
|
|
1253
|
-
},
|
|
1254
1207
|
"quro": {
|
|
1255
1208
|
"id": "quro",
|
|
1256
1209
|
"appDir": "TopoloQuro",
|
|
@@ -1316,17 +1269,15 @@ var APPLICATIONS = {
|
|
|
1316
1269
|
"roadmapper.topolo.app"
|
|
1317
1270
|
],
|
|
1318
1271
|
"routes": [],
|
|
1319
|
-
"serviceId":
|
|
1272
|
+
"serviceId": "roadmapper"
|
|
1320
1273
|
},
|
|
1321
1274
|
{
|
|
1322
1275
|
"name": "topolo-roadmapper-api",
|
|
1323
1276
|
"kind": "worker",
|
|
1324
|
-
"apiUrl":
|
|
1325
|
-
"domains": [
|
|
1326
|
-
"roadmapper-api.topolo.app"
|
|
1327
|
-
],
|
|
1277
|
+
"apiUrl": null,
|
|
1278
|
+
"domains": [],
|
|
1328
1279
|
"routes": [],
|
|
1329
|
-
"serviceId":
|
|
1280
|
+
"serviceId": null
|
|
1330
1281
|
}
|
|
1331
1282
|
]
|
|
1332
1283
|
},
|
|
@@ -1378,17 +1329,15 @@ var APPLICATIONS = {
|
|
|
1378
1329
|
"studio.topolo.app"
|
|
1379
1330
|
],
|
|
1380
1331
|
"routes": [],
|
|
1381
|
-
"serviceId":
|
|
1332
|
+
"serviceId": "social_studio"
|
|
1382
1333
|
},
|
|
1383
1334
|
{
|
|
1384
1335
|
"name": "topolo-social-studio-api",
|
|
1385
1336
|
"kind": "worker",
|
|
1386
|
-
"apiUrl":
|
|
1387
|
-
"domains": [
|
|
1388
|
-
"studio-api.topolo.app"
|
|
1389
|
-
],
|
|
1337
|
+
"apiUrl": null,
|
|
1338
|
+
"domains": [],
|
|
1390
1339
|
"routes": [],
|
|
1391
|
-
"serviceId":
|
|
1340
|
+
"serviceId": null
|
|
1392
1341
|
},
|
|
1393
1342
|
{
|
|
1394
1343
|
"name": "topolo-social-studio-queue",
|
|
@@ -1418,7 +1367,7 @@ var APPLICATIONS = {
|
|
|
1418
1367
|
"socialize.topolo.app"
|
|
1419
1368
|
],
|
|
1420
1369
|
"routes": [],
|
|
1421
|
-
"serviceId":
|
|
1370
|
+
"serviceId": "socialize"
|
|
1422
1371
|
},
|
|
1423
1372
|
{
|
|
1424
1373
|
"name": "topolo-socialize-api",
|
|
@@ -1428,7 +1377,7 @@ var APPLICATIONS = {
|
|
|
1428
1377
|
"socialize-api.topolo.app"
|
|
1429
1378
|
],
|
|
1430
1379
|
"routes": [],
|
|
1431
|
-
"serviceId":
|
|
1380
|
+
"serviceId": null
|
|
1432
1381
|
},
|
|
1433
1382
|
{
|
|
1434
1383
|
"name": "topolo-socialize-scheduler",
|
|
@@ -1629,12 +1578,10 @@ var APPLICATIONS = {
|
|
|
1629
1578
|
{
|
|
1630
1579
|
"name": "topolo-web-api",
|
|
1631
1580
|
"kind": "worker",
|
|
1632
|
-
"apiUrl":
|
|
1633
|
-
"domains": [
|
|
1634
|
-
"web-api.topolo.app"
|
|
1635
|
-
],
|
|
1581
|
+
"apiUrl": null,
|
|
1582
|
+
"domains": [],
|
|
1636
1583
|
"routes": [],
|
|
1637
|
-
"serviceId":
|
|
1584
|
+
"serviceId": null
|
|
1638
1585
|
},
|
|
1639
1586
|
{
|
|
1640
1587
|
"name": "topolo-web-runtime",
|
|
@@ -1657,7 +1604,7 @@ var APPLICATIONS = {
|
|
|
1657
1604
|
"web.topolo.app"
|
|
1658
1605
|
],
|
|
1659
1606
|
"routes": [],
|
|
1660
|
-
"serviceId":
|
|
1607
|
+
"serviceId": "web"
|
|
1661
1608
|
}
|
|
1662
1609
|
]
|
|
1663
1610
|
}
|
|
@@ -1720,16 +1667,20 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1720
1667
|
summary: "Browser applications should feel like one platform and should not create isolated navigation or account surfaces.",
|
|
1721
1668
|
appliesTo: ["browser"],
|
|
1722
1669
|
evidence: [
|
|
1723
|
-
"@topolo/
|
|
1724
|
-
"
|
|
1725
|
-
"Account menu and sign-out behavior use TopoloAppShell or TopoloAccountMenu",
|
|
1670
|
+
"@topolo-io/app-shell is used for the platform shell where the app has authenticated UI",
|
|
1671
|
+
"@topolo-io/app-launcher keeps the shared launcher/app switcher reachable from authenticated app chrome",
|
|
1672
|
+
"Account menu and sign-out behavior use TopoloAppShell or the ui-kit TopoloAccountMenu primitive",
|
|
1673
|
+
"Repeated app body surfaces use shared TopoloAppLayout primitives instead of local stat cards, empty states, or status badges",
|
|
1674
|
+
"Local preview supports deterministic visual QA fixtures for overview, list, detail, settings, and empty/loading states",
|
|
1726
1675
|
"Authenticated app body content stays inside the viewport on mobile and desktop widths"
|
|
1727
1676
|
],
|
|
1728
1677
|
implementation: [
|
|
1729
|
-
"Use TopoloAppShell for authenticated app layouts",
|
|
1730
|
-
"Use TopoloAccountMenu when a partial-shell surface still needs account chrome",
|
|
1678
|
+
"Use @topolo-io/app-shell TopoloAppShell for authenticated app layouts",
|
|
1679
|
+
"Use the @topolo-io/ui-kit TopoloAccountMenu primitive when a partial-shell surface still needs account chrome",
|
|
1731
1680
|
"Pass app-specific account actions as additive menu items instead of forking dropdowns",
|
|
1732
1681
|
"Use shared design tokens and platform UI primitives before creating local equivalents",
|
|
1682
|
+
"Use TopoloAppMetricCard, TopoloAppEmptyState, TopoloAppStatusBadge, TopoloAppGrid, and TopoloAppSection for repeated app body patterns",
|
|
1683
|
+
"Keep visual QA fixtures available through visualQa=1 or __devpreview=1 so screenshot checks do not depend on live API state",
|
|
1733
1684
|
"Keep mobile and desktop shell behavior aligned with the platform UI kit",
|
|
1734
1685
|
"Constrain app-owned workspace wrappers with min-width: 0, width: auto, and viewport-aware max-width so shell padding cannot create page-level horizontal overflow"
|
|
1735
1686
|
]
|
|
@@ -2111,6 +2062,8 @@ function firstString(...values) {
|
|
|
2111
2062
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
2112
2063
|
var TOPOLO_ACTION_ID_HEADER = "X-Topolo-Action-Id";
|
|
2113
2064
|
var TOPOLO_ACTION_NAME_HEADER = "X-Topolo-Action-Name";
|
|
2065
|
+
var TOPOLO_RESOURCE_TYPE_HEADER = "X-Topolo-Resource-Type";
|
|
2066
|
+
var TOPOLO_RESOURCE_ID_HEADER = "X-Topolo-Resource-ID";
|
|
2114
2067
|
var POSITIVE_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
2115
2068
|
var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
2116
2069
|
var CATALOG_CACHE_TTL_MS = 60 * 1e3;
|
|
@@ -2189,6 +2142,18 @@ var TopoloClient = class _TopoloClient {
|
|
|
2189
2142
|
if (opts.headers) {
|
|
2190
2143
|
for (const [k, v] of Object.entries(opts.headers)) headers.set(k, v);
|
|
2191
2144
|
}
|
|
2145
|
+
if (opts.resource) {
|
|
2146
|
+
const resourceType = opts.resource.resourceType.trim();
|
|
2147
|
+
const resourceId = opts.resource.resourceId.trim();
|
|
2148
|
+
if (!resourceType || !resourceId) {
|
|
2149
|
+
throw new TopoloSdkError(
|
|
2150
|
+
"invalid_resource_context",
|
|
2151
|
+
"Both resource.resourceType and resource.resourceId are required when resource context is provided."
|
|
2152
|
+
);
|
|
2153
|
+
}
|
|
2154
|
+
headers.set(TOPOLO_RESOURCE_TYPE_HEADER, resourceType);
|
|
2155
|
+
headers.set(TOPOLO_RESOURCE_ID_HEADER, resourceId);
|
|
2156
|
+
}
|
|
2192
2157
|
const controller = new AbortController();
|
|
2193
2158
|
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
2194
2159
|
const signal = opts.signal ? mergeSignals(opts.signal, controller.signal) : controller.signal;
|
|
@@ -2260,10 +2225,14 @@ var TopoloClient = class _TopoloClient {
|
|
|
2260
2225
|
if (!serviceKey) {
|
|
2261
2226
|
throw new TopoloSdkError("unknown_service", "service is required");
|
|
2262
2227
|
}
|
|
2263
|
-
if (serviceKey === "auth") {
|
|
2228
|
+
if (serviceKey === "auth" || serviceKey === "developers") {
|
|
2264
2229
|
const overrideUrl = resolveConfiguredServiceUrl(serviceKey, this.serviceUrls);
|
|
2265
2230
|
if (overrideUrl) return { serviceKey, baseUrl: overrideUrl };
|
|
2266
|
-
|
|
2231
|
+
if (serviceKey === "developers") {
|
|
2232
|
+
const derived = deriveDevelopersFromAuth(resolveConfiguredServiceUrl("auth", this.serviceUrls));
|
|
2233
|
+
if (derived) return { serviceKey, baseUrl: derived };
|
|
2234
|
+
}
|
|
2235
|
+
return { serviceKey, baseUrl: DEFAULT_SERVICE_URLS[serviceKey] };
|
|
2267
2236
|
}
|
|
2268
2237
|
const live = await this.resolveLiveCallableService(serviceKey);
|
|
2269
2238
|
if (live) {
|
|
@@ -2303,7 +2272,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2303
2272
|
if (!normalized) return null;
|
|
2304
2273
|
const configuredServiceId = resolveConfiguredServiceId(normalized, this.serviceIds);
|
|
2305
2274
|
if (configuredServiceId) return configuredServiceId;
|
|
2306
|
-
const authBase = resolveServiceUrl("
|
|
2275
|
+
const authBase = resolveServiceUrl("developers", this.serviceUrls);
|
|
2307
2276
|
const cacheKey = `${authBase}|${normalized}`;
|
|
2308
2277
|
const now = Date.now();
|
|
2309
2278
|
const cached = _TopoloClient.serviceIdCache.get(cacheKey);
|
|
@@ -2357,7 +2326,7 @@ var TopoloClient = class _TopoloClient {
|
|
|
2357
2326
|
if (this.serviceCatalogCache && this.serviceCatalogCache.expiresAt > now) {
|
|
2358
2327
|
return this.serviceCatalogCache.entries;
|
|
2359
2328
|
}
|
|
2360
|
-
const res = await this.request({ service: "
|
|
2329
|
+
const res = await this.request({ service: "developers", method: "GET", path: "/api/services/catalog" });
|
|
2361
2330
|
const raw = res.data?.services ?? res.services;
|
|
2362
2331
|
if (!Array.isArray(raw)) {
|
|
2363
2332
|
throw new TopoloSdkError(
|
|
@@ -2371,6 +2340,11 @@ var TopoloClient = class _TopoloClient {
|
|
|
2371
2340
|
const serviceId = typeof s.service_id === "string" ? s.service_id : typeof s.id === "string" ? s.id : null;
|
|
2372
2341
|
if (!serviceId) continue;
|
|
2373
2342
|
const permissions = Array.isArray(s.granted_permissions) ? s.granted_permissions.filter((permission) => typeof permission === "string" && permission.trim().length > 0) : [];
|
|
2343
|
+
const catalogApiKeyResources = normalizeApiKeyResourceMetadataList(
|
|
2344
|
+
s.api_key_resources ?? s.apiKeyResources
|
|
2345
|
+
);
|
|
2346
|
+
const apiKeyResource = normalizeApiKeyResourceMetadata(s.api_key_resource ?? s.apiKeyResource) ?? catalogApiKeyResources[0] ?? null;
|
|
2347
|
+
const apiKeyResources = catalogApiKeyResources.length > 0 ? catalogApiKeyResources : apiKeyResource ? [apiKeyResource] : [];
|
|
2374
2348
|
entries.push({
|
|
2375
2349
|
serviceId,
|
|
2376
2350
|
slug: typeof s.app_slug === "string" ? s.app_slug : null,
|
|
@@ -2381,7 +2355,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
2381
2355
|
status: typeof s.status === "string" ? s.status : null,
|
|
2382
2356
|
surfaceKind: typeof s.surface_kind === "string" ? s.surface_kind : null,
|
|
2383
2357
|
launchable: s.launchable === true,
|
|
2384
|
-
permissions
|
|
2358
|
+
permissions,
|
|
2359
|
+
apiKeyResource,
|
|
2360
|
+
apiKeyResources
|
|
2385
2361
|
});
|
|
2386
2362
|
}
|
|
2387
2363
|
this.serviceCatalogCache = {
|
|
@@ -2467,7 +2443,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
2467
2443
|
status: "bundled",
|
|
2468
2444
|
surfaceKind: "application",
|
|
2469
2445
|
launchable: Boolean(app.productionUrl),
|
|
2470
|
-
permissions: []
|
|
2446
|
+
permissions: [],
|
|
2447
|
+
apiKeyResource: null,
|
|
2448
|
+
apiKeyResources: []
|
|
2471
2449
|
}));
|
|
2472
2450
|
}
|
|
2473
2451
|
/**
|
|
@@ -2516,6 +2494,46 @@ function resolveConfiguredServiceId(slug, serviceIds) {
|
|
|
2516
2494
|
}
|
|
2517
2495
|
return null;
|
|
2518
2496
|
}
|
|
2497
|
+
function normalizeApiKeyResourceMetadata(input) {
|
|
2498
|
+
if (!isRecord(input)) return null;
|
|
2499
|
+
const resourceType = readString(input.resourceType ?? input.resource_type);
|
|
2500
|
+
const label = readString(input.label);
|
|
2501
|
+
const emptyLabel = readString(input.emptyLabel ?? input.empty_label);
|
|
2502
|
+
const resourceConcept = readString(input.resourceConcept ?? input.resource_concept);
|
|
2503
|
+
const canonicalResourceType = readString(input.canonicalResourceType ?? input.canonical_resource_type);
|
|
2504
|
+
const defaultEntitlement = readString(input.defaultEntitlement ?? input.default_entitlement);
|
|
2505
|
+
const exceptionPolicy = readString(input.exceptionPolicy ?? input.exception_policy);
|
|
2506
|
+
if (!resourceType || !label || !emptyLabel || resourceConcept !== "workspace" || canonicalResourceType !== "workspace" || defaultEntitlement !== "enterprise" || exceptionPolicy !== "app_or_organization") {
|
|
2507
|
+
return null;
|
|
2508
|
+
}
|
|
2509
|
+
return {
|
|
2510
|
+
resourceType,
|
|
2511
|
+
label,
|
|
2512
|
+
emptyLabel,
|
|
2513
|
+
resourceConcept,
|
|
2514
|
+
canonicalResourceType,
|
|
2515
|
+
defaultEntitlement,
|
|
2516
|
+
exceptionPolicy
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
function normalizeApiKeyResourceMetadataList(input) {
|
|
2520
|
+
if (!Array.isArray(input)) return [];
|
|
2521
|
+
const resources = [];
|
|
2522
|
+
const seenTypes = /* @__PURE__ */ new Set();
|
|
2523
|
+
for (const item of input) {
|
|
2524
|
+
const resource = normalizeApiKeyResourceMetadata(item);
|
|
2525
|
+
if (!resource || seenTypes.has(resource.resourceType)) continue;
|
|
2526
|
+
seenTypes.add(resource.resourceType);
|
|
2527
|
+
resources.push(resource);
|
|
2528
|
+
}
|
|
2529
|
+
return resources;
|
|
2530
|
+
}
|
|
2531
|
+
function readString(value) {
|
|
2532
|
+
return typeof value === "string" ? value.trim() : "";
|
|
2533
|
+
}
|
|
2534
|
+
function isRecord(value) {
|
|
2535
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2536
|
+
}
|
|
2519
2537
|
function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
2520
2538
|
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
2521
2539
|
const configured = serviceUrls?.[serviceKey];
|
|
@@ -2539,6 +2557,17 @@ function serviceKeyCandidates2(slug) {
|
|
|
2539
2557
|
function normalizeLookupKey(value) {
|
|
2540
2558
|
return String(value || "").trim().toLowerCase().replace(/\s+/g, "-");
|
|
2541
2559
|
}
|
|
2560
|
+
function deriveDevelopersFromAuth(authUrl) {
|
|
2561
|
+
if (!authUrl) return null;
|
|
2562
|
+
try {
|
|
2563
|
+
const url = new URL(authUrl);
|
|
2564
|
+
if (!/^auth\./i.test(url.hostname)) return null;
|
|
2565
|
+
url.hostname = url.hostname.replace(/^auth\./i, "developers.");
|
|
2566
|
+
return url.origin;
|
|
2567
|
+
} catch {
|
|
2568
|
+
return null;
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2542
2571
|
function catalogEntryMatches(entry, needle) {
|
|
2543
2572
|
return catalogEntryLookupKeys(entry).includes(needle);
|
|
2544
2573
|
}
|
|
@@ -2686,7 +2715,6 @@ var CrmModule = class {
|
|
|
2686
2715
|
constructor(client) {
|
|
2687
2716
|
this.client = client;
|
|
2688
2717
|
}
|
|
2689
|
-
client;
|
|
2690
2718
|
async listContacts(options = {}) {
|
|
2691
2719
|
const res = await this.client.request({
|
|
2692
2720
|
service: "crm",
|
|
@@ -2734,7 +2762,6 @@ var IdentityModule = class {
|
|
|
2734
2762
|
constructor(client) {
|
|
2735
2763
|
this.client = client;
|
|
2736
2764
|
}
|
|
2737
|
-
client;
|
|
2738
2765
|
/** Returns the resolved user, organization, and permission set for the
|
|
2739
2766
|
* current credential. Equivalent to `TopoloClient.introspect()` — exposed
|
|
2740
2767
|
* on this module for symmetry with the other domain modules. */
|
|
@@ -2748,7 +2775,6 @@ var P2PModule = class {
|
|
|
2748
2775
|
constructor(client) {
|
|
2749
2776
|
this.client = client;
|
|
2750
2777
|
}
|
|
2751
|
-
client;
|
|
2752
2778
|
// Directory ----------------------------------------------------------------
|
|
2753
2779
|
async listDirectory(options = {}) {
|
|
2754
2780
|
const res = await this.client.request({
|
|
@@ -3083,7 +3109,7 @@ function createTopoloWidgetError(error) {
|
|
|
3083
3109
|
}
|
|
3084
3110
|
function validateTopoloWidgetResponse(response) {
|
|
3085
3111
|
const errors = [];
|
|
3086
|
-
if (!
|
|
3112
|
+
if (!isRecord2(response)) {
|
|
3087
3113
|
return { ok: false, errors: ["response must be an object"] };
|
|
3088
3114
|
}
|
|
3089
3115
|
if (typeof response.success !== "boolean") {
|
|
@@ -3102,7 +3128,7 @@ function validateTopoloWidgetResponse(response) {
|
|
|
3102
3128
|
return { ok: errors.length === 0, errors };
|
|
3103
3129
|
}
|
|
3104
3130
|
function validateWidget(widget, path, errors) {
|
|
3105
|
-
if (!
|
|
3131
|
+
if (!isRecord2(widget)) {
|
|
3106
3132
|
errors.push(`${path} must be an object`);
|
|
3107
3133
|
return;
|
|
3108
3134
|
}
|
|
@@ -3129,7 +3155,7 @@ function validateWidget(widget, path, errors) {
|
|
|
3129
3155
|
case "chart":
|
|
3130
3156
|
validateNonEmptyString(widget.chartType, `${path}.chartType`, errors);
|
|
3131
3157
|
validateNonEmptyString(widget.title, `${path}.title`, errors);
|
|
3132
|
-
if (!
|
|
3158
|
+
if (!isRecord2(widget.data)) {
|
|
3133
3159
|
errors.push(`${path}.data must be an object`);
|
|
3134
3160
|
} else {
|
|
3135
3161
|
validateArray(widget.data.labels, `${path}.data.labels`, errors);
|
|
@@ -3145,7 +3171,7 @@ function validateSnapshotMetadata(snapshot, path, errors) {
|
|
|
3145
3171
|
errors.push(`${path} must be an object`);
|
|
3146
3172
|
return;
|
|
3147
3173
|
}
|
|
3148
|
-
if (!
|
|
3174
|
+
if (!isRecord2(snapshot)) {
|
|
3149
3175
|
errors.push(`${path} must be an object`);
|
|
3150
3176
|
return;
|
|
3151
3177
|
}
|
|
@@ -3165,7 +3191,7 @@ function validateSnapshotMetadata(snapshot, path, errors) {
|
|
|
3165
3191
|
}
|
|
3166
3192
|
snapshot.availableMetrics.forEach((metric, index) => {
|
|
3167
3193
|
const metricPath = `${path}.availableMetrics[${index}]`;
|
|
3168
|
-
if (!
|
|
3194
|
+
if (!isRecord2(metric)) {
|
|
3169
3195
|
errors.push(`${metricPath} must be an object`);
|
|
3170
3196
|
return;
|
|
3171
3197
|
}
|
|
@@ -3186,7 +3212,7 @@ function validateArray(value, path, errors) {
|
|
|
3186
3212
|
errors.push(`${path} must be an array`);
|
|
3187
3213
|
}
|
|
3188
3214
|
}
|
|
3189
|
-
function
|
|
3215
|
+
function isRecord2(value) {
|
|
3190
3216
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3191
3217
|
}
|
|
3192
3218
|
function toIsoTimestamp(input) {
|