@topolo/sdk 0.2.1 → 0.2.3
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 +17 -0
- package/dist/index.cjs +1198 -3
- package/dist/index.d.cts +747 -4
- package/dist/index.d.ts +747 -4
- package/dist/index.js +1191 -3
- package/package.json +2 -1
- package/src/application-requirements.ts +470 -0
- package/src/applications.generated.ts +831 -0
- package/src/index.ts +18 -0
- package/src/services.generated.ts +5 -3
- package/src/services.test.ts +163 -0
- package/src/services.ts +24 -0
package/src/index.ts
CHANGED
|
@@ -8,8 +8,26 @@ export {
|
|
|
8
8
|
export type { TopoloCredential, AgentIdentity } from './auth.js';
|
|
9
9
|
export {
|
|
10
10
|
DEFAULT_SERVICE_URLS,
|
|
11
|
+
APPLICATIONS,
|
|
12
|
+
APPLICATION_REQUIREMENTS,
|
|
13
|
+
APPLICATION_REQUIREMENTS_VERSION,
|
|
11
14
|
PLATFORM_SERVICE_IDS,
|
|
15
|
+
auditAllApplicationRequirements,
|
|
16
|
+
auditApplicationRequirements,
|
|
17
|
+
applicationRequirementScopes,
|
|
18
|
+
requirementsForApplication,
|
|
12
19
|
resolveServiceUrl,
|
|
20
|
+
type ApplicationCatalogEntry,
|
|
21
|
+
type ApplicationDeployTarget,
|
|
22
|
+
type ApplicationId,
|
|
23
|
+
type ApplicationRequirement,
|
|
24
|
+
type ApplicationRequirementAudit,
|
|
25
|
+
type ApplicationRequirementFinding,
|
|
26
|
+
type ApplicationRequirementMigrationItem,
|
|
27
|
+
type ApplicationRequirementScore,
|
|
28
|
+
type ApplicationRequirementScope,
|
|
29
|
+
type ApplicationRequirementStatus,
|
|
30
|
+
type ApplicationRequirementsAuditReport,
|
|
13
31
|
type ServiceId,
|
|
14
32
|
} from './services.js';
|
|
15
33
|
export {
|
|
@@ -7,12 +7,15 @@ export const SERVICES = {
|
|
|
7
7
|
auth: "https://auth.topolo.app",
|
|
8
8
|
bugfix: "https://bugfix.topolo.app",
|
|
9
9
|
bytes: "https://r2-media-manager-worker.topolo.workers.dev",
|
|
10
|
+
calendar: "https://calendar.topolo.app",
|
|
10
11
|
chat: "https://chat.topolo.app",
|
|
11
12
|
commerce: "https://topolo-commerce-api.topolo.workers.dev",
|
|
12
13
|
crm: "https://crm-api.topolo.app",
|
|
14
|
+
feed: "https://topolo-feed-api.topolo.app",
|
|
13
15
|
forecast: "https://forecast-worker-production.topolo.workers.dev",
|
|
14
16
|
learn: "https://topololearn-api.topolo.workers.dev",
|
|
15
|
-
|
|
17
|
+
mail: "https://mail.topolo.app",
|
|
18
|
+
mdm: "https://topolo-mdm-api.topolo.app",
|
|
16
19
|
messaging: "https://messages.topolo.app",
|
|
17
20
|
nexus: "https://topolo-nexus-gateway.topolo.workers.dev",
|
|
18
21
|
one: "https://topoloone-worker.topolo.workers.dev",
|
|
@@ -23,8 +26,7 @@ export const SERVICES = {
|
|
|
23
26
|
social_studio: "https://topolo-social-studio-api.topolo.workers.dev",
|
|
24
27
|
socialize: "https://socialize-prod-api.topolo.workers.dev",
|
|
25
28
|
support: "https://support.topolo.app",
|
|
26
|
-
|
|
27
|
-
"web.runtime": "https://sites.topolo.app",
|
|
29
|
+
web: "https://web-api.topolo.app",
|
|
28
30
|
} as const;
|
|
29
31
|
|
|
30
32
|
export type ServiceId = keyof typeof SERVICES;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
APPLICATION_REQUIREMENTS,
|
|
4
|
+
APPLICATION_REQUIREMENTS_VERSION,
|
|
5
|
+
APPLICATIONS,
|
|
6
|
+
DEFAULT_SERVICE_URLS,
|
|
7
|
+
auditAllApplicationRequirements,
|
|
8
|
+
auditApplicationRequirements,
|
|
9
|
+
applicationRequirementScopes,
|
|
10
|
+
requirementsForApplication,
|
|
11
|
+
} from './services.js';
|
|
12
|
+
|
|
13
|
+
const EXPECTED_APPLICATION_IDS = [
|
|
14
|
+
'admin',
|
|
15
|
+
'agent',
|
|
16
|
+
'auth',
|
|
17
|
+
'bugfix',
|
|
18
|
+
'bytes',
|
|
19
|
+
'calendar',
|
|
20
|
+
'chat',
|
|
21
|
+
'cli',
|
|
22
|
+
'cloudcontrol',
|
|
23
|
+
'commerce',
|
|
24
|
+
'crm',
|
|
25
|
+
'developers',
|
|
26
|
+
'docs',
|
|
27
|
+
'feed',
|
|
28
|
+
'forecast',
|
|
29
|
+
'learn',
|
|
30
|
+
'mail',
|
|
31
|
+
'mcp',
|
|
32
|
+
'mdm',
|
|
33
|
+
'messaging',
|
|
34
|
+
'nexus',
|
|
35
|
+
'one',
|
|
36
|
+
'pay',
|
|
37
|
+
'quro',
|
|
38
|
+
'roadmapper',
|
|
39
|
+
'social_studio',
|
|
40
|
+
'socialize',
|
|
41
|
+
'support',
|
|
42
|
+
'web',
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
describe('service registry', () => {
|
|
46
|
+
it('includes every production worker API that belongs to a platform application', () => {
|
|
47
|
+
expect(DEFAULT_SERVICE_URLS).toMatchObject({
|
|
48
|
+
calendar: 'https://calendar.topolo.app',
|
|
49
|
+
feed: 'https://topolo-feed-api.topolo.app',
|
|
50
|
+
mail: 'https://mail.topolo.app',
|
|
51
|
+
web: 'https://web-api.topolo.app',
|
|
52
|
+
});
|
|
53
|
+
expect(DEFAULT_SERVICE_URLS).not.toHaveProperty('web.api');
|
|
54
|
+
expect(DEFAULT_SERVICE_URLS).not.toHaveProperty('web.runtime');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('maps every callable service back to an application catalog entry', () => {
|
|
58
|
+
const applicationServices = new Set<string>(
|
|
59
|
+
Object.values(APPLICATIONS).flatMap((application) => [...application.services]),
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
for (const serviceId of Object.keys(DEFAULT_SERVICE_URLS)) {
|
|
63
|
+
expect(applicationServices.has(serviceId)).toBe(true);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('application catalog', () => {
|
|
69
|
+
it('covers every current Topolo application directory', () => {
|
|
70
|
+
expect(Object.keys(APPLICATIONS).sort()).toEqual(EXPECTED_APPLICATION_IDS);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('only references registered service IDs from application metadata', () => {
|
|
74
|
+
const registeredServices = new Set<string>(Object.keys(DEFAULT_SERVICE_URLS));
|
|
75
|
+
|
|
76
|
+
for (const application of Object.values(APPLICATIONS)) {
|
|
77
|
+
for (const serviceId of application.services) {
|
|
78
|
+
expect(registeredServices.has(serviceId)).toBe(true);
|
|
79
|
+
}
|
|
80
|
+
for (const target of application.deployTargets) {
|
|
81
|
+
if (target.serviceId) expect(registeredServices.has(target.serviceId)).toBe(true);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('treats TopoloWeb runtime as a deploy target, not an agent-callable API service', () => {
|
|
87
|
+
expect(APPLICATIONS.web.services).toEqual(['web']);
|
|
88
|
+
expect(
|
|
89
|
+
APPLICATIONS.web.deployTargets.find((target) => target.name === 'topoloweb-api')?.serviceId,
|
|
90
|
+
).toBe('web');
|
|
91
|
+
expect(
|
|
92
|
+
APPLICATIONS.web.deployTargets.find((target) => target.name === 'topoloweb-runtime')?.serviceId,
|
|
93
|
+
).toBeNull();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('treats TopoloFeed analytics as telemetry, not an agent-callable API service', () => {
|
|
97
|
+
expect(APPLICATIONS.feed.services).toEqual(['feed']);
|
|
98
|
+
expect(
|
|
99
|
+
APPLICATIONS.feed.deployTargets.find((target) => target.name === 'topolo-feed-api')?.serviceId,
|
|
100
|
+
).toBe('feed');
|
|
101
|
+
expect(
|
|
102
|
+
APPLICATIONS.feed.deployTargets.find((target) => target.name === 'topolo-feed-analytics-api')?.serviceId,
|
|
103
|
+
).toBeNull();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('application requirements', () => {
|
|
108
|
+
it('exposes a stable versioned requirement list', () => {
|
|
109
|
+
expect(APPLICATION_REQUIREMENTS_VERSION).toMatch(/^\d{4}-\d{2}-\d{2}\.\d+$/);
|
|
110
|
+
expect(APPLICATION_REQUIREMENTS.length).toBeGreaterThan(5);
|
|
111
|
+
expect(APPLICATION_REQUIREMENTS.map((requirement) => requirement.id)).toContain(
|
|
112
|
+
'shared-auth-boundary',
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('derives browser and API scopes from app metadata', () => {
|
|
117
|
+
expect(applicationRequirementScopes(APPLICATIONS.commerce)).toEqual(
|
|
118
|
+
expect.arrayContaining(['all', 'browser', 'api', 'agent_surface']),
|
|
119
|
+
);
|
|
120
|
+
expect(applicationRequirementScopes(APPLICATIONS.mail)).toEqual(
|
|
121
|
+
expect.arrayContaining(['all', 'browser', 'api', 'agent_surface']),
|
|
122
|
+
);
|
|
123
|
+
expect(applicationRequirementScopes(APPLICATIONS.cli)).toEqual(
|
|
124
|
+
expect.arrayContaining(['all', 'tooling', 'agent_surface']),
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it('filters requirements for a target application', () => {
|
|
129
|
+
const adminRequirementIds = requirementsForApplication('admin').map((requirement) => requirement.id);
|
|
130
|
+
const mailRequirementIds = requirementsForApplication('mail').map((requirement) => requirement.id);
|
|
131
|
+
const cliRequirementIds = requirementsForApplication('cli').map((requirement) => requirement.id);
|
|
132
|
+
|
|
133
|
+
expect(adminRequirementIds).toContain('shared-shell-and-launcher');
|
|
134
|
+
expect(adminRequirementIds).not.toContain('organization-scoped-data');
|
|
135
|
+
expect(mailRequirementIds).toContain('organization-scoped-data');
|
|
136
|
+
expect(mailRequirementIds).toContain('service-registration-and-scopes');
|
|
137
|
+
expect(cliRequirementIds).toContain('agent-and-operator-surfaces');
|
|
138
|
+
expect(cliRequirementIds).not.toContain('service-registration-and-scopes');
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('audits one application against the catalog-backed requirements', () => {
|
|
142
|
+
const audit = auditApplicationRequirements('mail');
|
|
143
|
+
const byRequirement = new Map(audit.findings.map((finding) => [finding.requirementId, finding]));
|
|
144
|
+
|
|
145
|
+
expect(audit.version).toBe(APPLICATION_REQUIREMENTS_VERSION);
|
|
146
|
+
expect(audit.application.id).toBe('mail');
|
|
147
|
+
expect(audit.score.total).toBe(audit.findings.length);
|
|
148
|
+
expect(byRequirement.get('platform-metadata')?.status).toBe('met');
|
|
149
|
+
expect(byRequirement.get('service-registration-and-scopes')?.status).toBe('partial');
|
|
150
|
+
expect(byRequirement.get('canonical-docs')?.status).toBe('needs_review');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('builds a sorted migration queue for all applications', () => {
|
|
154
|
+
const report = auditAllApplicationRequirements(['mail', 'admin']);
|
|
155
|
+
expect(report.applications).toHaveLength(2);
|
|
156
|
+
expect(report.migrationQueue.length).toBeGreaterThan(0);
|
|
157
|
+
expect(report.migrationQueue[0]).toMatchObject({
|
|
158
|
+
applicationId: expect.any(String),
|
|
159
|
+
requirementId: expect.any(String),
|
|
160
|
+
status: expect.stringMatching(/missing|partial|needs_review/),
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
package/src/services.ts
CHANGED
|
@@ -18,9 +18,33 @@ import {
|
|
|
18
18
|
PLATFORM_SERVICE_IDS,
|
|
19
19
|
type ServiceId,
|
|
20
20
|
} from './services.generated.js';
|
|
21
|
+
import {
|
|
22
|
+
APPLICATIONS,
|
|
23
|
+
type ApplicationCatalogEntry,
|
|
24
|
+
type ApplicationDeployTarget,
|
|
25
|
+
type ApplicationId,
|
|
26
|
+
} from './applications.generated.js';
|
|
27
|
+
export {
|
|
28
|
+
APPLICATION_REQUIREMENTS,
|
|
29
|
+
APPLICATION_REQUIREMENTS_VERSION,
|
|
30
|
+
auditAllApplicationRequirements,
|
|
31
|
+
auditApplicationRequirements,
|
|
32
|
+
applicationRequirementScopes,
|
|
33
|
+
requirementsForApplication,
|
|
34
|
+
type ApplicationRequirement,
|
|
35
|
+
type ApplicationRequirementAudit,
|
|
36
|
+
type ApplicationRequirementFinding,
|
|
37
|
+
type ApplicationRequirementMigrationItem,
|
|
38
|
+
type ApplicationRequirementScore,
|
|
39
|
+
type ApplicationRequirementScope,
|
|
40
|
+
type ApplicationRequirementStatus,
|
|
41
|
+
type ApplicationRequirementsAuditReport,
|
|
42
|
+
} from './application-requirements.js';
|
|
21
43
|
|
|
22
44
|
export { SERVICES, PLATFORM_SERVICE_IDS };
|
|
23
45
|
export type { ServiceId };
|
|
46
|
+
export { APPLICATIONS };
|
|
47
|
+
export type { ApplicationCatalogEntry, ApplicationDeployTarget, ApplicationId };
|
|
24
48
|
|
|
25
49
|
export const DEFAULT_SERVICE_URLS: Record<ServiceId, string> = SERVICES;
|
|
26
50
|
|