@topolo/sdk 0.4.6 → 0.4.7
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 +16 -9
- package/dist/index.d.cts +12 -12
- package/dist/index.d.ts +12 -12
- package/dist/index.js +16 -9
- package/package.json +1 -1
- package/src/application-requirements.ts +3 -1
- package/src/applications.generated.ts +9 -6
- package/src/services.generated.ts +1 -1
- package/src/services.test.ts +1 -1
- package/src/widgets.test.ts +39 -1
- package/src/widgets.ts +5 -3
package/dist/index.cjs
CHANGED
|
@@ -143,7 +143,7 @@ var SERVICES = {
|
|
|
143
143
|
nexus: "https://nexus-api.topolo.app",
|
|
144
144
|
notify: "https://notify.topolo.app",
|
|
145
145
|
observability_watch: "https://observability-watch.topolo.app",
|
|
146
|
-
one: "https://
|
|
146
|
+
one: "https://www.topolo.app",
|
|
147
147
|
p2p: "https://p2p.topolo.app",
|
|
148
148
|
pay: "https://pay.topolo.app",
|
|
149
149
|
people: "https://people.topolo.app",
|
|
@@ -1150,20 +1150,23 @@ var APPLICATIONS = {
|
|
|
1150
1150
|
{
|
|
1151
1151
|
"name": "topolo-one",
|
|
1152
1152
|
"kind": "worker",
|
|
1153
|
-
"apiUrl":
|
|
1154
|
-
"domains": [
|
|
1155
|
-
|
|
1153
|
+
"apiUrl": "https://one.topolo.app",
|
|
1154
|
+
"domains": [
|
|
1155
|
+
"one.topolo.app"
|
|
1156
|
+
],
|
|
1157
|
+
"routes": [
|
|
1158
|
+
"one.topolo.app/*"
|
|
1159
|
+
],
|
|
1156
1160
|
"serviceId": null
|
|
1157
1161
|
},
|
|
1158
1162
|
{
|
|
1159
1163
|
"name": "topolo-one-api",
|
|
1160
1164
|
"kind": "worker",
|
|
1161
|
-
"apiUrl": "https://
|
|
1165
|
+
"apiUrl": "https://www.topolo.app",
|
|
1162
1166
|
"domains": [
|
|
1163
|
-
"
|
|
1167
|
+
"www.topolo.app"
|
|
1164
1168
|
],
|
|
1165
1169
|
"routes": [
|
|
1166
|
-
"one.topolo.app/*",
|
|
1167
1170
|
"www.topolo.app/*"
|
|
1168
1171
|
],
|
|
1169
1172
|
"serviceId": "one"
|
|
@@ -1716,7 +1719,7 @@ var APPLICATIONS = {
|
|
|
1716
1719
|
};
|
|
1717
1720
|
|
|
1718
1721
|
// src/application-requirements.ts
|
|
1719
|
-
var APPLICATION_REQUIREMENTS_VERSION = "2026-
|
|
1722
|
+
var APPLICATION_REQUIREMENTS_VERSION = "2026-06-07.1";
|
|
1720
1723
|
var APPLICATION_REQUIREMENTS = [
|
|
1721
1724
|
{
|
|
1722
1725
|
id: "platform-metadata",
|
|
@@ -1860,11 +1863,13 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1860
1863
|
evidence: [
|
|
1861
1864
|
"The app-owned API exposes GET /api/widget",
|
|
1862
1865
|
"The endpoint returns TopoloWidgetApiResponse from @topolo/sdk",
|
|
1866
|
+
"Every returned widget includes snapshot.summary with app-owned operational prose",
|
|
1863
1867
|
"The endpoint derives organization/user context from the app auth boundary"
|
|
1864
1868
|
],
|
|
1865
1869
|
implementation: [
|
|
1866
1870
|
"Import createTopoloWidgetResponse from @topolo/sdk in the app backend",
|
|
1867
1871
|
"Return native app metrics or action widgets instead of generic launch-card fallbacks",
|
|
1872
|
+
"Populate snapshot.summary in the producing app for every widget instead of synthesizing summaries in TopoloOne",
|
|
1868
1873
|
"Add a route-level test that validates the response with validateTopoloWidgetResponse"
|
|
1869
1874
|
]
|
|
1870
1875
|
},
|
|
@@ -3192,12 +3197,14 @@ function validateWidget(widget, path, errors) {
|
|
|
3192
3197
|
}
|
|
3193
3198
|
function validateSnapshotMetadata(snapshot, path, errors) {
|
|
3194
3199
|
if (snapshot === void 0) {
|
|
3200
|
+
errors.push(`${path} must be an object`);
|
|
3195
3201
|
return;
|
|
3196
3202
|
}
|
|
3197
3203
|
if (!isRecord(snapshot)) {
|
|
3198
|
-
errors.push(`${path} must be an object
|
|
3204
|
+
errors.push(`${path} must be an object`);
|
|
3199
3205
|
return;
|
|
3200
3206
|
}
|
|
3207
|
+
validateNonEmptyString(snapshot.summary, `${path}.summary`, errors);
|
|
3201
3208
|
if (snapshot.defaultMetricKeys !== void 0 && !Array.isArray(snapshot.defaultMetricKeys)) {
|
|
3202
3209
|
errors.push(`${path}.defaultMetricKeys must be an array when provided`);
|
|
3203
3210
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -264,7 +264,7 @@ declare const SERVICES: {
|
|
|
264
264
|
readonly nexus: "https://nexus-api.topolo.app";
|
|
265
265
|
readonly notify: "https://notify.topolo.app";
|
|
266
266
|
readonly observability_watch: "https://observability-watch.topolo.app";
|
|
267
|
-
readonly one: "https://
|
|
267
|
+
readonly one: "https://www.topolo.app";
|
|
268
268
|
readonly p2p: "https://p2p.topolo.app";
|
|
269
269
|
readonly pay: "https://pay.topolo.app";
|
|
270
270
|
readonly people: "https://people.topolo.app";
|
|
@@ -1018,16 +1018,16 @@ declare const APPLICATIONS: {
|
|
|
1018
1018
|
readonly deployTargets: readonly [{
|
|
1019
1019
|
readonly name: "topolo-one";
|
|
1020
1020
|
readonly kind: "worker";
|
|
1021
|
-
readonly apiUrl:
|
|
1022
|
-
readonly domains: readonly [];
|
|
1023
|
-
readonly routes: readonly [];
|
|
1021
|
+
readonly apiUrl: "https://one.topolo.app";
|
|
1022
|
+
readonly domains: readonly ["one.topolo.app"];
|
|
1023
|
+
readonly routes: readonly ["one.topolo.app/*"];
|
|
1024
1024
|
readonly serviceId: null;
|
|
1025
1025
|
}, {
|
|
1026
1026
|
readonly name: "topolo-one-api";
|
|
1027
1027
|
readonly kind: "worker";
|
|
1028
|
-
readonly apiUrl: "https://
|
|
1029
|
-
readonly domains: readonly ["
|
|
1030
|
-
readonly routes: readonly ["
|
|
1028
|
+
readonly apiUrl: "https://www.topolo.app";
|
|
1029
|
+
readonly domains: readonly ["www.topolo.app"];
|
|
1030
|
+
readonly routes: readonly ["www.topolo.app/*"];
|
|
1031
1031
|
readonly serviceId: "one";
|
|
1032
1032
|
}, {
|
|
1033
1033
|
readonly name: "topolo-one-website";
|
|
@@ -1432,7 +1432,7 @@ type ApplicationId = keyof typeof APPLICATIONS;
|
|
|
1432
1432
|
type ApplicationCatalogEntry = (typeof APPLICATIONS)[ApplicationId];
|
|
1433
1433
|
type ApplicationDeployTarget = ApplicationCatalogEntry['deployTargets'][number];
|
|
1434
1434
|
|
|
1435
|
-
declare const APPLICATION_REQUIREMENTS_VERSION = "2026-
|
|
1435
|
+
declare const APPLICATION_REQUIREMENTS_VERSION = "2026-06-07.1";
|
|
1436
1436
|
type ApplicationRequirementScope = 'all' | 'browser' | 'api' | 'tooling' | 'agent_surface';
|
|
1437
1437
|
interface ApplicationRequirement {
|
|
1438
1438
|
id: string;
|
|
@@ -1541,8 +1541,8 @@ declare const APPLICATION_REQUIREMENTS: readonly [{
|
|
|
1541
1541
|
readonly title: "Expose a native dashboard widget contract";
|
|
1542
1542
|
readonly summary: "Launchable first-party applications must populate TopoloOne live workspace through an app-owned /api/widget endpoint using the SDK widget response contract.";
|
|
1543
1543
|
readonly appliesTo: readonly ["api"];
|
|
1544
|
-
readonly evidence: readonly ["The app-owned API exposes GET /api/widget", "The endpoint returns TopoloWidgetApiResponse from @topolo/sdk", "The endpoint derives organization/user context from the app auth boundary"];
|
|
1545
|
-
readonly implementation: readonly ["Import createTopoloWidgetResponse from @topolo/sdk in the app backend", "Return native app metrics or action widgets instead of generic launch-card fallbacks", "Add a route-level test that validates the response with validateTopoloWidgetResponse"];
|
|
1544
|
+
readonly evidence: readonly ["The app-owned API exposes GET /api/widget", "The endpoint returns TopoloWidgetApiResponse from @topolo/sdk", "Every returned widget includes snapshot.summary with app-owned operational prose", "The endpoint derives organization/user context from the app auth boundary"];
|
|
1545
|
+
readonly implementation: readonly ["Import createTopoloWidgetResponse from @topolo/sdk in the app backend", "Return native app metrics or action widgets instead of generic launch-card fallbacks", "Populate snapshot.summary in the producing app for every widget instead of synthesizing summaries in TopoloOne", "Add a route-level test that validates the response with validateTopoloWidgetResponse"];
|
|
1546
1546
|
}, {
|
|
1547
1547
|
readonly id: "observability-and-audit";
|
|
1548
1548
|
readonly title: "Emit platform audit and debugging signals";
|
|
@@ -1971,7 +1971,7 @@ interface TopoloWidgetBase {
|
|
|
1971
1971
|
serviceIcon?: string;
|
|
1972
1972
|
type: TopoloWidgetType;
|
|
1973
1973
|
lastUpdated: string;
|
|
1974
|
-
snapshot
|
|
1974
|
+
snapshot: TopoloWidgetSnapshotMetadata;
|
|
1975
1975
|
}
|
|
1976
1976
|
interface TopoloWidgetMetric {
|
|
1977
1977
|
key?: string;
|
|
@@ -1995,7 +1995,7 @@ interface TopoloWidgetSnapshotMetadata {
|
|
|
1995
1995
|
scope?: string;
|
|
1996
1996
|
scopeLabel?: string;
|
|
1997
1997
|
generatedAt?: string;
|
|
1998
|
-
summary
|
|
1998
|
+
summary: string;
|
|
1999
1999
|
defaultMetricKeys?: string[];
|
|
2000
2000
|
availableMetrics?: TopoloWidgetSnapshotMetric[];
|
|
2001
2001
|
highlights?: string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -264,7 +264,7 @@ declare const SERVICES: {
|
|
|
264
264
|
readonly nexus: "https://nexus-api.topolo.app";
|
|
265
265
|
readonly notify: "https://notify.topolo.app";
|
|
266
266
|
readonly observability_watch: "https://observability-watch.topolo.app";
|
|
267
|
-
readonly one: "https://
|
|
267
|
+
readonly one: "https://www.topolo.app";
|
|
268
268
|
readonly p2p: "https://p2p.topolo.app";
|
|
269
269
|
readonly pay: "https://pay.topolo.app";
|
|
270
270
|
readonly people: "https://people.topolo.app";
|
|
@@ -1018,16 +1018,16 @@ declare const APPLICATIONS: {
|
|
|
1018
1018
|
readonly deployTargets: readonly [{
|
|
1019
1019
|
readonly name: "topolo-one";
|
|
1020
1020
|
readonly kind: "worker";
|
|
1021
|
-
readonly apiUrl:
|
|
1022
|
-
readonly domains: readonly [];
|
|
1023
|
-
readonly routes: readonly [];
|
|
1021
|
+
readonly apiUrl: "https://one.topolo.app";
|
|
1022
|
+
readonly domains: readonly ["one.topolo.app"];
|
|
1023
|
+
readonly routes: readonly ["one.topolo.app/*"];
|
|
1024
1024
|
readonly serviceId: null;
|
|
1025
1025
|
}, {
|
|
1026
1026
|
readonly name: "topolo-one-api";
|
|
1027
1027
|
readonly kind: "worker";
|
|
1028
|
-
readonly apiUrl: "https://
|
|
1029
|
-
readonly domains: readonly ["
|
|
1030
|
-
readonly routes: readonly ["
|
|
1028
|
+
readonly apiUrl: "https://www.topolo.app";
|
|
1029
|
+
readonly domains: readonly ["www.topolo.app"];
|
|
1030
|
+
readonly routes: readonly ["www.topolo.app/*"];
|
|
1031
1031
|
readonly serviceId: "one";
|
|
1032
1032
|
}, {
|
|
1033
1033
|
readonly name: "topolo-one-website";
|
|
@@ -1432,7 +1432,7 @@ type ApplicationId = keyof typeof APPLICATIONS;
|
|
|
1432
1432
|
type ApplicationCatalogEntry = (typeof APPLICATIONS)[ApplicationId];
|
|
1433
1433
|
type ApplicationDeployTarget = ApplicationCatalogEntry['deployTargets'][number];
|
|
1434
1434
|
|
|
1435
|
-
declare const APPLICATION_REQUIREMENTS_VERSION = "2026-
|
|
1435
|
+
declare const APPLICATION_REQUIREMENTS_VERSION = "2026-06-07.1";
|
|
1436
1436
|
type ApplicationRequirementScope = 'all' | 'browser' | 'api' | 'tooling' | 'agent_surface';
|
|
1437
1437
|
interface ApplicationRequirement {
|
|
1438
1438
|
id: string;
|
|
@@ -1541,8 +1541,8 @@ declare const APPLICATION_REQUIREMENTS: readonly [{
|
|
|
1541
1541
|
readonly title: "Expose a native dashboard widget contract";
|
|
1542
1542
|
readonly summary: "Launchable first-party applications must populate TopoloOne live workspace through an app-owned /api/widget endpoint using the SDK widget response contract.";
|
|
1543
1543
|
readonly appliesTo: readonly ["api"];
|
|
1544
|
-
readonly evidence: readonly ["The app-owned API exposes GET /api/widget", "The endpoint returns TopoloWidgetApiResponse from @topolo/sdk", "The endpoint derives organization/user context from the app auth boundary"];
|
|
1545
|
-
readonly implementation: readonly ["Import createTopoloWidgetResponse from @topolo/sdk in the app backend", "Return native app metrics or action widgets instead of generic launch-card fallbacks", "Add a route-level test that validates the response with validateTopoloWidgetResponse"];
|
|
1544
|
+
readonly evidence: readonly ["The app-owned API exposes GET /api/widget", "The endpoint returns TopoloWidgetApiResponse from @topolo/sdk", "Every returned widget includes snapshot.summary with app-owned operational prose", "The endpoint derives organization/user context from the app auth boundary"];
|
|
1545
|
+
readonly implementation: readonly ["Import createTopoloWidgetResponse from @topolo/sdk in the app backend", "Return native app metrics or action widgets instead of generic launch-card fallbacks", "Populate snapshot.summary in the producing app for every widget instead of synthesizing summaries in TopoloOne", "Add a route-level test that validates the response with validateTopoloWidgetResponse"];
|
|
1546
1546
|
}, {
|
|
1547
1547
|
readonly id: "observability-and-audit";
|
|
1548
1548
|
readonly title: "Emit platform audit and debugging signals";
|
|
@@ -1971,7 +1971,7 @@ interface TopoloWidgetBase {
|
|
|
1971
1971
|
serviceIcon?: string;
|
|
1972
1972
|
type: TopoloWidgetType;
|
|
1973
1973
|
lastUpdated: string;
|
|
1974
|
-
snapshot
|
|
1974
|
+
snapshot: TopoloWidgetSnapshotMetadata;
|
|
1975
1975
|
}
|
|
1976
1976
|
interface TopoloWidgetMetric {
|
|
1977
1977
|
key?: string;
|
|
@@ -1995,7 +1995,7 @@ interface TopoloWidgetSnapshotMetadata {
|
|
|
1995
1995
|
scope?: string;
|
|
1996
1996
|
scopeLabel?: string;
|
|
1997
1997
|
generatedAt?: string;
|
|
1998
|
-
summary
|
|
1998
|
+
summary: string;
|
|
1999
1999
|
defaultMetricKeys?: string[];
|
|
2000
2000
|
availableMetrics?: TopoloWidgetSnapshotMetric[];
|
|
2001
2001
|
highlights?: string[];
|
package/dist/index.js
CHANGED
|
@@ -88,7 +88,7 @@ var SERVICES = {
|
|
|
88
88
|
nexus: "https://nexus-api.topolo.app",
|
|
89
89
|
notify: "https://notify.topolo.app",
|
|
90
90
|
observability_watch: "https://observability-watch.topolo.app",
|
|
91
|
-
one: "https://
|
|
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",
|
|
@@ -1095,20 +1095,23 @@ var APPLICATIONS = {
|
|
|
1095
1095
|
{
|
|
1096
1096
|
"name": "topolo-one",
|
|
1097
1097
|
"kind": "worker",
|
|
1098
|
-
"apiUrl":
|
|
1099
|
-
"domains": [
|
|
1100
|
-
|
|
1098
|
+
"apiUrl": "https://one.topolo.app",
|
|
1099
|
+
"domains": [
|
|
1100
|
+
"one.topolo.app"
|
|
1101
|
+
],
|
|
1102
|
+
"routes": [
|
|
1103
|
+
"one.topolo.app/*"
|
|
1104
|
+
],
|
|
1101
1105
|
"serviceId": null
|
|
1102
1106
|
},
|
|
1103
1107
|
{
|
|
1104
1108
|
"name": "topolo-one-api",
|
|
1105
1109
|
"kind": "worker",
|
|
1106
|
-
"apiUrl": "https://
|
|
1110
|
+
"apiUrl": "https://www.topolo.app",
|
|
1107
1111
|
"domains": [
|
|
1108
|
-
"
|
|
1112
|
+
"www.topolo.app"
|
|
1109
1113
|
],
|
|
1110
1114
|
"routes": [
|
|
1111
|
-
"one.topolo.app/*",
|
|
1112
1115
|
"www.topolo.app/*"
|
|
1113
1116
|
],
|
|
1114
1117
|
"serviceId": "one"
|
|
@@ -1661,7 +1664,7 @@ var APPLICATIONS = {
|
|
|
1661
1664
|
};
|
|
1662
1665
|
|
|
1663
1666
|
// src/application-requirements.ts
|
|
1664
|
-
var APPLICATION_REQUIREMENTS_VERSION = "2026-
|
|
1667
|
+
var APPLICATION_REQUIREMENTS_VERSION = "2026-06-07.1";
|
|
1665
1668
|
var APPLICATION_REQUIREMENTS = [
|
|
1666
1669
|
{
|
|
1667
1670
|
id: "platform-metadata",
|
|
@@ -1805,11 +1808,13 @@ var APPLICATION_REQUIREMENTS = [
|
|
|
1805
1808
|
evidence: [
|
|
1806
1809
|
"The app-owned API exposes GET /api/widget",
|
|
1807
1810
|
"The endpoint returns TopoloWidgetApiResponse from @topolo/sdk",
|
|
1811
|
+
"Every returned widget includes snapshot.summary with app-owned operational prose",
|
|
1808
1812
|
"The endpoint derives organization/user context from the app auth boundary"
|
|
1809
1813
|
],
|
|
1810
1814
|
implementation: [
|
|
1811
1815
|
"Import createTopoloWidgetResponse from @topolo/sdk in the app backend",
|
|
1812
1816
|
"Return native app metrics or action widgets instead of generic launch-card fallbacks",
|
|
1817
|
+
"Populate snapshot.summary in the producing app for every widget instead of synthesizing summaries in TopoloOne",
|
|
1813
1818
|
"Add a route-level test that validates the response with validateTopoloWidgetResponse"
|
|
1814
1819
|
]
|
|
1815
1820
|
},
|
|
@@ -3137,12 +3142,14 @@ function validateWidget(widget, path, errors) {
|
|
|
3137
3142
|
}
|
|
3138
3143
|
function validateSnapshotMetadata(snapshot, path, errors) {
|
|
3139
3144
|
if (snapshot === void 0) {
|
|
3145
|
+
errors.push(`${path} must be an object`);
|
|
3140
3146
|
return;
|
|
3141
3147
|
}
|
|
3142
3148
|
if (!isRecord(snapshot)) {
|
|
3143
|
-
errors.push(`${path} must be an object
|
|
3149
|
+
errors.push(`${path} must be an object`);
|
|
3144
3150
|
return;
|
|
3145
3151
|
}
|
|
3152
|
+
validateNonEmptyString(snapshot.summary, `${path}.summary`, errors);
|
|
3146
3153
|
if (snapshot.defaultMetricKeys !== void 0 && !Array.isArray(snapshot.defaultMetricKeys)) {
|
|
3147
3154
|
errors.push(`${path}.defaultMetricKeys must be an array when provided`);
|
|
3148
3155
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
type ApplicationId,
|
|
5
5
|
} from './applications.generated.js';
|
|
6
6
|
|
|
7
|
-
export const APPLICATION_REQUIREMENTS_VERSION = '2026-
|
|
7
|
+
export const APPLICATION_REQUIREMENTS_VERSION = '2026-06-07.1';
|
|
8
8
|
|
|
9
9
|
export type ApplicationRequirementScope =
|
|
10
10
|
| 'all'
|
|
@@ -218,11 +218,13 @@ export const APPLICATION_REQUIREMENTS = [
|
|
|
218
218
|
evidence: [
|
|
219
219
|
'The app-owned API exposes GET /api/widget',
|
|
220
220
|
'The endpoint returns TopoloWidgetApiResponse from @topolo/sdk',
|
|
221
|
+
'Every returned widget includes snapshot.summary with app-owned operational prose',
|
|
221
222
|
'The endpoint derives organization/user context from the app auth boundary',
|
|
222
223
|
],
|
|
223
224
|
implementation: [
|
|
224
225
|
'Import createTopoloWidgetResponse from @topolo/sdk in the app backend',
|
|
225
226
|
'Return native app metrics or action widgets instead of generic launch-card fallbacks',
|
|
227
|
+
'Populate snapshot.summary in the producing app for every widget instead of synthesizing summaries in TopoloOne',
|
|
226
228
|
'Add a route-level test that validates the response with validateTopoloWidgetResponse',
|
|
227
229
|
],
|
|
228
230
|
},
|
|
@@ -988,20 +988,23 @@ export const APPLICATIONS = {
|
|
|
988
988
|
{
|
|
989
989
|
"name": "topolo-one",
|
|
990
990
|
"kind": "worker",
|
|
991
|
-
"apiUrl":
|
|
992
|
-
"domains": [
|
|
993
|
-
|
|
991
|
+
"apiUrl": "https://one.topolo.app",
|
|
992
|
+
"domains": [
|
|
993
|
+
"one.topolo.app"
|
|
994
|
+
],
|
|
995
|
+
"routes": [
|
|
996
|
+
"one.topolo.app/*"
|
|
997
|
+
],
|
|
994
998
|
"serviceId": null
|
|
995
999
|
},
|
|
996
1000
|
{
|
|
997
1001
|
"name": "topolo-one-api",
|
|
998
1002
|
"kind": "worker",
|
|
999
|
-
"apiUrl": "https://
|
|
1003
|
+
"apiUrl": "https://www.topolo.app",
|
|
1000
1004
|
"domains": [
|
|
1001
|
-
"
|
|
1005
|
+
"www.topolo.app"
|
|
1002
1006
|
],
|
|
1003
1007
|
"routes": [
|
|
1004
|
-
"one.topolo.app/*",
|
|
1005
1008
|
"www.topolo.app/*"
|
|
1006
1009
|
],
|
|
1007
1010
|
"serviceId": "one"
|
|
@@ -33,7 +33,7 @@ export const SERVICES = {
|
|
|
33
33
|
nexus: "https://nexus-api.topolo.app",
|
|
34
34
|
notify: "https://notify.topolo.app",
|
|
35
35
|
observability_watch: "https://observability-watch.topolo.app",
|
|
36
|
-
one: "https://
|
|
36
|
+
one: "https://www.topolo.app",
|
|
37
37
|
p2p: "https://p2p.topolo.app",
|
|
38
38
|
pay: "https://pay.topolo.app",
|
|
39
39
|
people: "https://people.topolo.app",
|
package/src/services.test.ts
CHANGED
|
@@ -71,7 +71,7 @@ describe('service registry', () => {
|
|
|
71
71
|
consent: 'https://consent.topolo.app',
|
|
72
72
|
feed: 'https://feed-api.topolo.app',
|
|
73
73
|
mail: 'https://mail-api.topolo.app',
|
|
74
|
-
one: 'https://
|
|
74
|
+
one: 'https://www.topolo.app',
|
|
75
75
|
web: 'https://web-api.topolo.app',
|
|
76
76
|
});
|
|
77
77
|
expect(DEFAULT_SERVICE_URLS).toMatchObject({
|
package/src/widgets.test.ts
CHANGED
|
@@ -21,6 +21,9 @@ describe("Topolo widget contract", () => {
|
|
|
21
21
|
widgets: [
|
|
22
22
|
{
|
|
23
23
|
type: "stats",
|
|
24
|
+
snapshot: {
|
|
25
|
+
summary: "Bytes is reporting 12 files in the current workspace.",
|
|
26
|
+
},
|
|
24
27
|
stats: [{ key: "files", label: "Files", value: 12 }],
|
|
25
28
|
},
|
|
26
29
|
],
|
|
@@ -34,6 +37,9 @@ describe("Topolo widget contract", () => {
|
|
|
34
37
|
serviceName: "Bytes",
|
|
35
38
|
lastUpdated: "2026-04-25T00:00:00.000Z",
|
|
36
39
|
type: "stats",
|
|
40
|
+
snapshot: {
|
|
41
|
+
summary: "Bytes is reporting 12 files in the current workspace.",
|
|
42
|
+
},
|
|
37
43
|
stats: [{ key: "files", label: "Files", value: 12 }],
|
|
38
44
|
},
|
|
39
45
|
],
|
|
@@ -51,6 +57,9 @@ describe("Topolo widget contract", () => {
|
|
|
51
57
|
serviceName: "CRM",
|
|
52
58
|
lastUpdated: "2026-04-24T23:00:00.000Z",
|
|
53
59
|
type: "stats",
|
|
60
|
+
snapshot: {
|
|
61
|
+
summary: "CRM is tracking 3 contacts for this workspace.",
|
|
62
|
+
},
|
|
54
63
|
stats: [{ label: "Contacts", value: 3 }],
|
|
55
64
|
},
|
|
56
65
|
],
|
|
@@ -79,6 +88,9 @@ describe("Topolo widget contract", () => {
|
|
|
79
88
|
widgets: [
|
|
80
89
|
{
|
|
81
90
|
type: "notifications",
|
|
91
|
+
snapshot: {
|
|
92
|
+
summary: "CRM has one unread lead notification for review.",
|
|
93
|
+
},
|
|
82
94
|
unreadCount: 1,
|
|
83
95
|
notifications: [
|
|
84
96
|
{
|
|
@@ -100,7 +112,7 @@ describe("Topolo widget contract", () => {
|
|
|
100
112
|
});
|
|
101
113
|
});
|
|
102
114
|
|
|
103
|
-
it("keeps
|
|
115
|
+
it("keeps required snapshot metadata for configurable TopoloOne datapoints", () => {
|
|
104
116
|
const response = createTopoloWidgetResponse({
|
|
105
117
|
serviceId: "service_admin",
|
|
106
118
|
serviceName: "Admin",
|
|
@@ -111,6 +123,8 @@ describe("Topolo widget contract", () => {
|
|
|
111
123
|
stats: [{ label: "Team Members", value: 5 }],
|
|
112
124
|
snapshot: {
|
|
113
125
|
presetKey: "admin_morning_snapshot",
|
|
126
|
+
summary:
|
|
127
|
+
"Admin has 5 team members visible in the current workspace snapshot.",
|
|
114
128
|
defaultMetricKeys: ["team_members"],
|
|
115
129
|
availableMetrics: [
|
|
116
130
|
{
|
|
@@ -131,6 +145,8 @@ describe("Topolo widget contract", () => {
|
|
|
131
145
|
});
|
|
132
146
|
expect(response.widgets[0]).toMatchObject({
|
|
133
147
|
snapshot: {
|
|
148
|
+
summary:
|
|
149
|
+
"Admin has 5 team members visible in the current workspace snapshot.",
|
|
134
150
|
defaultMetricKeys: ["team_members"],
|
|
135
151
|
availableMetrics: [
|
|
136
152
|
{ key: "team_members", label: "Team Members", value: 5 },
|
|
@@ -156,7 +172,29 @@ describe("Topolo widget contract", () => {
|
|
|
156
172
|
expect(result.errors).toEqual([
|
|
157
173
|
"widgets[0].serviceId must be a non-empty string",
|
|
158
174
|
"widgets[0].lastUpdated must be a non-empty string",
|
|
175
|
+
"widgets[0].snapshot must be an object",
|
|
159
176
|
"widgets[0].type must be a supported Topolo widget type",
|
|
160
177
|
]);
|
|
161
178
|
});
|
|
179
|
+
|
|
180
|
+
it("reports missing snapshot summaries", () => {
|
|
181
|
+
const result = validateTopoloWidgetResponse({
|
|
182
|
+
success: true,
|
|
183
|
+
widgets: [
|
|
184
|
+
{
|
|
185
|
+
serviceId: "service_bad",
|
|
186
|
+
serviceName: "Bad App",
|
|
187
|
+
lastUpdated: "2026-04-25T00:00:00.000Z",
|
|
188
|
+
type: "stats",
|
|
189
|
+
snapshot: { summary: "" },
|
|
190
|
+
stats: [],
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
expect(result.ok).toBe(false);
|
|
196
|
+
expect(result.errors).toEqual([
|
|
197
|
+
"widgets[0].snapshot.summary must be a non-empty string",
|
|
198
|
+
]);
|
|
199
|
+
});
|
|
162
200
|
});
|
package/src/widgets.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface TopoloWidgetBase {
|
|
|
14
14
|
serviceIcon?: string;
|
|
15
15
|
type: TopoloWidgetType;
|
|
16
16
|
lastUpdated: string;
|
|
17
|
-
snapshot
|
|
17
|
+
snapshot: TopoloWidgetSnapshotMetadata;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export interface TopoloWidgetMetric {
|
|
@@ -41,7 +41,7 @@ export interface TopoloWidgetSnapshotMetadata {
|
|
|
41
41
|
scope?: string;
|
|
42
42
|
scopeLabel?: string;
|
|
43
43
|
generatedAt?: string;
|
|
44
|
-
summary
|
|
44
|
+
summary: string;
|
|
45
45
|
defaultMetricKeys?: string[];
|
|
46
46
|
availableMetrics?: TopoloWidgetSnapshotMetric[];
|
|
47
47
|
highlights?: string[];
|
|
@@ -291,12 +291,14 @@ function validateSnapshotMetadata(
|
|
|
291
291
|
errors: string[],
|
|
292
292
|
) {
|
|
293
293
|
if (snapshot === undefined) {
|
|
294
|
+
errors.push(`${path} must be an object`);
|
|
294
295
|
return;
|
|
295
296
|
}
|
|
296
297
|
if (!isRecord(snapshot)) {
|
|
297
|
-
errors.push(`${path} must be an object
|
|
298
|
+
errors.push(`${path} must be an object`);
|
|
298
299
|
return;
|
|
299
300
|
}
|
|
301
|
+
validateNonEmptyString(snapshot.summary, `${path}.summary`, errors);
|
|
300
302
|
if (
|
|
301
303
|
snapshot.defaultMetricKeys !== undefined &&
|
|
302
304
|
!Array.isArray(snapshot.defaultMetricKeys)
|