@ontrails/core 0.2.0
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 +849 -0
- package/README.md +190 -0
- package/package.json +36 -0
- package/src/activation-provenance.ts +116 -0
- package/src/activation-source-compatibility.ts +430 -0
- package/src/activation-source-derivation.ts +227 -0
- package/src/activation-source.ts +93 -0
- package/src/blob-ref.ts +90 -0
- package/src/branded.ts +135 -0
- package/src/collections.ts +99 -0
- package/src/compose-batch.ts +69 -0
- package/src/compose-schema.ts +36 -0
- package/src/context.ts +66 -0
- package/src/derive.ts +485 -0
- package/src/detours.ts +8 -0
- package/src/diagnostics.ts +21 -0
- package/src/draft.ts +350 -0
- package/src/entity.ts +346 -0
- package/src/error-rendering.ts +87 -0
- package/src/errors.ts +483 -0
- package/src/execute.ts +1577 -0
- package/src/fetch.ts +138 -0
- package/src/fire.ts +1172 -0
- package/src/glob.ts +81 -0
- package/src/guards.ts +37 -0
- package/src/index.ts +704 -0
- package/src/internal/fork-ctx.ts +69 -0
- package/src/layer-field-rendering.ts +193 -0
- package/src/layer.ts +81 -0
- package/src/observe.ts +361 -0
- package/src/path-scope.ts +66 -0
- package/src/path-security.ts +98 -0
- package/src/patterns/bulk.ts +16 -0
- package/src/patterns/change.ts +12 -0
- package/src/patterns/date-range.ts +12 -0
- package/src/patterns/index.ts +8 -0
- package/src/patterns/pagination.ts +22 -0
- package/src/patterns/progress.ts +13 -0
- package/src/patterns/sorting.ts +14 -0
- package/src/patterns/status.ts +11 -0
- package/src/patterns/timestamps.ts +12 -0
- package/src/permits.ts +12 -0
- package/src/queue.ts +163 -0
- package/src/redaction/index.ts +3 -0
- package/src/redaction/patterns.ts +50 -0
- package/src/redaction/redactor.ts +178 -0
- package/src/resilience.ts +234 -0
- package/src/resource-config.ts +804 -0
- package/src/resource.ts +194 -0
- package/src/result.ts +212 -0
- package/src/run.ts +76 -0
- package/src/runtime-builtins.ts +69 -0
- package/src/schedule-runtime.ts +689 -0
- package/src/schedule.ts +326 -0
- package/src/serialization.ts +265 -0
- package/src/sha256.ts +136 -0
- package/src/signal-diagnostics.ts +633 -0
- package/src/signal-ref.ts +111 -0
- package/src/signal.ts +104 -0
- package/src/store/accessor-protocol.ts +56 -0
- package/src/store/index.ts +4 -0
- package/src/structured-examples.ts +248 -0
- package/src/surface-derivation.ts +91 -0
- package/src/surface-filter.ts +101 -0
- package/src/surface-overlay.ts +694 -0
- package/src/surface-versioning.ts +42 -0
- package/src/topo.ts +835 -0
- package/src/tracing.ts +346 -0
- package/src/trail-id-glob.ts +15 -0
- package/src/trail.ts +1351 -0
- package/src/trails/derive-trail.ts +835 -0
- package/src/trails/index.ts +9 -0
- package/src/trails/ingest.ts +152 -0
- package/src/trails-db.ts +212 -0
- package/src/transport-error-map.ts +163 -0
- package/src/type-utils.ts +87 -0
- package/src/types.ts +300 -0
- package/src/validate-established-topo.ts +73 -0
- package/src/validate-topo.ts +725 -0
- package/src/validation.ts +330 -0
- package/src/version-marker.ts +716 -0
- package/src/version-resolution.ts +308 -0
- package/src/version-runtime.ts +120 -0
- package/src/webhook.ts +461 -0
- package/src/workspace.ts +244 -0
- package/src/zod-wrappers.ts +72 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AmbiguousError,
|
|
3
|
+
TrailsError,
|
|
4
|
+
ValidationError,
|
|
5
|
+
VersionNotSupportedError,
|
|
6
|
+
} from './errors.js';
|
|
7
|
+
import { Result } from './result.js';
|
|
8
|
+
import {
|
|
9
|
+
deriveSupportedTrailVersions,
|
|
10
|
+
getTrailVersionEntryKind,
|
|
11
|
+
isArchivedTrailVersionEntry,
|
|
12
|
+
} from './trail.js';
|
|
13
|
+
import type {
|
|
14
|
+
AnyTrail,
|
|
15
|
+
TrailVersionForkEntry,
|
|
16
|
+
TrailVersionRevisionEntry,
|
|
17
|
+
} from './trail.js';
|
|
18
|
+
import {
|
|
19
|
+
TRAIL_VERSION_MARKER_LENGTH,
|
|
20
|
+
TRAIL_VERSION_MARKER_MIN_PREFIX_LENGTH,
|
|
21
|
+
deriveTrailVersionMarkers,
|
|
22
|
+
} from './version-marker.js';
|
|
23
|
+
|
|
24
|
+
export type TrailVersionReference = number | string;
|
|
25
|
+
|
|
26
|
+
export interface ParsedTrailVersionReference {
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly version?: TrailVersionReference | undefined;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type ResolvedTrailVersion =
|
|
32
|
+
| {
|
|
33
|
+
readonly current: true;
|
|
34
|
+
readonly kind: 'current';
|
|
35
|
+
readonly marker?: string | undefined;
|
|
36
|
+
readonly version?: number | undefined;
|
|
37
|
+
}
|
|
38
|
+
| {
|
|
39
|
+
readonly current: false;
|
|
40
|
+
readonly deprecated: boolean;
|
|
41
|
+
readonly entry: TrailVersionForkEntry;
|
|
42
|
+
readonly kind: 'fork';
|
|
43
|
+
readonly marker?: string | undefined;
|
|
44
|
+
readonly version: number;
|
|
45
|
+
}
|
|
46
|
+
| {
|
|
47
|
+
readonly current: false;
|
|
48
|
+
readonly deprecated: boolean;
|
|
49
|
+
readonly entry: TrailVersionRevisionEntry;
|
|
50
|
+
readonly kind: 'revision';
|
|
51
|
+
readonly marker?: string | undefined;
|
|
52
|
+
readonly version: number;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
interface ParsedVersionReference {
|
|
56
|
+
readonly display: number | string;
|
|
57
|
+
readonly markerPrefix?: string | undefined;
|
|
58
|
+
readonly number?: number | undefined;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
type MarkerResolvableTrail = Pick<
|
|
62
|
+
AnyTrail,
|
|
63
|
+
| 'composes'
|
|
64
|
+
| 'detours'
|
|
65
|
+
| 'id'
|
|
66
|
+
| 'input'
|
|
67
|
+
| 'output'
|
|
68
|
+
| 'resources'
|
|
69
|
+
| 'version'
|
|
70
|
+
| 'versions'
|
|
71
|
+
>;
|
|
72
|
+
|
|
73
|
+
const versionRefPattern = /^(.+)@(.+)$/;
|
|
74
|
+
const positiveIntegerPattern = /^[1-9]\d*$/;
|
|
75
|
+
const markerPrefixPattern = /^[0-9a-fA-F]+$/;
|
|
76
|
+
|
|
77
|
+
const parsePositiveInteger = (value: string): number | undefined => {
|
|
78
|
+
if (!positiveIntegerPattern.test(value)) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
const version = Number(value);
|
|
82
|
+
return Number.isSafeInteger(version) ? version : undefined;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const isInlineVersionReference = (value: string): boolean =>
|
|
86
|
+
parsePositiveInteger(value) !== undefined ||
|
|
87
|
+
(value.length >= TRAIL_VERSION_MARKER_MIN_PREFIX_LENGTH &&
|
|
88
|
+
value.length <= TRAIL_VERSION_MARKER_LENGTH &&
|
|
89
|
+
markerPrefixPattern.test(value));
|
|
90
|
+
|
|
91
|
+
const unsupportedVersion = (
|
|
92
|
+
trail: Pick<AnyTrail, 'id' | 'version' | 'versions'>,
|
|
93
|
+
requested: number | string,
|
|
94
|
+
reason: string
|
|
95
|
+
): VersionNotSupportedError => {
|
|
96
|
+
const supported = deriveSupportedTrailVersions(trail);
|
|
97
|
+
return new VersionNotSupportedError(trail.id, requested, supported, reason);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const parseTrailIdVersionReference = (
|
|
101
|
+
id: string
|
|
102
|
+
): Result<ParsedTrailVersionReference, ValidationError> => {
|
|
103
|
+
const match = versionRefPattern.exec(id);
|
|
104
|
+
if (match === null) {
|
|
105
|
+
return Result.ok({ id });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const [, baseId, rawVersion] = match;
|
|
109
|
+
if (baseId === undefined || rawVersion === undefined) {
|
|
110
|
+
return Result.err(
|
|
111
|
+
new ValidationError(
|
|
112
|
+
'Trail version reference must use trail.id@N or trail.id@<marker-prefix>'
|
|
113
|
+
)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
if (!isInlineVersionReference(rawVersion)) {
|
|
117
|
+
return Result.ok({ id });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return Result.ok({ id: baseId, version: rawVersion });
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const parseVersionReference = (
|
|
124
|
+
reference: TrailVersionReference
|
|
125
|
+
): Result<ParsedVersionReference, Error> => {
|
|
126
|
+
if (typeof reference === 'number') {
|
|
127
|
+
return Number.isSafeInteger(reference) && reference > 0
|
|
128
|
+
? Result.ok({ display: reference, number: reference })
|
|
129
|
+
: Result.err(
|
|
130
|
+
new ValidationError(
|
|
131
|
+
'Trail version reference must be a positive integer'
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const markerRequested = reference.startsWith('@');
|
|
137
|
+
const raw = markerRequested ? reference.slice(1) : reference;
|
|
138
|
+
if (raw.length === 0) {
|
|
139
|
+
return Result.err(
|
|
140
|
+
new ValidationError('Trail version reference must not be empty')
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const number = parsePositiveInteger(raw);
|
|
145
|
+
if (!markerRequested && number !== undefined) {
|
|
146
|
+
return Result.ok({
|
|
147
|
+
display: reference,
|
|
148
|
+
markerPrefix:
|
|
149
|
+
raw.length >= TRAIL_VERSION_MARKER_MIN_PREFIX_LENGTH &&
|
|
150
|
+
raw.length <= TRAIL_VERSION_MARKER_LENGTH &&
|
|
151
|
+
markerPrefixPattern.test(raw)
|
|
152
|
+
? raw.toLowerCase()
|
|
153
|
+
: undefined,
|
|
154
|
+
number,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (
|
|
159
|
+
raw.length >= TRAIL_VERSION_MARKER_MIN_PREFIX_LENGTH &&
|
|
160
|
+
raw.length <= TRAIL_VERSION_MARKER_LENGTH &&
|
|
161
|
+
markerPrefixPattern.test(raw)
|
|
162
|
+
) {
|
|
163
|
+
return Result.ok({
|
|
164
|
+
display: reference,
|
|
165
|
+
markerPrefix: raw.toLowerCase(),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return Result.err(
|
|
170
|
+
new ValidationError(
|
|
171
|
+
'Trail version reference must be a positive integer or marker prefix'
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const trailHasVersion = (
|
|
177
|
+
trail: Pick<AnyTrail, 'version' | 'versions'>,
|
|
178
|
+
version: number
|
|
179
|
+
): boolean =>
|
|
180
|
+
trail.version === version || trail.versions?.[version] !== undefined;
|
|
181
|
+
|
|
182
|
+
const resolveMarkerReference = (
|
|
183
|
+
trail: MarkerResolvableTrail,
|
|
184
|
+
requested: number | string,
|
|
185
|
+
prefix: string
|
|
186
|
+
): Result<{ readonly marker: string; readonly version: number }, Error> => {
|
|
187
|
+
let records: ReturnType<typeof deriveTrailVersionMarkers>;
|
|
188
|
+
try {
|
|
189
|
+
records = deriveTrailVersionMarkers(trail);
|
|
190
|
+
} catch (error: unknown) {
|
|
191
|
+
return Result.err(
|
|
192
|
+
error instanceof TrailsError
|
|
193
|
+
? error
|
|
194
|
+
: new ValidationError(
|
|
195
|
+
`Trail version marker derivation failed: ${String(error)}`
|
|
196
|
+
)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
const matches = records.filter((record) => record.marker.startsWith(prefix));
|
|
200
|
+
|
|
201
|
+
if (matches.length === 0) {
|
|
202
|
+
return Result.err(unsupportedVersion(trail, requested, 'marker missing'));
|
|
203
|
+
}
|
|
204
|
+
if (matches.length > 1) {
|
|
205
|
+
return Result.err(
|
|
206
|
+
new AmbiguousError(
|
|
207
|
+
`Trail version marker prefix ${prefix} is ambiguous across versions ${matches.map((record) => record.version).join(', ')}`
|
|
208
|
+
)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const match = matches[0] as (typeof matches)[number];
|
|
213
|
+
|
|
214
|
+
return Result.ok({ marker: match.marker, version: match.version });
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const resolveRequestedVersionNumber = (
|
|
218
|
+
trail: MarkerResolvableTrail,
|
|
219
|
+
reference: TrailVersionReference
|
|
220
|
+
): Result<
|
|
221
|
+
{ readonly marker?: string | undefined; readonly version: number },
|
|
222
|
+
Error
|
|
223
|
+
> => {
|
|
224
|
+
const parsed = parseVersionReference(reference);
|
|
225
|
+
if (parsed.isErr()) {
|
|
226
|
+
return parsed;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const { display, markerPrefix, number } = parsed.value;
|
|
230
|
+
if (number !== undefined && trailHasVersion(trail, number)) {
|
|
231
|
+
return Result.ok({ version: number });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (markerPrefix !== undefined) {
|
|
235
|
+
const marker = resolveMarkerReference(trail, display, markerPrefix);
|
|
236
|
+
if (marker.isOk()) {
|
|
237
|
+
return marker;
|
|
238
|
+
}
|
|
239
|
+
if (number === undefined) {
|
|
240
|
+
return marker;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return Result.err(unsupportedVersion(trail, display, 'missing'));
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
export const resolveTrailVersion = (
|
|
248
|
+
trail: MarkerResolvableTrail,
|
|
249
|
+
reference?: TrailVersionReference | undefined
|
|
250
|
+
): Result<ResolvedTrailVersion, Error> => {
|
|
251
|
+
if (reference === undefined) {
|
|
252
|
+
return Result.ok({
|
|
253
|
+
current: true,
|
|
254
|
+
kind: 'current',
|
|
255
|
+
...(trail.version === undefined ? {} : { version: trail.version }),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (trail.version === undefined) {
|
|
260
|
+
return Result.err(unsupportedVersion(trail, reference, 'unversioned'));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const requested = resolveRequestedVersionNumber(trail, reference);
|
|
264
|
+
if (requested.isErr()) {
|
|
265
|
+
return requested;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (requested.value.version === trail.version) {
|
|
269
|
+
return Result.ok({
|
|
270
|
+
current: true,
|
|
271
|
+
kind: 'current',
|
|
272
|
+
...(requested.value.marker === undefined
|
|
273
|
+
? {}
|
|
274
|
+
: { marker: requested.value.marker }),
|
|
275
|
+
version: trail.version,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const entry = trail.versions?.[requested.value.version];
|
|
280
|
+
if (entry === undefined) {
|
|
281
|
+
return Result.err(unsupportedVersion(trail, reference, 'missing'));
|
|
282
|
+
}
|
|
283
|
+
if (isArchivedTrailVersionEntry(entry)) {
|
|
284
|
+
return Result.err(unsupportedVersion(trail, reference, 'archived'));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const kind = getTrailVersionEntryKind(entry);
|
|
288
|
+
const base = {
|
|
289
|
+
current: false,
|
|
290
|
+
deprecated: entry.status?.state === 'deprecated',
|
|
291
|
+
...(requested.value.marker === undefined
|
|
292
|
+
? {}
|
|
293
|
+
: { marker: requested.value.marker }),
|
|
294
|
+
version: requested.value.version,
|
|
295
|
+
} as const;
|
|
296
|
+
|
|
297
|
+
return kind === 'fork'
|
|
298
|
+
? Result.ok({
|
|
299
|
+
...base,
|
|
300
|
+
entry: entry as TrailVersionForkEntry,
|
|
301
|
+
kind,
|
|
302
|
+
})
|
|
303
|
+
: Result.ok({
|
|
304
|
+
...base,
|
|
305
|
+
entry: entry as TrailVersionRevisionEntry,
|
|
306
|
+
kind,
|
|
307
|
+
});
|
|
308
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { InternalError, ValidationError } from './errors.js';
|
|
2
|
+
import { Result } from './result.js';
|
|
3
|
+
import type { ExecuteTrailOptions } from './execute.js';
|
|
4
|
+
import { getTrailVersionEntryKind } from './trail.js';
|
|
5
|
+
import type { AnyTrail, TrailVersionEntry } from './trail.js';
|
|
6
|
+
import { validateInput, validateOutput } from './validation.js';
|
|
7
|
+
|
|
8
|
+
export type TrailVersionCurrentExecutor<
|
|
9
|
+
Options extends ExecuteTrailOptions = ExecuteTrailOptions,
|
|
10
|
+
> = (
|
|
11
|
+
trail: AnyTrail,
|
|
12
|
+
input: unknown,
|
|
13
|
+
options?: Options
|
|
14
|
+
) => Promise<Result<unknown, Error>>;
|
|
15
|
+
|
|
16
|
+
const normalizeTransposeError = (
|
|
17
|
+
trail: AnyTrail,
|
|
18
|
+
version: number,
|
|
19
|
+
phase: 'input' | 'output',
|
|
20
|
+
error: unknown
|
|
21
|
+
): InternalError => {
|
|
22
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
23
|
+
const options: { cause?: Error; context: Record<string, unknown> } = {
|
|
24
|
+
context: { phase, trailId: trail.id, version },
|
|
25
|
+
};
|
|
26
|
+
if (error instanceof Error) {
|
|
27
|
+
options.cause = error;
|
|
28
|
+
}
|
|
29
|
+
return new InternalError(
|
|
30
|
+
`Trail "${trail.id}" version ${version} transpose.${phase} failed: ${message}`,
|
|
31
|
+
options
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const runTransposeInput = async (
|
|
36
|
+
trail: AnyTrail,
|
|
37
|
+
version: number,
|
|
38
|
+
entry: TrailVersionEntry,
|
|
39
|
+
input: unknown
|
|
40
|
+
): Promise<Result<unknown, Error>> => {
|
|
41
|
+
if (entry.transpose === undefined) {
|
|
42
|
+
return Result.ok(input);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
return Result.ok(await entry.transpose.input({ input }));
|
|
47
|
+
} catch (error: unknown) {
|
|
48
|
+
return Result.err(normalizeTransposeError(trail, version, 'input', error));
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const runTransposeOutput = async (
|
|
53
|
+
trail: AnyTrail,
|
|
54
|
+
version: number,
|
|
55
|
+
entry: TrailVersionEntry,
|
|
56
|
+
output: unknown
|
|
57
|
+
): Promise<Result<unknown, Error>> => {
|
|
58
|
+
if (entry.transpose === undefined) {
|
|
59
|
+
return Result.ok(output);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
return Result.ok(await entry.transpose.output({ output }));
|
|
64
|
+
} catch (error: unknown) {
|
|
65
|
+
return Result.err(normalizeTransposeError(trail, version, 'output', error));
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const executeTrailRevision = async <
|
|
70
|
+
Options extends ExecuteTrailOptions = ExecuteTrailOptions,
|
|
71
|
+
>(
|
|
72
|
+
trail: AnyTrail,
|
|
73
|
+
version: number,
|
|
74
|
+
entry: TrailVersionEntry,
|
|
75
|
+
rawInput: unknown,
|
|
76
|
+
options: Options | undefined,
|
|
77
|
+
executeCurrentTrail: TrailVersionCurrentExecutor<Options>
|
|
78
|
+
): Promise<Result<unknown, Error>> => {
|
|
79
|
+
if (getTrailVersionEntryKind(entry) !== 'revision') {
|
|
80
|
+
return Result.err(
|
|
81
|
+
new ValidationError(
|
|
82
|
+
`Trail "${trail.id}" version ${version} is not a revision entry`
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const historicalInput = validateInput(entry.input, rawInput);
|
|
88
|
+
if (historicalInput.isErr()) {
|
|
89
|
+
return historicalInput;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const currentInput = await runTransposeInput(
|
|
93
|
+
trail,
|
|
94
|
+
version,
|
|
95
|
+
entry,
|
|
96
|
+
historicalInput.value
|
|
97
|
+
);
|
|
98
|
+
if (currentInput.isErr()) {
|
|
99
|
+
return currentInput;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const currentOutput = await executeCurrentTrail(
|
|
103
|
+
trail,
|
|
104
|
+
currentInput.value,
|
|
105
|
+
options
|
|
106
|
+
);
|
|
107
|
+
if (currentOutput.isErr()) {
|
|
108
|
+
return currentOutput;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const historicalOutput = await runTransposeOutput(
|
|
112
|
+
trail,
|
|
113
|
+
version,
|
|
114
|
+
entry,
|
|
115
|
+
currentOutput.value
|
|
116
|
+
);
|
|
117
|
+
return historicalOutput.isErr()
|
|
118
|
+
? historicalOutput
|
|
119
|
+
: validateOutput(entry.output, historicalOutput.value);
|
|
120
|
+
};
|