@ontrails/trails 1.0.0-beta.15 → 1.0.0-beta.16
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/CHANGELOG.md +197 -2
- package/README.md +27 -0
- package/package.json +19 -8
- package/src/app.ts +15 -5
- package/src/cli.ts +303 -10
- package/src/completions.ts +240 -0
- package/src/load-app-mirror.ts +160 -0
- package/src/local-state-io.ts +153 -0
- package/src/project-writes.ts +320 -0
- package/src/run-collision.ts +125 -0
- package/src/run-completions-install.ts +179 -0
- package/src/run-example.ts +149 -0
- package/src/run-examples.ts +148 -0
- package/src/run-quiet.ts +75 -0
- package/src/run-trace.ts +273 -0
- package/src/run-warden.ts +39 -0
- package/src/run-watch.ts +432 -0
- package/src/scaffold-versions.generated.ts +12 -0
- package/src/trails/add-surface.ts +45 -23
- package/src/trails/add-trail.ts +27 -17
- package/src/trails/add-verify.ts +57 -17
- package/src/trails/completions-complete.ts +165 -0
- package/src/trails/completions.ts +47 -0
- package/src/trails/create-scaffold.ts +86 -33
- package/src/trails/create.ts +11 -3
- package/src/trails/dev-clean.ts +6 -1
- package/src/trails/dev-reset.ts +6 -1
- package/src/trails/dev-stats.ts +6 -1
- package/src/trails/dev-support.ts +29 -17
- package/src/trails/draft-promote.ts +289 -80
- package/src/trails/guide.ts +54 -34
- package/src/trails/load-app.ts +251 -56
- package/src/trails/root-dir.ts +21 -0
- package/src/trails/run-example.ts +482 -0
- package/src/trails/run-examples.ts +141 -0
- package/src/trails/run.ts +403 -0
- package/src/trails/survey.ts +506 -200
- package/src/trails/topo-activation.ts +385 -0
- package/src/trails/topo-compile.ts +55 -0
- package/src/trails/topo-history.ts +6 -1
- package/src/trails/topo-output-schemas.ts +175 -0
- package/src/trails/topo-pin.ts +19 -6
- package/src/trails/topo-read-support.ts +171 -228
- package/src/trails/topo-reports.ts +400 -25
- package/src/trails/topo-store-support.ts +43 -19
- package/src/trails/topo-support.ts +18 -28
- package/src/trails/topo-unpin.ts +6 -1
- package/src/trails/topo-verify.ts +18 -5
- package/src/trails/topo.ts +60 -23
- package/src/trails/warden-guide.ts +121 -0
- package/src/trails/warden.ts +137 -56
- package/src/versions.ts +3 -18
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-lint.log +0 -3
- package/.turbo/turbo-typecheck.log +0 -1
- package/__tests__/examples.test.ts +0 -45
- package/dist/bin/trails.d.ts +0 -3
- package/dist/bin/trails.d.ts.map +0 -1
- package/dist/bin/trails.js +0 -4
- package/dist/bin/trails.js.map +0 -1
- package/dist/src/app.d.ts +0 -2
- package/dist/src/app.d.ts.map +0 -1
- package/dist/src/app.js +0 -22
- package/dist/src/app.js.map +0 -1
- package/dist/src/clack.d.ts +0 -9
- package/dist/src/clack.d.ts.map +0 -1
- package/dist/src/clack.js +0 -84
- package/dist/src/clack.js.map +0 -1
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.d.ts.map +0 -1
- package/dist/src/cli.js +0 -14
- package/dist/src/cli.js.map +0 -1
- package/dist/src/trails/add-surface.d.ts +0 -13
- package/dist/src/trails/add-surface.d.ts.map +0 -1
- package/dist/src/trails/add-surface.js +0 -110
- package/dist/src/trails/add-surface.js.map +0 -1
- package/dist/src/trails/add-trail.d.ts +0 -12
- package/dist/src/trails/add-trail.d.ts.map +0 -1
- package/dist/src/trails/add-trail.js +0 -104
- package/dist/src/trails/add-trail.js.map +0 -1
- package/dist/src/trails/add-trailhead.d.ts +0 -13
- package/dist/src/trails/add-trailhead.d.ts.map +0 -1
- package/dist/src/trails/add-trailhead.js +0 -88
- package/dist/src/trails/add-trailhead.js.map +0 -1
- package/dist/src/trails/add-verify.d.ts +0 -10
- package/dist/src/trails/add-verify.d.ts.map +0 -1
- package/dist/src/trails/add-verify.js +0 -68
- package/dist/src/trails/add-verify.js.map +0 -1
- package/dist/src/trails/create-scaffold.d.ts +0 -15
- package/dist/src/trails/create-scaffold.d.ts.map +0 -1
- package/dist/src/trails/create-scaffold.js +0 -295
- package/dist/src/trails/create-scaffold.js.map +0 -1
- package/dist/src/trails/create.d.ts +0 -18
- package/dist/src/trails/create.d.ts.map +0 -1
- package/dist/src/trails/create.js +0 -126
- package/dist/src/trails/create.js.map +0 -1
- package/dist/src/trails/dev-clean.d.ts +0 -9
- package/dist/src/trails/dev-clean.d.ts.map +0 -1
- package/dist/src/trails/dev-clean.js +0 -66
- package/dist/src/trails/dev-clean.js.map +0 -1
- package/dist/src/trails/dev-reset.d.ts +0 -6
- package/dist/src/trails/dev-reset.d.ts.map +0 -1
- package/dist/src/trails/dev-reset.js +0 -39
- package/dist/src/trails/dev-reset.js.map +0 -1
- package/dist/src/trails/dev-stats.d.ts +0 -7
- package/dist/src/trails/dev-stats.d.ts.map +0 -1
- package/dist/src/trails/dev-stats.js +0 -61
- package/dist/src/trails/dev-stats.js.map +0 -1
- package/dist/src/trails/dev-support.d.ts +0 -64
- package/dist/src/trails/dev-support.d.ts.map +0 -1
- package/dist/src/trails/dev-support.js +0 -181
- package/dist/src/trails/dev-support.js.map +0 -1
- package/dist/src/trails/draft-promote.d.ts +0 -18
- package/dist/src/trails/draft-promote.d.ts.map +0 -1
- package/dist/src/trails/draft-promote.js +0 -400
- package/dist/src/trails/draft-promote.js.map +0 -1
- package/dist/src/trails/guide.d.ts +0 -21
- package/dist/src/trails/guide.d.ts.map +0 -1
- package/dist/src/trails/guide.js +0 -61
- package/dist/src/trails/guide.js.map +0 -1
- package/dist/src/trails/load-app.d.ts +0 -12
- package/dist/src/trails/load-app.d.ts.map +0 -1
- package/dist/src/trails/load-app.js +0 -415
- package/dist/src/trails/load-app.js.map +0 -1
- package/dist/src/trails/project.d.ts +0 -8
- package/dist/src/trails/project.d.ts.map +0 -1
- package/dist/src/trails/project.js +0 -54
- package/dist/src/trails/project.js.map +0 -1
- package/dist/src/trails/survey.d.ts +0 -18
- package/dist/src/trails/survey.d.ts.map +0 -1
- package/dist/src/trails/survey.js +0 -234
- package/dist/src/trails/survey.js.map +0 -1
- package/dist/src/trails/topo-constants.d.ts +0 -3
- package/dist/src/trails/topo-constants.d.ts.map +0 -1
- package/dist/src/trails/topo-constants.js +0 -3
- package/dist/src/trails/topo-constants.js.map +0 -1
- package/dist/src/trails/topo-export.d.ts +0 -19
- package/dist/src/trails/topo-export.d.ts.map +0 -1
- package/dist/src/trails/topo-export.js +0 -31
- package/dist/src/trails/topo-export.js.map +0 -1
- package/dist/src/trails/topo-history.d.ts +0 -20
- package/dist/src/trails/topo-history.d.ts.map +0 -1
- package/dist/src/trails/topo-history.js +0 -32
- package/dist/src/trails/topo-history.js.map +0 -1
- package/dist/src/trails/topo-pin.d.ts +0 -17
- package/dist/src/trails/topo-pin.d.ts.map +0 -1
- package/dist/src/trails/topo-pin.js +0 -31
- package/dist/src/trails/topo-pin.js.map +0 -1
- package/dist/src/trails/topo-read-support.d.ts +0 -58
- package/dist/src/trails/topo-read-support.d.ts.map +0 -1
- package/dist/src/trails/topo-read-support.js +0 -167
- package/dist/src/trails/topo-read-support.js.map +0 -1
- package/dist/src/trails/topo-reports.d.ts +0 -54
- package/dist/src/trails/topo-reports.d.ts.map +0 -1
- package/dist/src/trails/topo-reports.js +0 -128
- package/dist/src/trails/topo-reports.js.map +0 -1
- package/dist/src/trails/topo-show.d.ts +0 -23
- package/dist/src/trails/topo-show.d.ts.map +0 -1
- package/dist/src/trails/topo-show.js +0 -49
- package/dist/src/trails/topo-show.js.map +0 -1
- package/dist/src/trails/topo-store-support.d.ts +0 -13
- package/dist/src/trails/topo-store-support.d.ts.map +0 -1
- package/dist/src/trails/topo-store-support.js +0 -55
- package/dist/src/trails/topo-store-support.js.map +0 -1
- package/dist/src/trails/topo-support.d.ts +0 -76
- package/dist/src/trails/topo-support.d.ts.map +0 -1
- package/dist/src/trails/topo-support.js +0 -132
- package/dist/src/trails/topo-support.js.map +0 -1
- package/dist/src/trails/topo-unpin.d.ts +0 -20
- package/dist/src/trails/topo-unpin.d.ts.map +0 -1
- package/dist/src/trails/topo-unpin.js +0 -44
- package/dist/src/trails/topo-unpin.js.map +0 -1
- package/dist/src/trails/topo-verify.d.ts +0 -5
- package/dist/src/trails/topo-verify.d.ts.map +0 -1
- package/dist/src/trails/topo-verify.js +0 -24
- package/dist/src/trails/topo-verify.js.map +0 -1
- package/dist/src/trails/topo.d.ts +0 -5
- package/dist/src/trails/topo.d.ts.map +0 -1
- package/dist/src/trails/topo.js +0 -63
- package/dist/src/trails/topo.js.map +0 -1
- package/dist/src/trails/warden.d.ts +0 -20
- package/dist/src/trails/warden.d.ts.map +0 -1
- package/dist/src/trails/warden.js +0 -98
- package/dist/src/trails/warden.js.map +0 -1
- package/dist/src/versions.d.ts +0 -12
- package/dist/src/versions.d.ts.map +0 -1
- package/dist/src/versions.js +0 -23
- package/dist/src/versions.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/__tests__/add-trail.test.ts +0 -97
- package/src/__tests__/create.test.ts +0 -415
- package/src/__tests__/draft-promote.test.ts +0 -144
- package/src/__tests__/guide.test.ts +0 -96
- package/src/__tests__/load-app.test.ts +0 -419
- package/src/__tests__/survey.test.ts +0 -377
- package/src/__tests__/topo-dev.test.ts +0 -426
- package/src/__tests__/warden.test.ts +0 -74
- package/src/trails/topo-export.ts +0 -35
- package/src/trails/topo-show.ts +0 -54
- package/tsconfig.json +0 -9
- package/tsconfig.tests.json +0 -10
package/src/trails/survey.ts
CHANGED
|
@@ -1,245 +1,461 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `survey` trail -- Full topo introspection.
|
|
3
3
|
*
|
|
4
|
-
* Lists trails,
|
|
5
|
-
*
|
|
4
|
+
* Lists trails, looks up trails/resources/signals, and diffs against previous
|
|
5
|
+
* versions.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { join } from 'node:path';
|
|
8
|
+
import { basename, extname, join } from 'node:path';
|
|
9
9
|
|
|
10
10
|
import type { Topo } from '@ontrails/core';
|
|
11
|
-
import { NotFoundError, Result, trail } from '@ontrails/core';
|
|
12
|
-
import type { DiffResult } from '@ontrails/schema';
|
|
13
11
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
deriveSafePath,
|
|
13
|
+
NotFoundError,
|
|
14
|
+
Result,
|
|
15
|
+
trail,
|
|
16
|
+
ValidationError,
|
|
17
|
+
} from '@ontrails/core';
|
|
18
|
+
import type { DiffEntry, DiffResult, TopoGraph } from '@ontrails/topographer';
|
|
19
|
+
import {
|
|
20
|
+
createTopoStore,
|
|
21
|
+
deriveTopoGraphDiff,
|
|
22
|
+
deriveTopoGraph,
|
|
23
|
+
TOPO_GRAPH_SCHEMA_VERSION,
|
|
24
|
+
readTopoGraph,
|
|
25
|
+
} from '@ontrails/topographer';
|
|
19
26
|
import { z } from 'zod';
|
|
20
27
|
|
|
21
|
-
import {
|
|
28
|
+
import { writeIsolatedExampleJsonFile } from '../local-state-io.js';
|
|
29
|
+
|
|
30
|
+
import { tryLoadFreshAppLease } from './load-app.js';
|
|
31
|
+
import { resolveTrailRootDir } from './root-dir.js';
|
|
22
32
|
import {
|
|
23
33
|
buildCurrentTopoBrief,
|
|
24
|
-
buildCurrentTopoDetail,
|
|
25
34
|
buildCurrentTopoList,
|
|
35
|
+
buildCurrentTopoMatches,
|
|
36
|
+
buildCurrentTrailDetail,
|
|
37
|
+
buildCurrentResourceDetail,
|
|
38
|
+
buildCurrentSignalDetail,
|
|
39
|
+
readSurfaceLayerNamesFromContext,
|
|
26
40
|
} from './topo-read-support.js';
|
|
27
|
-
import {
|
|
41
|
+
import {
|
|
42
|
+
activationOverviewOutput,
|
|
43
|
+
resourceDetailOutput,
|
|
44
|
+
signalDetailOutput,
|
|
45
|
+
trailDetailOutput,
|
|
46
|
+
} from './topo-output-schemas.js';
|
|
47
|
+
import { createIsolatedExampleInput } from './topo-support.js';
|
|
48
|
+
import { briefReportSchema } from './topo-reports.js';
|
|
49
|
+
import type { SurfaceLayerNames } from './topo-reports.js';
|
|
28
50
|
|
|
29
51
|
export {
|
|
52
|
+
briefReportSchema,
|
|
30
53
|
deriveBriefReport,
|
|
31
54
|
deriveResourceDetail,
|
|
55
|
+
deriveSignalDetail,
|
|
32
56
|
deriveSurveyList,
|
|
33
57
|
deriveTrailDetail,
|
|
34
58
|
} from './topo-reports.js';
|
|
35
59
|
export type {
|
|
36
60
|
BriefReport,
|
|
61
|
+
SignalDetailReport,
|
|
62
|
+
SurfaceLayerNames,
|
|
37
63
|
SurveyListReport,
|
|
38
64
|
TrailDetailReport,
|
|
39
65
|
} from './topo-reports.js';
|
|
40
66
|
|
|
41
67
|
// ---------------------------------------------------------------------------
|
|
42
|
-
//
|
|
68
|
+
// Survey diff helpers
|
|
43
69
|
// ---------------------------------------------------------------------------
|
|
44
70
|
|
|
45
|
-
|
|
71
|
+
interface SurveyDiffReport {
|
|
72
|
+
readonly against: string;
|
|
73
|
+
readonly breaking: readonly DiffEntry[];
|
|
74
|
+
readonly hasBreaking: boolean;
|
|
75
|
+
readonly info: readonly DiffEntry[];
|
|
76
|
+
readonly mode: 'diff';
|
|
77
|
+
readonly warnings: readonly DiffEntry[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const formatDiff = (diff: DiffResult, against: string): SurveyDiffReport => ({
|
|
81
|
+
against,
|
|
46
82
|
breaking: diff.breaking,
|
|
47
83
|
hasBreaking: diff.hasBreaking,
|
|
48
84
|
info: diff.info,
|
|
85
|
+
mode: 'diff',
|
|
49
86
|
warnings: diff.warnings,
|
|
50
87
|
});
|
|
51
88
|
|
|
89
|
+
const createDiffExampleInput = (): {
|
|
90
|
+
readonly against: string;
|
|
91
|
+
readonly module: string;
|
|
92
|
+
readonly rootDir: string;
|
|
93
|
+
} => {
|
|
94
|
+
const input = createIsolatedExampleInput('survey-diff');
|
|
95
|
+
writeIsolatedExampleJsonFile(input.rootDir, 'baseline/topo.lock', {
|
|
96
|
+
activationGraph: {
|
|
97
|
+
edgeCount: 0,
|
|
98
|
+
edges: [],
|
|
99
|
+
sourceCount: 0,
|
|
100
|
+
sourceKeys: [],
|
|
101
|
+
trailIds: [],
|
|
102
|
+
},
|
|
103
|
+
activationSources: {},
|
|
104
|
+
entries: [],
|
|
105
|
+
generatedAt: '2026-01-01T00:00:00.000Z',
|
|
106
|
+
topoGraphSchemaVersion: TOPO_GRAPH_SCHEMA_VERSION,
|
|
107
|
+
} satisfies TopoGraph);
|
|
108
|
+
return { ...input, against: 'baseline' };
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const isNotFound = (error: unknown): boolean =>
|
|
112
|
+
typeof error === 'object' &&
|
|
113
|
+
error !== null &&
|
|
114
|
+
(error as NodeJS.ErrnoException).code === 'ENOENT';
|
|
115
|
+
|
|
116
|
+
const readTopoGraphFile = async (
|
|
117
|
+
filePath: string
|
|
118
|
+
): Promise<TopoGraph | null> => {
|
|
119
|
+
try {
|
|
120
|
+
return (await Bun.file(filePath).json()) as TopoGraph;
|
|
121
|
+
} catch (error: unknown) {
|
|
122
|
+
if (isNotFound(error)) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const readStoredTopoGraph = (
|
|
130
|
+
rootDir: string,
|
|
131
|
+
against: string
|
|
132
|
+
): TopoGraph | undefined => {
|
|
133
|
+
try {
|
|
134
|
+
const store = createTopoStore({ rootDir });
|
|
135
|
+
const stored =
|
|
136
|
+
store.exports.get({ pin: against }) ??
|
|
137
|
+
store.exports.get({ snapshotId: against });
|
|
138
|
+
return stored === undefined
|
|
139
|
+
? undefined
|
|
140
|
+
: (JSON.parse(stored.topoGraphJson) as TopoGraph);
|
|
141
|
+
} catch (error: unknown) {
|
|
142
|
+
if (error instanceof NotFoundError) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const readPathTopoGraph = async (
|
|
150
|
+
rootDir: string,
|
|
151
|
+
against: string
|
|
152
|
+
): Promise<Result<TopoGraph | null, Error>> => {
|
|
153
|
+
const safePath = deriveSafePath(rootDir, against);
|
|
154
|
+
if (safePath.isErr()) {
|
|
155
|
+
return safePath;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return Result.ok(
|
|
159
|
+
basename(safePath.value) === 'topo.lock' ||
|
|
160
|
+
extname(safePath.value) === '.json'
|
|
161
|
+
? await readTopoGraphFile(safePath.value)
|
|
162
|
+
: await readTopoGraph({ dir: safePath.value })
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const describeAgainstPathTarget = (against: string): string =>
|
|
167
|
+
basename(against) === 'topo.lock' || extname(against) === '.json'
|
|
168
|
+
? 'workspace-relative TopoGraph file'
|
|
169
|
+
: 'workspace-relative directory containing topo.lock';
|
|
170
|
+
|
|
171
|
+
const topoGraphNotFound = (against: string): NotFoundError =>
|
|
172
|
+
new NotFoundError(
|
|
173
|
+
`No TopoGraph found for: ${against}. Tried ${describeAgainstPathTarget(
|
|
174
|
+
against
|
|
175
|
+
)}, then topo-store pin and snapshot references.`
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
const readAgainstTopoGraph = async (
|
|
179
|
+
rootDir: string,
|
|
180
|
+
against?: string | undefined
|
|
181
|
+
): Promise<Result<{ against: string; map: TopoGraph }, Error>> => {
|
|
182
|
+
if (against === undefined || against === 'saved') {
|
|
183
|
+
const map = await readTopoGraph({ dir: join(rootDir, '.trails') });
|
|
184
|
+
return map === null
|
|
185
|
+
? Result.err(
|
|
186
|
+
new NotFoundError(
|
|
187
|
+
'No saved TopoGraph found. Run `trails topo compile` first.'
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
: Result.ok({ against: 'saved', map });
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Treat explicit filesystem targets as the most local user intent; stored
|
|
194
|
+
// pins and snapshot ids are fallback references when no path exists.
|
|
195
|
+
const pathMap = await readPathTopoGraph(rootDir, against);
|
|
196
|
+
if (pathMap.isErr()) {
|
|
197
|
+
return pathMap;
|
|
198
|
+
}
|
|
199
|
+
if (pathMap.value !== null) {
|
|
200
|
+
return Result.ok({ against, map: pathMap.value });
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const storedMap = readStoredTopoGraph(rootDir, against);
|
|
204
|
+
if (storedMap !== undefined) {
|
|
205
|
+
return Result.ok({ against, map: storedMap });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return Result.err(topoGraphNotFound(against));
|
|
209
|
+
};
|
|
210
|
+
|
|
52
211
|
const buildSurveyDiff = async (
|
|
53
212
|
app: Topo,
|
|
54
213
|
rootDir: string,
|
|
55
|
-
breakingOnly: boolean
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'No saved surface map found. Run `trails topo export` first.'
|
|
63
|
-
)
|
|
64
|
-
);
|
|
214
|
+
breakingOnly: boolean,
|
|
215
|
+
against?: string | undefined
|
|
216
|
+
): Promise<Result<SurveyDiffReport, Error>> => {
|
|
217
|
+
const currentMap = deriveTopoGraph(app);
|
|
218
|
+
const previous = await readAgainstTopoGraph(rootDir, against);
|
|
219
|
+
if (previous.isErr()) {
|
|
220
|
+
return previous;
|
|
65
221
|
}
|
|
66
222
|
|
|
67
|
-
const diff =
|
|
223
|
+
const diff = deriveTopoGraphDiff(previous.value.map, currentMap);
|
|
68
224
|
return Result.ok(
|
|
69
225
|
breakingOnly
|
|
70
|
-
? formatDiff({
|
|
71
|
-
|
|
72
|
-
entries: diff.breaking,
|
|
73
|
-
info: [],
|
|
74
|
-
warnings: [],
|
|
75
|
-
})
|
|
76
|
-
: formatDiff(diff)
|
|
226
|
+
? formatDiff({ ...diff, info: [], warnings: [] }, previous.value.against)
|
|
227
|
+
: formatDiff(diff, previous.value.against)
|
|
77
228
|
);
|
|
78
229
|
};
|
|
79
230
|
|
|
80
|
-
const
|
|
231
|
+
const buildSurveyLookup = (
|
|
81
232
|
app: Topo,
|
|
82
|
-
|
|
233
|
+
entityId: string,
|
|
234
|
+
rootDir: string,
|
|
235
|
+
surfaceLayerNames?: Partial<SurfaceLayerNames> | undefined
|
|
236
|
+
): Result<object, Error> => {
|
|
237
|
+
const matches = buildCurrentTopoMatches(app, entityId, {
|
|
238
|
+
rootDir,
|
|
239
|
+
surfaceLayerNames,
|
|
240
|
+
});
|
|
241
|
+
return Result.ok({ matches });
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const buildSurveyTrailDetail = (
|
|
245
|
+
app: Topo,
|
|
246
|
+
id: string,
|
|
247
|
+
rootDir: string,
|
|
248
|
+
surfaceLayerNames?: Partial<SurfaceLayerNames> | undefined
|
|
249
|
+
): Result<object, Error> => {
|
|
250
|
+
const detail = buildCurrentTrailDetail(app, id, {
|
|
251
|
+
rootDir,
|
|
252
|
+
surfaceLayerNames,
|
|
253
|
+
});
|
|
254
|
+
return detail === undefined
|
|
255
|
+
? Result.err(new NotFoundError(`Trail not found: ${id}`))
|
|
256
|
+
: Result.ok(detail);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const buildSurveyResourceDetail = (
|
|
260
|
+
app: Topo,
|
|
261
|
+
id: string,
|
|
83
262
|
rootDir: string
|
|
84
263
|
): Result<object, Error> => {
|
|
85
|
-
const detail =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return Result.err(
|
|
90
|
-
new NotFoundError(`Trail or resource not found: ${trailId}`)
|
|
91
|
-
);
|
|
264
|
+
const detail = buildCurrentResourceDetail(app, id, { rootDir });
|
|
265
|
+
return detail === undefined
|
|
266
|
+
? Result.err(new NotFoundError(`Resource not found: ${id}`))
|
|
267
|
+
: Result.ok(detail);
|
|
92
268
|
};
|
|
93
269
|
|
|
94
|
-
const
|
|
270
|
+
const buildSurveySignalDetail = (
|
|
95
271
|
app: Topo,
|
|
272
|
+
id: string,
|
|
96
273
|
rootDir: string
|
|
97
|
-
):
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return Result.ok({
|
|
103
|
-
hash: exported.value.hash,
|
|
104
|
-
lockPath: exported.value.lockPath,
|
|
105
|
-
mapPath: exported.value.mapPath,
|
|
106
|
-
});
|
|
274
|
+
): Result<object, Error> => {
|
|
275
|
+
const detail = buildCurrentSignalDetail(app, id, { rootDir });
|
|
276
|
+
return detail === undefined
|
|
277
|
+
? Result.err(new NotFoundError(`Signal not found: ${id}`))
|
|
278
|
+
: Result.ok(detail);
|
|
107
279
|
};
|
|
108
280
|
|
|
109
281
|
interface SurveyInput {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
generate: boolean;
|
|
114
|
-
openapi: boolean;
|
|
115
|
-
trailId?: string | undefined;
|
|
282
|
+
id?: string | undefined;
|
|
283
|
+
module?: string | undefined;
|
|
284
|
+
rootDir?: string | undefined;
|
|
116
285
|
}
|
|
117
286
|
|
|
118
|
-
type SurveyMode = '
|
|
287
|
+
type SurveyMode = 'lookup' | 'overview';
|
|
119
288
|
|
|
120
|
-
|
|
121
|
-
const modeChecks: readonly [(input: SurveyInput) => boolean, SurveyMode][] = [
|
|
122
|
-
[(i) => i.brief, 'brief'],
|
|
123
|
-
[(i) => i.diffSaved, 'diff'],
|
|
124
|
-
[(i) => Boolean(i.trailId), 'detail'],
|
|
125
|
-
[(i) => i.generate, 'generate'],
|
|
126
|
-
[(i) => i.openapi, 'openapi'],
|
|
127
|
-
];
|
|
289
|
+
type SurveyEnvelope = { readonly mode: SurveyMode } & Record<string, unknown>;
|
|
128
290
|
|
|
129
|
-
/** Determine which survey mode was requested, falling back to '
|
|
291
|
+
/** Determine which survey mode was requested, falling back to 'overview'. */
|
|
130
292
|
const deriveSurveyMode = (input: SurveyInput): SurveyMode =>
|
|
131
|
-
|
|
293
|
+
input.id === undefined || input.id === '' ? 'overview' : 'lookup';
|
|
132
294
|
|
|
133
295
|
type SurveyHandler = (
|
|
134
296
|
app: Topo,
|
|
135
297
|
input: SurveyInput,
|
|
136
|
-
rootDir: string
|
|
298
|
+
rootDir: string,
|
|
299
|
+
surfaceLayerNames?: Partial<SurfaceLayerNames> | undefined
|
|
137
300
|
) => Result<object, Error> | Promise<Result<object, Error>>;
|
|
138
301
|
|
|
139
302
|
/** Handlers keyed by survey mode. */
|
|
140
303
|
const surveyHandlers: Record<SurveyMode, SurveyHandler> = {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
buildSurveyDiff(app, rootDir, input.breakingOnly),
|
|
147
|
-
generate: (app, _input, rootDir) => buildSurveyGenerate(app, rootDir),
|
|
148
|
-
list: (app, _input, rootDir) =>
|
|
304
|
+
lookup: (app, input, rootDir, surfaceLayerNames) =>
|
|
305
|
+
input.id === undefined || input.id === ''
|
|
306
|
+
? Result.err(new ValidationError('Survey lookup requires an id'))
|
|
307
|
+
: buildSurveyLookup(app, input.id, rootDir, surfaceLayerNames),
|
|
308
|
+
overview: (app, _input, rootDir) =>
|
|
149
309
|
Result.ok(buildCurrentTopoList(app, { rootDir })),
|
|
150
|
-
openapi: (app) => Result.ok(deriveOpenApiSpec(app)),
|
|
151
310
|
};
|
|
152
311
|
|
|
312
|
+
const envelopeSurveyValue = (
|
|
313
|
+
mode: SurveyMode,
|
|
314
|
+
value: object
|
|
315
|
+
): SurveyEnvelope => ({ ...value, mode });
|
|
316
|
+
|
|
153
317
|
/** Dispatch to the appropriate survey sub-command based on input flags. */
|
|
154
|
-
const dispatchSurvey = (
|
|
318
|
+
const dispatchSurvey = async (
|
|
155
319
|
app: Topo,
|
|
156
320
|
input: SurveyInput,
|
|
157
|
-
rootDir: string
|
|
158
|
-
|
|
321
|
+
rootDir: string,
|
|
322
|
+
surfaceLayerNames?: Partial<SurfaceLayerNames> | undefined
|
|
323
|
+
): Promise<Result<SurveyEnvelope, Error>> => {
|
|
159
324
|
const mode = deriveSurveyMode(input);
|
|
160
325
|
const handler = surveyHandlers[mode];
|
|
161
|
-
|
|
326
|
+
const result = await handler(app, input, rootDir, surfaceLayerNames);
|
|
327
|
+
if (result.isErr()) {
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
return Result.ok(envelopeSurveyValue(mode, result.value));
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
const detailInputSchema = z.object({
|
|
334
|
+
id: z.string().describe('Trail, resource, or signal ID'),
|
|
335
|
+
module: z.string().optional().describe('Path to the app module'),
|
|
336
|
+
rootDir: z.string().optional().describe('Workspace root directory'),
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
const withFreshSurveyApp = async <T>(
|
|
340
|
+
input: { readonly module?: string | undefined },
|
|
341
|
+
rootDir: string,
|
|
342
|
+
consume: (app: Topo) => Promise<Result<T, Error>> | Result<T, Error>
|
|
343
|
+
): Promise<Result<T, Error>> => {
|
|
344
|
+
const leaseResult = await tryLoadFreshAppLease(input.module, rootDir);
|
|
345
|
+
if (leaseResult.isErr()) {
|
|
346
|
+
return Result.err(leaseResult.error);
|
|
347
|
+
}
|
|
348
|
+
const lease = leaseResult.value;
|
|
349
|
+
try {
|
|
350
|
+
return await consume(lease.app);
|
|
351
|
+
} finally {
|
|
352
|
+
lease.release();
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const withResolvedSurveyApp = async <T>(
|
|
357
|
+
input: {
|
|
358
|
+
readonly module?: string | undefined;
|
|
359
|
+
readonly rootDir?: string | undefined;
|
|
360
|
+
},
|
|
361
|
+
cwd: string | undefined,
|
|
362
|
+
consume: (
|
|
363
|
+
app: Topo,
|
|
364
|
+
rootDir: string
|
|
365
|
+
) => Promise<Result<T, Error>> | Result<T, Error>
|
|
366
|
+
): Promise<Result<T, Error>> => {
|
|
367
|
+
const rootDirResult = resolveTrailRootDir(input.rootDir, cwd);
|
|
368
|
+
if (rootDirResult.isErr()) {
|
|
369
|
+
return Result.err(rootDirResult.error);
|
|
370
|
+
}
|
|
371
|
+
const rootDir = rootDirResult.value;
|
|
372
|
+
return withFreshSurveyApp(input, rootDir, (app) => consume(app, rootDir));
|
|
162
373
|
};
|
|
163
374
|
|
|
375
|
+
const moduleInputSchema = z.object({
|
|
376
|
+
module: z.string().optional().describe('Path to the app module'),
|
|
377
|
+
rootDir: z.string().optional().describe('Workspace root directory'),
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
const diffEntryOutput = z.object({
|
|
381
|
+
change: z.enum(['added', 'removed', 'modified']),
|
|
382
|
+
details: z.array(z.string()).readonly(),
|
|
383
|
+
id: z.string(),
|
|
384
|
+
kind: z.enum(['contour', 'trail', 'signal', 'resource']),
|
|
385
|
+
severity: z.enum(['info', 'warning', 'breaking']),
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
const diffOutput = z.object({
|
|
389
|
+
against: z.string(),
|
|
390
|
+
breaking: z.array(diffEntryOutput),
|
|
391
|
+
hasBreaking: z.boolean(),
|
|
392
|
+
info: z.array(diffEntryOutput),
|
|
393
|
+
mode: z.literal('diff'),
|
|
394
|
+
warnings: z.array(diffEntryOutput),
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
const surveyMatchOutput = z.discriminatedUnion('kind', [
|
|
398
|
+
z.object({
|
|
399
|
+
detail: trailDetailOutput,
|
|
400
|
+
kind: z.literal('trail'),
|
|
401
|
+
}),
|
|
402
|
+
z.object({
|
|
403
|
+
detail: resourceDetailOutput,
|
|
404
|
+
kind: z.literal('resource'),
|
|
405
|
+
}),
|
|
406
|
+
z.object({
|
|
407
|
+
detail: signalDetailOutput,
|
|
408
|
+
kind: z.literal('signal'),
|
|
409
|
+
}),
|
|
410
|
+
]);
|
|
411
|
+
|
|
164
412
|
// ---------------------------------------------------------------------------
|
|
165
413
|
// Trail definition
|
|
166
414
|
// ---------------------------------------------------------------------------
|
|
167
415
|
|
|
168
416
|
export const surveyTrail = trail('survey', {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// module graph that a prior import may have frozen. Other modes read
|
|
175
|
-
// the in-memory topo and benefit from the standard import cache.
|
|
176
|
-
//
|
|
177
|
-
// For diff specifically, use a disposable lease rather than retained
|
|
178
|
-
// fresh mirrors — the returned diff result is serialisable data, not
|
|
179
|
-
// a Topo reference with deferred imports, so the mirror can be
|
|
180
|
-
// released the moment dispatchSurvey returns. That keeps MCP/dev
|
|
181
|
-
// sessions that poll diff repeatedly from growing .trails-tmp/
|
|
182
|
-
// without bound.
|
|
183
|
-
if (mode === 'diff') {
|
|
184
|
-
const lease = await loadFreshAppLease(input.module, rootDir);
|
|
185
|
-
try {
|
|
186
|
-
return await dispatchSurvey(lease.app, input, rootDir);
|
|
187
|
-
} finally {
|
|
188
|
-
lease.release();
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const app = await loadApp(input.module, rootDir);
|
|
193
|
-
return dispatchSurvey(app, input, rootDir);
|
|
194
|
-
},
|
|
417
|
+
args: ['id'],
|
|
418
|
+
blaze: async (input, ctx) =>
|
|
419
|
+
withResolvedSurveyApp(input, ctx.cwd, (app, rootDir) =>
|
|
420
|
+
dispatchSurvey(app, input, rootDir, readSurfaceLayerNamesFromContext(ctx))
|
|
421
|
+
),
|
|
195
422
|
description: 'Full topo introspection',
|
|
196
423
|
examples: [
|
|
197
424
|
{
|
|
198
|
-
description: '
|
|
199
|
-
input:
|
|
200
|
-
name: '
|
|
425
|
+
description: 'Show all registered trails, resources, and signals',
|
|
426
|
+
input: createIsolatedExampleInput('survey-overview'),
|
|
427
|
+
name: 'Overview',
|
|
201
428
|
},
|
|
202
429
|
{
|
|
203
|
-
description: '
|
|
204
|
-
input: {
|
|
205
|
-
name: '
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
description: 'Generate an OpenAPI 3.1 specification for the topo',
|
|
209
|
-
input: { module: './src/app.ts', openapi: true },
|
|
210
|
-
name: 'OpenAPI spec',
|
|
430
|
+
description: 'Find every trail, resource, or signal with a matching ID',
|
|
431
|
+
input: { ...createIsolatedExampleInput('survey-lookup'), id: 'survey' },
|
|
432
|
+
name: 'Lookup by ID',
|
|
211
433
|
},
|
|
212
434
|
],
|
|
213
435
|
input: z.object({
|
|
214
|
-
|
|
215
|
-
.
|
|
216
|
-
.
|
|
217
|
-
.describe('
|
|
218
|
-
brief: z.boolean().default(false).describe('Quick capability summary'),
|
|
219
|
-
diffSaved: z
|
|
220
|
-
.boolean()
|
|
221
|
-
.default(false)
|
|
222
|
-
.describe('Diff against the saved local surface map'),
|
|
223
|
-
generate: z
|
|
224
|
-
.boolean()
|
|
225
|
-
.default(false)
|
|
226
|
-
.describe('Generate surface map and lock file'),
|
|
436
|
+
id: z
|
|
437
|
+
.string()
|
|
438
|
+
.optional()
|
|
439
|
+
.describe('Trail, resource, or signal ID to look up'),
|
|
227
440
|
module: z.string().optional().describe('Path to the app module'),
|
|
228
|
-
|
|
229
|
-
trailId: z.string().optional().describe('Trail ID for detail view'),
|
|
441
|
+
rootDir: z.string().optional().describe('Workspace root directory'),
|
|
230
442
|
}),
|
|
231
443
|
intent: 'read',
|
|
232
|
-
output: z.
|
|
444
|
+
output: z.discriminatedUnion('mode', [
|
|
233
445
|
z.object({
|
|
446
|
+
activation: activationOverviewOutput,
|
|
234
447
|
count: z.number(),
|
|
235
448
|
entries: z.array(
|
|
236
449
|
z.object({
|
|
450
|
+
activatedBy: z.array(z.string()).readonly(),
|
|
451
|
+
activates: z.array(z.string()).readonly(),
|
|
237
452
|
examples: z.number(),
|
|
238
453
|
id: z.string(),
|
|
239
454
|
kind: z.string(),
|
|
240
455
|
safety: z.string(),
|
|
241
456
|
})
|
|
242
457
|
),
|
|
458
|
+
mode: z.literal('overview'),
|
|
243
459
|
resourceCount: z.number(),
|
|
244
460
|
resources: z.array(
|
|
245
461
|
z.object({
|
|
@@ -251,71 +467,161 @@ export const surveyTrail = trail('survey', {
|
|
|
251
467
|
usedBy: z.array(z.string()),
|
|
252
468
|
})
|
|
253
469
|
),
|
|
470
|
+
signalCount: z.number(),
|
|
471
|
+
signals: z.array(
|
|
472
|
+
z.object({
|
|
473
|
+
consumers: z.array(z.string()).readonly(),
|
|
474
|
+
description: z.string().nullable(),
|
|
475
|
+
examples: z.number(),
|
|
476
|
+
from: z.array(z.string()).readonly(),
|
|
477
|
+
id: z.string(),
|
|
478
|
+
kind: z.literal('signal'),
|
|
479
|
+
payloadSchema: z.boolean(),
|
|
480
|
+
producers: z.array(z.string()).readonly(),
|
|
481
|
+
})
|
|
482
|
+
),
|
|
254
483
|
}),
|
|
255
484
|
z.object({
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
detours: z.boolean(),
|
|
259
|
-
examples: z.boolean(),
|
|
260
|
-
outputSchemas: z.boolean(),
|
|
261
|
-
resources: z.boolean(),
|
|
262
|
-
signals: z.boolean(),
|
|
263
|
-
}),
|
|
264
|
-
name: z.string(),
|
|
265
|
-
resources: z.number(),
|
|
266
|
-
signals: z.number(),
|
|
267
|
-
trails: z.number(),
|
|
268
|
-
version: z.string(),
|
|
269
|
-
}),
|
|
270
|
-
z.object({
|
|
271
|
-
breaking: z.array(z.unknown()),
|
|
272
|
-
hasBreaking: z.boolean(),
|
|
273
|
-
info: z.array(z.unknown()),
|
|
274
|
-
warnings: z.array(z.unknown()),
|
|
275
|
-
}),
|
|
276
|
-
z.object({
|
|
277
|
-
crosses: z.array(z.string()),
|
|
278
|
-
description: z.unknown().nullable(),
|
|
279
|
-
detours: z.unknown().nullable(),
|
|
280
|
-
examples: z.array(z.unknown()),
|
|
281
|
-
id: z.string(),
|
|
282
|
-
intent: z.enum(['read', 'write', 'destroy']),
|
|
283
|
-
kind: z.string(),
|
|
284
|
-
resources: z.array(z.string()),
|
|
285
|
-
safety: z.string(),
|
|
286
|
-
}),
|
|
287
|
-
z.object({
|
|
288
|
-
description: z.string().nullable(),
|
|
289
|
-
health: z.enum(['available', 'none']),
|
|
290
|
-
id: z.string(),
|
|
291
|
-
kind: z.literal('resource'),
|
|
292
|
-
lifetime: z.literal('singleton'),
|
|
293
|
-
usedBy: z.array(z.string()),
|
|
294
|
-
}),
|
|
295
|
-
z.object({
|
|
296
|
-
hash: z.string(),
|
|
297
|
-
lockPath: z.string(),
|
|
298
|
-
mapPath: z.string(),
|
|
299
|
-
}),
|
|
300
|
-
z.object({
|
|
301
|
-
components: z.object({
|
|
302
|
-
schemas: z.record(z.string(), z.unknown()),
|
|
303
|
-
}),
|
|
304
|
-
info: z.object({
|
|
305
|
-
description: z.string().optional(),
|
|
306
|
-
title: z.string(),
|
|
307
|
-
version: z.string(),
|
|
308
|
-
}),
|
|
309
|
-
openapi: z.literal('3.1.0'),
|
|
310
|
-
paths: z.record(z.string(), z.record(z.string(), z.unknown())),
|
|
311
|
-
servers: z
|
|
312
|
-
.array(
|
|
313
|
-
z.object({
|
|
314
|
-
description: z.string().optional(),
|
|
315
|
-
url: z.string(),
|
|
316
|
-
})
|
|
317
|
-
)
|
|
318
|
-
.optional(),
|
|
485
|
+
matches: z.array(surveyMatchOutput),
|
|
486
|
+
mode: z.literal('lookup'),
|
|
319
487
|
}),
|
|
320
488
|
]),
|
|
321
489
|
});
|
|
490
|
+
|
|
491
|
+
export const surveyBriefTrail = trail('survey.brief', {
|
|
492
|
+
blaze: async (input, ctx) =>
|
|
493
|
+
withResolvedSurveyApp(input, ctx.cwd, (app, rootDir) =>
|
|
494
|
+
Result.ok(buildCurrentTopoBrief(app, { rootDir }))
|
|
495
|
+
),
|
|
496
|
+
description: 'Summarize topo capabilities',
|
|
497
|
+
examples: [
|
|
498
|
+
{
|
|
499
|
+
description: 'Show counts and feature flags',
|
|
500
|
+
input: createIsolatedExampleInput('survey-brief'),
|
|
501
|
+
name: 'Brief capability report',
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
input: moduleInputSchema,
|
|
505
|
+
intent: 'read',
|
|
506
|
+
output: briefReportSchema,
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
export const surveyDiffTrail = trail('survey.diff', {
|
|
510
|
+
blaze: async (input, ctx) =>
|
|
511
|
+
withResolvedSurveyApp(input, ctx.cwd, (app, rootDir) =>
|
|
512
|
+
buildSurveyDiff(app, rootDir, input.breakingOnly, input.against)
|
|
513
|
+
),
|
|
514
|
+
description: 'Diff the current topo against a saved TopoGraph',
|
|
515
|
+
examples: [
|
|
516
|
+
{
|
|
517
|
+
description: 'Compare current topo to a saved TopoGraph directory',
|
|
518
|
+
input: createDiffExampleInput(),
|
|
519
|
+
name: 'Diff against baseline',
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
description: 'Reject an empty saved map target',
|
|
523
|
+
error: 'ValidationError',
|
|
524
|
+
input: { against: '' },
|
|
525
|
+
name: 'Reject empty diff target',
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
description: 'Reject an empty target before filtering breaking drift',
|
|
529
|
+
error: 'ValidationError',
|
|
530
|
+
input: {
|
|
531
|
+
against: '',
|
|
532
|
+
breakingOnly: true,
|
|
533
|
+
},
|
|
534
|
+
name: 'Reject empty breaking-only target',
|
|
535
|
+
},
|
|
536
|
+
],
|
|
537
|
+
input: z.object({
|
|
538
|
+
against: z
|
|
539
|
+
.string()
|
|
540
|
+
.min(1)
|
|
541
|
+
.optional()
|
|
542
|
+
.describe(
|
|
543
|
+
'Saved TopoGraph target: "saved", a workspace path (topo.lock, .json file, or directory with topo.lock), then a pin/snapshot id'
|
|
544
|
+
),
|
|
545
|
+
breakingOnly: z
|
|
546
|
+
.boolean()
|
|
547
|
+
.default(false)
|
|
548
|
+
.describe('Only show breaking changes'),
|
|
549
|
+
module: z.string().optional().describe('Path to the app module'),
|
|
550
|
+
rootDir: z.string().optional().describe('Workspace root directory'),
|
|
551
|
+
}),
|
|
552
|
+
intent: 'read',
|
|
553
|
+
output: diffOutput,
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
export const surveyTrailDetailTrail = trail('survey.trail', {
|
|
557
|
+
args: ['id'],
|
|
558
|
+
blaze: async (input, ctx) =>
|
|
559
|
+
withResolvedSurveyApp(input, ctx.cwd, (app, rootDir) =>
|
|
560
|
+
buildSurveyTrailDetail(
|
|
561
|
+
app,
|
|
562
|
+
input.id,
|
|
563
|
+
rootDir,
|
|
564
|
+
readSurfaceLayerNamesFromContext(ctx)
|
|
565
|
+
)
|
|
566
|
+
),
|
|
567
|
+
description: 'Inspect one trail by ID',
|
|
568
|
+
examples: [
|
|
569
|
+
{
|
|
570
|
+
description: 'Show trail contract detail',
|
|
571
|
+
input: {
|
|
572
|
+
...createIsolatedExampleInput('survey-trail-detail'),
|
|
573
|
+
id: 'survey',
|
|
574
|
+
},
|
|
575
|
+
name: 'Trail detail',
|
|
576
|
+
},
|
|
577
|
+
],
|
|
578
|
+
input: detailInputSchema,
|
|
579
|
+
intent: 'read',
|
|
580
|
+
output: trailDetailOutput,
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
export const surveyResourceTrail = trail('survey.resource', {
|
|
584
|
+
args: ['id'],
|
|
585
|
+
blaze: async (input, ctx) =>
|
|
586
|
+
withResolvedSurveyApp(input, ctx.cwd, (app, rootDir) =>
|
|
587
|
+
buildSurveyResourceDetail(app, input.id, rootDir)
|
|
588
|
+
),
|
|
589
|
+
description: 'Inspect one resource by ID',
|
|
590
|
+
examples: [
|
|
591
|
+
{
|
|
592
|
+
description: 'Show resource usage detail',
|
|
593
|
+
error: 'NotFoundError',
|
|
594
|
+
input: {
|
|
595
|
+
...createIsolatedExampleInput('survey-resource-detail'),
|
|
596
|
+
id: 'db.main',
|
|
597
|
+
},
|
|
598
|
+
name: 'Resource detail',
|
|
599
|
+
},
|
|
600
|
+
],
|
|
601
|
+
input: detailInputSchema,
|
|
602
|
+
intent: 'read',
|
|
603
|
+
output: resourceDetailOutput,
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
export const surveySignalTrail = trail('survey.signal', {
|
|
607
|
+
args: ['id'],
|
|
608
|
+
blaze: async (input, ctx) =>
|
|
609
|
+
withResolvedSurveyApp(input, ctx.cwd, (app, rootDir) =>
|
|
610
|
+
buildSurveySignalDetail(app, input.id, rootDir)
|
|
611
|
+
),
|
|
612
|
+
description: 'Inspect one signal by ID',
|
|
613
|
+
examples: [
|
|
614
|
+
{
|
|
615
|
+
description: 'Show signal producer and consumer detail',
|
|
616
|
+
error: 'NotFoundError',
|
|
617
|
+
input: {
|
|
618
|
+
...createIsolatedExampleInput('survey-signal-detail'),
|
|
619
|
+
id: 'hello.greeted',
|
|
620
|
+
},
|
|
621
|
+
name: 'Signal detail',
|
|
622
|
+
},
|
|
623
|
+
],
|
|
624
|
+
input: detailInputSchema,
|
|
625
|
+
intent: 'read',
|
|
626
|
+
output: signalDetailOutput,
|
|
627
|
+
});
|