@contractspec/lib.contracts 1.50.0 → 1.52.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/dist/app-config/contracts.d.ts +51 -51
- package/dist/app-config/events.d.ts +27 -27
- package/dist/app-config/lifecycle-contracts.d.ts +55 -55
- package/dist/app-config/runtime.d.ts +1 -1
- package/dist/app-config/spec.d.ts +1 -1
- package/dist/capabilities/capabilities.d.ts +40 -4
- package/dist/capabilities/capabilities.js +125 -0
- package/dist/capabilities/context.d.ts +88 -0
- package/dist/capabilities/context.js +87 -0
- package/dist/capabilities/docs/capabilities.docblock.js +191 -2
- package/dist/capabilities/guards.d.ts +110 -0
- package/dist/capabilities/guards.js +146 -0
- package/dist/capabilities/index.d.ts +4 -1
- package/dist/capabilities/index.js +4 -1
- package/dist/capabilities/validation.d.ts +76 -0
- package/dist/capabilities/validation.js +141 -0
- package/dist/client/react/feature-render.d.ts +2 -2
- package/dist/contract-registry/schemas.d.ts +4 -4
- package/dist/data-views/runtime.d.ts +1 -1
- package/dist/events.d.ts +6 -0
- package/dist/examples/schema.d.ts +7 -7
- package/dist/experiments/spec.d.ts +1 -1
- package/dist/features/install.d.ts +4 -4
- package/dist/features/types.d.ts +4 -4
- package/dist/index.d.ts +21 -13
- package/dist/index.js +11 -3
- package/dist/install.d.ts +1 -1
- package/dist/integrations/openbanking/contracts/accounts.d.ts +67 -67
- package/dist/integrations/openbanking/contracts/balances.d.ts +35 -35
- package/dist/integrations/openbanking/contracts/transactions.d.ts +49 -49
- package/dist/integrations/openbanking/models.d.ts +55 -55
- package/dist/integrations/operations.d.ts +103 -103
- package/dist/integrations/spec.d.ts +1 -1
- package/dist/knowledge/operations.d.ts +67 -67
- package/dist/llm/exporters.d.ts +2 -2
- package/dist/markdown.d.ts +1 -1
- package/dist/onboarding-base.d.ts +29 -29
- package/dist/operations/operation.d.ts +6 -0
- package/dist/policy/context.d.ts +237 -0
- package/dist/policy/context.js +227 -0
- package/dist/policy/guards.d.ts +145 -0
- package/dist/policy/guards.js +254 -0
- package/dist/policy/index.d.ts +12 -1
- package/dist/policy/index.js +11 -1
- package/dist/policy/spec.d.ts +1 -1
- package/dist/policy/validation.d.ts +67 -0
- package/dist/policy/validation.js +307 -0
- package/dist/presentations/presentations.d.ts +6 -0
- package/dist/tests/spec.d.ts +1 -1
- package/dist/themes.d.ts +1 -1
- package/dist/translations/index.d.ts +6 -0
- package/dist/translations/index.js +5 -0
- package/dist/translations/registry.d.ts +144 -0
- package/dist/translations/registry.js +223 -0
- package/dist/translations/spec.d.ts +126 -0
- package/dist/translations/spec.js +31 -0
- package/dist/translations/validation.d.ts +85 -0
- package/dist/translations/validation.js +328 -0
- package/dist/workflow/context.d.ts +191 -0
- package/dist/workflow/context.js +227 -0
- package/dist/workflow/index.d.ts +4 -2
- package/dist/workflow/index.js +4 -2
- package/dist/workflow/spec.d.ts +1 -1
- package/dist/workflow/validation.d.ts +64 -2
- package/dist/workflow/validation.js +194 -1
- package/package.json +18 -6
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
//#region src/translations/validation.ts
|
|
2
|
+
/**
|
|
3
|
+
* Validate a translation spec for internal consistency.
|
|
4
|
+
*
|
|
5
|
+
* @param spec - Translation spec to validate
|
|
6
|
+
* @returns Validation result with any issues found
|
|
7
|
+
*/
|
|
8
|
+
function validateTranslationSpec(spec) {
|
|
9
|
+
const issues = [];
|
|
10
|
+
validateMeta(spec, issues);
|
|
11
|
+
validateLocale(spec, issues);
|
|
12
|
+
validateMessages(spec, issues);
|
|
13
|
+
validatePluralRules(spec, issues);
|
|
14
|
+
return {
|
|
15
|
+
valid: issues.filter((i) => i.level === "error").length === 0,
|
|
16
|
+
issues
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function validateMeta(spec, issues) {
|
|
20
|
+
const { meta } = spec;
|
|
21
|
+
if (!meta.key?.trim()) issues.push({
|
|
22
|
+
level: "error",
|
|
23
|
+
message: "Translation spec must have a non-empty key",
|
|
24
|
+
path: "meta.key"
|
|
25
|
+
});
|
|
26
|
+
if (!meta.version?.trim()) issues.push({
|
|
27
|
+
level: "error",
|
|
28
|
+
message: "Translation spec must have a non-empty version",
|
|
29
|
+
path: "meta.version"
|
|
30
|
+
});
|
|
31
|
+
if (!meta.domain?.trim()) issues.push({
|
|
32
|
+
level: "error",
|
|
33
|
+
message: "Translation spec must have a non-empty domain",
|
|
34
|
+
path: "meta.domain"
|
|
35
|
+
});
|
|
36
|
+
if (!meta.owners?.length) issues.push({
|
|
37
|
+
level: "warning",
|
|
38
|
+
message: "Translation spec should specify owners",
|
|
39
|
+
path: "meta.owners"
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function validateLocale(spec, issues) {
|
|
43
|
+
if (!spec.locale?.trim()) issues.push({
|
|
44
|
+
level: "error",
|
|
45
|
+
message: "Translation spec must specify a locale",
|
|
46
|
+
path: "locale"
|
|
47
|
+
});
|
|
48
|
+
else if (!isValidLocaleFormat(spec.locale)) issues.push({
|
|
49
|
+
level: "warning",
|
|
50
|
+
message: `Locale "${spec.locale}" may not be a valid ISO 639-1 code`,
|
|
51
|
+
path: "locale"
|
|
52
|
+
});
|
|
53
|
+
if (spec.fallback && !isValidLocaleFormat(spec.fallback)) issues.push({
|
|
54
|
+
level: "warning",
|
|
55
|
+
message: `Fallback locale "${spec.fallback}" may not be a valid ISO 639-1 code`,
|
|
56
|
+
path: "fallback"
|
|
57
|
+
});
|
|
58
|
+
if (spec.fallback === spec.locale) issues.push({
|
|
59
|
+
level: "warning",
|
|
60
|
+
message: "Fallback locale is the same as primary locale",
|
|
61
|
+
path: "fallback"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function validateMessages(spec, issues) {
|
|
65
|
+
const { messages } = spec;
|
|
66
|
+
if (!messages || Object.keys(messages).length === 0) {
|
|
67
|
+
issues.push({
|
|
68
|
+
level: "warning",
|
|
69
|
+
message: "Translation spec has no messages",
|
|
70
|
+
path: "messages"
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
for (const [key, message] of Object.entries(messages)) {
|
|
75
|
+
const path = `messages.${key}`;
|
|
76
|
+
if (!message.value?.trim()) issues.push({
|
|
77
|
+
level: "error",
|
|
78
|
+
message: `Message "${key}" has an empty value`,
|
|
79
|
+
path: `${path}.value`
|
|
80
|
+
});
|
|
81
|
+
const valueParams = extractPlaceholders(message.value);
|
|
82
|
+
const declaredPlaceholders = message.placeholders ?? [];
|
|
83
|
+
for (const placeholder of declaredPlaceholders) if (!valueParams.includes(placeholder.name)) issues.push({
|
|
84
|
+
level: "warning",
|
|
85
|
+
message: `Placeholder "${placeholder.name}" is defined but not used in message "${key}"`,
|
|
86
|
+
path: `${path}.placeholders`
|
|
87
|
+
});
|
|
88
|
+
if (message.placeholders !== void 0) {
|
|
89
|
+
for (const param of valueParams) if (!declaredPlaceholders.find((p) => p.name === param)) issues.push({
|
|
90
|
+
level: "info",
|
|
91
|
+
message: `Placeholder "{${param}}" used in message "${key}" but not declared`,
|
|
92
|
+
path: `${path}.placeholders`
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const icuResult = validateICUFormat(message.value);
|
|
96
|
+
if (!icuResult.valid) issues.push({
|
|
97
|
+
level: "error",
|
|
98
|
+
message: `Message "${key}" has invalid ICU format: ${icuResult.error}`,
|
|
99
|
+
path: `${path}.value`
|
|
100
|
+
});
|
|
101
|
+
if (message.variants?.length) {
|
|
102
|
+
const seenVariants = /* @__PURE__ */ new Set();
|
|
103
|
+
for (const variant of message.variants) {
|
|
104
|
+
const variantKey = `${variant.type}:${variant.key}`;
|
|
105
|
+
if (seenVariants.has(variantKey)) issues.push({
|
|
106
|
+
level: "warning",
|
|
107
|
+
message: `Duplicate variant "${variantKey}" in message "${key}"`,
|
|
108
|
+
path: `${path}.variants`
|
|
109
|
+
});
|
|
110
|
+
seenVariants.add(variantKey);
|
|
111
|
+
if (!variant.value?.trim()) issues.push({
|
|
112
|
+
level: "error",
|
|
113
|
+
message: `Variant "${variantKey}" has an empty value in message "${key}"`,
|
|
114
|
+
path: `${path}.variants`
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (message.maxLength !== void 0) {
|
|
119
|
+
if (message.maxLength <= 0) issues.push({
|
|
120
|
+
level: "error",
|
|
121
|
+
message: `Message "${key}" has invalid maxLength (must be positive)`,
|
|
122
|
+
path: `${path}.maxLength`
|
|
123
|
+
});
|
|
124
|
+
else if (message.value.length > message.maxLength) issues.push({
|
|
125
|
+
level: "warning",
|
|
126
|
+
message: `Message "${key}" value exceeds maxLength (${message.value.length} > ${message.maxLength})`,
|
|
127
|
+
path: `${path}.value`
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function validatePluralRules(spec, issues) {
|
|
133
|
+
if (!spec.pluralRules?.length) return;
|
|
134
|
+
for (let i = 0; i < spec.pluralRules.length; i++) {
|
|
135
|
+
const rule = spec.pluralRules[i];
|
|
136
|
+
if (!rule) continue;
|
|
137
|
+
const path = `pluralRules[${i}]`;
|
|
138
|
+
if (!rule.variable?.trim()) issues.push({
|
|
139
|
+
level: "error",
|
|
140
|
+
message: "Plural rule must specify a variable name",
|
|
141
|
+
path: `${path}.variable`
|
|
142
|
+
});
|
|
143
|
+
if (!rule.rules?.length) issues.push({
|
|
144
|
+
level: "error",
|
|
145
|
+
message: "Plural rule must have at least one category",
|
|
146
|
+
path: `${path}.rules`
|
|
147
|
+
});
|
|
148
|
+
else if (!rule.rules.some((r) => r.category === "other")) issues.push({
|
|
149
|
+
level: "error",
|
|
150
|
+
message: `Plural rule "${rule.variable}" must have an "other" category`,
|
|
151
|
+
path: `${path}.rules`
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Validate ICU message format syntax.
|
|
157
|
+
*
|
|
158
|
+
* This is a simplified validator that checks for balanced braces
|
|
159
|
+
* and extracts placeholders, plurals, and selects.
|
|
160
|
+
*
|
|
161
|
+
* @param message - Message string to validate
|
|
162
|
+
* @returns Validation result with extracted components
|
|
163
|
+
*/
|
|
164
|
+
function validateICUFormat(message) {
|
|
165
|
+
const placeholders = [];
|
|
166
|
+
const plurals = [];
|
|
167
|
+
const selects = [];
|
|
168
|
+
let braceDepth = 0;
|
|
169
|
+
let currentPlaceholder = "";
|
|
170
|
+
let inPlaceholder = false;
|
|
171
|
+
try {
|
|
172
|
+
for (let i = 0; i < message.length; i++) {
|
|
173
|
+
const char = message[i];
|
|
174
|
+
const prevChar = i > 0 ? message[i - 1] : "";
|
|
175
|
+
if (char === "'" && i + 1 < message.length) {
|
|
176
|
+
const nextChar = message[i + 1];
|
|
177
|
+
if (nextChar === "{" || nextChar === "}") {
|
|
178
|
+
i++;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (char === "{") {
|
|
183
|
+
if (prevChar !== "'") {
|
|
184
|
+
braceDepth++;
|
|
185
|
+
if (braceDepth === 1) {
|
|
186
|
+
inPlaceholder = true;
|
|
187
|
+
currentPlaceholder = "";
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
} else if (char === "}") {
|
|
191
|
+
if (prevChar !== "'") {
|
|
192
|
+
braceDepth--;
|
|
193
|
+
if (braceDepth === 0 && inPlaceholder) {
|
|
194
|
+
processPlaceholder(currentPlaceholder.trim(), placeholders, plurals, selects);
|
|
195
|
+
inPlaceholder = false;
|
|
196
|
+
}
|
|
197
|
+
if (braceDepth < 0) return {
|
|
198
|
+
valid: false,
|
|
199
|
+
error: "Unbalanced closing brace",
|
|
200
|
+
placeholders: [],
|
|
201
|
+
plurals: [],
|
|
202
|
+
selects: []
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
} else if (inPlaceholder) currentPlaceholder += char;
|
|
206
|
+
}
|
|
207
|
+
if (braceDepth !== 0) return {
|
|
208
|
+
valid: false,
|
|
209
|
+
error: "Unbalanced opening brace",
|
|
210
|
+
placeholders: [],
|
|
211
|
+
plurals: [],
|
|
212
|
+
selects: []
|
|
213
|
+
};
|
|
214
|
+
return {
|
|
215
|
+
valid: true,
|
|
216
|
+
placeholders,
|
|
217
|
+
plurals,
|
|
218
|
+
selects
|
|
219
|
+
};
|
|
220
|
+
} catch (error) {
|
|
221
|
+
return {
|
|
222
|
+
valid: false,
|
|
223
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
224
|
+
placeholders: [],
|
|
225
|
+
plurals: [],
|
|
226
|
+
selects: []
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function processPlaceholder(placeholder, placeholders, plurals, selects) {
|
|
231
|
+
const parts = placeholder.split(",").map((p) => p.trim());
|
|
232
|
+
const name = parts[0];
|
|
233
|
+
const type = parts[1]?.toLowerCase();
|
|
234
|
+
if (name && !placeholders.includes(name)) placeholders.push(name);
|
|
235
|
+
if (type === "plural" || type === "selectordinal") {
|
|
236
|
+
if (name && !plurals.includes(name)) plurals.push(name);
|
|
237
|
+
} else if (type === "select") {
|
|
238
|
+
if (name && !selects.includes(name)) selects.push(name);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Find messages that exist in source but not in target.
|
|
243
|
+
*
|
|
244
|
+
* @param sourceSpec - Source translation spec (usually base locale like 'en')
|
|
245
|
+
* @param targetSpec - Target translation spec to check
|
|
246
|
+
* @returns Array of missing translations
|
|
247
|
+
*/
|
|
248
|
+
function findMissingTranslations(sourceSpec, targetSpec) {
|
|
249
|
+
const missing = [];
|
|
250
|
+
for (const [key, message] of Object.entries(sourceSpec.messages)) if (!targetSpec.messages[key]) missing.push({
|
|
251
|
+
messageKey: key,
|
|
252
|
+
sourceLocale: sourceSpec.locale,
|
|
253
|
+
targetLocale: targetSpec.locale,
|
|
254
|
+
sourceMessage: message
|
|
255
|
+
});
|
|
256
|
+
return missing;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Find all missing translations across a registry.
|
|
260
|
+
*
|
|
261
|
+
* Compares each locale against a base locale to find missing keys.
|
|
262
|
+
*
|
|
263
|
+
* @param registry - Translation registry
|
|
264
|
+
* @param specKey - Translation spec key to check
|
|
265
|
+
* @param baseLocale - Base locale to compare against
|
|
266
|
+
* @returns Map of locale to missing translations
|
|
267
|
+
*/
|
|
268
|
+
function findAllMissingTranslations(registry, specKey, baseLocale) {
|
|
269
|
+
const result = /* @__PURE__ */ new Map();
|
|
270
|
+
const baseSpec = registry.getLatest(specKey, baseLocale);
|
|
271
|
+
if (!baseSpec) return result;
|
|
272
|
+
const locales = registry.listLocales(specKey);
|
|
273
|
+
for (const locale of locales) {
|
|
274
|
+
if (locale === baseLocale) continue;
|
|
275
|
+
const targetSpec = registry.getLatest(specKey, locale);
|
|
276
|
+
if (targetSpec) {
|
|
277
|
+
const missing = findMissingTranslations(baseSpec, targetSpec);
|
|
278
|
+
if (missing.length > 0) result.set(locale, missing);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return result;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Validate all translation specs in a registry.
|
|
285
|
+
*
|
|
286
|
+
* @param registry - Translation registry to validate
|
|
287
|
+
* @returns Validation result
|
|
288
|
+
*/
|
|
289
|
+
function validateTranslationRegistry(registry) {
|
|
290
|
+
const issues = [];
|
|
291
|
+
for (const spec of registry.list()) {
|
|
292
|
+
const specResult = validateTranslationSpec(spec);
|
|
293
|
+
issues.push(...specResult.issues.map((i) => ({
|
|
294
|
+
...i,
|
|
295
|
+
path: `${spec.meta.key}.v${spec.meta.version}:${spec.locale}${i.path ? `.${i.path}` : ""}`
|
|
296
|
+
})));
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
valid: issues.filter((i) => i.level === "error").length === 0,
|
|
300
|
+
issues
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
var TranslationValidationError = class extends Error {
|
|
304
|
+
constructor(message, issues) {
|
|
305
|
+
super(message);
|
|
306
|
+
this.issues = issues;
|
|
307
|
+
this.name = "TranslationValidationError";
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
/**
|
|
311
|
+
* Assert that a translation spec is valid, throwing if not.
|
|
312
|
+
*
|
|
313
|
+
* @param spec - Translation spec to validate
|
|
314
|
+
* @throws {TranslationValidationError} If validation fails
|
|
315
|
+
*/
|
|
316
|
+
function assertTranslationSpecValid(spec) {
|
|
317
|
+
const result = validateTranslationSpec(spec);
|
|
318
|
+
if (!result.valid) throw new TranslationValidationError(`Translation ${spec.meta.key}.v${spec.meta.version}:${spec.locale} is invalid`, result.issues);
|
|
319
|
+
}
|
|
320
|
+
function isValidLocaleFormat(locale) {
|
|
321
|
+
return /^[a-z]{2}(-[A-Z]{2})?$/.test(locale);
|
|
322
|
+
}
|
|
323
|
+
function extractPlaceholders(value) {
|
|
324
|
+
return validateICUFormat(value).placeholders;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
//#endregion
|
|
328
|
+
export { TranslationValidationError, assertTranslationSpecValid, findAllMissingTranslations, findMissingTranslations, validateICUFormat, validateTranslationRegistry, validateTranslationSpec };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { Step, WorkflowSpec } from "./spec.js";
|
|
2
|
+
import { StepExecution, WorkflowState } from "./state.js";
|
|
3
|
+
|
|
4
|
+
//#region src/workflow/context.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown when a workflow operation fails.
|
|
8
|
+
*/
|
|
9
|
+
declare class WorkflowContextError extends Error {
|
|
10
|
+
readonly errorType: WorkflowContextErrorType;
|
|
11
|
+
readonly workflowId: string;
|
|
12
|
+
readonly details?: Record<string, unknown>;
|
|
13
|
+
constructor(type: WorkflowContextErrorType, workflowId: string, message: string, details?: Record<string, unknown>);
|
|
14
|
+
}
|
|
15
|
+
type WorkflowContextErrorType = 'invalid_transition' | 'workflow_completed' | 'workflow_failed' | 'step_not_found' | 'guard_rejected' | 'sla_violated';
|
|
16
|
+
interface WorkflowTransitionResult {
|
|
17
|
+
success: boolean;
|
|
18
|
+
previousStep: string;
|
|
19
|
+
currentStep: string;
|
|
20
|
+
status: WorkflowState['status'];
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
interface AvailableTransition {
|
|
24
|
+
from: string;
|
|
25
|
+
to: string;
|
|
26
|
+
label?: string;
|
|
27
|
+
condition?: string;
|
|
28
|
+
}
|
|
29
|
+
interface SlaStatus {
|
|
30
|
+
key: string;
|
|
31
|
+
type: 'workflow' | 'step';
|
|
32
|
+
stepId?: string;
|
|
33
|
+
limitMs: number;
|
|
34
|
+
elapsedMs: number;
|
|
35
|
+
remainingMs: number;
|
|
36
|
+
violated: boolean;
|
|
37
|
+
percentUsed: number;
|
|
38
|
+
}
|
|
39
|
+
interface WorkflowEvent {
|
|
40
|
+
timestamp: Date;
|
|
41
|
+
type: 'step_started' | 'step_completed' | 'step_failed' | 'step_retried' | 'transition';
|
|
42
|
+
stepId?: string;
|
|
43
|
+
fromStep?: string;
|
|
44
|
+
toStep?: string;
|
|
45
|
+
input?: unknown;
|
|
46
|
+
output?: unknown;
|
|
47
|
+
error?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Runtime context for interacting with a workflow instance.
|
|
51
|
+
*
|
|
52
|
+
* Provides a simplified interface over WorkflowRunner for common
|
|
53
|
+
* workflow operations like state access, transitions, and SLA tracking.
|
|
54
|
+
*/
|
|
55
|
+
interface WorkflowContext<TData = Record<string, unknown>> {
|
|
56
|
+
/** Unique workflow instance identifier. */
|
|
57
|
+
readonly workflowId: string;
|
|
58
|
+
/** Workflow spec key. */
|
|
59
|
+
readonly workflowKey: string;
|
|
60
|
+
/** Workflow spec version. */
|
|
61
|
+
readonly workflowVersion: string;
|
|
62
|
+
/** Current step identifier. */
|
|
63
|
+
readonly currentStep: string;
|
|
64
|
+
/** Current workflow status. */
|
|
65
|
+
readonly status: WorkflowState['status'];
|
|
66
|
+
/** Workflow data/state. */
|
|
67
|
+
readonly data: TData;
|
|
68
|
+
/** Execution history. */
|
|
69
|
+
readonly history: readonly StepExecution[];
|
|
70
|
+
/**
|
|
71
|
+
* Get the current workflow state.
|
|
72
|
+
* @returns Full workflow state object
|
|
73
|
+
*/
|
|
74
|
+
getState(): WorkflowState;
|
|
75
|
+
/**
|
|
76
|
+
* Get a value from workflow data.
|
|
77
|
+
* @param key - Data key to retrieve
|
|
78
|
+
* @returns Value or undefined
|
|
79
|
+
*/
|
|
80
|
+
getData<T = unknown>(key: string): T | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Check if workflow is in a terminal state.
|
|
83
|
+
* @returns True if completed, failed, or cancelled
|
|
84
|
+
*/
|
|
85
|
+
isTerminal(): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Check if workflow is running.
|
|
88
|
+
* @returns True if status is 'running'
|
|
89
|
+
*/
|
|
90
|
+
isRunning(): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Get the current step definition.
|
|
93
|
+
* @returns Step definition or undefined
|
|
94
|
+
*/
|
|
95
|
+
getCurrentStepDef(): Step | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* Get the retry count for a step.
|
|
98
|
+
* @param stepId - Step to check (defaults to current step)
|
|
99
|
+
* @returns Number of retry attempts
|
|
100
|
+
*/
|
|
101
|
+
getRetryCount(stepId?: string): number;
|
|
102
|
+
/**
|
|
103
|
+
* Check if a transition to a target step is valid.
|
|
104
|
+
* @param toStepId - Target step identifier
|
|
105
|
+
* @returns True if transition is valid from current step
|
|
106
|
+
*/
|
|
107
|
+
canTransition(toStepId: string): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Get all available transitions from current step.
|
|
110
|
+
* @returns Array of available transitions
|
|
111
|
+
*/
|
|
112
|
+
getAvailableTransitions(): AvailableTransition[];
|
|
113
|
+
/**
|
|
114
|
+
* Check if the current step has any outgoing transitions.
|
|
115
|
+
* @returns True if there are outgoing transitions
|
|
116
|
+
*/
|
|
117
|
+
hasNextStep(): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Get remaining time for an SLA constraint.
|
|
120
|
+
* @param slaKey - 'totalDuration' or step ID
|
|
121
|
+
* @returns Remaining milliseconds, or null if no SLA configured
|
|
122
|
+
*/
|
|
123
|
+
getRemainingTime(slaKey: string): number | null;
|
|
124
|
+
/**
|
|
125
|
+
* Check if an SLA constraint has been violated.
|
|
126
|
+
* @param slaKey - 'totalDuration' or step ID
|
|
127
|
+
* @returns True if SLA has been violated
|
|
128
|
+
*/
|
|
129
|
+
isSlaViolated(slaKey: string): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Get status of all SLA constraints.
|
|
132
|
+
* @returns Array of SLA statuses
|
|
133
|
+
*/
|
|
134
|
+
getAllSlaStatuses(): SlaStatus[];
|
|
135
|
+
/**
|
|
136
|
+
* Check if compensation/rollback is available.
|
|
137
|
+
* @returns True if workflow has compensation strategy
|
|
138
|
+
*/
|
|
139
|
+
hasCompensation(): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Get steps that have compensation handlers.
|
|
142
|
+
* @returns Array of step IDs with compensation
|
|
143
|
+
*/
|
|
144
|
+
getCompensableSteps(): string[];
|
|
145
|
+
/**
|
|
146
|
+
* Convert execution history to workflow events.
|
|
147
|
+
* @returns Array of workflow events
|
|
148
|
+
*/
|
|
149
|
+
getEvents(): WorkflowEvent[];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Creates a workflow context from state and spec.
|
|
153
|
+
*
|
|
154
|
+
* @param state - Current workflow state
|
|
155
|
+
* @param spec - Workflow specification
|
|
156
|
+
* @returns WorkflowContext for interacting with the workflow
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const state = await runner.getState(workflowId);
|
|
161
|
+
* const spec = registry.get(state.workflowName, state.workflowVersion);
|
|
162
|
+
* const ctx = createWorkflowContext(state, spec);
|
|
163
|
+
*
|
|
164
|
+
* console.log('Current step:', ctx.currentStep);
|
|
165
|
+
* console.log('Available transitions:', ctx.getAvailableTransitions());
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
declare function createWorkflowContext<TData = Record<string, unknown>>(state: WorkflowState, spec: WorkflowSpec): WorkflowContext<TData>;
|
|
169
|
+
/**
|
|
170
|
+
* Calculate workflow progress as a percentage.
|
|
171
|
+
*
|
|
172
|
+
* @param ctx - Workflow context
|
|
173
|
+
* @returns Progress percentage (0-100)
|
|
174
|
+
*/
|
|
175
|
+
declare function calculateWorkflowProgress(ctx: WorkflowContext): number;
|
|
176
|
+
/**
|
|
177
|
+
* Get the duration of a workflow in milliseconds.
|
|
178
|
+
*
|
|
179
|
+
* @param ctx - Workflow context
|
|
180
|
+
* @returns Duration in milliseconds
|
|
181
|
+
*/
|
|
182
|
+
declare function getWorkflowDuration(ctx: WorkflowContext): number;
|
|
183
|
+
/**
|
|
184
|
+
* Get the average step duration in milliseconds.
|
|
185
|
+
*
|
|
186
|
+
* @param ctx - Workflow context
|
|
187
|
+
* @returns Average duration or 0 if no completed steps
|
|
188
|
+
*/
|
|
189
|
+
declare function getAverageStepDuration(ctx: WorkflowContext): number;
|
|
190
|
+
//#endregion
|
|
191
|
+
export { AvailableTransition, SlaStatus, WorkflowContext, WorkflowContextError, WorkflowContextErrorType, WorkflowEvent, WorkflowTransitionResult, calculateWorkflowProgress, createWorkflowContext, getAverageStepDuration, getWorkflowDuration };
|