@topolo/sdk 0.4.7 → 0.4.8
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 +145 -135
- package/dist/index.d.cts +84 -92
- package/dist/index.d.ts +84 -92
- package/dist/index.js +145 -135
- package/package.json +1 -1
- package/src/application-requirements.ts +9 -5
- package/src/applications.generated.ts +52 -108
- package/src/client.test.ts +74 -0
- package/src/client.ts +101 -0
- 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 +13 -14
- package/src/services.test.ts +18 -7
- package/src/widgets.test.ts +216 -0
package/dist/index.js
CHANGED
|
@@ -58,32 +58,32 @@ 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
88
|
nexus: "https://nexus-api.topolo.app",
|
|
89
89
|
notify: "https://notify.topolo.app",
|
|
@@ -92,20 +92,19 @@ var SERVICES = {
|
|
|
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
|
},
|
|
@@ -645,12 +636,10 @@ var APPLICATIONS = {
|
|
|
645
636
|
{
|
|
646
637
|
"name": "topolo-feed-api",
|
|
647
638
|
"kind": "worker",
|
|
648
|
-
"apiUrl":
|
|
649
|
-
"domains": [
|
|
650
|
-
"feed-api.topolo.app"
|
|
651
|
-
],
|
|
639
|
+
"apiUrl": null,
|
|
640
|
+
"domains": [],
|
|
652
641
|
"routes": [],
|
|
653
|
-
"serviceId":
|
|
642
|
+
"serviceId": null
|
|
654
643
|
},
|
|
655
644
|
{
|
|
656
645
|
"name": "topolo-feed-web",
|
|
@@ -660,7 +649,7 @@ var APPLICATIONS = {
|
|
|
660
649
|
"feed.topolo.app"
|
|
661
650
|
],
|
|
662
651
|
"routes": [],
|
|
663
|
-
"serviceId":
|
|
652
|
+
"serviceId": "feed"
|
|
664
653
|
}
|
|
665
654
|
]
|
|
666
655
|
},
|
|
@@ -712,17 +701,15 @@ var APPLICATIONS = {
|
|
|
712
701
|
"forecast.topolo.app"
|
|
713
702
|
],
|
|
714
703
|
"routes": [],
|
|
715
|
-
"serviceId":
|
|
704
|
+
"serviceId": "forecast"
|
|
716
705
|
},
|
|
717
706
|
{
|
|
718
707
|
"name": "topolo-forecast-api",
|
|
719
708
|
"kind": "worker",
|
|
720
|
-
"apiUrl":
|
|
721
|
-
"domains": [
|
|
722
|
-
"forecast-api.topolo.app"
|
|
723
|
-
],
|
|
709
|
+
"apiUrl": null,
|
|
710
|
+
"domains": [],
|
|
724
711
|
"routes": [],
|
|
725
|
-
"serviceId":
|
|
712
|
+
"serviceId": null
|
|
726
713
|
}
|
|
727
714
|
]
|
|
728
715
|
},
|
|
@@ -864,17 +851,15 @@ var APPLICATIONS = {
|
|
|
864
851
|
"learn.topolo.app"
|
|
865
852
|
],
|
|
866
853
|
"routes": [],
|
|
867
|
-
"serviceId":
|
|
854
|
+
"serviceId": "learn"
|
|
868
855
|
},
|
|
869
856
|
{
|
|
870
857
|
"name": "topolo-learn-api",
|
|
871
858
|
"kind": "worker",
|
|
872
|
-
"apiUrl":
|
|
873
|
-
"domains": [
|
|
874
|
-
"learn-api.topolo.app"
|
|
875
|
-
],
|
|
859
|
+
"apiUrl": null,
|
|
860
|
+
"domains": [],
|
|
876
861
|
"routes": [],
|
|
877
|
-
"serviceId":
|
|
862
|
+
"serviceId": null
|
|
878
863
|
}
|
|
879
864
|
]
|
|
880
865
|
},
|
|
@@ -920,17 +905,15 @@ var APPLICATIONS = {
|
|
|
920
905
|
"mail.topolo.app"
|
|
921
906
|
],
|
|
922
907
|
"routes": [],
|
|
923
|
-
"serviceId":
|
|
908
|
+
"serviceId": "mail"
|
|
924
909
|
},
|
|
925
910
|
{
|
|
926
911
|
"name": "topolo-mail-api",
|
|
927
912
|
"kind": "worker",
|
|
928
|
-
"apiUrl":
|
|
929
|
-
"domains": [
|
|
930
|
-
"mail-api.topolo.app"
|
|
931
|
-
],
|
|
913
|
+
"apiUrl": null,
|
|
914
|
+
"domains": [],
|
|
932
915
|
"routes": [],
|
|
933
|
-
"serviceId":
|
|
916
|
+
"serviceId": null
|
|
934
917
|
}
|
|
935
918
|
]
|
|
936
919
|
},
|
|
@@ -947,12 +930,10 @@ var APPLICATIONS = {
|
|
|
947
930
|
{
|
|
948
931
|
"name": "topolo-mdm-api",
|
|
949
932
|
"kind": "worker",
|
|
950
|
-
"apiUrl":
|
|
951
|
-
"domains": [
|
|
952
|
-
"mdm-api.topolo.app"
|
|
953
|
-
],
|
|
933
|
+
"apiUrl": null,
|
|
934
|
+
"domains": [],
|
|
954
935
|
"routes": [],
|
|
955
|
-
"serviceId":
|
|
936
|
+
"serviceId": null
|
|
956
937
|
},
|
|
957
938
|
{
|
|
958
939
|
"name": "topolo-mdm-console",
|
|
@@ -962,7 +943,7 @@ var APPLICATIONS = {
|
|
|
962
943
|
"mdm.topolo.app"
|
|
963
944
|
],
|
|
964
945
|
"routes": [],
|
|
965
|
-
"serviceId":
|
|
946
|
+
"serviceId": "mdm"
|
|
966
947
|
}
|
|
967
948
|
]
|
|
968
949
|
},
|
|
@@ -1221,36 +1202,6 @@ var APPLICATIONS = {
|
|
|
1221
1202
|
}
|
|
1222
1203
|
]
|
|
1223
1204
|
},
|
|
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
1205
|
"quro": {
|
|
1255
1206
|
"id": "quro",
|
|
1256
1207
|
"appDir": "TopoloQuro",
|
|
@@ -1316,17 +1267,15 @@ var APPLICATIONS = {
|
|
|
1316
1267
|
"roadmapper.topolo.app"
|
|
1317
1268
|
],
|
|
1318
1269
|
"routes": [],
|
|
1319
|
-
"serviceId":
|
|
1270
|
+
"serviceId": "roadmapper"
|
|
1320
1271
|
},
|
|
1321
1272
|
{
|
|
1322
1273
|
"name": "topolo-roadmapper-api",
|
|
1323
1274
|
"kind": "worker",
|
|
1324
|
-
"apiUrl":
|
|
1325
|
-
"domains": [
|
|
1326
|
-
"roadmapper-api.topolo.app"
|
|
1327
|
-
],
|
|
1275
|
+
"apiUrl": null,
|
|
1276
|
+
"domains": [],
|
|
1328
1277
|
"routes": [],
|
|
1329
|
-
"serviceId":
|
|
1278
|
+
"serviceId": null
|
|
1330
1279
|
}
|
|
1331
1280
|
]
|
|
1332
1281
|
},
|
|
@@ -1378,17 +1327,15 @@ var APPLICATIONS = {
|
|
|
1378
1327
|
"studio.topolo.app"
|
|
1379
1328
|
],
|
|
1380
1329
|
"routes": [],
|
|
1381
|
-
"serviceId":
|
|
1330
|
+
"serviceId": "social_studio"
|
|
1382
1331
|
},
|
|
1383
1332
|
{
|
|
1384
1333
|
"name": "topolo-social-studio-api",
|
|
1385
1334
|
"kind": "worker",
|
|
1386
|
-
"apiUrl":
|
|
1387
|
-
"domains": [
|
|
1388
|
-
"studio-api.topolo.app"
|
|
1389
|
-
],
|
|
1335
|
+
"apiUrl": null,
|
|
1336
|
+
"domains": [],
|
|
1390
1337
|
"routes": [],
|
|
1391
|
-
"serviceId":
|
|
1338
|
+
"serviceId": null
|
|
1392
1339
|
},
|
|
1393
1340
|
{
|
|
1394
1341
|
"name": "topolo-social-studio-queue",
|
|
@@ -1418,17 +1365,15 @@ var APPLICATIONS = {
|
|
|
1418
1365
|
"socialize.topolo.app"
|
|
1419
1366
|
],
|
|
1420
1367
|
"routes": [],
|
|
1421
|
-
"serviceId":
|
|
1368
|
+
"serviceId": "socialize"
|
|
1422
1369
|
},
|
|
1423
1370
|
{
|
|
1424
1371
|
"name": "topolo-socialize-api",
|
|
1425
1372
|
"kind": "worker",
|
|
1426
|
-
"apiUrl":
|
|
1427
|
-
"domains": [
|
|
1428
|
-
"socialize-api.topolo.app"
|
|
1429
|
-
],
|
|
1373
|
+
"apiUrl": null,
|
|
1374
|
+
"domains": [],
|
|
1430
1375
|
"routes": [],
|
|
1431
|
-
"serviceId":
|
|
1376
|
+
"serviceId": null
|
|
1432
1377
|
},
|
|
1433
1378
|
{
|
|
1434
1379
|
"name": "topolo-socialize-scheduler",
|
|
@@ -1629,12 +1574,10 @@ var APPLICATIONS = {
|
|
|
1629
1574
|
{
|
|
1630
1575
|
"name": "topolo-web-api",
|
|
1631
1576
|
"kind": "worker",
|
|
1632
|
-
"apiUrl":
|
|
1633
|
-
"domains": [
|
|
1634
|
-
"web-api.topolo.app"
|
|
1635
|
-
],
|
|
1577
|
+
"apiUrl": null,
|
|
1578
|
+
"domains": [],
|
|
1636
1579
|
"routes": [],
|
|
1637
|
-
"serviceId":
|
|
1580
|
+
"serviceId": null
|
|
1638
1581
|
},
|
|
1639
1582
|
{
|
|
1640
1583
|
"name": "topolo-web-runtime",
|
|
@@ -1657,7 +1600,7 @@ var APPLICATIONS = {
|
|
|
1657
1600
|
"web.topolo.app"
|
|
1658
1601
|
],
|
|
1659
1602
|
"routes": [],
|
|
1660
|
-
"serviceId":
|
|
1603
|
+
"serviceId": "web"
|
|
1661
1604
|
}
|
|
1662
1605
|
]
|
|
1663
1606
|
}
|
|
@@ -1720,16 +1663,20 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1720
1663
|
summary: "Browser applications should feel like one platform and should not create isolated navigation or account surfaces.",
|
|
1721
1664
|
appliesTo: ["browser"],
|
|
1722
1665
|
evidence: [
|
|
1723
|
-
"@topolo/
|
|
1724
|
-
"
|
|
1725
|
-
"Account menu and sign-out behavior use TopoloAppShell or TopoloAccountMenu",
|
|
1666
|
+
"@topolo-io/app-shell is used for the platform shell where the app has authenticated UI",
|
|
1667
|
+
"@topolo-io/app-launcher keeps the shared launcher/app switcher reachable from authenticated app chrome",
|
|
1668
|
+
"Account menu and sign-out behavior use TopoloAppShell or the ui-kit TopoloAccountMenu primitive",
|
|
1669
|
+
"Repeated app body surfaces use shared TopoloAppLayout primitives instead of local stat cards, empty states, or status badges",
|
|
1670
|
+
"Local preview supports deterministic visual QA fixtures for overview, list, detail, settings, and empty/loading states",
|
|
1726
1671
|
"Authenticated app body content stays inside the viewport on mobile and desktop widths"
|
|
1727
1672
|
],
|
|
1728
1673
|
implementation: [
|
|
1729
|
-
"Use TopoloAppShell for authenticated app layouts",
|
|
1730
|
-
"Use TopoloAccountMenu when a partial-shell surface still needs account chrome",
|
|
1674
|
+
"Use @topolo-io/app-shell TopoloAppShell for authenticated app layouts",
|
|
1675
|
+
"Use the @topolo-io/ui-kit TopoloAccountMenu primitive when a partial-shell surface still needs account chrome",
|
|
1731
1676
|
"Pass app-specific account actions as additive menu items instead of forking dropdowns",
|
|
1732
1677
|
"Use shared design tokens and platform UI primitives before creating local equivalents",
|
|
1678
|
+
"Use TopoloAppMetricCard, TopoloAppEmptyState, TopoloAppStatusBadge, TopoloAppGrid, and TopoloAppSection for repeated app body patterns",
|
|
1679
|
+
"Keep visual QA fixtures available through visualQa=1 or __devpreview=1 so screenshot checks do not depend on live API state",
|
|
1733
1680
|
"Keep mobile and desktop shell behavior aligned with the platform UI kit",
|
|
1734
1681
|
"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
1682
|
]
|
|
@@ -2111,6 +2058,8 @@ function firstString(...values) {
|
|
|
2111
2058
|
var WRITE_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
2112
2059
|
var TOPOLO_ACTION_ID_HEADER = "X-Topolo-Action-Id";
|
|
2113
2060
|
var TOPOLO_ACTION_NAME_HEADER = "X-Topolo-Action-Name";
|
|
2061
|
+
var TOPOLO_RESOURCE_TYPE_HEADER = "X-Topolo-Resource-Type";
|
|
2062
|
+
var TOPOLO_RESOURCE_ID_HEADER = "X-Topolo-Resource-ID";
|
|
2114
2063
|
var POSITIVE_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
2115
2064
|
var NEGATIVE_CACHE_TTL_MS = 60 * 1e3;
|
|
2116
2065
|
var CATALOG_CACHE_TTL_MS = 60 * 1e3;
|
|
@@ -2189,6 +2138,18 @@ var TopoloClient = class _TopoloClient {
|
|
|
2189
2138
|
if (opts.headers) {
|
|
2190
2139
|
for (const [k, v] of Object.entries(opts.headers)) headers.set(k, v);
|
|
2191
2140
|
}
|
|
2141
|
+
if (opts.resource) {
|
|
2142
|
+
const resourceType = opts.resource.resourceType.trim();
|
|
2143
|
+
const resourceId = opts.resource.resourceId.trim();
|
|
2144
|
+
if (!resourceType || !resourceId) {
|
|
2145
|
+
throw new TopoloSdkError(
|
|
2146
|
+
"invalid_resource_context",
|
|
2147
|
+
"Both resource.resourceType and resource.resourceId are required when resource context is provided."
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
headers.set(TOPOLO_RESOURCE_TYPE_HEADER, resourceType);
|
|
2151
|
+
headers.set(TOPOLO_RESOURCE_ID_HEADER, resourceId);
|
|
2152
|
+
}
|
|
2192
2153
|
const controller = new AbortController();
|
|
2193
2154
|
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
2194
2155
|
const signal = opts.signal ? mergeSignals(opts.signal, controller.signal) : controller.signal;
|
|
@@ -2371,6 +2332,11 @@ var TopoloClient = class _TopoloClient {
|
|
|
2371
2332
|
const serviceId = typeof s.service_id === "string" ? s.service_id : typeof s.id === "string" ? s.id : null;
|
|
2372
2333
|
if (!serviceId) continue;
|
|
2373
2334
|
const permissions = Array.isArray(s.granted_permissions) ? s.granted_permissions.filter((permission) => typeof permission === "string" && permission.trim().length > 0) : [];
|
|
2335
|
+
const catalogApiKeyResources = normalizeApiKeyResourceMetadataList(
|
|
2336
|
+
s.api_key_resources ?? s.apiKeyResources
|
|
2337
|
+
);
|
|
2338
|
+
const apiKeyResource = normalizeApiKeyResourceMetadata(s.api_key_resource ?? s.apiKeyResource) ?? catalogApiKeyResources[0] ?? null;
|
|
2339
|
+
const apiKeyResources = catalogApiKeyResources.length > 0 ? catalogApiKeyResources : apiKeyResource ? [apiKeyResource] : [];
|
|
2374
2340
|
entries.push({
|
|
2375
2341
|
serviceId,
|
|
2376
2342
|
slug: typeof s.app_slug === "string" ? s.app_slug : null,
|
|
@@ -2381,7 +2347,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
2381
2347
|
status: typeof s.status === "string" ? s.status : null,
|
|
2382
2348
|
surfaceKind: typeof s.surface_kind === "string" ? s.surface_kind : null,
|
|
2383
2349
|
launchable: s.launchable === true,
|
|
2384
|
-
permissions
|
|
2350
|
+
permissions,
|
|
2351
|
+
apiKeyResource,
|
|
2352
|
+
apiKeyResources
|
|
2385
2353
|
});
|
|
2386
2354
|
}
|
|
2387
2355
|
this.serviceCatalogCache = {
|
|
@@ -2467,7 +2435,9 @@ var TopoloClient = class _TopoloClient {
|
|
|
2467
2435
|
status: "bundled",
|
|
2468
2436
|
surfaceKind: "application",
|
|
2469
2437
|
launchable: Boolean(app.productionUrl),
|
|
2470
|
-
permissions: []
|
|
2438
|
+
permissions: [],
|
|
2439
|
+
apiKeyResource: null,
|
|
2440
|
+
apiKeyResources: []
|
|
2471
2441
|
}));
|
|
2472
2442
|
}
|
|
2473
2443
|
/**
|
|
@@ -2516,6 +2486,46 @@ function resolveConfiguredServiceId(slug, serviceIds) {
|
|
|
2516
2486
|
}
|
|
2517
2487
|
return null;
|
|
2518
2488
|
}
|
|
2489
|
+
function normalizeApiKeyResourceMetadata(input) {
|
|
2490
|
+
if (!isRecord(input)) return null;
|
|
2491
|
+
const resourceType = readString(input.resourceType ?? input.resource_type);
|
|
2492
|
+
const label = readString(input.label);
|
|
2493
|
+
const emptyLabel = readString(input.emptyLabel ?? input.empty_label);
|
|
2494
|
+
const resourceConcept = readString(input.resourceConcept ?? input.resource_concept);
|
|
2495
|
+
const canonicalResourceType = readString(input.canonicalResourceType ?? input.canonical_resource_type);
|
|
2496
|
+
const defaultEntitlement = readString(input.defaultEntitlement ?? input.default_entitlement);
|
|
2497
|
+
const exceptionPolicy = readString(input.exceptionPolicy ?? input.exception_policy);
|
|
2498
|
+
if (!resourceType || !label || !emptyLabel || resourceConcept !== "workspace" || canonicalResourceType !== "workspace" || defaultEntitlement !== "enterprise" || exceptionPolicy !== "app_or_organization") {
|
|
2499
|
+
return null;
|
|
2500
|
+
}
|
|
2501
|
+
return {
|
|
2502
|
+
resourceType,
|
|
2503
|
+
label,
|
|
2504
|
+
emptyLabel,
|
|
2505
|
+
resourceConcept,
|
|
2506
|
+
canonicalResourceType,
|
|
2507
|
+
defaultEntitlement,
|
|
2508
|
+
exceptionPolicy
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
function normalizeApiKeyResourceMetadataList(input) {
|
|
2512
|
+
if (!Array.isArray(input)) return [];
|
|
2513
|
+
const resources = [];
|
|
2514
|
+
const seenTypes = /* @__PURE__ */ new Set();
|
|
2515
|
+
for (const item of input) {
|
|
2516
|
+
const resource = normalizeApiKeyResourceMetadata(item);
|
|
2517
|
+
if (!resource || seenTypes.has(resource.resourceType)) continue;
|
|
2518
|
+
seenTypes.add(resource.resourceType);
|
|
2519
|
+
resources.push(resource);
|
|
2520
|
+
}
|
|
2521
|
+
return resources;
|
|
2522
|
+
}
|
|
2523
|
+
function readString(value) {
|
|
2524
|
+
return typeof value === "string" ? value.trim() : "";
|
|
2525
|
+
}
|
|
2526
|
+
function isRecord(value) {
|
|
2527
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2528
|
+
}
|
|
2519
2529
|
function resolveConfiguredServiceUrl(slug, serviceUrls) {
|
|
2520
2530
|
for (const serviceKey of serviceKeyCandidates2(slug)) {
|
|
2521
2531
|
const configured = serviceUrls?.[serviceKey];
|
|
@@ -3083,7 +3093,7 @@ function createTopoloWidgetError(error) {
|
|
|
3083
3093
|
}
|
|
3084
3094
|
function validateTopoloWidgetResponse(response) {
|
|
3085
3095
|
const errors = [];
|
|
3086
|
-
if (!
|
|
3096
|
+
if (!isRecord2(response)) {
|
|
3087
3097
|
return { ok: false, errors: ["response must be an object"] };
|
|
3088
3098
|
}
|
|
3089
3099
|
if (typeof response.success !== "boolean") {
|
|
@@ -3102,7 +3112,7 @@ function validateTopoloWidgetResponse(response) {
|
|
|
3102
3112
|
return { ok: errors.length === 0, errors };
|
|
3103
3113
|
}
|
|
3104
3114
|
function validateWidget(widget, path, errors) {
|
|
3105
|
-
if (!
|
|
3115
|
+
if (!isRecord2(widget)) {
|
|
3106
3116
|
errors.push(`${path} must be an object`);
|
|
3107
3117
|
return;
|
|
3108
3118
|
}
|
|
@@ -3129,7 +3139,7 @@ function validateWidget(widget, path, errors) {
|
|
|
3129
3139
|
case "chart":
|
|
3130
3140
|
validateNonEmptyString(widget.chartType, `${path}.chartType`, errors);
|
|
3131
3141
|
validateNonEmptyString(widget.title, `${path}.title`, errors);
|
|
3132
|
-
if (!
|
|
3142
|
+
if (!isRecord2(widget.data)) {
|
|
3133
3143
|
errors.push(`${path}.data must be an object`);
|
|
3134
3144
|
} else {
|
|
3135
3145
|
validateArray(widget.data.labels, `${path}.data.labels`, errors);
|
|
@@ -3145,7 +3155,7 @@ function validateSnapshotMetadata(snapshot, path, errors) {
|
|
|
3145
3155
|
errors.push(`${path} must be an object`);
|
|
3146
3156
|
return;
|
|
3147
3157
|
}
|
|
3148
|
-
if (!
|
|
3158
|
+
if (!isRecord2(snapshot)) {
|
|
3149
3159
|
errors.push(`${path} must be an object`);
|
|
3150
3160
|
return;
|
|
3151
3161
|
}
|
|
@@ -3165,7 +3175,7 @@ function validateSnapshotMetadata(snapshot, path, errors) {
|
|
|
3165
3175
|
}
|
|
3166
3176
|
snapshot.availableMetrics.forEach((metric, index) => {
|
|
3167
3177
|
const metricPath = `${path}.availableMetrics[${index}]`;
|
|
3168
|
-
if (!
|
|
3178
|
+
if (!isRecord2(metric)) {
|
|
3169
3179
|
errors.push(`${metricPath} must be an object`);
|
|
3170
3180
|
return;
|
|
3171
3181
|
}
|
|
@@ -3186,7 +3196,7 @@ function validateArray(value, path, errors) {
|
|
|
3186
3196
|
errors.push(`${path} must be an array`);
|
|
3187
3197
|
}
|
|
3188
3198
|
}
|
|
3189
|
-
function
|
|
3199
|
+
function isRecord2(value) {
|
|
3190
3200
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3191
3201
|
}
|
|
3192
3202
|
function toIsoTimestamp(input) {
|
package/package.json
CHANGED
|
@@ -125,16 +125,20 @@ export const APPLICATION_REQUIREMENTS = [
|
|
|
125
125
|
'Browser applications should feel like one platform and should not create isolated navigation or account surfaces.',
|
|
126
126
|
appliesTo: ['browser'],
|
|
127
127
|
evidence: [
|
|
128
|
-
'@topolo/
|
|
129
|
-
'
|
|
130
|
-
'Account menu and sign-out behavior use TopoloAppShell or TopoloAccountMenu',
|
|
128
|
+
'@topolo-io/app-shell is used for the platform shell where the app has authenticated UI',
|
|
129
|
+
'@topolo-io/app-launcher keeps the shared launcher/app switcher reachable from authenticated app chrome',
|
|
130
|
+
'Account menu and sign-out behavior use TopoloAppShell or the ui-kit TopoloAccountMenu primitive',
|
|
131
|
+
'Repeated app body surfaces use shared TopoloAppLayout primitives instead of local stat cards, empty states, or status badges',
|
|
132
|
+
'Local preview supports deterministic visual QA fixtures for overview, list, detail, settings, and empty/loading states',
|
|
131
133
|
'Authenticated app body content stays inside the viewport on mobile and desktop widths',
|
|
132
134
|
],
|
|
133
135
|
implementation: [
|
|
134
|
-
'Use TopoloAppShell for authenticated app layouts',
|
|
135
|
-
'Use TopoloAccountMenu when a partial-shell surface still needs account chrome',
|
|
136
|
+
'Use @topolo-io/app-shell TopoloAppShell for authenticated app layouts',
|
|
137
|
+
'Use the @topolo-io/ui-kit TopoloAccountMenu primitive when a partial-shell surface still needs account chrome',
|
|
136
138
|
'Pass app-specific account actions as additive menu items instead of forking dropdowns',
|
|
137
139
|
'Use shared design tokens and platform UI primitives before creating local equivalents',
|
|
140
|
+
'Use TopoloAppMetricCard, TopoloAppEmptyState, TopoloAppStatusBadge, TopoloAppGrid, and TopoloAppSection for repeated app body patterns',
|
|
141
|
+
'Keep visual QA fixtures available through visualQa=1 or __devpreview=1 so screenshot checks do not depend on live API state',
|
|
138
142
|
'Keep mobile and desktop shell behavior aligned with the platform UI kit',
|
|
139
143
|
'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',
|
|
140
144
|
],
|