@topolo/sdk 0.2.4 → 0.2.6
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/README.md +23 -0
- package/dist/index.cjs +440 -18
- package/dist/index.d.cts +338 -59
- package/dist/index.d.ts +338 -59
- package/dist/index.js +428 -17
- package/package.json +1 -1
- package/src/application-requirements.ts +27 -5
- package/src/applications.generated.ts +243 -1
- package/src/index.ts +29 -0
- package/src/services.generated.ts +20 -0
- package/src/services.test.ts +27 -0
- package/src/widgets.test.ts +123 -0
- package/src/widgets.ts +288 -0
package/dist/index.js
CHANGED
|
@@ -60,14 +60,20 @@ var TopoloHttpError = class extends TopoloSdkError {
|
|
|
60
60
|
var SERVICES = {
|
|
61
61
|
agent: "https://topolo-agent-worker.topolo.workers.dev",
|
|
62
62
|
auth: "https://auth.topolo.app",
|
|
63
|
+
books: "https://books.topolo.app",
|
|
63
64
|
bugfix: "https://bugfix.topolo.app",
|
|
64
65
|
bytes: "https://r2-media-manager-worker.topolo.workers.dev",
|
|
65
66
|
calendar: "https://calendar.topolo.app",
|
|
66
67
|
chat: "https://chat.topolo.app",
|
|
67
68
|
commerce: "https://topolo-commerce-api.topolo.workers.dev",
|
|
68
69
|
crm: "https://crm-api.topolo.app",
|
|
70
|
+
customer_success: "https://customer-success.topolo.app",
|
|
69
71
|
feed: "https://topolo-feed-api.topolo.app",
|
|
72
|
+
flow: "https://flow.topolo.app",
|
|
70
73
|
forecast: "https://forecast-worker-production.topolo.workers.dev",
|
|
74
|
+
forms: "https://forms.topolo.app",
|
|
75
|
+
insights: "https://insights.topolo.app",
|
|
76
|
+
inventory: "https://inventory.topolo.app",
|
|
71
77
|
learn: "https://topololearn-api.topolo.workers.dev",
|
|
72
78
|
mail: "https://mail.topolo.app",
|
|
73
79
|
mdm: "https://topolo-mdm-api.topolo.app",
|
|
@@ -75,16 +81,30 @@ var SERVICES = {
|
|
|
75
81
|
nexus: "https://topolo-nexus-gateway.topolo.workers.dev",
|
|
76
82
|
one: "https://one.topolo.app",
|
|
77
83
|
pay: "https://topolo-pay.topolo.workers.dev",
|
|
84
|
+
people: "https://people.topolo.app",
|
|
78
85
|
"quro.api": "https://api.ol0.me",
|
|
79
86
|
"quro.redirect": "https://ol0.me",
|
|
80
87
|
roadmapper: "https://roadmapper-api.topolo.app",
|
|
88
|
+
sign: "https://sign.topolo.app",
|
|
81
89
|
social_studio: "https://topolo-social-studio-api.topolo.workers.dev",
|
|
82
90
|
socialize: "https://socialize-prod-api.topolo.workers.dev",
|
|
83
91
|
support: "https://support.topolo.app",
|
|
92
|
+
survey: "https://survey.topolo.app",
|
|
93
|
+
voice: "https://voice.topolo.app",
|
|
84
94
|
web: "https://web-api.topolo.app"
|
|
85
95
|
};
|
|
86
96
|
var PLATFORM_SERVICE_IDS = {
|
|
87
|
-
|
|
97
|
+
books: "srv_topolo_books",
|
|
98
|
+
crm: "srv_iCwM4jGXcwlj",
|
|
99
|
+
customer_success: "srv_topolo_customer_success",
|
|
100
|
+
flow: "srv_topolo_flow",
|
|
101
|
+
forms: "srv_topolo_forms",
|
|
102
|
+
insights: "srv_topolo_insights",
|
|
103
|
+
inventory: "srv_topolo_inventory",
|
|
104
|
+
people: "srv_topolo_people",
|
|
105
|
+
sign: "srv_topolo_sign",
|
|
106
|
+
survey: "srv_topolo_survey",
|
|
107
|
+
voice: "srv_topolo_voice"
|
|
88
108
|
};
|
|
89
109
|
|
|
90
110
|
// src/applications.generated.ts
|
|
@@ -159,6 +179,30 @@ var APPLICATIONS = {
|
|
|
159
179
|
}
|
|
160
180
|
]
|
|
161
181
|
},
|
|
182
|
+
"books": {
|
|
183
|
+
"id": "books",
|
|
184
|
+
"appDir": "TopoloBooks",
|
|
185
|
+
"name": "topolo-books",
|
|
186
|
+
"packageName": "topolo-books",
|
|
187
|
+
"productionUrl": "https://books.topolo.app",
|
|
188
|
+
"services": [
|
|
189
|
+
"books"
|
|
190
|
+
],
|
|
191
|
+
"deployTargets": [
|
|
192
|
+
{
|
|
193
|
+
"name": "topolo-books",
|
|
194
|
+
"kind": "worker",
|
|
195
|
+
"apiUrl": "https://books.topolo.app",
|
|
196
|
+
"domains": [
|
|
197
|
+
"books.topolo.app"
|
|
198
|
+
],
|
|
199
|
+
"routes": [
|
|
200
|
+
"books.topolo.app"
|
|
201
|
+
],
|
|
202
|
+
"serviceId": "books"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
},
|
|
162
206
|
"bugfix": {
|
|
163
207
|
"id": "bugfix",
|
|
164
208
|
"appDir": "TopoloBugFix",
|
|
@@ -360,6 +404,30 @@ var APPLICATIONS = {
|
|
|
360
404
|
}
|
|
361
405
|
]
|
|
362
406
|
},
|
|
407
|
+
"customer_success": {
|
|
408
|
+
"id": "customer_success",
|
|
409
|
+
"appDir": "TopoloCustomerSuccess",
|
|
410
|
+
"name": "topolo-customer-success",
|
|
411
|
+
"packageName": "topolo-customer-success",
|
|
412
|
+
"productionUrl": "https://customer-success.topolo.app",
|
|
413
|
+
"services": [
|
|
414
|
+
"customer_success"
|
|
415
|
+
],
|
|
416
|
+
"deployTargets": [
|
|
417
|
+
{
|
|
418
|
+
"name": "topolo-customer-success",
|
|
419
|
+
"kind": "worker",
|
|
420
|
+
"apiUrl": "https://customer-success.topolo.app",
|
|
421
|
+
"domains": [
|
|
422
|
+
"customer-success.topolo.app"
|
|
423
|
+
],
|
|
424
|
+
"routes": [
|
|
425
|
+
"customer-success.topolo.app"
|
|
426
|
+
],
|
|
427
|
+
"serviceId": "customer_success"
|
|
428
|
+
}
|
|
429
|
+
]
|
|
430
|
+
},
|
|
363
431
|
"developers": {
|
|
364
432
|
"id": "developers",
|
|
365
433
|
"appDir": "TopoloDevelopers",
|
|
@@ -436,6 +504,30 @@ var APPLICATIONS = {
|
|
|
436
504
|
}
|
|
437
505
|
]
|
|
438
506
|
},
|
|
507
|
+
"flow": {
|
|
508
|
+
"id": "flow",
|
|
509
|
+
"appDir": "TopoloFlow",
|
|
510
|
+
"name": "topolo-flow",
|
|
511
|
+
"packageName": "topolo-flow",
|
|
512
|
+
"productionUrl": "https://flow.topolo.app",
|
|
513
|
+
"services": [
|
|
514
|
+
"flow"
|
|
515
|
+
],
|
|
516
|
+
"deployTargets": [
|
|
517
|
+
{
|
|
518
|
+
"name": "topolo-flow",
|
|
519
|
+
"kind": "worker",
|
|
520
|
+
"apiUrl": "https://flow.topolo.app",
|
|
521
|
+
"domains": [
|
|
522
|
+
"flow.topolo.app"
|
|
523
|
+
],
|
|
524
|
+
"routes": [
|
|
525
|
+
"flow.topolo.app"
|
|
526
|
+
],
|
|
527
|
+
"serviceId": "flow"
|
|
528
|
+
}
|
|
529
|
+
]
|
|
530
|
+
},
|
|
439
531
|
"forecast": {
|
|
440
532
|
"id": "forecast",
|
|
441
533
|
"appDir": "TopoloForecast",
|
|
@@ -464,6 +556,78 @@ var APPLICATIONS = {
|
|
|
464
556
|
}
|
|
465
557
|
]
|
|
466
558
|
},
|
|
559
|
+
"forms": {
|
|
560
|
+
"id": "forms",
|
|
561
|
+
"appDir": "TopoloForms",
|
|
562
|
+
"name": "topolo-forms",
|
|
563
|
+
"packageName": "topolo-forms",
|
|
564
|
+
"productionUrl": "https://forms.topolo.app",
|
|
565
|
+
"services": [
|
|
566
|
+
"forms"
|
|
567
|
+
],
|
|
568
|
+
"deployTargets": [
|
|
569
|
+
{
|
|
570
|
+
"name": "topolo-forms",
|
|
571
|
+
"kind": "worker",
|
|
572
|
+
"apiUrl": "https://forms.topolo.app",
|
|
573
|
+
"domains": [
|
|
574
|
+
"forms.topolo.app"
|
|
575
|
+
],
|
|
576
|
+
"routes": [
|
|
577
|
+
"forms.topolo.app"
|
|
578
|
+
],
|
|
579
|
+
"serviceId": "forms"
|
|
580
|
+
}
|
|
581
|
+
]
|
|
582
|
+
},
|
|
583
|
+
"insights": {
|
|
584
|
+
"id": "insights",
|
|
585
|
+
"appDir": "TopoloInsights",
|
|
586
|
+
"name": "topolo-insights",
|
|
587
|
+
"packageName": "topolo-insights",
|
|
588
|
+
"productionUrl": "https://insights.topolo.app",
|
|
589
|
+
"services": [
|
|
590
|
+
"insights"
|
|
591
|
+
],
|
|
592
|
+
"deployTargets": [
|
|
593
|
+
{
|
|
594
|
+
"name": "topolo-insights",
|
|
595
|
+
"kind": "worker",
|
|
596
|
+
"apiUrl": "https://insights.topolo.app",
|
|
597
|
+
"domains": [
|
|
598
|
+
"insights.topolo.app"
|
|
599
|
+
],
|
|
600
|
+
"routes": [
|
|
601
|
+
"insights.topolo.app"
|
|
602
|
+
],
|
|
603
|
+
"serviceId": "insights"
|
|
604
|
+
}
|
|
605
|
+
]
|
|
606
|
+
},
|
|
607
|
+
"inventory": {
|
|
608
|
+
"id": "inventory",
|
|
609
|
+
"appDir": "TopoloInventory",
|
|
610
|
+
"name": "topolo-inventory",
|
|
611
|
+
"packageName": "topolo-inventory",
|
|
612
|
+
"productionUrl": "https://inventory.topolo.app",
|
|
613
|
+
"services": [
|
|
614
|
+
"inventory"
|
|
615
|
+
],
|
|
616
|
+
"deployTargets": [
|
|
617
|
+
{
|
|
618
|
+
"name": "topolo-inventory",
|
|
619
|
+
"kind": "worker",
|
|
620
|
+
"apiUrl": "https://inventory.topolo.app",
|
|
621
|
+
"domains": [
|
|
622
|
+
"inventory.topolo.app"
|
|
623
|
+
],
|
|
624
|
+
"routes": [
|
|
625
|
+
"inventory.topolo.app"
|
|
626
|
+
],
|
|
627
|
+
"serviceId": "inventory"
|
|
628
|
+
}
|
|
629
|
+
]
|
|
630
|
+
},
|
|
467
631
|
"learn": {
|
|
468
632
|
"id": "learn",
|
|
469
633
|
"appDir": "TopoloLearn",
|
|
@@ -664,7 +828,9 @@ var APPLICATIONS = {
|
|
|
664
828
|
"kind": "worker",
|
|
665
829
|
"apiUrl": null,
|
|
666
830
|
"domains": [
|
|
667
|
-
"one.topolo.io"
|
|
831
|
+
"one.topolo.io",
|
|
832
|
+
"topolo.io",
|
|
833
|
+
"www.topolo.io"
|
|
668
834
|
],
|
|
669
835
|
"routes": [],
|
|
670
836
|
"serviceId": null
|
|
@@ -701,6 +867,30 @@ var APPLICATIONS = {
|
|
|
701
867
|
}
|
|
702
868
|
]
|
|
703
869
|
},
|
|
870
|
+
"people": {
|
|
871
|
+
"id": "people",
|
|
872
|
+
"appDir": "TopoloPeople",
|
|
873
|
+
"name": "topolo-people",
|
|
874
|
+
"packageName": "topolo-people",
|
|
875
|
+
"productionUrl": "https://people.topolo.app",
|
|
876
|
+
"services": [
|
|
877
|
+
"people"
|
|
878
|
+
],
|
|
879
|
+
"deployTargets": [
|
|
880
|
+
{
|
|
881
|
+
"name": "topolo-people",
|
|
882
|
+
"kind": "worker",
|
|
883
|
+
"apiUrl": "https://people.topolo.app",
|
|
884
|
+
"domains": [
|
|
885
|
+
"people.topolo.app"
|
|
886
|
+
],
|
|
887
|
+
"routes": [
|
|
888
|
+
"people.topolo.app"
|
|
889
|
+
],
|
|
890
|
+
"serviceId": "people"
|
|
891
|
+
}
|
|
892
|
+
]
|
|
893
|
+
},
|
|
704
894
|
"quro": {
|
|
705
895
|
"id": "quro",
|
|
706
896
|
"appDir": "TopoloQuro",
|
|
@@ -772,6 +962,30 @@ var APPLICATIONS = {
|
|
|
772
962
|
}
|
|
773
963
|
]
|
|
774
964
|
},
|
|
965
|
+
"sign": {
|
|
966
|
+
"id": "sign",
|
|
967
|
+
"appDir": "TopoloSign",
|
|
968
|
+
"name": "topolo-sign",
|
|
969
|
+
"packageName": "topolo-sign",
|
|
970
|
+
"productionUrl": "https://sign.topolo.app",
|
|
971
|
+
"services": [
|
|
972
|
+
"sign"
|
|
973
|
+
],
|
|
974
|
+
"deployTargets": [
|
|
975
|
+
{
|
|
976
|
+
"name": "topolo-sign",
|
|
977
|
+
"kind": "worker",
|
|
978
|
+
"apiUrl": "https://sign.topolo.app",
|
|
979
|
+
"domains": [
|
|
980
|
+
"sign.topolo.app"
|
|
981
|
+
],
|
|
982
|
+
"routes": [
|
|
983
|
+
"sign.topolo.app"
|
|
984
|
+
],
|
|
985
|
+
"serviceId": "sign"
|
|
986
|
+
}
|
|
987
|
+
]
|
|
988
|
+
},
|
|
775
989
|
"social_studio": {
|
|
776
990
|
"id": "social_studio",
|
|
777
991
|
"appDir": "TopoloSocialStudio",
|
|
@@ -868,6 +1082,54 @@ var APPLICATIONS = {
|
|
|
868
1082
|
}
|
|
869
1083
|
]
|
|
870
1084
|
},
|
|
1085
|
+
"survey": {
|
|
1086
|
+
"id": "survey",
|
|
1087
|
+
"appDir": "TopoloSurvey",
|
|
1088
|
+
"name": "topolo-survey",
|
|
1089
|
+
"packageName": "topolo-survey",
|
|
1090
|
+
"productionUrl": "https://survey.topolo.app",
|
|
1091
|
+
"services": [
|
|
1092
|
+
"survey"
|
|
1093
|
+
],
|
|
1094
|
+
"deployTargets": [
|
|
1095
|
+
{
|
|
1096
|
+
"name": "topolo-survey",
|
|
1097
|
+
"kind": "worker",
|
|
1098
|
+
"apiUrl": "https://survey.topolo.app",
|
|
1099
|
+
"domains": [
|
|
1100
|
+
"survey.topolo.app"
|
|
1101
|
+
],
|
|
1102
|
+
"routes": [
|
|
1103
|
+
"survey.topolo.app"
|
|
1104
|
+
],
|
|
1105
|
+
"serviceId": "survey"
|
|
1106
|
+
}
|
|
1107
|
+
]
|
|
1108
|
+
},
|
|
1109
|
+
"voice": {
|
|
1110
|
+
"id": "voice",
|
|
1111
|
+
"appDir": "TopoloVoice",
|
|
1112
|
+
"name": "topolo-voice",
|
|
1113
|
+
"packageName": "topolo-voice",
|
|
1114
|
+
"productionUrl": "https://voice.topolo.app",
|
|
1115
|
+
"services": [
|
|
1116
|
+
"voice"
|
|
1117
|
+
],
|
|
1118
|
+
"deployTargets": [
|
|
1119
|
+
{
|
|
1120
|
+
"name": "topolo-voice",
|
|
1121
|
+
"kind": "worker",
|
|
1122
|
+
"apiUrl": "https://voice.topolo.app",
|
|
1123
|
+
"domains": [
|
|
1124
|
+
"voice.topolo.app"
|
|
1125
|
+
],
|
|
1126
|
+
"routes": [
|
|
1127
|
+
"voice.topolo.app"
|
|
1128
|
+
],
|
|
1129
|
+
"serviceId": "voice"
|
|
1130
|
+
}
|
|
1131
|
+
]
|
|
1132
|
+
},
|
|
871
1133
|
"web": {
|
|
872
1134
|
"id": "web",
|
|
873
1135
|
"appDir": "TopoloWeb",
|
|
@@ -913,7 +1175,7 @@ var APPLICATIONS = {
|
|
|
913
1175
|
};
|
|
914
1176
|
|
|
915
1177
|
// src/application-requirements.ts
|
|
916
|
-
var APPLICATION_REQUIREMENTS_VERSION = "2026-04-
|
|
1178
|
+
var APPLICATION_REQUIREMENTS_VERSION = "2026-04-25.1";
|
|
917
1179
|
var APPLICATION_REQUIREMENTS = [
|
|
918
1180
|
{
|
|
919
1181
|
id: "platform-metadata",
|
|
@@ -1045,6 +1307,22 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1045
1307
|
"Keep command output JSON-stable for agents and human-readable with --no-json"
|
|
1046
1308
|
]
|
|
1047
1309
|
},
|
|
1310
|
+
{
|
|
1311
|
+
id: "native-dashboard-widget",
|
|
1312
|
+
title: "Expose a native dashboard widget contract",
|
|
1313
|
+
summary: "Launchable first-party applications must populate TopoloOne live workspace through an app-owned /api/widget endpoint using the SDK widget response contract.",
|
|
1314
|
+
appliesTo: ["api"],
|
|
1315
|
+
evidence: [
|
|
1316
|
+
"The app-owned API exposes GET /api/widget",
|
|
1317
|
+
"The endpoint returns TopoloWidgetApiResponse from @topolo/sdk",
|
|
1318
|
+
"The endpoint derives organization/user context from the app auth boundary"
|
|
1319
|
+
],
|
|
1320
|
+
implementation: [
|
|
1321
|
+
"Import createTopoloWidgetResponse from @topolo/sdk in the app backend",
|
|
1322
|
+
"Return native app metrics or action widgets instead of generic launch-card fallbacks",
|
|
1323
|
+
"Add a route-level test that validates the response with validateTopoloWidgetResponse"
|
|
1324
|
+
]
|
|
1325
|
+
},
|
|
1048
1326
|
{
|
|
1049
1327
|
id: "observability-and-audit",
|
|
1050
1328
|
title: "Emit platform audit and debugging signals",
|
|
@@ -1080,9 +1358,8 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1080
1358
|
];
|
|
1081
1359
|
function applicationRequirementScopes(application) {
|
|
1082
1360
|
const scopes = /* @__PURE__ */ new Set(["all"]);
|
|
1083
|
-
const
|
|
1084
|
-
const
|
|
1085
|
-
const hasApiSurface = application.services.length > 0 || deployTargets.some((target) => Boolean(target.apiUrl));
|
|
1361
|
+
const hasBrowserSurface = Boolean(application.productionUrl) || application.deployTargets.some((target) => target.kind === "pages");
|
|
1362
|
+
const hasApiSurface = application.services.length > 0 || application.deployTargets.some((target) => Boolean(target.apiUrl));
|
|
1086
1363
|
if (hasBrowserSurface) scopes.add("browser");
|
|
1087
1364
|
if (hasApiSurface) scopes.add("api");
|
|
1088
1365
|
if (application.id === "cli" || application.id === "mcp" || application.id === "cloudcontrol") {
|
|
@@ -1217,6 +1494,13 @@ function evaluateRequirement(application, requirement) {
|
|
|
1217
1494
|
}
|
|
1218
1495
|
return finding(requirement, "missing", "No SDK service or tooling surface is registered.", evidence);
|
|
1219
1496
|
}
|
|
1497
|
+
case "native-dashboard-widget":
|
|
1498
|
+
return finding(
|
|
1499
|
+
requirement,
|
|
1500
|
+
"needs_review",
|
|
1501
|
+
"Catalog metadata cannot verify app-owned /api/widget implementation details.",
|
|
1502
|
+
evidence
|
|
1503
|
+
);
|
|
1220
1504
|
case "observability-and-audit":
|
|
1221
1505
|
return finding(
|
|
1222
1506
|
requirement,
|
|
@@ -1270,11 +1554,10 @@ function statusRank(status) {
|
|
|
1270
1554
|
// src/services.ts
|
|
1271
1555
|
var DEFAULT_SERVICE_URLS = SERVICES;
|
|
1272
1556
|
function resolveServiceUrl(service, overrides) {
|
|
1273
|
-
|
|
1274
|
-
const override = overrides == null ? void 0 : overrides[service];
|
|
1557
|
+
const override = overrides?.[service];
|
|
1275
1558
|
if (override) return override;
|
|
1276
1559
|
const envKey = `TOPOLO_SERVICE_URL_${service.replace(/\./g, "_").toUpperCase()}`;
|
|
1277
|
-
const envValue = typeof process !== "undefined" ?
|
|
1560
|
+
const envValue = typeof process !== "undefined" ? process.env?.[envKey] : void 0;
|
|
1278
1561
|
if (envValue) return envValue;
|
|
1279
1562
|
return DEFAULT_SERVICE_URLS[service];
|
|
1280
1563
|
}
|
|
@@ -1290,9 +1573,8 @@ var TopoloClient = class {
|
|
|
1290
1573
|
fetchImpl;
|
|
1291
1574
|
debug;
|
|
1292
1575
|
constructor(options) {
|
|
1293
|
-
var _a;
|
|
1294
1576
|
if (!options.credential) throw new TopoloAuthError("credential is required");
|
|
1295
|
-
if (!
|
|
1577
|
+
if (!options.agent?.clientName) throw new TopoloAuthError("agent.clientName is required");
|
|
1296
1578
|
this.credential = options.credential;
|
|
1297
1579
|
this.agent = options.agent;
|
|
1298
1580
|
this.serviceUrls = options.serviceUrls;
|
|
@@ -1482,7 +1764,6 @@ var CrmModule = class {
|
|
|
1482
1764
|
}
|
|
1483
1765
|
client;
|
|
1484
1766
|
async listContacts(options = {}) {
|
|
1485
|
-
var _a, _b, _c;
|
|
1486
1767
|
const res = await this.client.request({
|
|
1487
1768
|
service: "crm",
|
|
1488
1769
|
path: "/api/contacts",
|
|
@@ -1492,12 +1773,12 @@ var CrmModule = class {
|
|
|
1492
1773
|
pageSize: options.pageSize
|
|
1493
1774
|
}
|
|
1494
1775
|
});
|
|
1495
|
-
const rows = Array.isArray(res
|
|
1776
|
+
const rows = Array.isArray(res?.contacts) ? res.contacts : Array.isArray(res?.data) ? res.data : [];
|
|
1496
1777
|
return {
|
|
1497
1778
|
contacts: rows.map(toSummary),
|
|
1498
|
-
total:
|
|
1499
|
-
page:
|
|
1500
|
-
pageSize:
|
|
1779
|
+
total: res?.total ?? res?.pagination?.total ?? rows.length,
|
|
1780
|
+
page: res?.page ?? res?.pagination?.page ?? options.page ?? 1,
|
|
1781
|
+
pageSize: res?.pageSize ?? res?.pagination?.pageSize ?? options.pageSize ?? rows.length
|
|
1501
1782
|
};
|
|
1502
1783
|
}
|
|
1503
1784
|
async getContact(contactId) {
|
|
@@ -1618,6 +1899,126 @@ var TopoloOAuth = class {
|
|
|
1618
1899
|
}
|
|
1619
1900
|
};
|
|
1620
1901
|
|
|
1902
|
+
// src/widgets.ts
|
|
1903
|
+
var TOPOLO_WIDGET_ENDPOINT = "/api/widget";
|
|
1904
|
+
var TOPOLO_WIDGET_REFRESH_INTERVAL_MS = 6e4;
|
|
1905
|
+
function defineTopoloStatsWidget(widget) {
|
|
1906
|
+
return { ...widget, type: "stats" };
|
|
1907
|
+
}
|
|
1908
|
+
function defineTopoloRecentActivityWidget(widget) {
|
|
1909
|
+
return { ...widget, type: "recent-activity" };
|
|
1910
|
+
}
|
|
1911
|
+
function defineTopoloQuickActionsWidget(widget) {
|
|
1912
|
+
return { ...widget, type: "quick-actions" };
|
|
1913
|
+
}
|
|
1914
|
+
function defineTopoloNotificationsWidget(widget) {
|
|
1915
|
+
return { ...widget, type: "notifications" };
|
|
1916
|
+
}
|
|
1917
|
+
function defineTopoloChartWidget(widget) {
|
|
1918
|
+
return { ...widget, type: "chart" };
|
|
1919
|
+
}
|
|
1920
|
+
function createTopoloWidgetResponse({
|
|
1921
|
+
serviceId,
|
|
1922
|
+
serviceName,
|
|
1923
|
+
widgets,
|
|
1924
|
+
now
|
|
1925
|
+
}) {
|
|
1926
|
+
const lastUpdated = toIsoTimestamp(now);
|
|
1927
|
+
return {
|
|
1928
|
+
success: true,
|
|
1929
|
+
widgets: widgets.map((widget) => ({
|
|
1930
|
+
...widget,
|
|
1931
|
+
serviceId: widget.serviceId?.trim() || serviceId,
|
|
1932
|
+
serviceName: widget.serviceName?.trim() || serviceName,
|
|
1933
|
+
lastUpdated: widget.lastUpdated?.trim() || lastUpdated
|
|
1934
|
+
}))
|
|
1935
|
+
};
|
|
1936
|
+
}
|
|
1937
|
+
function createTopoloWidgetError(error) {
|
|
1938
|
+
return {
|
|
1939
|
+
success: false,
|
|
1940
|
+
widgets: [],
|
|
1941
|
+
error
|
|
1942
|
+
};
|
|
1943
|
+
}
|
|
1944
|
+
function validateTopoloWidgetResponse(response) {
|
|
1945
|
+
const errors = [];
|
|
1946
|
+
if (!isRecord(response)) {
|
|
1947
|
+
return { ok: false, errors: ["response must be an object"] };
|
|
1948
|
+
}
|
|
1949
|
+
if (typeof response.success !== "boolean") {
|
|
1950
|
+
errors.push("success must be a boolean");
|
|
1951
|
+
}
|
|
1952
|
+
if (!Array.isArray(response.widgets)) {
|
|
1953
|
+
errors.push("widgets must be an array");
|
|
1954
|
+
return { ok: errors.length === 0, errors };
|
|
1955
|
+
}
|
|
1956
|
+
response.widgets.forEach((widget, index) => {
|
|
1957
|
+
validateWidget(widget, `widgets[${index}]`, errors);
|
|
1958
|
+
});
|
|
1959
|
+
if (response.success === false && response.error !== void 0 && typeof response.error !== "string") {
|
|
1960
|
+
errors.push("error must be a string when provided");
|
|
1961
|
+
}
|
|
1962
|
+
return { ok: errors.length === 0, errors };
|
|
1963
|
+
}
|
|
1964
|
+
function validateWidget(widget, path, errors) {
|
|
1965
|
+
if (!isRecord(widget)) {
|
|
1966
|
+
errors.push(`${path} must be an object`);
|
|
1967
|
+
return;
|
|
1968
|
+
}
|
|
1969
|
+
validateNonEmptyString(widget.serviceId, `${path}.serviceId`, errors);
|
|
1970
|
+
validateNonEmptyString(widget.serviceName, `${path}.serviceName`, errors);
|
|
1971
|
+
validateNonEmptyString(widget.lastUpdated, `${path}.lastUpdated`, errors);
|
|
1972
|
+
switch (widget.type) {
|
|
1973
|
+
case "stats":
|
|
1974
|
+
validateArray(widget.stats, `${path}.stats`, errors);
|
|
1975
|
+
break;
|
|
1976
|
+
case "recent-activity":
|
|
1977
|
+
validateArray(widget.activities, `${path}.activities`, errors);
|
|
1978
|
+
break;
|
|
1979
|
+
case "quick-actions":
|
|
1980
|
+
validateArray(widget.actions, `${path}.actions`, errors);
|
|
1981
|
+
break;
|
|
1982
|
+
case "notifications":
|
|
1983
|
+
validateArray(widget.notifications, `${path}.notifications`, errors);
|
|
1984
|
+
if (typeof widget.unreadCount !== "number") {
|
|
1985
|
+
errors.push(`${path}.unreadCount must be a number`);
|
|
1986
|
+
}
|
|
1987
|
+
break;
|
|
1988
|
+
case "chart":
|
|
1989
|
+
validateNonEmptyString(widget.chartType, `${path}.chartType`, errors);
|
|
1990
|
+
validateNonEmptyString(widget.title, `${path}.title`, errors);
|
|
1991
|
+
if (!isRecord(widget.data)) {
|
|
1992
|
+
errors.push(`${path}.data must be an object`);
|
|
1993
|
+
} else {
|
|
1994
|
+
validateArray(widget.data.labels, `${path}.data.labels`, errors);
|
|
1995
|
+
validateArray(widget.data.values, `${path}.data.values`, errors);
|
|
1996
|
+
}
|
|
1997
|
+
break;
|
|
1998
|
+
default:
|
|
1999
|
+
errors.push(`${path}.type must be a supported Topolo widget type`);
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
function validateNonEmptyString(value, path, errors) {
|
|
2003
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
2004
|
+
errors.push(`${path} must be a non-empty string`);
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
function validateArray(value, path, errors) {
|
|
2008
|
+
if (!Array.isArray(value)) {
|
|
2009
|
+
errors.push(`${path} must be an array`);
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
function isRecord(value) {
|
|
2013
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2014
|
+
}
|
|
2015
|
+
function toIsoTimestamp(input) {
|
|
2016
|
+
if (input instanceof Date) {
|
|
2017
|
+
return input.toISOString();
|
|
2018
|
+
}
|
|
2019
|
+
return input ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2020
|
+
}
|
|
2021
|
+
|
|
1621
2022
|
// src/index.ts
|
|
1622
2023
|
function createTopolo(options) {
|
|
1623
2024
|
const client = new TopoloClient(options);
|
|
@@ -1635,6 +2036,8 @@ export {
|
|
|
1635
2036
|
DEFAULT_SERVICE_URLS,
|
|
1636
2037
|
IdentityModule,
|
|
1637
2038
|
PLATFORM_SERVICE_IDS,
|
|
2039
|
+
TOPOLO_WIDGET_ENDPOINT,
|
|
2040
|
+
TOPOLO_WIDGET_REFRESH_INTERVAL_MS,
|
|
1638
2041
|
TopoloAuthError,
|
|
1639
2042
|
TopoloClient,
|
|
1640
2043
|
TopoloHttpError,
|
|
@@ -1645,6 +2048,14 @@ export {
|
|
|
1645
2048
|
auditAllApplicationRequirements,
|
|
1646
2049
|
auditApplicationRequirements,
|
|
1647
2050
|
createTopolo,
|
|
2051
|
+
createTopoloWidgetError,
|
|
2052
|
+
createTopoloWidgetResponse,
|
|
2053
|
+
defineTopoloChartWidget,
|
|
2054
|
+
defineTopoloNotificationsWidget,
|
|
2055
|
+
defineTopoloQuickActionsWidget,
|
|
2056
|
+
defineTopoloRecentActivityWidget,
|
|
2057
|
+
defineTopoloStatsWidget,
|
|
1648
2058
|
requirementsForApplication,
|
|
1649
|
-
resolveServiceUrl
|
|
2059
|
+
resolveServiceUrl,
|
|
2060
|
+
validateTopoloWidgetResponse
|
|
1650
2061
|
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APPLICATIONS,
|
|
3
3
|
type ApplicationCatalogEntry,
|
|
4
|
-
type ApplicationDeployTarget,
|
|
5
4
|
type ApplicationId,
|
|
6
5
|
} from './applications.generated.js';
|
|
7
6
|
|
|
8
|
-
export const APPLICATION_REQUIREMENTS_VERSION = '2026-04-
|
|
7
|
+
export const APPLICATION_REQUIREMENTS_VERSION = '2026-04-25.1';
|
|
9
8
|
|
|
10
9
|
export type ApplicationRequirementScope =
|
|
11
10
|
| 'all'
|
|
@@ -206,6 +205,23 @@ export const APPLICATION_REQUIREMENTS = [
|
|
|
206
205
|
'Keep command output JSON-stable for agents and human-readable with --no-json',
|
|
207
206
|
],
|
|
208
207
|
},
|
|
208
|
+
{
|
|
209
|
+
id: 'native-dashboard-widget',
|
|
210
|
+
title: 'Expose a native dashboard widget contract',
|
|
211
|
+
summary:
|
|
212
|
+
'Launchable first-party applications must populate TopoloOne live workspace through an app-owned /api/widget endpoint using the SDK widget response contract.',
|
|
213
|
+
appliesTo: ['api'],
|
|
214
|
+
evidence: [
|
|
215
|
+
'The app-owned API exposes GET /api/widget',
|
|
216
|
+
'The endpoint returns TopoloWidgetApiResponse from @topolo/sdk',
|
|
217
|
+
'The endpoint derives organization/user context from the app auth boundary',
|
|
218
|
+
],
|
|
219
|
+
implementation: [
|
|
220
|
+
'Import createTopoloWidgetResponse from @topolo/sdk in the app backend',
|
|
221
|
+
'Return native app metrics or action widgets instead of generic launch-card fallbacks',
|
|
222
|
+
'Add a route-level test that validates the response with validateTopoloWidgetResponse',
|
|
223
|
+
],
|
|
224
|
+
},
|
|
209
225
|
{
|
|
210
226
|
id: 'observability-and-audit',
|
|
211
227
|
title: 'Emit platform audit and debugging signals',
|
|
@@ -246,12 +262,11 @@ export function applicationRequirementScopes(
|
|
|
246
262
|
application: ApplicationCatalogEntry,
|
|
247
263
|
): ApplicationRequirementScope[] {
|
|
248
264
|
const scopes = new Set<ApplicationRequirementScope>(['all']);
|
|
249
|
-
const deployTargets = application.deployTargets as readonly ApplicationDeployTarget[];
|
|
250
265
|
const hasBrowserSurface =
|
|
251
|
-
Boolean(application.productionUrl) || deployTargets.some((target) => target.kind === 'pages');
|
|
266
|
+
Boolean(application.productionUrl) || application.deployTargets.some((target) => target.kind === 'pages');
|
|
252
267
|
const hasApiSurface =
|
|
253
268
|
application.services.length > 0 ||
|
|
254
|
-
deployTargets.some((target) => Boolean(target.apiUrl));
|
|
269
|
+
application.deployTargets.some((target) => Boolean(target.apiUrl));
|
|
255
270
|
|
|
256
271
|
if (hasBrowserSurface) scopes.add('browser');
|
|
257
272
|
if (hasApiSurface) scopes.add('api');
|
|
@@ -413,6 +428,13 @@ function evaluateRequirement(
|
|
|
413
428
|
}
|
|
414
429
|
return finding(requirement, 'missing', 'No SDK service or tooling surface is registered.', evidence);
|
|
415
430
|
}
|
|
431
|
+
case 'native-dashboard-widget':
|
|
432
|
+
return finding(
|
|
433
|
+
requirement,
|
|
434
|
+
'needs_review',
|
|
435
|
+
'Catalog metadata cannot verify app-owned /api/widget implementation details.',
|
|
436
|
+
evidence,
|
|
437
|
+
);
|
|
416
438
|
case 'observability-and-audit':
|
|
417
439
|
return finding(
|
|
418
440
|
requirement,
|