@siglo/http 0.0.0-stage → 1.0.1
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/LICENSE +21 -0
- package/README.md +38 -2
- package/dist/client/fetch.d.ts +46 -0
- package/dist/client/fetch.d.ts.map +1 -0
- package/dist/client/fetch.js +330 -0
- package/dist/client/fetch.js.map +1 -0
- package/dist/client/retry.d.ts +30 -0
- package/dist/client/retry.d.ts.map +1 -0
- package/dist/client/retry.js +82 -0
- package/dist/client/retry.js.map +1 -0
- package/dist/client/trace.d.ts +23 -0
- package/dist/client/trace.d.ts.map +1 -0
- package/dist/client/trace.js +103 -0
- package/dist/client/trace.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/policy/asl-bridge.d.ts +21 -0
- package/dist/policy/asl-bridge.d.ts.map +1 -0
- package/dist/policy/asl-bridge.js +82 -0
- package/dist/policy/asl-bridge.js.map +1 -0
- package/dist/schema/validator.d.ts +14 -0
- package/dist/schema/validator.d.ts.map +1 -0
- package/dist/schema/validator.js +154 -0
- package/dist/schema/validator.js.map +1 -0
- package/dist/step.d.ts +15 -0
- package/dist/step.d.ts.map +1 -0
- package/dist/step.js +165 -0
- package/dist/step.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +18 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mock-agent.d.ts +64 -0
- package/dist/testing/mock-agent.d.ts.map +1 -0
- package/dist/testing/mock-agent.js +233 -0
- package/dist/testing/mock-agent.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -4
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.injectTraceHeaders = injectTraceHeaders;
|
|
4
|
+
exports.recordRequestSpanAttributes = recordRequestSpanAttributes;
|
|
5
|
+
exports.recordResponseSpanAttributes = recordResponseSpanAttributes;
|
|
6
|
+
exports.getActiveTraceId = getActiveTraceId;
|
|
7
|
+
const api_1 = require("@opentelemetry/api");
|
|
8
|
+
/**
|
|
9
|
+
* Injects W3C distributed trace context (traceparent and tracestate) into request headers
|
|
10
|
+
* from the active OpenTelemetry span and context.
|
|
11
|
+
*/
|
|
12
|
+
function injectTraceHeaders(carrier = {}, customSpan) {
|
|
13
|
+
const activeCtx = api_1.context.active();
|
|
14
|
+
try {
|
|
15
|
+
api_1.propagation.inject(activeCtx, carrier, api_1.defaultTextMapSetter);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
// If propagation fails, continue to spanContext fallback
|
|
19
|
+
}
|
|
20
|
+
const targetSpan = customSpan || api_1.trace.getActiveSpan();
|
|
21
|
+
if (targetSpan) {
|
|
22
|
+
try {
|
|
23
|
+
const spanCtx = typeof targetSpan.spanContext === 'function'
|
|
24
|
+
? targetSpan.spanContext()
|
|
25
|
+
: targetSpan.spanContext;
|
|
26
|
+
if (spanCtx && spanCtx.traceId && !carrier['traceparent']) {
|
|
27
|
+
const flags = (spanCtx.traceFlags ?? 0).toString(16).padStart(2, '0');
|
|
28
|
+
const spanId = spanCtx.spanId || '0000000000000000';
|
|
29
|
+
carrier['traceparent'] = `00-${spanCtx.traceId}-${spanId}-${flags}`;
|
|
30
|
+
if (spanCtx.traceState) {
|
|
31
|
+
carrier['tracestate'] =
|
|
32
|
+
typeof spanCtx.traceState.serialize === 'function'
|
|
33
|
+
? spanCtx.traceState.serialize()
|
|
34
|
+
: String(spanCtx.traceState);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Ignore span context extraction error
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return carrier;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Attaches standard HTTP semantic convention attributes to the active OpenTelemetry span.
|
|
46
|
+
*/
|
|
47
|
+
function recordRequestSpanAttributes(method, url, serverAddress, customSpan) {
|
|
48
|
+
const activeSpan = customSpan || api_1.trace.getActiveSpan();
|
|
49
|
+
if (activeSpan && typeof activeSpan.setAttribute === 'function') {
|
|
50
|
+
try {
|
|
51
|
+
activeSpan.setAttribute('http.request.method', method.toUpperCase());
|
|
52
|
+
activeSpan.setAttribute('url.full', url);
|
|
53
|
+
activeSpan.setAttribute('server.address', serverAddress);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Ignore attribute recording errors
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Attaches standard response semantic convention attributes to the active OpenTelemetry span.
|
|
62
|
+
*/
|
|
63
|
+
function recordResponseSpanAttributes(statusCode, customSpan) {
|
|
64
|
+
const activeSpan = customSpan || api_1.trace.getActiveSpan();
|
|
65
|
+
if (activeSpan && typeof activeSpan.setAttribute === 'function') {
|
|
66
|
+
try {
|
|
67
|
+
activeSpan.setAttribute('http.response.status_code', statusCode);
|
|
68
|
+
if (statusCode >= 400 && typeof activeSpan.setStatus === 'function') {
|
|
69
|
+
activeSpan.setStatus({
|
|
70
|
+
code: api_1.SpanStatusCode.ERROR,
|
|
71
|
+
message: `HTTP error status ${statusCode}`
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Ignore attribute recording errors
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Extracts current active traceId if present.
|
|
82
|
+
*/
|
|
83
|
+
function getActiveTraceId(customSpan) {
|
|
84
|
+
const activeSpan = customSpan || api_1.trace.getActiveSpan();
|
|
85
|
+
if (activeSpan) {
|
|
86
|
+
try {
|
|
87
|
+
if (typeof activeSpan.spanContext === 'function') {
|
|
88
|
+
return activeSpan.spanContext()?.traceId;
|
|
89
|
+
}
|
|
90
|
+
if (activeSpan.spanContext && typeof activeSpan.spanContext === 'object') {
|
|
91
|
+
return activeSpan.spanContext.traceId;
|
|
92
|
+
}
|
|
93
|
+
if (activeSpan.traceId) {
|
|
94
|
+
return activeSpan.traceId;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=trace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.js","sourceRoot":"","sources":["../../src/client/trace.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { httpStep, HttpStep } from './step';
|
|
2
|
+
export { httpStep, HttpStep };
|
|
3
|
+
export default httpStep;
|
|
4
|
+
export * from './types';
|
|
5
|
+
export * from './client/retry';
|
|
6
|
+
export * from './client/trace';
|
|
7
|
+
export * from './client/fetch';
|
|
8
|
+
export * from './policy/asl-bridge';
|
|
9
|
+
export * from './schema/validator';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC9B,eAAe,QAAQ,CAAC;AAExB,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.HttpStep = exports.httpStep = void 0;
|
|
18
|
+
const step_1 = require("./step");
|
|
19
|
+
Object.defineProperty(exports, "httpStep", { enumerable: true, get: function () { return step_1.httpStep; } });
|
|
20
|
+
Object.defineProperty(exports, "HttpStep", { enumerable: true, get: function () { return step_1.HttpStep; } });
|
|
21
|
+
exports.default = step_1.httpStep;
|
|
22
|
+
__exportStar(require("./types"), exports);
|
|
23
|
+
__exportStar(require("./client/retry"), exports);
|
|
24
|
+
__exportStar(require("./client/trace"), exports);
|
|
25
|
+
__exportStar(require("./client/fetch"), exports);
|
|
26
|
+
__exportStar(require("./policy/asl-bridge"), exports);
|
|
27
|
+
__exportStar(require("./schema/validator"), exports);
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,iCAA4C;AAEnC,yFAFA,eAAQ,OAEA;AAAE,yFAFA,eAAQ,OAEA;AAC3B,kBAAe,eAAQ,CAAC;AAExB,0CAAwB;AACxB,iDAA+B;AAC/B,iDAA+B;AAC/B,iDAA+B;AAC/B,sDAAoC;AACpC,qDAAmC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface HostInfo {
|
|
2
|
+
hostname: string;
|
|
3
|
+
host: string;
|
|
4
|
+
port?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Safely parses the destination hostname, host with port, and port from a target URL string.
|
|
8
|
+
*/
|
|
9
|
+
export declare function extractHostInfo(targetUrl: string): HostInfo;
|
|
10
|
+
/**
|
|
11
|
+
* Verifies that the resolved URL's hostname is permitted by the active AsyncLocalStorage
|
|
12
|
+
* network egress perimeter policy.
|
|
13
|
+
*
|
|
14
|
+
* If blocked, throws a non-retryable NetworkPolicyViolationException tagged with `phase: 'before'`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assertNetworkPolicy(stepName: string, resolvedUrl: string, host: string, port?: string | number, fallbackPolicy?: any): void;
|
|
17
|
+
/**
|
|
18
|
+
* Extracts a static hostname from a URL option if it is provided as a static string.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractStaticHostname(urlOption: unknown): string | undefined;
|
|
21
|
+
//# sourceMappingURL=asl-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asl-bridge.d.ts","sourceRoot":"","sources":["../../src/policy/asl-bridge.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CA2B3D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EACtB,cAAc,CAAC,EAAE,GAAG,GACnB,IAAI,CA4BN;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAU5E"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractHostInfo = extractHostInfo;
|
|
4
|
+
exports.assertNetworkPolicy = assertNetworkPolicy;
|
|
5
|
+
exports.extractStaticHostname = extractStaticHostname;
|
|
6
|
+
const core_1 = require("@siglo/core");
|
|
7
|
+
/**
|
|
8
|
+
* Safely parses the destination hostname, host with port, and port from a target URL string.
|
|
9
|
+
*/
|
|
10
|
+
function extractHostInfo(targetUrl) {
|
|
11
|
+
try {
|
|
12
|
+
const urlToParse = targetUrl.includes('://') ? targetUrl : `http://${targetUrl}`;
|
|
13
|
+
const parsed = new URL(urlToParse);
|
|
14
|
+
return {
|
|
15
|
+
hostname: parsed.hostname,
|
|
16
|
+
host: parsed.host,
|
|
17
|
+
port: parsed.port || undefined
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Fallback if URL constructor still fails on malformed input
|
|
22
|
+
const withoutProto = targetUrl.replace(/^[a-z]+:\/\//, '');
|
|
23
|
+
const slashIdx = withoutProto.indexOf('/');
|
|
24
|
+
const hostPart = slashIdx !== -1 ? withoutProto.slice(0, slashIdx) : withoutProto;
|
|
25
|
+
const colonIdx = hostPart.lastIndexOf(':');
|
|
26
|
+
if (colonIdx !== -1) {
|
|
27
|
+
return {
|
|
28
|
+
hostname: hostPart.slice(0, colonIdx),
|
|
29
|
+
host: hostPart,
|
|
30
|
+
port: hostPart.slice(colonIdx + 1)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
hostname: hostPart,
|
|
35
|
+
host: hostPart
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Verifies that the resolved URL's hostname is permitted by the active AsyncLocalStorage
|
|
41
|
+
* network egress perimeter policy.
|
|
42
|
+
*
|
|
43
|
+
* If blocked, throws a non-retryable NetworkPolicyViolationException tagged with `phase: 'before'`.
|
|
44
|
+
*/
|
|
45
|
+
function assertNetworkPolicy(stepName, resolvedUrl, host, port, fallbackPolicy) {
|
|
46
|
+
const activeStore = core_1.networkPolicyStorage.getStore() || fallbackPolicy;
|
|
47
|
+
if (!activeStore || activeStore.enabled === false) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const allowed = (0, core_1.isHostAllowed)(resolvedUrl, host, activeStore, port);
|
|
51
|
+
if (!allowed) {
|
|
52
|
+
const allowedHosts = activeStore.allowedHosts || [];
|
|
53
|
+
const exception = new core_1.NetworkPolicyViolationException(stepName, resolvedUrl, host, allowedHosts, {
|
|
54
|
+
phase: 'before',
|
|
55
|
+
retryable: false
|
|
56
|
+
});
|
|
57
|
+
// Explicitly guarantee phase: 'before' and retryable: false as specified in roadmap
|
|
58
|
+
Object.defineProperty(exception, 'phase', {
|
|
59
|
+
get: () => 'before',
|
|
60
|
+
set: () => { },
|
|
61
|
+
configurable: true
|
|
62
|
+
});
|
|
63
|
+
exception.retryable = false;
|
|
64
|
+
throw exception;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Extracts a static hostname from a URL option if it is provided as a static string.
|
|
69
|
+
*/
|
|
70
|
+
function extractStaticHostname(urlOption) {
|
|
71
|
+
if (typeof urlOption !== 'string') {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const parsed = new URL(urlOption);
|
|
76
|
+
return parsed.hostname;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=asl-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asl-bridge.js","sourceRoot":"","sources":["../../src/policy/asl-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ValidationErrorDetail } from '@siglo/core';
|
|
2
|
+
export interface ValidationResult<T = any> {
|
|
3
|
+
success: boolean;
|
|
4
|
+
data?: T;
|
|
5
|
+
errors?: ValidationErrorDetail[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Validates a payload against a Standard Schema (~standard), Zod, Valibot, ArkType,
|
|
9
|
+
* or standard parsing validator.
|
|
10
|
+
*
|
|
11
|
+
* If validation fails, throws a Siglo ValidationException tagged with the provided phase.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validatePayload<T = any>(schema: any, data: unknown, phase: 'validation' | 'action', stepName?: string): Promise<T>;
|
|
14
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/schema/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzE,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,GAAG;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,qBAAqB,EAAE,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,CAAC,GAAG,GAAG,EAC3C,MAAM,EAAE,GAAG,EACX,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,YAAY,GAAG,QAAQ,EAC9B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,CAAC,CAwJZ"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validatePayload = validatePayload;
|
|
4
|
+
const core_1 = require("@siglo/core");
|
|
5
|
+
/**
|
|
6
|
+
* Validates a payload against a Standard Schema (~standard), Zod, Valibot, ArkType,
|
|
7
|
+
* or standard parsing validator.
|
|
8
|
+
*
|
|
9
|
+
* If validation fails, throws a Siglo ValidationException tagged with the provided phase.
|
|
10
|
+
*/
|
|
11
|
+
async function validatePayload(schema, data, phase, stepName) {
|
|
12
|
+
if (!schema) {
|
|
13
|
+
return data;
|
|
14
|
+
}
|
|
15
|
+
// 1. Standard Schema specification (~standard v1)
|
|
16
|
+
if (typeof schema === 'object' && schema !== null && schema['~standard']) {
|
|
17
|
+
const standard = schema['~standard'];
|
|
18
|
+
const result = await standard.validate(data);
|
|
19
|
+
if (result && result.issues) {
|
|
20
|
+
const details = result.issues.map((issue) => ({
|
|
21
|
+
field: issue.path && issue.path.length > 0
|
|
22
|
+
? issue.path.map((segment) => String(typeof segment === 'object' && segment !== null ? segment.key : segment)).join('.')
|
|
23
|
+
: '$root$',
|
|
24
|
+
message: issue.message || 'Validation failed',
|
|
25
|
+
error: issue
|
|
26
|
+
}));
|
|
27
|
+
const exception = new core_1.ValidationException(details, { phase, stepName, retryable: false });
|
|
28
|
+
Object.defineProperty(exception, 'phase', {
|
|
29
|
+
get: () => phase,
|
|
30
|
+
set: () => { },
|
|
31
|
+
configurable: true
|
|
32
|
+
});
|
|
33
|
+
throw exception;
|
|
34
|
+
}
|
|
35
|
+
if (!result || !('value' in result)) {
|
|
36
|
+
throw new TypeError('Standard Schema validator must return value or issues');
|
|
37
|
+
}
|
|
38
|
+
return result.value;
|
|
39
|
+
}
|
|
40
|
+
// 2. safeParse (Zod, Valibot, etc.)
|
|
41
|
+
if (typeof schema.safeParse === 'function') {
|
|
42
|
+
const result = await schema.safeParse(data);
|
|
43
|
+
if (!result.success) {
|
|
44
|
+
const issues = result.error?.issues;
|
|
45
|
+
const details = Array.isArray(issues) && issues.length > 0
|
|
46
|
+
? issues.map((i) => ({
|
|
47
|
+
field: i.path && i.path.length > 0 ? i.path.join('.') : '$root$',
|
|
48
|
+
message: i.message || 'Validation failed',
|
|
49
|
+
error: i
|
|
50
|
+
}))
|
|
51
|
+
: [
|
|
52
|
+
{
|
|
53
|
+
field: '$root$',
|
|
54
|
+
message: result.error?.message || 'Schema validation failed',
|
|
55
|
+
error: result.error
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
const exception = new core_1.ValidationException(details, { phase, stepName, retryable: false });
|
|
59
|
+
Object.defineProperty(exception, 'phase', {
|
|
60
|
+
get: () => phase,
|
|
61
|
+
set: () => { },
|
|
62
|
+
configurable: true
|
|
63
|
+
});
|
|
64
|
+
throw exception;
|
|
65
|
+
}
|
|
66
|
+
return result.data;
|
|
67
|
+
}
|
|
68
|
+
// 3. parse() method (Zod synchronous/asynchronous parser)
|
|
69
|
+
if (typeof schema.parse === 'function') {
|
|
70
|
+
try {
|
|
71
|
+
const parsed = await schema.parse(data);
|
|
72
|
+
return (parsed !== undefined ? parsed : data);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const issues = err?.issues;
|
|
76
|
+
const details = Array.isArray(issues) && issues.length > 0
|
|
77
|
+
? issues.map((i) => ({
|
|
78
|
+
field: i.path && i.path.length > 0 ? i.path.join('.') : '$root$',
|
|
79
|
+
message: i.message || 'Validation failed',
|
|
80
|
+
error: i
|
|
81
|
+
}))
|
|
82
|
+
: [
|
|
83
|
+
{
|
|
84
|
+
field: '$root$',
|
|
85
|
+
message: err?.message || 'Schema validation failed',
|
|
86
|
+
error: err
|
|
87
|
+
}
|
|
88
|
+
];
|
|
89
|
+
const exception = new core_1.ValidationException(details, { phase, stepName, retryable: false });
|
|
90
|
+
Object.defineProperty(exception, 'phase', {
|
|
91
|
+
get: () => phase,
|
|
92
|
+
set: () => { },
|
|
93
|
+
configurable: true
|
|
94
|
+
});
|
|
95
|
+
throw exception;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// 4. validate() method (Joi, Yup, etc.)
|
|
99
|
+
if (typeof schema.validate === 'function') {
|
|
100
|
+
try {
|
|
101
|
+
const result = await schema.validate(data);
|
|
102
|
+
// Yup returns parsed data, Joi returns { error, value }
|
|
103
|
+
if (result && typeof result === 'object' && 'error' in result && result.error) {
|
|
104
|
+
const details = Array.isArray(result.error.details)
|
|
105
|
+
? result.error.details.map((d) => ({
|
|
106
|
+
field: d.path ? (Array.isArray(d.path) ? d.path.join('.') : String(d.path)) : '$root$',
|
|
107
|
+
message: d.message || 'Validation failed',
|
|
108
|
+
error: d
|
|
109
|
+
}))
|
|
110
|
+
: [{ field: '$root$', message: result.error.message || 'Validation failed', error: result.error }];
|
|
111
|
+
const exception = new core_1.ValidationException(details, { phase, stepName, retryable: false });
|
|
112
|
+
Object.defineProperty(exception, 'phase', {
|
|
113
|
+
get: () => phase,
|
|
114
|
+
set: () => { },
|
|
115
|
+
configurable: true
|
|
116
|
+
});
|
|
117
|
+
throw exception;
|
|
118
|
+
}
|
|
119
|
+
return (result && 'value' in result ? result.value : result);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
if (err instanceof core_1.ValidationException)
|
|
123
|
+
throw err;
|
|
124
|
+
const exception = new core_1.ValidationException([{ field: '$root$', message: err?.message || 'Validation failed', error: err }], { phase, stepName, retryable: false });
|
|
125
|
+
Object.defineProperty(exception, 'phase', {
|
|
126
|
+
get: () => phase,
|
|
127
|
+
set: () => { },
|
|
128
|
+
configurable: true
|
|
129
|
+
});
|
|
130
|
+
throw exception;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// 5. Function validator (custom predicate / mapper)
|
|
134
|
+
if (typeof schema === 'function') {
|
|
135
|
+
try {
|
|
136
|
+
const result = await schema(data);
|
|
137
|
+
if (result === false) {
|
|
138
|
+
throw new Error('Custom validation function returned false');
|
|
139
|
+
}
|
|
140
|
+
return (result !== true && result !== undefined ? result : data);
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
const exception = new core_1.ValidationException([{ field: '$root$', message: err?.message || 'Validation failed', error: err }], { phase, stepName, retryable: false });
|
|
144
|
+
Object.defineProperty(exception, 'phase', {
|
|
145
|
+
get: () => phase,
|
|
146
|
+
set: () => { },
|
|
147
|
+
configurable: true
|
|
148
|
+
});
|
|
149
|
+
throw exception;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return data;
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/schema/validator.ts"],"names":[],"mappings":";;AAcA,0CA6JC;AA3KD,sCAAyE;AAQzE;;;;;GAKG;AACI,KAAK,UAAU,eAAe,CACnC,MAAW,EACX,IAAa,EACb,KAA8B,EAC9B,QAAiB;IAEjB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAS,CAAC;IACnB,CAAC;IAED,kDAAkD;IAClD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QACzE,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YAC5B,MAAM,OAAO,GAA4B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,CAAC;gBAC1E,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;oBACxC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAY,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;oBAC7H,CAAC,CAAC,QAAQ;gBACZ,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,mBAAmB;gBAC7C,KAAK,EAAE,KAAK;aACb,CAAC,CAAC,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,0BAAmB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1F,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE;gBACxC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;gBAChB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;gBACb,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,MAAM,SAAS,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,SAAS,CAAC,uDAAuD,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,MAAM,CAAC,KAAU,CAAC;IAC3B,CAAC;IAED,oCAAoC;IACpC,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;QAC3C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC;YACpC,MAAM,OAAO,GACX,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;gBACxC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;oBACtB,KAAK,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ;oBAChE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,mBAAmB;oBACzC,KAAK,EAAE,CAAC;iBACT,CAAC,CAAC;gBACL,CAAC,CAAC;oBACE;wBACE,KAAK,EAAE,QAAQ;wBACf,OAAO,EAAE,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,0BAA0B;wBAC5D,KAAK,EAAE,MAAM,CAAC,KAAK;qBACpB;iBACF,CAAC;YACR,MAAM,SAAS,GAAG,IAAI,0BAAmB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1F,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE;gBACxC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;gBAChB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;gBACb,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,MAAM,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,MAAM,CAAC,IAAS,CAAC;IAC1B,CAAC;IAED,0DAA0D;IAC1D,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAM,CAAC;QACrD,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,CAAC;YAC3B,MAAM,OAAO,GACX,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;gBACxC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;oBACtB,KAAK,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ;oBAChE,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,mBAAmB;oBACzC,KAAK,EAAE,CAAC;iBACT,CAAC,CAAC;gBACL,CAAC,CAAC;oBACE;wBACE,KAAK,EAAE,QAAQ;wBACf,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,0BAA0B;wBACnD,KAAK,EAAE,GAAG;qBACX;iBACF,CAAC;YACR,MAAM,SAAS,GAAG,IAAI,0BAAmB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1F,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE;gBACxC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;gBAChB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;gBACb,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,MAAM,SAAS,CAAC;QAClB,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3C,wDAAwD;YACxD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC9E,MAAM,OAAO,GAA4B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;oBAC1E,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;wBACpC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ;wBACtF,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,mBAAmB;wBACzC,KAAK,EAAE,CAAC;qBACT,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,mBAAmB,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;gBACrG,MAAM,SAAS,GAAG,IAAI,0BAAmB,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC1F,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE;oBACxC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;oBAChB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;oBACb,YAAY,EAAE,IAAI;iBACnB,CAAC,CAAC;gBACH,MAAM,SAAS,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,MAAM,IAAI,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAM,CAAC;QACpE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,IAAI,GAAG,YAAY,0BAAmB;gBAAE,MAAM,GAAG,CAAC;YAClD,MAAM,SAAS,GAAG,IAAI,0BAAmB,CACvC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,mBAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAC/E,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CACtC,CAAC;YACF,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE;gBACxC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;gBAChB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;gBACb,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,MAAM,SAAS,CAAC;QAClB,CAAC;IACH,CAAC;IAED,oDAAoD;IACpD,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,CAAC,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAM,CAAC;QACxE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,SAAS,GAAG,IAAI,0BAAmB,CACvC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,IAAI,mBAAmB,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAC/E,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,CACtC,CAAC;YACF,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,OAAO,EAAE;gBACxC,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK;gBAChB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;gBACb,YAAY,EAAE,IAAI;aACnB,CAAC,CAAC;YACH,MAAM,SAAS,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,IAAS,CAAC;AACnB,CAAC"}
|
package/dist/step.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Step } from '@siglo/core';
|
|
2
|
+
import { HttpStepOptions, HttpStepResult, CompensationHttpConfig, HttpStepInstance } from './types';
|
|
3
|
+
export declare class HttpStep<TInput = any, TOutput = Record<string, any>, TName extends string = string> extends Step<TInput, HttpStepResult<TOutput>, TName> implements HttpStepInstance<TInput, TOutput, TName> {
|
|
4
|
+
private httpOptions;
|
|
5
|
+
constructor(name: TName, options: HttpStepOptions<TInput, TOutput>);
|
|
6
|
+
/**
|
|
7
|
+
* Declarative saga rollback compensation via HTTP request.
|
|
8
|
+
*/
|
|
9
|
+
compensateWithHttp(config: CompensationHttpConfig<TInput, TOutput>): this;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates a resilient, W3C-traced HTTP client step for Siglo workflows.
|
|
13
|
+
*/
|
|
14
|
+
export declare function httpStep<const TName extends string, TInput = any, TOutput = Record<string, any>>(name: TName, options: HttpStepOptions<TInput, TOutput>): HttpStep<TInput, TOutput, TName>;
|
|
15
|
+
//# sourceMappingURL=step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAsC,MAAM,aAAa,CAAC;AACvE,OAAO,EAEL,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAKjB,qBAAa,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,KAAK,SAAS,MAAM,GAAG,MAAM,CAC9F,SAAQ,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,KAAK,CACnD,YAAW,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;IAEnD,OAAO,CAAC,WAAW,CAAmC;gBAE1C,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC;IA4IlE;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,sBAAsB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CA+B1E;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,CAAC,KAAK,SAAS,MAAM,EAAE,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC9F,IAAI,EAAE,KAAK,EACX,OAAO,EAAE,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,GACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAElC"}
|
package/dist/step.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpStep = void 0;
|
|
4
|
+
exports.httpStep = httpStep;
|
|
5
|
+
const core_1 = require("@siglo/core");
|
|
6
|
+
const asl_bridge_1 = require("./policy/asl-bridge");
|
|
7
|
+
const validator_1 = require("./schema/validator");
|
|
8
|
+
const fetch_1 = require("./client/fetch");
|
|
9
|
+
class HttpStep extends core_1.Step {
|
|
10
|
+
httpOptions;
|
|
11
|
+
constructor(name, options) {
|
|
12
|
+
const action = async (ctx) => {
|
|
13
|
+
// 1. Resolve parameters dynamically from context
|
|
14
|
+
const resolvedUrl = typeof options.url === 'function' ? options.url(ctx) : options.url;
|
|
15
|
+
const { hostname, port } = (0, asl_bridge_1.extractHostInfo)(resolvedUrl);
|
|
16
|
+
// Asserts hostname against active AsyncLocalStorage (ASL) network policy
|
|
17
|
+
(0, asl_bridge_1.assertNetworkPolicy)(name, resolvedUrl, hostname, port);
|
|
18
|
+
const resolvedHeaders = typeof options.headers === 'function' ? options.headers(ctx) : (options.headers || {});
|
|
19
|
+
const resolvedQuery = typeof options.query === 'function' ? options.query(ctx) : options.query;
|
|
20
|
+
const resolvedBody = typeof options.body === 'function' ? options.body(ctx) : options.body;
|
|
21
|
+
// 2. VALIDATION Phase: Validate outgoing request payload before touching the network
|
|
22
|
+
if (options.requestSchema && resolvedBody !== undefined) {
|
|
23
|
+
await (0, validator_1.validatePayload)(options.requestSchema, resolvedBody, 'validation', name);
|
|
24
|
+
}
|
|
25
|
+
// 3. ACTION Phase: Network Execution via executeHttpRequest
|
|
26
|
+
const res = await (0, fetch_1.executeHttpRequest)({
|
|
27
|
+
capture: options.capture,
|
|
28
|
+
stepName: name,
|
|
29
|
+
url: resolvedUrl,
|
|
30
|
+
method: options.method || 'GET',
|
|
31
|
+
headers: resolvedHeaders,
|
|
32
|
+
query: resolvedQuery,
|
|
33
|
+
body: resolvedBody,
|
|
34
|
+
responseType: options.responseType || 'json',
|
|
35
|
+
retryOnStatus: options.retryOnStatus,
|
|
36
|
+
maxRetries: options.maxRetries,
|
|
37
|
+
allowNotFound: options.allowNotFound,
|
|
38
|
+
timeoutMs: options.timeoutMs,
|
|
39
|
+
signal: ctx?.$signal || ctx?.signal,
|
|
40
|
+
span: ctx?.span || ctx?.$span,
|
|
41
|
+
clock: options.clock,
|
|
42
|
+
sleep: options.sleep
|
|
43
|
+
});
|
|
44
|
+
// Handle 404 when allowNotFound is true
|
|
45
|
+
if (res.notFound) {
|
|
46
|
+
const notFoundPayload = {
|
|
47
|
+
notFound: true,
|
|
48
|
+
data: null,
|
|
49
|
+
$httpMetadata: res.metadata,
|
|
50
|
+
httpMetadata: res.metadata
|
|
51
|
+
};
|
|
52
|
+
return notFoundPayload;
|
|
53
|
+
}
|
|
54
|
+
// 4. Validate incoming response payload if responseSchema is defined
|
|
55
|
+
let validatedData = res.data;
|
|
56
|
+
if (options.responseSchema) {
|
|
57
|
+
validatedData = await (0, validator_1.validatePayload)(options.responseSchema, res.data, 'action', name);
|
|
58
|
+
}
|
|
59
|
+
// 5. Attach $httpMetadata and construct return object
|
|
60
|
+
if (typeof validatedData === 'object' &&
|
|
61
|
+
validatedData !== null &&
|
|
62
|
+
!Array.isArray(validatedData) &&
|
|
63
|
+
typeof validatedData.then !== 'function' &&
|
|
64
|
+
!(typeof Blob !== 'undefined' && validatedData instanceof Blob) &&
|
|
65
|
+
!(typeof ArrayBuffer !== 'undefined' && validatedData instanceof ArrayBuffer)) {
|
|
66
|
+
return {
|
|
67
|
+
...validatedData,
|
|
68
|
+
data: validatedData,
|
|
69
|
+
$httpMetadata: res.metadata,
|
|
70
|
+
httpMetadata: res.metadata
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const wrappedResult = {
|
|
74
|
+
data: validatedData,
|
|
75
|
+
$httpMetadata: res.metadata,
|
|
76
|
+
httpMetadata: res.metadata
|
|
77
|
+
};
|
|
78
|
+
return wrappedResult;
|
|
79
|
+
};
|
|
80
|
+
super(name, ((ctx) => (0, core_1.observeEcosystem)({ version: 1, kind: 'http', outcome: 'failure',
|
|
81
|
+
method: options.method || 'GET', url: typeof options.url === 'string' ? options.url : undefined }, () => action(ctx), result => ({ ...result.$httpMetadata, policy: 'allowed' }))));
|
|
82
|
+
this.httpOptions = options;
|
|
83
|
+
// Static host assertion for graph inspection
|
|
84
|
+
const staticHost = (0, asl_bridge_1.extractStaticHostname)(options.url);
|
|
85
|
+
if (staticHost) {
|
|
86
|
+
this.allowNetwork([staticHost]);
|
|
87
|
+
}
|
|
88
|
+
// 1. BEFORE Phase: Validate ASL Network Egress Perimeter early
|
|
89
|
+
this.onBefore(async (ctx) => {
|
|
90
|
+
try {
|
|
91
|
+
const resolvedUrl = typeof options.url === 'function' ? options.url(ctx) : options.url;
|
|
92
|
+
const { hostname, port } = (0, asl_bridge_1.extractHostInfo)(resolvedUrl);
|
|
93
|
+
// Asserts hostname against active AsyncLocalStorage (ASL) network policy
|
|
94
|
+
(0, asl_bridge_1.assertNetworkPolicy)(name, resolvedUrl, hostname, port);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
(0, core_1.recordInspection)({ version: 1, kind: 'http', outcome: 'failure', method: options.method || 'GET',
|
|
98
|
+
url: typeof options.url === 'string' ? options.url : undefined,
|
|
99
|
+
policy: error?.name === 'NetworkPolicyViolationException' ? 'denied' : 'unknown' });
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
});
|
|
104
|
+
// 4. AFTER Phase: Safely attach telemetry if context is extensible
|
|
105
|
+
this.onAfter(async (output, ctx) => {
|
|
106
|
+
try {
|
|
107
|
+
if (output && output.$httpMetadata && ctx && typeof ctx === 'object') {
|
|
108
|
+
if (!Object.isFrozen(ctx) && Object.isExtensible(ctx)) {
|
|
109
|
+
if (!ctx.$steps) {
|
|
110
|
+
ctx.$steps = {};
|
|
111
|
+
}
|
|
112
|
+
if (!ctx.$steps[name]) {
|
|
113
|
+
ctx.$steps[name] = {};
|
|
114
|
+
}
|
|
115
|
+
ctx.$steps[name].httpMetadata = output.$httpMetadata;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// Ignore if context is immutable or sealed
|
|
121
|
+
}
|
|
122
|
+
return output;
|
|
123
|
+
});
|
|
124
|
+
// 5. COMPENSATION Phase: Register declarative saga compensation if configured
|
|
125
|
+
if (options.compensate) {
|
|
126
|
+
this.compensateWithHttp(options.compensate);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Declarative saga rollback compensation via HTTP request.
|
|
131
|
+
*/
|
|
132
|
+
compensateWithHttp(config) {
|
|
133
|
+
this.compensate(async (res, ctx) => {
|
|
134
|
+
const compUrl = typeof config.url === 'function' ? config.url(ctx, res) : config.url;
|
|
135
|
+
const compMethod = config.method || 'DELETE';
|
|
136
|
+
const compHeaders = typeof config.headers === 'function' ? config.headers(ctx, res) : (config.headers || {});
|
|
137
|
+
const compQuery = typeof config.query === 'function' ? config.query(ctx, res) : config.query;
|
|
138
|
+
const compBody = typeof config.body === 'function' ? config.body(ctx, res) : config.body;
|
|
139
|
+
// Verify ASL network policy for compensation endpoint
|
|
140
|
+
const { hostname, port } = (0, asl_bridge_1.extractHostInfo)(compUrl);
|
|
141
|
+
(0, asl_bridge_1.assertNetworkPolicy)(`${this.name}:compensate`, compUrl, hostname, port);
|
|
142
|
+
await (0, fetch_1.executeHttpRequest)({
|
|
143
|
+
stepName: `${this.name}:compensate`,
|
|
144
|
+
url: compUrl,
|
|
145
|
+
method: compMethod,
|
|
146
|
+
headers: compHeaders,
|
|
147
|
+
query: compQuery,
|
|
148
|
+
body: compBody,
|
|
149
|
+
clock: this.httpOptions.clock,
|
|
150
|
+
sleep: this.httpOptions.sleep,
|
|
151
|
+
retryOnStatus: this.httpOptions.retryOnStatus,
|
|
152
|
+
maxRetries: this.httpOptions.maxRetries
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
return this;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.HttpStep = HttpStep;
|
|
159
|
+
/**
|
|
160
|
+
* Creates a resilient, W3C-traced HTTP client step for Siglo workflows.
|
|
161
|
+
*/
|
|
162
|
+
function httpStep(name, options) {
|
|
163
|
+
return new HttpStep(name, options);
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=step.js.map
|