@bleedingdev/modern-js-bff-core 3.5.0-ultramodern.4 → 3.5.0-ultramodern.41
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/adapter-kit/index.js +6 -2
- package/dist/cjs/adapter-kit/parity-scenarios/cross-project-denial.js +55 -0
- package/dist/cjs/adapter-kit/parity-scenarios/envelope.js +128 -0
- package/dist/cjs/adapter-kit/parity-scenarios/operation-context.js +158 -0
- package/dist/cjs/adapter-kit/parity-scenarios/schema.js +109 -0
- package/dist/cjs/adapter-kit/parity-scenarios/shared.js +71 -0
- package/dist/cjs/adapter-kit/parity.js +26 -368
- package/dist/cjs/index.js +29 -48
- package/dist/cjs/operators/http.js +2 -2
- package/dist/cjs/security/crossProjectPolicy.js +123 -62
- package/dist/esm/adapter-kit/index.mjs +6 -2
- package/dist/esm/adapter-kit/parity-scenarios/cross-project-denial.mjs +17 -0
- package/dist/esm/adapter-kit/parity-scenarios/envelope.mjs +90 -0
- package/dist/esm/adapter-kit/parity-scenarios/operation-context.mjs +117 -0
- package/dist/esm/adapter-kit/parity-scenarios/schema.mjs +71 -0
- package/dist/esm/adapter-kit/parity-scenarios/shared.mjs +21 -0
- package/dist/esm/adapter-kit/parity.mjs +19 -361
- package/dist/esm/index.mjs +0 -1
- package/dist/esm/operators/http.mjs +2 -2
- package/dist/esm/security/crossProjectPolicy.mjs +123 -62
- package/dist/esm/security/operationContracts.mjs +2 -2
- package/dist/esm-node/adapter-kit/index.mjs +6 -2
- package/dist/esm-node/adapter-kit/parity-scenarios/cross-project-denial.mjs +18 -0
- package/dist/esm-node/adapter-kit/parity-scenarios/envelope.mjs +91 -0
- package/dist/esm-node/adapter-kit/parity-scenarios/operation-context.mjs +118 -0
- package/dist/esm-node/adapter-kit/parity-scenarios/schema.mjs +72 -0
- package/dist/esm-node/adapter-kit/parity-scenarios/shared.mjs +22 -0
- package/dist/esm-node/adapter-kit/parity.mjs +19 -361
- package/dist/esm-node/index.mjs +0 -1
- package/dist/esm-node/operators/http.mjs +2 -2
- package/dist/esm-node/security/crossProjectPolicy.mjs +123 -62
- package/dist/types/adapter-kit/index.d.ts +2 -2
- package/dist/types/adapter-kit/parity-scenarios/cross-project-denial.d.ts +2 -0
- package/dist/types/adapter-kit/parity-scenarios/envelope.d.ts +2 -0
- package/dist/types/adapter-kit/parity-scenarios/operation-context.d.ts +3 -0
- package/dist/types/adapter-kit/parity-scenarios/schema.d.ts +2 -0
- package/dist/types/adapter-kit/parity-scenarios/shared.d.ts +32 -0
- package/dist/types/adapter-kit/parity.d.ts +12 -71
- package/dist/types/index.d.ts +0 -1
- package/dist/types/operators/http.d.ts +1 -1
- package/dist/types/security/crossProjectPolicy.d.ts +17 -8
- package/package.json +9 -9
- package/dist/cjs/contracts/eventContracts.js +0 -72
- package/dist/esm/contracts/eventContracts.mjs +0 -28
- package/dist/esm-node/contracts/eventContracts.mjs +0 -29
- package/dist/types/contracts/eventContracts.d.ts +0 -22
|
@@ -3,7 +3,7 @@ import type { ResponseMeta } from '../operators/http';
|
|
|
3
3
|
import type { APIHandlerInfo, ApiHandler } from '../router';
|
|
4
4
|
import { type CrossProjectPolicyConfig, type CrossProjectPolicyViolation } from '../security/crossProjectPolicy';
|
|
5
5
|
import { HttpMethod } from '../types';
|
|
6
|
-
/** Lowercase route-registration method shared by
|
|
6
|
+
/** Lowercase route-registration method shared by supported adapter routers. */
|
|
7
7
|
export type ApiRouteMethod = Lowercase<`${HttpMethod}`>;
|
|
8
8
|
/**
|
|
9
9
|
* Maps an `APIHandlerInfo.httpMethod` onto the lowercase router method.
|
|
@@ -74,7 +74,7 @@ export type ApiHandlerInput = {
|
|
|
74
74
|
* Positional invocation convention for plain function handlers: route params
|
|
75
75
|
* in declaration order followed by the full input object.
|
|
76
76
|
*/
|
|
77
|
-
export declare const buildPositionalHandlerArgs: (input: ApiHandlerInput) => unknown[];
|
|
77
|
+
export declare const buildPositionalHandlerArgs: (input: ApiHandlerInput, routePath?: string) => unknown[];
|
|
78
78
|
export type CrossProjectPolicyDenial = {
|
|
79
79
|
status: number;
|
|
80
80
|
body: {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { AdapterParityScenario, AdapterParityScenarioContext } from './shared';
|
|
2
|
+
export declare const createOperationContextSuccessScenarios: ({ helloContract, validEnvelope, validOperationId, }: AdapterParityScenarioContext) => AdapterParityScenario[];
|
|
3
|
+
export declare const createOperationContextDenialScenarios: ({ helloContract, validEnvelope, validOperationId, }: AdapterParityScenarioContext) => AdapterParityScenario[];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CrossProjectOperationContract, CrossProjectPolicyViolationReason } from '../../security/crossProjectPolicy';
|
|
2
|
+
export declare const PARITY_REQUEST_ID = "crm";
|
|
3
|
+
export declare const PARITY_PRODUCER_REQUEST_ID = "crm.producer-a";
|
|
4
|
+
export type ParityExpectation = {
|
|
5
|
+
kind: 'payload';
|
|
6
|
+
status: number;
|
|
7
|
+
payload: unknown;
|
|
8
|
+
} | {
|
|
9
|
+
kind: 'denied';
|
|
10
|
+
status: number;
|
|
11
|
+
reason: CrossProjectPolicyViolationReason;
|
|
12
|
+
};
|
|
13
|
+
export type AdapterParityScenario = {
|
|
14
|
+
name: string;
|
|
15
|
+
/** Run against policy-enabled server instead of the open one. */
|
|
16
|
+
policy: boolean;
|
|
17
|
+
request: {
|
|
18
|
+
method: 'get' | 'post' | 'patch';
|
|
19
|
+
path: string;
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
body?: unknown;
|
|
22
|
+
};
|
|
23
|
+
expected: ParityExpectation;
|
|
24
|
+
};
|
|
25
|
+
export type AdapterParityScenarioContext = {
|
|
26
|
+
helloContract: CrossProjectOperationContract;
|
|
27
|
+
validEnvelope: string;
|
|
28
|
+
validOperationId: string;
|
|
29
|
+
};
|
|
30
|
+
export declare const envelopeHeader: (requestId: unknown) => string;
|
|
31
|
+
export declare const detailHeader: (details: Record<string, unknown>) => string;
|
|
32
|
+
export declare const deniedScenario: (name: string, reason: CrossProjectPolicyViolationReason, headers: Record<string, string>) => AdapterParityScenario;
|
|
@@ -1,84 +1,25 @@
|
|
|
1
1
|
import type { APIHandlerInfo } from '../router';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* One shared table of scenarios executed against every BFF server adapter
|
|
7
|
-
* in its own test harness. Each scenario asserts the adapters produce
|
|
8
|
-
* identical observable results: HTTP status, payload value and
|
|
9
|
-
* policy-rejection reason.
|
|
10
|
-
*
|
|
11
|
-
* The express/koa adapters were removed from the fork, and this is internal
|
|
12
|
-
* test support rather than a package subpath. Their expectations are retained
|
|
13
|
-
* in the per-adapter drift pins as documentation of the historical behavior.
|
|
14
|
-
* The live executable consumer of this table is the hono lane test
|
|
15
|
-
* (`@modern-js/plugin-bff` runs it against `createHonoRoutes` plus the
|
|
16
|
-
* cross-project policy middleware), while bff-core tests validate the table
|
|
17
|
-
* shape and assertion helpers.
|
|
18
|
-
*
|
|
19
|
-
* Transport details intentionally NOT asserted: express serialized scalar
|
|
20
|
-
* bodies as JSON while koa sent `text/plain`; {@link toParityResult}
|
|
21
|
-
* normalizes both to the decoded payload value before comparison.
|
|
22
|
-
*
|
|
23
|
-
* Intentionally OUT OF SCOPE (known, accepted adapter drift — do not add
|
|
24
|
-
* scenarios without deciding the drift first):
|
|
25
|
-
* - operator route-middlewares: express applied them, koa ignored them;
|
|
26
|
-
* - multipart/form-data: payload shapes differ per body parser;
|
|
27
|
-
* - undefined-returning plain handlers are pinned via a per-adapter
|
|
28
|
-
* scenario below: express ended the response 200/empty, koa served its
|
|
29
|
-
* stock 404 ("Not Found"), hono serves its stock "404 Not Found";
|
|
30
|
-
* - farrow schema-mode handlers are pinned per-adapter below: express/koa
|
|
31
|
-
* unwrapped the result envelope (200/400/500), the hono lane has no
|
|
32
|
-
* schema-mode unwrapping and passes the raw envelope through.
|
|
33
|
-
*/
|
|
34
|
-
export declare const PARITY_REQUEST_ID = "crm";
|
|
35
|
-
export declare const PARITY_PRODUCER_REQUEST_ID = "crm.producer-a";
|
|
2
|
+
import type { AdapterParityScenario } from './parity-scenarios/shared';
|
|
3
|
+
export type { AdapterParityScenario, ParityExpectation, } from './parity-scenarios/shared';
|
|
4
|
+
export { PARITY_PRODUCER_REQUEST_ID, PARITY_REQUEST_ID, } from './parity-scenarios/shared';
|
|
36
5
|
/**
|
|
37
6
|
* Handler fixtures registered in both adapters before running the table.
|
|
38
7
|
*/
|
|
39
8
|
export declare const createParityApiHandlerInfos: () => APIHandlerInfo[];
|
|
40
9
|
/**
|
|
41
|
-
* `bff` config slice for
|
|
42
|
-
* switches stay at
|
|
10
|
+
* `bff` config slice for policy-enabled parity server. All `require*`
|
|
11
|
+
* switches stay at strict defaults.
|
|
43
12
|
*/
|
|
44
13
|
export declare const createParityBffConfig: () => {
|
|
45
14
|
requestId: string;
|
|
46
15
|
crossProjectPolicy: {
|
|
47
16
|
enabled: boolean;
|
|
48
17
|
allowedNamespaces: string[];
|
|
18
|
+
allowClientAssertedNamespace: boolean;
|
|
49
19
|
};
|
|
50
20
|
};
|
|
51
|
-
export type ParityAdapterId = 'express' | 'koa' | 'hono';
|
|
52
|
-
export type ParityExpectation = {
|
|
53
|
-
kind: 'payload';
|
|
54
|
-
status: number;
|
|
55
|
-
payload: unknown;
|
|
56
|
-
} | {
|
|
57
|
-
kind: 'denied';
|
|
58
|
-
status: number;
|
|
59
|
-
reason: CrossProjectPolicyViolationReason;
|
|
60
|
-
} | {
|
|
61
|
-
/** Pinned, intentional adapter drift: each adapter has its own expectation. */
|
|
62
|
-
kind: 'perAdapter';
|
|
63
|
-
expectations: Record<ParityAdapterId, {
|
|
64
|
-
status: number;
|
|
65
|
-
payload: unknown;
|
|
66
|
-
}>;
|
|
67
|
-
};
|
|
68
|
-
export type AdapterParityScenario = {
|
|
69
|
-
name: string;
|
|
70
|
-
/** Run against the policy-enabled server instead of the open one. */
|
|
71
|
-
policy: boolean;
|
|
72
|
-
request: {
|
|
73
|
-
method: 'get' | 'post' | 'patch';
|
|
74
|
-
path: string;
|
|
75
|
-
headers?: Record<string, string>;
|
|
76
|
-
body?: unknown;
|
|
77
|
-
};
|
|
78
|
-
expected: ParityExpectation;
|
|
79
|
-
};
|
|
80
21
|
export declare const createAdapterParityScenarios: () => AdapterParityScenario[];
|
|
81
|
-
/** Structural slice of
|
|
22
|
+
/** Structural slice of supertest response used for normalization. */
|
|
82
23
|
export type ParityHttpResponse = {
|
|
83
24
|
status: number;
|
|
84
25
|
/** Content-type mime, e.g. `application/json`. */
|
|
@@ -86,17 +27,17 @@ export type ParityHttpResponse = {
|
|
|
86
27
|
body: unknown;
|
|
87
28
|
text: string;
|
|
88
29
|
};
|
|
89
|
-
|
|
30
|
+
type AdapterParityResult = {
|
|
90
31
|
status: number;
|
|
91
32
|
payload: unknown;
|
|
92
33
|
};
|
|
93
34
|
/**
|
|
94
|
-
* Normalizes
|
|
95
|
-
*
|
|
35
|
+
* Normalizes raw HTTP response into an observable payload value so JSON and
|
|
36
|
+
* text encodings of the same scalar compare equal.
|
|
96
37
|
*/
|
|
97
38
|
export declare const toParityResult: (res: ParityHttpResponse) => AdapterParityResult;
|
|
98
39
|
/**
|
|
99
|
-
* Framework-agnostic assertion: throws a descriptive error when
|
|
40
|
+
* Framework-agnostic assertion: throws a descriptive error when adapter
|
|
100
41
|
* response deviates from the scenario expectation.
|
|
101
42
|
*/
|
|
102
|
-
export declare const assertParityResult: (scenario: AdapterParityScenario, res: ParityHttpResponse
|
|
43
|
+
export declare const assertParityResult: (scenario: AdapterParityScenario, res: ParityHttpResponse) => void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ export * from './adapter-kit';
|
|
|
2
2
|
export { Api } from './api';
|
|
3
3
|
export * from './client';
|
|
4
4
|
export type * from './compatible';
|
|
5
|
-
export * from './contracts/eventContracts';
|
|
6
5
|
export { HttpError, ValidationError } from './errors/http';
|
|
7
6
|
export * from './operators/http';
|
|
8
7
|
export * from './router';
|
|
@@ -38,7 +38,7 @@ export declare const HttpCode: (statusCode: number) => Operator<void>;
|
|
|
38
38
|
export declare const SetHeaders: (headers: Record<string, string>) => Operator<void>;
|
|
39
39
|
export declare const Redirect: (url: string) => Operator<void>;
|
|
40
40
|
export declare const Upload: <Schema extends z.ZodType>(urlPath: string, schema?: Schema) => Operator<{
|
|
41
|
-
|
|
41
|
+
formData: z.input<Schema>;
|
|
42
42
|
}, {
|
|
43
43
|
formData: z.output<Schema>;
|
|
44
44
|
}>;
|
|
@@ -10,14 +10,16 @@
|
|
|
10
10
|
* authorization boundary: any caller can echo an allowed `requestId` and a
|
|
11
11
|
* matching operation context.
|
|
12
12
|
*
|
|
13
|
-
* To
|
|
13
|
+
* To use `allowedNamespaces`, supply
|
|
14
14
|
* {@link CrossProjectPolicyConfig.verifyProducerIdentity}: a server-side
|
|
15
15
|
* hook that derives the producer namespace from a VERIFIED channel (mTLS
|
|
16
16
|
* peer identity, gateway-authenticated JWT claims, service-mesh headers
|
|
17
|
-
* stripped at the edge, ...).
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* stripped at the edge, ...). Requests fail closed when a namespace allowlist
|
|
18
|
+
* is configured without this hook unless `allowClientAssertedNamespace` is
|
|
19
|
+
* explicitly enabled. That escape hatch keeps legacy local/demo ergonomics:
|
|
20
|
+
* the client-asserted namespace must match the allowlist. When the hook is
|
|
21
|
+
* present, the client-asserted namespace must match the verified namespace
|
|
22
|
+
* and the allowlist is checked against the verified value.
|
|
21
23
|
*
|
|
22
24
|
* Client-side counterparts in `@modern-js/create-request` (identity binding,
|
|
23
25
|
* operation contract validation) are developer-experience aids that fail
|
|
@@ -46,6 +48,12 @@ export interface CrossProjectPolicyConfig {
|
|
|
46
48
|
requireOperationSchemaHash?: boolean;
|
|
47
49
|
requireOperationVersion?: boolean;
|
|
48
50
|
allowedNamespaces?: string[];
|
|
51
|
+
/**
|
|
52
|
+
* Explicit local/demo escape hatch for legacy clients that only provide
|
|
53
|
+
* client-built requestId namespaces. Defaults to false. Enabling this keeps
|
|
54
|
+
* `allowedNamespaces` advisory and must not be used as authorization.
|
|
55
|
+
*/
|
|
56
|
+
allowClientAssertedNamespace?: boolean;
|
|
49
57
|
envelopeHeader?: string;
|
|
50
58
|
operationContextHeader?: string;
|
|
51
59
|
operationContextDetailHeader?: string;
|
|
@@ -53,7 +61,7 @@ export interface CrossProjectPolicyConfig {
|
|
|
53
61
|
allowUnknownOperations?: boolean;
|
|
54
62
|
denyStatus?: number;
|
|
55
63
|
/**
|
|
56
|
-
* Server-side hook binding
|
|
64
|
+
* Server-side hook binding producer namespace to VERIFIED identity
|
|
57
65
|
* channel (mTLS peer, gateway-authenticated JWT, mesh identity headers).
|
|
58
66
|
*
|
|
59
67
|
* When provided, the namespace asserted by the client envelope must match
|
|
@@ -61,8 +69,9 @@ export interface CrossProjectPolicyConfig {
|
|
|
61
69
|
* against the verified value instead of the client-asserted one. Returning
|
|
62
70
|
* `undefined` (identity could not be verified) denies the request.
|
|
63
71
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
72
|
+
* By default, `allowedNamespaces` requires this hook and fails closed
|
|
73
|
+
* without it. Set `allowClientAssertedNamespace` only for local/demo
|
|
74
|
+
* ergonomics where advisory client-asserted namespace checks are acceptable.
|
|
66
75
|
*/
|
|
67
76
|
verifyProducerIdentity?: (headers: Record<string, unknown>) => string | undefined;
|
|
68
77
|
}
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"modern",
|
|
18
18
|
"modern.js"
|
|
19
19
|
],
|
|
20
|
-
"version": "3.5.0-ultramodern.
|
|
20
|
+
"version": "3.5.0-ultramodern.41",
|
|
21
21
|
"types": "./dist/types/index.d.ts",
|
|
22
22
|
"main": "./dist/cjs/index.js",
|
|
23
23
|
"exports": {
|
|
@@ -35,19 +35,19 @@
|
|
|
35
35
|
"@swc/helpers": "^0.5.23",
|
|
36
36
|
"koa-compose": "^4.1.0",
|
|
37
37
|
"reflect-metadata": "^0.2.2",
|
|
38
|
-
"type-fest": "5.
|
|
39
|
-
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.
|
|
38
|
+
"type-fest": "5.8.0",
|
|
39
|
+
"@modern-js/utils": "npm:@bleedingdev/modern-js-utils@3.5.0-ultramodern.41"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@rslib/core": "0.23.
|
|
42
|
+
"@rslib/core": "0.23.2",
|
|
43
43
|
"@types/koa-compose": "^3.2.9",
|
|
44
|
-
"@types/node": "^26.
|
|
45
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
44
|
+
"@types/node": "^26.1.1",
|
|
45
|
+
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
46
46
|
"tsconfig-paths": "^4.2.0",
|
|
47
47
|
"zod": "^4.4.3",
|
|
48
|
-
"@modern-js/bff-runtime": "npm:@bleedingdev/modern-js-bff-runtime@3.5.0-ultramodern.
|
|
49
|
-
"@
|
|
50
|
-
"@
|
|
48
|
+
"@modern-js/bff-runtime": "npm:@bleedingdev/modern-js-bff-runtime@3.5.0-ultramodern.41",
|
|
49
|
+
"@scripts/rstest-config": "2.66.0",
|
|
50
|
+
"@modern-js/types": "npm:@bleedingdev/modern-js-types@3.5.0-ultramodern.41"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"tsconfig-paths": "^4.2.0",
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __webpack_require__ = {};
|
|
3
|
-
(()=>{
|
|
4
|
-
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
-
var define = (defs, kind)=>{
|
|
6
|
-
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
[kind]: defs[key]
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
define(getters, "get");
|
|
12
|
-
define(values, "value");
|
|
13
|
-
};
|
|
14
|
-
})();
|
|
15
|
-
(()=>{
|
|
16
|
-
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
-
})();
|
|
18
|
-
(()=>{
|
|
19
|
-
__webpack_require__.r = (exports1)=>{
|
|
20
|
-
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
-
value: 'Module'
|
|
22
|
-
});
|
|
23
|
-
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
-
value: true
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
})();
|
|
28
|
-
var __webpack_exports__ = {};
|
|
29
|
-
__webpack_require__.r(__webpack_exports__);
|
|
30
|
-
const defineEventContract = (input)=>{
|
|
31
|
-
const normalizedName = input.name.trim();
|
|
32
|
-
if (!normalizedName) throw new Error('Event contract name must be non-empty');
|
|
33
|
-
if (!Number.isFinite(input.version) || input.version <= 0) throw new Error('Event contract version must be a positive number');
|
|
34
|
-
if (!input.schemaHash || !input.schemaHash.trim()) throw new Error('Event contract schemaHash must be non-empty');
|
|
35
|
-
return {
|
|
36
|
-
name: normalizedName,
|
|
37
|
-
version: Math.floor(input.version),
|
|
38
|
-
schemaHash: input.schemaHash.trim(),
|
|
39
|
-
description: input.description
|
|
40
|
-
};
|
|
41
|
-
};
|
|
42
|
-
const createEventEnvelope = (contract, payload, meta)=>({
|
|
43
|
-
name: contract.name,
|
|
44
|
-
version: contract.version,
|
|
45
|
-
schemaHash: contract.schemaHash,
|
|
46
|
-
timestamp: Date.now(),
|
|
47
|
-
payload,
|
|
48
|
-
...meta ? {
|
|
49
|
-
meta
|
|
50
|
-
} : {}
|
|
51
|
-
});
|
|
52
|
-
const isEventEnvelope = (value)=>{
|
|
53
|
-
if (!value || 'object' != typeof value || Array.isArray(value)) return false;
|
|
54
|
-
const candidate = value;
|
|
55
|
-
return 'string' == typeof candidate.name && candidate.name.length > 0 && 'number' == typeof candidate.version && candidate.version > 0 && 'string' == typeof candidate.schemaHash && candidate.schemaHash.length > 0 && 'number' == typeof candidate.timestamp && Number.isFinite(candidate.timestamp) && 'payload' in candidate;
|
|
56
|
-
};
|
|
57
|
-
__webpack_require__.d(__webpack_exports__, {}, {
|
|
58
|
-
createEventEnvelope: createEventEnvelope,
|
|
59
|
-
defineEventContract: defineEventContract,
|
|
60
|
-
isEventEnvelope: isEventEnvelope
|
|
61
|
-
});
|
|
62
|
-
exports.createEventEnvelope = __webpack_exports__.createEventEnvelope;
|
|
63
|
-
exports.defineEventContract = __webpack_exports__.defineEventContract;
|
|
64
|
-
exports.isEventEnvelope = __webpack_exports__.isEventEnvelope;
|
|
65
|
-
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
66
|
-
"createEventEnvelope",
|
|
67
|
-
"defineEventContract",
|
|
68
|
-
"isEventEnvelope"
|
|
69
|
-
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
70
|
-
Object.defineProperty(exports, '__esModule', {
|
|
71
|
-
value: true
|
|
72
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const defineEventContract = (input)=>{
|
|
2
|
-
const normalizedName = input.name.trim();
|
|
3
|
-
if (!normalizedName) throw new Error('Event contract name must be non-empty');
|
|
4
|
-
if (!Number.isFinite(input.version) || input.version <= 0) throw new Error('Event contract version must be a positive number');
|
|
5
|
-
if (!input.schemaHash || !input.schemaHash.trim()) throw new Error('Event contract schemaHash must be non-empty');
|
|
6
|
-
return {
|
|
7
|
-
name: normalizedName,
|
|
8
|
-
version: Math.floor(input.version),
|
|
9
|
-
schemaHash: input.schemaHash.trim(),
|
|
10
|
-
description: input.description
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
const createEventEnvelope = (contract, payload, meta)=>({
|
|
14
|
-
name: contract.name,
|
|
15
|
-
version: contract.version,
|
|
16
|
-
schemaHash: contract.schemaHash,
|
|
17
|
-
timestamp: Date.now(),
|
|
18
|
-
payload,
|
|
19
|
-
...meta ? {
|
|
20
|
-
meta
|
|
21
|
-
} : {}
|
|
22
|
-
});
|
|
23
|
-
const isEventEnvelope = (value)=>{
|
|
24
|
-
if (!value || 'object' != typeof value || Array.isArray(value)) return false;
|
|
25
|
-
const candidate = value;
|
|
26
|
-
return 'string' == typeof candidate.name && candidate.name.length > 0 && 'number' == typeof candidate.version && candidate.version > 0 && 'string' == typeof candidate.schemaHash && candidate.schemaHash.length > 0 && 'number' == typeof candidate.timestamp && Number.isFinite(candidate.timestamp) && 'payload' in candidate;
|
|
27
|
-
};
|
|
28
|
-
export { createEventEnvelope, defineEventContract, isEventEnvelope };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import "node:module";
|
|
2
|
-
const defineEventContract = (input)=>{
|
|
3
|
-
const normalizedName = input.name.trim();
|
|
4
|
-
if (!normalizedName) throw new Error('Event contract name must be non-empty');
|
|
5
|
-
if (!Number.isFinite(input.version) || input.version <= 0) throw new Error('Event contract version must be a positive number');
|
|
6
|
-
if (!input.schemaHash || !input.schemaHash.trim()) throw new Error('Event contract schemaHash must be non-empty');
|
|
7
|
-
return {
|
|
8
|
-
name: normalizedName,
|
|
9
|
-
version: Math.floor(input.version),
|
|
10
|
-
schemaHash: input.schemaHash.trim(),
|
|
11
|
-
description: input.description
|
|
12
|
-
};
|
|
13
|
-
};
|
|
14
|
-
const createEventEnvelope = (contract, payload, meta)=>({
|
|
15
|
-
name: contract.name,
|
|
16
|
-
version: contract.version,
|
|
17
|
-
schemaHash: contract.schemaHash,
|
|
18
|
-
timestamp: Date.now(),
|
|
19
|
-
payload,
|
|
20
|
-
...meta ? {
|
|
21
|
-
meta
|
|
22
|
-
} : {}
|
|
23
|
-
});
|
|
24
|
-
const isEventEnvelope = (value)=>{
|
|
25
|
-
if (!value || 'object' != typeof value || Array.isArray(value)) return false;
|
|
26
|
-
const candidate = value;
|
|
27
|
-
return 'string' == typeof candidate.name && candidate.name.length > 0 && 'number' == typeof candidate.version && candidate.version > 0 && 'string' == typeof candidate.schemaHash && candidate.schemaHash.length > 0 && 'number' == typeof candidate.timestamp && Number.isFinite(candidate.timestamp) && 'payload' in candidate;
|
|
28
|
-
};
|
|
29
|
-
export { createEventEnvelope, defineEventContract, isEventEnvelope };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export type EventContract<Name extends string = string, Payload = unknown> = {
|
|
2
|
-
name: Name;
|
|
3
|
-
version: number;
|
|
4
|
-
schemaHash: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
};
|
|
7
|
-
export type EventEnvelope<TContract extends EventContract = EventContract, TMeta extends Record<string, unknown> = Record<string, unknown>> = {
|
|
8
|
-
name: TContract['name'];
|
|
9
|
-
version: TContract['version'];
|
|
10
|
-
schemaHash: TContract['schemaHash'];
|
|
11
|
-
timestamp: number;
|
|
12
|
-
payload: TContract extends EventContract<string, infer TPayload> ? TPayload : unknown;
|
|
13
|
-
meta?: TMeta;
|
|
14
|
-
};
|
|
15
|
-
export declare const defineEventContract: <Name extends string, Payload = unknown>(input: {
|
|
16
|
-
name: Name;
|
|
17
|
-
version: number;
|
|
18
|
-
schemaHash: string;
|
|
19
|
-
description?: string;
|
|
20
|
-
}) => EventContract<Name, Payload>;
|
|
21
|
-
export declare const createEventEnvelope: <TContract extends EventContract, TMeta extends Record<string, unknown> = Record<string, unknown>>(contract: TContract, payload: TContract extends EventContract<string, infer TPayload> ? TPayload : unknown, meta?: TMeta) => EventEnvelope<TContract, TMeta>;
|
|
22
|
-
export declare const isEventEnvelope: (value: unknown) => value is EventEnvelope<EventContract, Record<string, unknown>>;
|