@ontrails/trails 1.0.0-beta.10 → 1.0.0-beta.11
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/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +27 -0
- package/dist/src/trails/survey.d.ts +40 -0
- package/dist/src/trails/survey.d.ts.map +1 -1
- package/dist/src/trails/survey.js +83 -8
- package/dist/src/trails/survey.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/survey.test.ts +63 -6
- package/src/trails/survey.ts +145 -9
package/.turbo/turbo-lint.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# trails
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.11
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Add services as a first-class primitive.
|
|
8
|
+
|
|
9
|
+
Services make infrastructure dependencies declarative, injectable, and governable. Define a service with `service()`, declare it on a trail with `services: [db]`, and access it with `db.from(ctx)` or `ctx.service()`.
|
|
10
|
+
|
|
11
|
+
**Core:** `service()` factory, `ServiceSpec<T>`, `ServiceContext`, singleton resolution in `executeTrail`, in-flight creation dedup, `isService` guard, `findDuplicateServiceId`, topo service discovery and validation, `services` field on trail specs.
|
|
12
|
+
|
|
13
|
+
**Testing:** Auto-resolution of `mock` factories in `testAll`, `testExamples`, `testContracts`, and `testFollows`. Explicit `services` overrides with correct precedence (`explicit > ctx.extensions > auto-mock`). Service mock propagation through follow graphs.
|
|
14
|
+
|
|
15
|
+
**Warden:** `service-declarations` rule validates `db.from(ctx)` and `ctx.service()` usage matches declared `services: [...]`. `service-exists` rule validates declared service IDs resolve in project context. Scope-aware AST walking skips nested function boundaries.
|
|
16
|
+
|
|
17
|
+
**Surfaces:** Service overrides thread through `dispatch` and `blaze` on CLI, MCP, and HTTP.
|
|
18
|
+
|
|
19
|
+
**Introspection:** Survey and surface map outputs include service graph. Topo exposes `.services`, `.getService()`, `.hasService()`, `.listServices()`, `.serviceIds()`, `.serviceCount`.
|
|
20
|
+
|
|
21
|
+
**Docs:** ADR-009 accepted. Unified services guide, updated vocabulary, getting-started, architecture, and package READMEs.
|
|
22
|
+
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @ontrails/core@1.0.0-beta.11
|
|
25
|
+
- @ontrails/warden@1.0.0-beta.11
|
|
26
|
+
- @ontrails/cli@1.0.0-beta.11
|
|
27
|
+
- @ontrails/schema@1.0.0-beta.11
|
|
28
|
+
- @ontrails/logging@1.0.0-beta.11
|
|
29
|
+
|
|
3
30
|
## 1.0.0-beta.10
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
|
@@ -10,6 +10,7 @@ export interface BriefReport {
|
|
|
10
10
|
readonly version: string;
|
|
11
11
|
readonly contractVersion: string;
|
|
12
12
|
readonly features: {
|
|
13
|
+
readonly services: boolean;
|
|
13
14
|
readonly outputSchemas: boolean;
|
|
14
15
|
readonly examples: boolean;
|
|
15
16
|
readonly detours: boolean;
|
|
@@ -17,9 +18,48 @@ export interface BriefReport {
|
|
|
17
18
|
};
|
|
18
19
|
readonly trails: number;
|
|
19
20
|
readonly events: number;
|
|
21
|
+
readonly services: number;
|
|
22
|
+
}
|
|
23
|
+
export interface SurveyListReport {
|
|
24
|
+
readonly count: number;
|
|
25
|
+
readonly entries: readonly {
|
|
26
|
+
readonly examples: number;
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly kind: string;
|
|
29
|
+
readonly safety: string;
|
|
30
|
+
}[];
|
|
31
|
+
readonly serviceCount: number;
|
|
32
|
+
readonly services: readonly {
|
|
33
|
+
readonly description: string | null;
|
|
34
|
+
readonly health: 'available' | 'none';
|
|
35
|
+
readonly id: string;
|
|
36
|
+
readonly kind: 'service';
|
|
37
|
+
readonly lifetime: 'singleton';
|
|
38
|
+
readonly usedBy: readonly string[];
|
|
39
|
+
}[];
|
|
40
|
+
}
|
|
41
|
+
export interface TrailDetailReport {
|
|
42
|
+
readonly description: string | null;
|
|
43
|
+
readonly detours: Trail<unknown, unknown>['detours'] | null;
|
|
44
|
+
readonly examples: readonly unknown[];
|
|
45
|
+
readonly follow: readonly string[];
|
|
46
|
+
readonly id: string;
|
|
47
|
+
readonly intent: 'read' | 'write' | 'destroy';
|
|
48
|
+
readonly kind: string;
|
|
49
|
+
readonly safety: string;
|
|
50
|
+
readonly services: readonly string[];
|
|
20
51
|
}
|
|
21
52
|
/** Generate a compact capability report for the given topo. */
|
|
22
53
|
export declare const generateBriefReport: (app: Topo) => BriefReport;
|
|
54
|
+
export declare const generateSurveyList: (app: Topo) => SurveyListReport;
|
|
55
|
+
/**
|
|
56
|
+
* Build a human-readable detail view for a single trail.
|
|
57
|
+
*
|
|
58
|
+
* Overlaps with `trailToEntry` in `@ontrails/schema` which builds the
|
|
59
|
+
* surface-map entry. The two serve different audiences (human display vs
|
|
60
|
+
* machine-diffable surface map) so they are kept separate.
|
|
61
|
+
*/
|
|
62
|
+
export declare const generateTrailDetail: (item: Trail<unknown, unknown>) => TrailDetailReport;
|
|
23
63
|
export declare const surveyTrail: Trail<{
|
|
24
64
|
breakingOnly: boolean;
|
|
25
65
|
brief: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"survey.d.ts","sourceRoot":"","sources":["../../../src/trails/survey.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAoBlD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;QAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"survey.d.ts","sourceRoot":"","sources":["../../../src/trails/survey.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAoBlD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;QAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACzB,EAAE,CAAC;IACJ,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS;QAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QACpC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC;QACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;QACzB,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;QAC/B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;KACpC,EAAE,CAAC;CACL;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;IAC5D,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAiCD,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,GAAI,KAAK,IAAI,KAAG,WAmB/C,CAAC;AAwDF,eAAO,MAAM,kBAAkB,GAAI,KAAK,IAAI,KAAG,gBA4B9C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,KAC5B,iBAgBF,CAAC;AA+HF,eAAO,MAAM,WAAW;;;;;;;;UAmItB,CAAC"}
|
|
@@ -22,11 +22,12 @@ const detectFeatures = (app) => {
|
|
|
22
22
|
hasDetours: trails.some((r) => trailHas(r, 'detours')),
|
|
23
23
|
hasExamples: trails.some((r) => trailHas(r, 'examples')),
|
|
24
24
|
hasOutputSchemas: trails.some((r) => trailHas(r, 'output')),
|
|
25
|
+
hasServices: trails.some((r) => Array.isArray(r['services']) && r['services'].length > 0),
|
|
25
26
|
};
|
|
26
27
|
};
|
|
27
28
|
/** Generate a compact capability report for the given topo. */
|
|
28
29
|
export const generateBriefReport = (app) => {
|
|
29
|
-
const { hasDetours, hasExamples, hasOutputSchemas } = detectFeatures(app);
|
|
30
|
+
const { hasDetours, hasExamples, hasOutputSchemas, hasServices } = detectFeatures(app);
|
|
30
31
|
return {
|
|
31
32
|
contractVersion: '2026-03',
|
|
32
33
|
events: app.events.size,
|
|
@@ -35,8 +36,10 @@ export const generateBriefReport = (app) => {
|
|
|
35
36
|
events: app.events.size > 0,
|
|
36
37
|
examples: hasExamples,
|
|
37
38
|
outputSchemas: hasOutputSchemas,
|
|
39
|
+
services: hasServices,
|
|
38
40
|
},
|
|
39
41
|
name: app.name,
|
|
42
|
+
services: app.services.size,
|
|
40
43
|
trails: app.trails.size,
|
|
41
44
|
version: '0.1.0',
|
|
42
45
|
};
|
|
@@ -53,7 +56,33 @@ const safetyLabel = (entry) => {
|
|
|
53
56
|
}
|
|
54
57
|
return '-';
|
|
55
58
|
};
|
|
56
|
-
const
|
|
59
|
+
const buildServiceUsage = (app) => {
|
|
60
|
+
const usage = new Map();
|
|
61
|
+
for (const trailDef of app.list()) {
|
|
62
|
+
for (const declaredService of trailDef.services) {
|
|
63
|
+
const users = usage.get(declaredService.id) ?? [];
|
|
64
|
+
users.push(trailDef.id);
|
|
65
|
+
usage.set(declaredService.id, users);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return new Map([...usage.entries()].map(([id, users]) => [id, users.toSorted()]));
|
|
69
|
+
};
|
|
70
|
+
const serviceHealthStatus = (service) => service.health === undefined ? 'none' : 'available';
|
|
71
|
+
const formatServiceList = (app) => {
|
|
72
|
+
const usage = buildServiceUsage(app);
|
|
73
|
+
return app
|
|
74
|
+
.listServices()
|
|
75
|
+
.map((service) => ({
|
|
76
|
+
description: service.description ?? null,
|
|
77
|
+
health: serviceHealthStatus(service),
|
|
78
|
+
id: service.id,
|
|
79
|
+
kind: service.kind,
|
|
80
|
+
lifetime: 'singleton',
|
|
81
|
+
usedBy: usage.get(service.id) ?? [],
|
|
82
|
+
}))
|
|
83
|
+
.toSorted((a, b) => a.id.localeCompare(b.id));
|
|
84
|
+
};
|
|
85
|
+
export const generateSurveyList = (app) => {
|
|
57
86
|
const items = app.list();
|
|
58
87
|
const entries = items.map((item) => {
|
|
59
88
|
const safety = safetyLabel(item);
|
|
@@ -67,7 +96,13 @@ const formatTrailList = (app) => {
|
|
|
67
96
|
safety,
|
|
68
97
|
};
|
|
69
98
|
});
|
|
70
|
-
|
|
99
|
+
const services = formatServiceList(app);
|
|
100
|
+
return {
|
|
101
|
+
count: items.length,
|
|
102
|
+
entries,
|
|
103
|
+
serviceCount: services.length,
|
|
104
|
+
services,
|
|
105
|
+
};
|
|
71
106
|
};
|
|
72
107
|
/**
|
|
73
108
|
* Build a human-readable detail view for a single trail.
|
|
@@ -76,15 +111,30 @@ const formatTrailList = (app) => {
|
|
|
76
111
|
* surface-map entry. The two serve different audiences (human display vs
|
|
77
112
|
* machine-diffable surface map) so they are kept separate.
|
|
78
113
|
*/
|
|
79
|
-
const
|
|
114
|
+
export const generateTrailDetail = (item) => {
|
|
80
115
|
const safety = safetyLabel(item);
|
|
81
116
|
return {
|
|
82
117
|
description: item.description ?? null,
|
|
83
118
|
detours: item.detours ?? null,
|
|
84
119
|
examples: item.examples ?? [],
|
|
120
|
+
follow: item.follow.toSorted(),
|
|
85
121
|
id: item.id,
|
|
122
|
+
intent: item.intent,
|
|
86
123
|
kind: item.kind,
|
|
87
124
|
safety,
|
|
125
|
+
services: item.services.map((service) => service.id).toSorted(),
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
const formatServiceDetail = (app, serviceId) => {
|
|
129
|
+
const item = app.getService(serviceId);
|
|
130
|
+
const usedBy = buildServiceUsage(app).get(serviceId) ?? [];
|
|
131
|
+
return {
|
|
132
|
+
description: item?.description ?? null,
|
|
133
|
+
health: item ? serviceHealthStatus(item) : 'none',
|
|
134
|
+
id: serviceId,
|
|
135
|
+
kind: 'service',
|
|
136
|
+
lifetime: 'singleton',
|
|
137
|
+
usedBy,
|
|
88
138
|
};
|
|
89
139
|
};
|
|
90
140
|
const formatDiff = (diff) => ({
|
|
@@ -111,10 +161,13 @@ const buildSurveyDiff = async (app, breakingOnly) => {
|
|
|
111
161
|
};
|
|
112
162
|
const buildSurveyDetail = (app, trailId) => {
|
|
113
163
|
const item = app.get(trailId);
|
|
114
|
-
if (
|
|
115
|
-
return Result.
|
|
164
|
+
if (item) {
|
|
165
|
+
return Result.ok(generateTrailDetail(item));
|
|
166
|
+
}
|
|
167
|
+
if (app.getService(trailId)) {
|
|
168
|
+
return Result.ok(formatServiceDetail(app, trailId));
|
|
116
169
|
}
|
|
117
|
-
return Result.
|
|
170
|
+
return Result.err(new Error(`Trail or service not found: ${trailId}`));
|
|
118
171
|
};
|
|
119
172
|
const buildSurveyGenerate = async (app) => {
|
|
120
173
|
const surfaceMap = generateSurfaceMap(app);
|
|
@@ -139,7 +192,7 @@ const surveyHandlers = {
|
|
|
139
192
|
detail: (app, input) => buildSurveyDetail(app, input.trailId ?? ''),
|
|
140
193
|
diff: (app, input) => buildSurveyDiff(app, input.breakingOnly),
|
|
141
194
|
generate: (app) => buildSurveyGenerate(app),
|
|
142
|
-
list: (app) => Result.ok(
|
|
195
|
+
list: (app) => Result.ok(generateSurveyList(app)),
|
|
143
196
|
openapi: (app) => Result.ok(generateOpenApiSpec(app)),
|
|
144
197
|
};
|
|
145
198
|
/** Dispatch to the appropriate survey sub-command based on input flags. */
|
|
@@ -198,6 +251,15 @@ export const surveyTrail = trail('survey', {
|
|
|
198
251
|
kind: z.string(),
|
|
199
252
|
safety: z.string(),
|
|
200
253
|
})),
|
|
254
|
+
serviceCount: z.number(),
|
|
255
|
+
services: z.array(z.object({
|
|
256
|
+
description: z.string().nullable(),
|
|
257
|
+
health: z.enum(['available', 'none']),
|
|
258
|
+
id: z.string(),
|
|
259
|
+
kind: z.literal('service'),
|
|
260
|
+
lifetime: z.literal('singleton'),
|
|
261
|
+
usedBy: z.array(z.string()),
|
|
262
|
+
})),
|
|
201
263
|
}),
|
|
202
264
|
z.object({
|
|
203
265
|
contractVersion: z.string(),
|
|
@@ -207,8 +269,10 @@ export const surveyTrail = trail('survey', {
|
|
|
207
269
|
events: z.boolean(),
|
|
208
270
|
examples: z.boolean(),
|
|
209
271
|
outputSchemas: z.boolean(),
|
|
272
|
+
services: z.boolean(),
|
|
210
273
|
}),
|
|
211
274
|
name: z.string(),
|
|
275
|
+
services: z.number(),
|
|
212
276
|
trails: z.number(),
|
|
213
277
|
version: z.string(),
|
|
214
278
|
}),
|
|
@@ -222,9 +286,20 @@ export const surveyTrail = trail('survey', {
|
|
|
222
286
|
description: z.unknown().nullable(),
|
|
223
287
|
detours: z.unknown().nullable(),
|
|
224
288
|
examples: z.array(z.unknown()),
|
|
289
|
+
follow: z.array(z.string()),
|
|
225
290
|
id: z.string(),
|
|
291
|
+
intent: z.enum(['read', 'write', 'destroy']),
|
|
226
292
|
kind: z.string(),
|
|
227
293
|
safety: z.string(),
|
|
294
|
+
services: z.array(z.string()),
|
|
295
|
+
}),
|
|
296
|
+
z.object({
|
|
297
|
+
description: z.string().nullable(),
|
|
298
|
+
health: z.enum(['available', 'none']),
|
|
299
|
+
id: z.string(),
|
|
300
|
+
kind: z.literal('service'),
|
|
301
|
+
lifetime: z.literal('singleton'),
|
|
302
|
+
usedBy: z.array(z.string()),
|
|
228
303
|
}),
|
|
229
304
|
z.object({
|
|
230
305
|
hash: z.string(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"survey.js","sourceRoot":"","sources":["../../../src/trails/survey.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"survey.js","sourceRoot":"","sources":["../../../src/trails/survey.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test';
|
|
2
2
|
|
|
3
|
-
import { topo, trail
|
|
3
|
+
import { Result, service, topo, trail } from '@ontrails/core';
|
|
4
4
|
import {
|
|
5
5
|
generateSurfaceMap,
|
|
6
6
|
hashSurfaceMap,
|
|
@@ -9,8 +9,16 @@ import {
|
|
|
9
9
|
import type { SurfaceMap } from '@ontrails/schema';
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
12
|
+
import {
|
|
13
|
+
generateBriefReport,
|
|
14
|
+
generateSurveyList,
|
|
15
|
+
generateTrailDetail,
|
|
16
|
+
} from '../trails/survey.js';
|
|
17
|
+
import type {
|
|
18
|
+
BriefReport,
|
|
19
|
+
SurveyListReport,
|
|
20
|
+
TrailDetailReport,
|
|
21
|
+
} from '../trails/survey.js';
|
|
14
22
|
|
|
15
23
|
// ---------------------------------------------------------------------------
|
|
16
24
|
// Test fixtures
|
|
@@ -35,6 +43,11 @@ const helloTrail = trail('hello', {
|
|
|
35
43
|
const name = input.name ?? 'world';
|
|
36
44
|
return Result.ok({ message: `Hello, ${name}!` });
|
|
37
45
|
},
|
|
46
|
+
services: [
|
|
47
|
+
service('db.main', {
|
|
48
|
+
create: () => Result.ok({ source: 'factory' }),
|
|
49
|
+
}),
|
|
50
|
+
],
|
|
38
51
|
});
|
|
39
52
|
|
|
40
53
|
const byeTrail = trail('bye', {
|
|
@@ -44,7 +57,16 @@ const byeTrail = trail('bye', {
|
|
|
44
57
|
run: (input) => Result.ok({ message: `Goodbye, ${input.name}!` }),
|
|
45
58
|
});
|
|
46
59
|
|
|
47
|
-
const
|
|
60
|
+
const [dbService] = helloTrail.services;
|
|
61
|
+
if (!dbService) {
|
|
62
|
+
throw new Error('Expected helloTrail to declare db.main');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const app = topo('test-app', {
|
|
66
|
+
bye: byeTrail,
|
|
67
|
+
dbService,
|
|
68
|
+
hello: helloTrail,
|
|
69
|
+
});
|
|
48
70
|
|
|
49
71
|
// ---------------------------------------------------------------------------
|
|
50
72
|
// Tests
|
|
@@ -53,10 +75,11 @@ const app = topo('test-app', { bye: byeTrail, hello: helloTrail });
|
|
|
53
75
|
describe('trails survey', () => {
|
|
54
76
|
test('generateSurfaceMap includes all trails', () => {
|
|
55
77
|
const surfaceMap = generateSurfaceMap(app);
|
|
56
|
-
expect(surfaceMap.entries.length).toBe(
|
|
78
|
+
expect(surfaceMap.entries.length).toBe(3);
|
|
57
79
|
const ids = surfaceMap.entries.map((e) => e.id);
|
|
58
80
|
expect(ids).toContain('hello');
|
|
59
81
|
expect(ids).toContain('bye');
|
|
82
|
+
expect(ids).toContain('db.main');
|
|
60
83
|
});
|
|
61
84
|
|
|
62
85
|
test('surface map entries have expected fields', () => {
|
|
@@ -66,6 +89,7 @@ describe('trails survey', () => {
|
|
|
66
89
|
expect(hello?.kind).toBe('trail');
|
|
67
90
|
expect(hello?.intent).toBe('read');
|
|
68
91
|
expect(hello?.exampleCount).toBe(1);
|
|
92
|
+
expect(hello?.services).toEqual(['db.main']);
|
|
69
93
|
});
|
|
70
94
|
|
|
71
95
|
test('JSON output is valid JSON', () => {
|
|
@@ -73,7 +97,7 @@ describe('trails survey', () => {
|
|
|
73
97
|
const json = JSON.stringify(surfaceMap, null, 2);
|
|
74
98
|
const parsed = JSON.parse(json) as SurfaceMap;
|
|
75
99
|
expect(parsed.version).toBe('1.0');
|
|
76
|
-
expect(parsed.entries.length).toBe(
|
|
100
|
+
expect(parsed.entries.length).toBe(3);
|
|
77
101
|
});
|
|
78
102
|
|
|
79
103
|
test('hashSurfaceMap produces stable hash', () => {
|
|
@@ -130,6 +154,7 @@ describe('trails survey --brief', () => {
|
|
|
130
154
|
const report = generateBriefReport(app);
|
|
131
155
|
expect(report.trails).toBe(2);
|
|
132
156
|
expect(report.events).toBe(0);
|
|
157
|
+
expect(report.services).toBe(1);
|
|
133
158
|
});
|
|
134
159
|
|
|
135
160
|
test('detects features in use', () => {
|
|
@@ -138,6 +163,7 @@ describe('trails survey --brief', () => {
|
|
|
138
163
|
expect(report.features.examples).toBe(true);
|
|
139
164
|
expect(report.features.detours).toBe(true);
|
|
140
165
|
expect(report.features.events).toBe(false);
|
|
166
|
+
expect(report.features.services).toBe(true);
|
|
141
167
|
});
|
|
142
168
|
|
|
143
169
|
test('JSON output is valid', () => {
|
|
@@ -146,6 +172,7 @@ describe('trails survey --brief', () => {
|
|
|
146
172
|
const parsed = JSON.parse(json) as BriefReport;
|
|
147
173
|
expect(parsed.name).toBe('test-app');
|
|
148
174
|
expect(parsed.trails).toBe(2);
|
|
175
|
+
expect(parsed.services).toBe(1);
|
|
149
176
|
});
|
|
150
177
|
|
|
151
178
|
test('empty app reports zero features', () => {
|
|
@@ -155,5 +182,35 @@ describe('trails survey --brief', () => {
|
|
|
155
182
|
expect(report.features.outputSchemas).toBe(false);
|
|
156
183
|
expect(report.features.examples).toBe(false);
|
|
157
184
|
expect(report.features.detours).toBe(false);
|
|
185
|
+
expect(report.features.services).toBe(false);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe('trails survey detail', () => {
|
|
190
|
+
test('trail detail includes declared services, follow, and intent', () => {
|
|
191
|
+
const detail = generateTrailDetail(helloTrail);
|
|
192
|
+
const parsed = structuredClone(detail) as TrailDetailReport;
|
|
193
|
+
|
|
194
|
+
expect(parsed.follow).toEqual([]);
|
|
195
|
+
expect(parsed.intent).toBe('read');
|
|
196
|
+
expect(parsed.services).toEqual(['db.main']);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe('trails survey services section', () => {
|
|
201
|
+
test('list output includes service lifetime and health status', () => {
|
|
202
|
+
const report = generateSurveyList(app);
|
|
203
|
+
const parsed = structuredClone(report) as SurveyListReport;
|
|
204
|
+
const db = parsed.services.find((entry) => entry.id === 'db.main');
|
|
205
|
+
|
|
206
|
+
expect(parsed.serviceCount).toBe(1);
|
|
207
|
+
expect(db).toEqual({
|
|
208
|
+
description: null,
|
|
209
|
+
health: 'none',
|
|
210
|
+
id: 'db.main',
|
|
211
|
+
kind: 'service',
|
|
212
|
+
lifetime: 'singleton',
|
|
213
|
+
usedBy: ['hello'],
|
|
214
|
+
});
|
|
158
215
|
});
|
|
159
216
|
});
|
package/src/trails/survey.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface BriefReport {
|
|
|
30
30
|
readonly version: string;
|
|
31
31
|
readonly contractVersion: string;
|
|
32
32
|
readonly features: {
|
|
33
|
+
readonly services: boolean;
|
|
33
34
|
readonly outputSchemas: boolean;
|
|
34
35
|
readonly examples: boolean;
|
|
35
36
|
readonly detours: boolean;
|
|
@@ -37,6 +38,38 @@ export interface BriefReport {
|
|
|
37
38
|
};
|
|
38
39
|
readonly trails: number;
|
|
39
40
|
readonly events: number;
|
|
41
|
+
readonly services: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SurveyListReport {
|
|
45
|
+
readonly count: number;
|
|
46
|
+
readonly entries: readonly {
|
|
47
|
+
readonly examples: number;
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly kind: string;
|
|
50
|
+
readonly safety: string;
|
|
51
|
+
}[];
|
|
52
|
+
readonly serviceCount: number;
|
|
53
|
+
readonly services: readonly {
|
|
54
|
+
readonly description: string | null;
|
|
55
|
+
readonly health: 'available' | 'none';
|
|
56
|
+
readonly id: string;
|
|
57
|
+
readonly kind: 'service';
|
|
58
|
+
readonly lifetime: 'singleton';
|
|
59
|
+
readonly usedBy: readonly string[];
|
|
60
|
+
}[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface TrailDetailReport {
|
|
64
|
+
readonly description: string | null;
|
|
65
|
+
readonly detours: Trail<unknown, unknown>['detours'] | null;
|
|
66
|
+
readonly examples: readonly unknown[];
|
|
67
|
+
readonly follow: readonly string[];
|
|
68
|
+
readonly id: string;
|
|
69
|
+
readonly intent: 'read' | 'write' | 'destroy';
|
|
70
|
+
readonly kind: string;
|
|
71
|
+
readonly safety: string;
|
|
72
|
+
readonly services: readonly string[];
|
|
40
73
|
}
|
|
41
74
|
|
|
42
75
|
/** Check if a trail has a specific feature. */
|
|
@@ -50,7 +83,12 @@ const trailHas = (raw: Record<string, unknown>, key: string): boolean => {
|
|
|
50
83
|
/** Detect which features are used across trails. */
|
|
51
84
|
const detectFeatures = (
|
|
52
85
|
app: Topo
|
|
53
|
-
): {
|
|
86
|
+
): {
|
|
87
|
+
hasDetours: boolean;
|
|
88
|
+
hasExamples: boolean;
|
|
89
|
+
hasOutputSchemas: boolean;
|
|
90
|
+
hasServices: boolean;
|
|
91
|
+
} => {
|
|
54
92
|
const trails = [...app.trails.values()].map(
|
|
55
93
|
(item) => item as unknown as Record<string, unknown>
|
|
56
94
|
);
|
|
@@ -58,12 +96,17 @@ const detectFeatures = (
|
|
|
58
96
|
hasDetours: trails.some((r) => trailHas(r, 'detours')),
|
|
59
97
|
hasExamples: trails.some((r) => trailHas(r, 'examples')),
|
|
60
98
|
hasOutputSchemas: trails.some((r) => trailHas(r, 'output')),
|
|
99
|
+
hasServices: trails.some(
|
|
100
|
+
(r) =>
|
|
101
|
+
Array.isArray(r['services']) && (r['services'] as unknown[]).length > 0
|
|
102
|
+
),
|
|
61
103
|
};
|
|
62
104
|
};
|
|
63
105
|
|
|
64
106
|
/** Generate a compact capability report for the given topo. */
|
|
65
107
|
export const generateBriefReport = (app: Topo): BriefReport => {
|
|
66
|
-
const { hasDetours, hasExamples, hasOutputSchemas } =
|
|
108
|
+
const { hasDetours, hasExamples, hasOutputSchemas, hasServices } =
|
|
109
|
+
detectFeatures(app);
|
|
67
110
|
|
|
68
111
|
return {
|
|
69
112
|
contractVersion: '2026-03',
|
|
@@ -73,8 +116,10 @@ export const generateBriefReport = (app: Topo): BriefReport => {
|
|
|
73
116
|
events: app.events.size > 0,
|
|
74
117
|
examples: hasExamples,
|
|
75
118
|
outputSchemas: hasOutputSchemas,
|
|
119
|
+
services: hasServices,
|
|
76
120
|
},
|
|
77
121
|
name: app.name,
|
|
122
|
+
services: app.services.size,
|
|
78
123
|
trails: app.trails.size,
|
|
79
124
|
version: '0.1.0',
|
|
80
125
|
};
|
|
@@ -96,7 +141,45 @@ const safetyLabel = (entry: {
|
|
|
96
141
|
return '-';
|
|
97
142
|
};
|
|
98
143
|
|
|
99
|
-
const
|
|
144
|
+
const buildServiceUsage = (
|
|
145
|
+
app: Topo
|
|
146
|
+
): ReadonlyMap<string, readonly string[]> => {
|
|
147
|
+
const usage = new Map<string, string[]>();
|
|
148
|
+
|
|
149
|
+
for (const trailDef of app.list()) {
|
|
150
|
+
for (const declaredService of trailDef.services) {
|
|
151
|
+
const users = usage.get(declaredService.id) ?? [];
|
|
152
|
+
users.push(trailDef.id);
|
|
153
|
+
usage.set(declaredService.id, users);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return new Map(
|
|
158
|
+
[...usage.entries()].map(([id, users]) => [id, users.toSorted()] as const)
|
|
159
|
+
);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const serviceHealthStatus = (service: {
|
|
163
|
+
health?: unknown;
|
|
164
|
+
}): 'available' | 'none' =>
|
|
165
|
+
service.health === undefined ? 'none' : 'available';
|
|
166
|
+
|
|
167
|
+
const formatServiceList = (app: Topo): SurveyListReport['services'] => {
|
|
168
|
+
const usage = buildServiceUsage(app);
|
|
169
|
+
return app
|
|
170
|
+
.listServices()
|
|
171
|
+
.map((service) => ({
|
|
172
|
+
description: service.description ?? null,
|
|
173
|
+
health: serviceHealthStatus(service),
|
|
174
|
+
id: service.id,
|
|
175
|
+
kind: service.kind,
|
|
176
|
+
lifetime: 'singleton' as const,
|
|
177
|
+
usedBy: usage.get(service.id) ?? [],
|
|
178
|
+
}))
|
|
179
|
+
.toSorted((a, b) => a.id.localeCompare(b.id));
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const generateSurveyList = (app: Topo): SurveyListReport => {
|
|
100
183
|
const items = app.list();
|
|
101
184
|
const entries = items.map((item) => {
|
|
102
185
|
const safety = safetyLabel(
|
|
@@ -116,7 +199,14 @@ const formatTrailList = (app: Topo): object => {
|
|
|
116
199
|
};
|
|
117
200
|
});
|
|
118
201
|
|
|
119
|
-
|
|
202
|
+
const services = formatServiceList(app);
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
count: items.length,
|
|
206
|
+
entries,
|
|
207
|
+
serviceCount: services.length,
|
|
208
|
+
services,
|
|
209
|
+
};
|
|
120
210
|
};
|
|
121
211
|
|
|
122
212
|
/**
|
|
@@ -126,7 +216,9 @@ const formatTrailList = (app: Topo): object => {
|
|
|
126
216
|
* surface-map entry. The two serve different audiences (human display vs
|
|
127
217
|
* machine-diffable surface map) so they are kept separate.
|
|
128
218
|
*/
|
|
129
|
-
const
|
|
219
|
+
export const generateTrailDetail = (
|
|
220
|
+
item: Trail<unknown, unknown>
|
|
221
|
+
): TrailDetailReport => {
|
|
130
222
|
const safety = safetyLabel(
|
|
131
223
|
item as unknown as { intent?: 'read' | 'write' | 'destroy' }
|
|
132
224
|
);
|
|
@@ -135,9 +227,26 @@ const formatTrailDetail = (item: Trail<unknown, unknown>): object => {
|
|
|
135
227
|
description: item.description ?? null,
|
|
136
228
|
detours: item.detours ?? null,
|
|
137
229
|
examples: item.examples ?? [],
|
|
230
|
+
follow: item.follow.toSorted(),
|
|
138
231
|
id: item.id,
|
|
232
|
+
intent: item.intent,
|
|
139
233
|
kind: item.kind,
|
|
140
234
|
safety,
|
|
235
|
+
services: item.services.map((service) => service.id).toSorted(),
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const formatServiceDetail = (app: Topo, serviceId: string): object => {
|
|
240
|
+
const item = app.getService(serviceId);
|
|
241
|
+
const usedBy = buildServiceUsage(app).get(serviceId) ?? [];
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
description: item?.description ?? null,
|
|
245
|
+
health: item ? serviceHealthStatus(item) : 'none',
|
|
246
|
+
id: serviceId,
|
|
247
|
+
kind: 'service',
|
|
248
|
+
lifetime: 'singleton',
|
|
249
|
+
usedBy,
|
|
141
250
|
};
|
|
142
251
|
};
|
|
143
252
|
|
|
@@ -180,10 +289,13 @@ const buildSurveyDetail = (
|
|
|
180
289
|
trailId: string
|
|
181
290
|
): Result<object, Error> => {
|
|
182
291
|
const item = app.get(trailId);
|
|
183
|
-
if (
|
|
184
|
-
return Result.
|
|
292
|
+
if (item) {
|
|
293
|
+
return Result.ok(generateTrailDetail(item as Trail<unknown, unknown>));
|
|
294
|
+
}
|
|
295
|
+
if (app.getService(trailId)) {
|
|
296
|
+
return Result.ok(formatServiceDetail(app, trailId));
|
|
185
297
|
}
|
|
186
|
-
return Result.
|
|
298
|
+
return Result.err(new Error(`Trail or service not found: ${trailId}`));
|
|
187
299
|
};
|
|
188
300
|
|
|
189
301
|
const buildSurveyGenerate = async (
|
|
@@ -231,7 +343,7 @@ const surveyHandlers: Record<SurveyMode, SurveyHandler> = {
|
|
|
231
343
|
detail: (app, input) => buildSurveyDetail(app, input.trailId ?? ''),
|
|
232
344
|
diff: (app, input) => buildSurveyDiff(app, input.breakingOnly),
|
|
233
345
|
generate: (app) => buildSurveyGenerate(app),
|
|
234
|
-
list: (app) => Result.ok(
|
|
346
|
+
list: (app) => Result.ok(generateSurveyList(app)),
|
|
235
347
|
openapi: (app) => Result.ok(generateOpenApiSpec(app)),
|
|
236
348
|
};
|
|
237
349
|
|
|
@@ -298,6 +410,17 @@ export const surveyTrail = trail('survey', {
|
|
|
298
410
|
safety: z.string(),
|
|
299
411
|
})
|
|
300
412
|
),
|
|
413
|
+
serviceCount: z.number(),
|
|
414
|
+
services: z.array(
|
|
415
|
+
z.object({
|
|
416
|
+
description: z.string().nullable(),
|
|
417
|
+
health: z.enum(['available', 'none']),
|
|
418
|
+
id: z.string(),
|
|
419
|
+
kind: z.literal('service'),
|
|
420
|
+
lifetime: z.literal('singleton'),
|
|
421
|
+
usedBy: z.array(z.string()),
|
|
422
|
+
})
|
|
423
|
+
),
|
|
301
424
|
}),
|
|
302
425
|
z.object({
|
|
303
426
|
contractVersion: z.string(),
|
|
@@ -307,8 +430,10 @@ export const surveyTrail = trail('survey', {
|
|
|
307
430
|
events: z.boolean(),
|
|
308
431
|
examples: z.boolean(),
|
|
309
432
|
outputSchemas: z.boolean(),
|
|
433
|
+
services: z.boolean(),
|
|
310
434
|
}),
|
|
311
435
|
name: z.string(),
|
|
436
|
+
services: z.number(),
|
|
312
437
|
trails: z.number(),
|
|
313
438
|
version: z.string(),
|
|
314
439
|
}),
|
|
@@ -322,9 +447,20 @@ export const surveyTrail = trail('survey', {
|
|
|
322
447
|
description: z.unknown().nullable(),
|
|
323
448
|
detours: z.unknown().nullable(),
|
|
324
449
|
examples: z.array(z.unknown()),
|
|
450
|
+
follow: z.array(z.string()),
|
|
325
451
|
id: z.string(),
|
|
452
|
+
intent: z.enum(['read', 'write', 'destroy']),
|
|
326
453
|
kind: z.string(),
|
|
327
454
|
safety: z.string(),
|
|
455
|
+
services: z.array(z.string()),
|
|
456
|
+
}),
|
|
457
|
+
z.object({
|
|
458
|
+
description: z.string().nullable(),
|
|
459
|
+
health: z.enum(['available', 'none']),
|
|
460
|
+
id: z.string(),
|
|
461
|
+
kind: z.literal('service'),
|
|
462
|
+
lifetime: z.literal('singleton'),
|
|
463
|
+
usedBy: z.array(z.string()),
|
|
328
464
|
}),
|
|
329
465
|
z.object({
|
|
330
466
|
hash: z.string(),
|