@bleedingdev/modern-js-bff-effect 3.9.0-ultramodern.3 → 3.9.0-ultramodern.5
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/cjs/assembly.js +50 -0
- package/dist/cjs/data-platform/trace.js +2 -2
- package/dist/cjs/effect/edge-dispatcher.js +7 -7
- package/dist/cjs/effect/edge.js +15 -2
- package/dist/cjs/effect/endpoint-contracts.js +2 -2
- package/dist/cjs/effect/generated-entry.js +57 -0
- package/dist/cjs/effect/handler/batch-handler.js +5 -4
- package/dist/cjs/effect/handler/batch.js +8 -1
- package/dist/cjs/effect/operation-context.js +7 -7
- package/dist/cjs/effect-client/index.js +2 -2
- package/dist/cjs/microvertical-api.js +120 -0
- package/dist/esm/assembly.mjs +12 -0
- package/dist/esm/data-platform/trace.mjs +1 -1
- package/dist/esm/effect/edge-dispatcher.mjs +5 -5
- package/dist/esm/effect/edge.mjs +1 -0
- package/dist/esm/effect/endpoint-contracts.mjs +1 -1
- package/dist/esm/effect/generated-entry.mjs +19 -0
- package/dist/esm/effect/handler/batch-handler.mjs +5 -4
- package/dist/esm/effect/handler/batch.mjs +8 -1
- package/dist/esm/effect/operation-context.mjs +1 -1
- package/dist/esm/effect-client/index.mjs +1 -1
- package/dist/esm/microvertical-api.mjs +67 -0
- package/dist/esm-node/assembly.mjs +13 -0
- package/dist/esm-node/data-platform/trace.mjs +1 -1
- package/dist/esm-node/effect/edge-dispatcher.mjs +5 -5
- package/dist/esm-node/effect/edge.mjs +1 -0
- package/dist/esm-node/effect/endpoint-contracts.mjs +1 -1
- package/dist/esm-node/effect/generated-entry.mjs +20 -0
- package/dist/esm-node/effect/handler/batch-handler.mjs +5 -4
- package/dist/esm-node/effect/handler/batch.mjs +8 -1
- package/dist/esm-node/effect/operation-context.mjs +1 -1
- package/dist/esm-node/effect-client/index.mjs +1 -1
- package/dist/esm-node/microvertical-api.mjs +68 -0
- package/dist/types/assembly.d.ts +10 -0
- package/dist/types/effect/context.d.ts +1 -1
- package/dist/types/effect/edge-context.d.ts +1 -1
- package/dist/types/effect/edge-dispatcher.d.ts +1 -1
- package/dist/types/effect/edge.d.ts +1 -0
- package/dist/types/effect/endpoint-contracts.d.ts +1 -1
- package/dist/types/effect/generated-entry.d.ts +7 -0
- package/dist/types/effect/handler/batch.d.ts +7 -1
- package/dist/types/effect/operation-context.d.ts +1 -1
- package/dist/types/effect-client/index.d.ts +1 -1
- package/dist/types/effect-client/types.d.ts +1 -1
- package/dist/types/microvertical-api.d.ts +65 -0
- package/package.json +30 -4
- package/src/assembly.ts +43 -0
- package/src/data-platform/batch/queue.ts +2 -3
- package/src/data-platform/trace.ts +1 -1
- package/src/effect/edge-dispatcher.ts +7 -4
- package/src/effect/edge.ts +1 -0
- package/src/effect/endpoint-contracts.ts +1 -1
- package/src/effect/entry-shape.ts +4 -1
- package/src/effect/generated-entry.ts +36 -0
- package/src/effect/handler/batch-handler.ts +21 -16
- package/src/effect/handler/batch.ts +9 -1
- package/src/effect/operation-context.ts +1 -1
- package/src/effect-client/index.ts +1 -1
- package/src/effect-client/types.ts +1 -1
- package/src/microvertical-api.ts +102 -0
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
evaluateCrossProjectPolicy,
|
|
4
4
|
type NormalizedCrossProjectPolicy,
|
|
5
5
|
resolveCrossProjectRequestObservation,
|
|
6
|
-
} from '@modern-js/
|
|
6
|
+
} from '@modern-js/server-runtime-extensions/bff-policy';
|
|
7
|
+
import * as Effect from 'effect/Effect';
|
|
7
8
|
import { toHeaderRecord } from '../headers';
|
|
8
9
|
import {
|
|
9
10
|
type DispatchEffectBffRequestOptions,
|
|
@@ -285,9 +286,11 @@ export async function createEffectBffEdgeDispatcher(
|
|
|
285
286
|
disposePromise ??= (async () => {
|
|
286
287
|
acceptingRequests = false;
|
|
287
288
|
if (activeDispatches > 0) {
|
|
288
|
-
await
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
await Effect.runPromise(
|
|
290
|
+
Effect.callback<void>(resume => {
|
|
291
|
+
resolveDrain = () => resume(Effect.void);
|
|
292
|
+
}),
|
|
293
|
+
);
|
|
291
294
|
}
|
|
292
295
|
await loaded.dispose?.();
|
|
293
296
|
})();
|
package/src/effect/edge.ts
CHANGED
|
@@ -42,8 +42,11 @@ function loadNodeValidatorAwareHandlerFactoryRegistry(): ValidatorAwareHandlerFa
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
declare const __MODERN_EFFECT_NODE_RUNTIME__: boolean;
|
|
46
|
+
|
|
45
47
|
const validatorAwareHandlerFactoryRegistry =
|
|
46
|
-
|
|
48
|
+
typeof __MODERN_EFFECT_NODE_RUNTIME__ !== 'undefined' &&
|
|
49
|
+
__MODERN_EFFECT_NODE_RUNTIME__
|
|
47
50
|
? loadNodeValidatorAwareHandlerFactoryRegistry()
|
|
48
51
|
: createLocalValidatorAwareHandlerFactoryRegistry();
|
|
49
52
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createEffectBffEdgeDispatcher,
|
|
3
|
+
type EffectBffEdgeHandlerOptions,
|
|
4
|
+
} from './edge-dispatcher';
|
|
5
|
+
|
|
6
|
+
type OperationContracts = NonNullable<
|
|
7
|
+
EffectBffEdgeHandlerOptions['crossProjectPolicy']
|
|
8
|
+
>['expectedOperationContracts'];
|
|
9
|
+
|
|
10
|
+
export function createEffectBffEdgeDispatcherFactory(
|
|
11
|
+
module: EffectBffEdgeHandlerOptions['module'],
|
|
12
|
+
generatedOperationContracts: OperationContracts,
|
|
13
|
+
) {
|
|
14
|
+
return (options?: Omit<EffectBffEdgeHandlerOptions, 'module'>) => {
|
|
15
|
+
const policy = options?.crossProjectPolicy;
|
|
16
|
+
const crossProjectPolicy =
|
|
17
|
+
policy === undefined ||
|
|
18
|
+
policy === null ||
|
|
19
|
+
policy.expectedOperationContracts === null ||
|
|
20
|
+
typeof policy.expectedOperationContracts !== 'object' ||
|
|
21
|
+
Array.isArray(policy.expectedOperationContracts)
|
|
22
|
+
? policy
|
|
23
|
+
: {
|
|
24
|
+
...policy,
|
|
25
|
+
expectedOperationContracts: {
|
|
26
|
+
...policy.expectedOperationContracts,
|
|
27
|
+
...generatedOperationContracts,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
return createEffectBffEdgeDispatcher({
|
|
31
|
+
...options,
|
|
32
|
+
crossProjectPolicy,
|
|
33
|
+
module,
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
|
|
2
|
+
import * as Effect from 'effect/Effect';
|
|
2
3
|
import {
|
|
3
4
|
type DataBatchResponsePayload,
|
|
4
5
|
DEFAULT_DATA_BATCH_HEADER,
|
|
@@ -417,14 +418,16 @@ export function createDataPlatformBatchRequestHandler<TContext>(options: {
|
|
|
417
418
|
);
|
|
418
419
|
} catch (error) {
|
|
419
420
|
if (error instanceof BatchItemTimeoutError) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
421
|
+
Effect.runSync(
|
|
422
|
+
Effect.logError({
|
|
423
|
+
event: 'bff.batch.item.timeout',
|
|
424
|
+
batchId: payload.batchId,
|
|
425
|
+
itemId,
|
|
426
|
+
method: itemMethod,
|
|
427
|
+
path: itemPathname,
|
|
428
|
+
errorName: error.name,
|
|
429
|
+
}),
|
|
430
|
+
);
|
|
428
431
|
return toBatchItemError(
|
|
429
432
|
itemId,
|
|
430
433
|
504,
|
|
@@ -435,14 +438,16 @@ export function createDataPlatformBatchRequestHandler<TContext>(options: {
|
|
|
435
438
|
return toBatchResponseItem(itemId, error, itemMethod === 'HEAD');
|
|
436
439
|
}
|
|
437
440
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
441
|
+
Effect.runSync(
|
|
442
|
+
Effect.logError({
|
|
443
|
+
event: 'bff.batch.item.failure',
|
|
444
|
+
batchId: payload.batchId,
|
|
445
|
+
itemId,
|
|
446
|
+
method: itemMethod,
|
|
447
|
+
path: itemPathname,
|
|
448
|
+
errorName: error instanceof Error ? error.name : 'UnknownError',
|
|
449
|
+
}),
|
|
450
|
+
);
|
|
446
451
|
return toBatchItemError(itemId, 500, 'Internal Server Error');
|
|
447
452
|
} finally {
|
|
448
453
|
request.signal.removeEventListener('abort', abortFromBatchRequest);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @effect-diagnostics anyUnknownInErrorContext:off asyncFunction:off globalDate:off globalTimers:off newPromise:off strictBooleanExpressions:off
|
|
2
2
|
|
|
3
|
+
import * as Data from 'effect/Data';
|
|
3
4
|
import {
|
|
4
5
|
type DataBatchRequestPayload,
|
|
5
6
|
type DataBatchResponseItem,
|
|
@@ -117,7 +118,14 @@ export function toBatchItemError(
|
|
|
117
118
|
};
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
export class BatchItemTimeoutError extends
|
|
121
|
+
export class BatchItemTimeoutError extends Data.TaggedError(
|
|
122
|
+
'BatchItemTimeoutError',
|
|
123
|
+
)<{ readonly message: string }> {
|
|
124
|
+
constructor(message: string) {
|
|
125
|
+
super({ message });
|
|
126
|
+
this.name = 'Error';
|
|
127
|
+
}
|
|
128
|
+
}
|
|
121
129
|
|
|
122
130
|
export function promiseWithTimeout<T>(
|
|
123
131
|
effect: Promise<T>,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createRequestContextHeaders,
|
|
4
4
|
type RequestContextInput,
|
|
5
|
-
} from '@modern-js/
|
|
5
|
+
} from '@modern-js/runtime-extensions/request-context';
|
|
6
6
|
import * as Data from 'effect/Data';
|
|
7
7
|
import * as Effect from 'effect/Effect';
|
|
8
8
|
import * as Exit from 'effect/Exit';
|
|
@@ -59,7 +59,7 @@ export type EffectRequestContext = {
|
|
|
59
59
|
headers: Record<string, string>;
|
|
60
60
|
} & Record<string, unknown>;
|
|
61
61
|
|
|
62
|
-
/** Structural slice of `@modern-js/
|
|
62
|
+
/** Structural slice of `@modern-js/runtime-extensions/request-policy` the runtime relies on. */
|
|
63
63
|
export type EffectRequestRuntime = {
|
|
64
64
|
createRequest: (options: {
|
|
65
65
|
path: string;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Schema } from 'effect';
|
|
2
|
+
|
|
3
|
+
const MicroVerticalAppIdSchema = Schema.String.pipe(
|
|
4
|
+
Schema.brand('MicroVerticalAppId'),
|
|
5
|
+
Schema.decodeTo(Schema.String),
|
|
6
|
+
);
|
|
7
|
+
const MicroVerticalUnitIdSchema = Schema.String.pipe(
|
|
8
|
+
Schema.brand('MicroVerticalUnitId'),
|
|
9
|
+
Schema.decodeTo(Schema.String),
|
|
10
|
+
);
|
|
11
|
+
const MicroVerticalOperationIdSchema = Schema.String.pipe(
|
|
12
|
+
Schema.brand('MicroVerticalOperationId'),
|
|
13
|
+
Schema.decodeTo(Schema.String),
|
|
14
|
+
);
|
|
15
|
+
const MicroVerticalTraceIdSchema = Schema.String.pipe(
|
|
16
|
+
Schema.brand('MicroVerticalTraceId'),
|
|
17
|
+
Schema.decodeTo(Schema.String),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const MicroVerticalBuildMarkerSchema = Schema.Struct({
|
|
21
|
+
appId: MicroVerticalAppIdSchema,
|
|
22
|
+
build: Schema.String,
|
|
23
|
+
buildMarker: Schema.String,
|
|
24
|
+
deployProfile: Schema.String,
|
|
25
|
+
packageName: Schema.String,
|
|
26
|
+
sourceRevision: Schema.String,
|
|
27
|
+
surface: Schema.String,
|
|
28
|
+
unitId: MicroVerticalUnitIdSchema,
|
|
29
|
+
version: Schema.String,
|
|
30
|
+
});
|
|
31
|
+
export type MicroVerticalBuildMarker =
|
|
32
|
+
typeof MicroVerticalBuildMarkerSchema.Type;
|
|
33
|
+
|
|
34
|
+
export const MicroVerticalReadinessSchema = Schema.Struct({
|
|
35
|
+
checks: Schema.Struct({
|
|
36
|
+
api: Schema.Literal('ready'),
|
|
37
|
+
moduleFederation: Schema.Literal('ready'),
|
|
38
|
+
ssr: Schema.Literal('ready'),
|
|
39
|
+
translations: Schema.Literal('ready'),
|
|
40
|
+
}),
|
|
41
|
+
marker: MicroVerticalBuildMarkerSchema,
|
|
42
|
+
status: Schema.Literal('ready'),
|
|
43
|
+
versionSkew: Schema.Literal('none'),
|
|
44
|
+
});
|
|
45
|
+
export type MicroVerticalReadiness = typeof MicroVerticalReadinessSchema.Type;
|
|
46
|
+
|
|
47
|
+
export const MicroVerticalOperationSourceSchema = Schema.Literals([
|
|
48
|
+
'client',
|
|
49
|
+
'server',
|
|
50
|
+
'generated-client',
|
|
51
|
+
'effect-adapter',
|
|
52
|
+
'data-platform',
|
|
53
|
+
'unknown',
|
|
54
|
+
]);
|
|
55
|
+
export type MicroVerticalOperationSource =
|
|
56
|
+
typeof MicroVerticalOperationSourceSchema.Type;
|
|
57
|
+
|
|
58
|
+
export const MicroVerticalOperationContextSchema = Schema.Struct({
|
|
59
|
+
method: Schema.String,
|
|
60
|
+
operationId: MicroVerticalOperationIdSchema,
|
|
61
|
+
routePath: Schema.String,
|
|
62
|
+
source: MicroVerticalOperationSourceSchema,
|
|
63
|
+
traceId: Schema.optionalKey(MicroVerticalTraceIdSchema),
|
|
64
|
+
});
|
|
65
|
+
export type MicroVerticalOperationContext =
|
|
66
|
+
typeof MicroVerticalOperationContextSchema.Type;
|
|
67
|
+
|
|
68
|
+
export const createMicroVerticalOperationContext = <
|
|
69
|
+
const Method extends string,
|
|
70
|
+
const OperationId extends string,
|
|
71
|
+
const RoutePath extends string,
|
|
72
|
+
>(input: {
|
|
73
|
+
readonly method: Method;
|
|
74
|
+
readonly operationId: OperationId;
|
|
75
|
+
readonly routePath: RoutePath;
|
|
76
|
+
// eslint-disable-next-line effect-native/no-threaded-correlation-parameter -- This pure browser-safe contract deliberately carries optional trace metadata; it does not perform ambient request work.
|
|
77
|
+
readonly traceId?: string;
|
|
78
|
+
}): Readonly<typeof input & { source: 'generated-client' }> => {
|
|
79
|
+
const context = {
|
|
80
|
+
method: input.method,
|
|
81
|
+
operationId: input.operationId,
|
|
82
|
+
routePath: input.routePath,
|
|
83
|
+
source: 'generated-client' as const,
|
|
84
|
+
};
|
|
85
|
+
return input.traceId === undefined
|
|
86
|
+
? context
|
|
87
|
+
: { ...context, traceId: input.traceId };
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const microVerticalOperationAttributes = (
|
|
91
|
+
operationContext: MicroVerticalOperationContext,
|
|
92
|
+
) => {
|
|
93
|
+
const attributes = {
|
|
94
|
+
'modernjs.operation.id': operationContext.operationId,
|
|
95
|
+
'modernjs.operation.method': operationContext.method,
|
|
96
|
+
'modernjs.operation.route': operationContext.routePath,
|
|
97
|
+
'modernjs.operation.source': operationContext.source,
|
|
98
|
+
};
|
|
99
|
+
return operationContext.traceId === undefined
|
|
100
|
+
? attributes
|
|
101
|
+
: { ...attributes, 'modernjs.trace.id': operationContext.traceId };
|
|
102
|
+
};
|