@bleedingdev/modern-js-runtime-extensions 3.9.0-ultramodern.9 → 3.9.3-ultramodern.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/dist/cjs/{reactContext.js → localisedUrls/config.js} +14 -10
- package/dist/cjs/localisedUrls/index.js +95 -0
- package/dist/cjs/localisedUrls/normalise.js +87 -0
- package/dist/cjs/localisedUrls/pathname.js +68 -0
- package/dist/cjs/localisedUrls/patterns.js +214 -0
- package/dist/cjs/localisedUrls/redirect.js +104 -0
- package/dist/cjs/localisedUrls/resolve.js +78 -0
- package/dist/cjs/localisedUrls/routeIdentity.js +92 -0
- package/dist/cjs/localisedUrls/routes.js +217 -0
- package/dist/cjs/localisedUrls/types.js +18 -0
- package/dist/cjs/rendererHead.js +18 -5
- package/dist/cjs/request-policy/policyCore.js +1 -1
- package/dist/cjs/request-policy/transport.js +2 -2
- package/dist/cjs/routerState.js +85 -77
- package/dist/cjs/routerStatePlugin.js +63 -9
- package/dist/esm/localisedUrls/config.mjs +11 -0
- package/dist/esm/localisedUrls/index.mjs +8 -0
- package/dist/esm/localisedUrls/normalise.mjs +37 -0
- package/dist/esm/localisedUrls/pathname.mjs +24 -0
- package/dist/esm/localisedUrls/patterns.mjs +152 -0
- package/dist/esm/localisedUrls/redirect.mjs +57 -0
- package/dist/esm/localisedUrls/resolve.mjs +37 -0
- package/dist/esm/localisedUrls/routeIdentity.mjs +54 -0
- package/dist/esm/localisedUrls/routes.mjs +176 -0
- package/dist/esm/localisedUrls/types.mjs +0 -0
- package/dist/esm/rendererHead.mjs +14 -5
- package/dist/esm/request-policy/policyCore.mjs +1 -1
- package/dist/esm/request-policy/transport.mjs +2 -2
- package/dist/esm/routerState.mjs +81 -73
- package/dist/esm/routerStatePlugin.mjs +62 -11
- package/dist/esm-node/localisedUrls/config.mjs +12 -0
- package/dist/esm-node/localisedUrls/index.mjs +9 -0
- package/dist/esm-node/localisedUrls/normalise.mjs +38 -0
- package/dist/esm-node/localisedUrls/pathname.mjs +25 -0
- package/dist/esm-node/localisedUrls/patterns.mjs +153 -0
- package/dist/esm-node/localisedUrls/redirect.mjs +58 -0
- package/dist/esm-node/localisedUrls/resolve.mjs +38 -0
- package/dist/esm-node/localisedUrls/routeIdentity.mjs +55 -0
- package/dist/esm-node/localisedUrls/routes.mjs +177 -0
- package/dist/esm-node/localisedUrls/types.mjs +1 -0
- package/dist/esm-node/rendererHead.mjs +14 -5
- package/dist/esm-node/request-policy/policyCore.mjs +1 -1
- package/dist/esm-node/request-policy/transport.mjs +2 -2
- package/dist/esm-node/routerState.mjs +81 -73
- package/dist/esm-node/routerStatePlugin.mjs +62 -11
- package/dist/types/helmetCompat.d.ts +1 -1
- package/dist/types/localisedUrls/config.d.ts +9 -0
- package/dist/types/localisedUrls/index.d.ts +10 -0
- package/dist/types/localisedUrls/normalise.d.ts +10 -0
- package/dist/types/localisedUrls/pathname.d.ts +4 -0
- package/dist/types/localisedUrls/patterns.d.ts +11 -0
- package/dist/types/localisedUrls/redirect.d.ts +19 -0
- package/dist/types/localisedUrls/resolve.d.ts +7 -0
- package/dist/types/localisedUrls/routeIdentity.d.ts +22 -0
- package/dist/types/localisedUrls/routes.d.ts +3 -0
- package/dist/types/localisedUrls/types.d.ts +14 -0
- package/dist/types/rendererHead.d.ts +5 -3
- package/dist/types/request-policy/types.d.ts +1 -1
- package/dist/types/routeHydration.d.ts +2 -2
- package/dist/types/routerProvider.d.ts +1 -3
- package/dist/types/routerState.d.ts +11 -6
- package/dist/types/routerStatePlugin.d.ts +12 -0
- package/dist/types/routerStateTypes.d.ts +47 -17
- package/package.json +42 -44
- package/src/helmetCompat.ts +1 -1
- package/src/localisedUrls/config.ts +18 -0
- package/src/localisedUrls/index.ts +25 -0
- package/src/localisedUrls/normalise.ts +62 -0
- package/src/localisedUrls/pathname.ts +60 -0
- package/src/localisedUrls/patterns.ts +283 -0
- package/src/localisedUrls/redirect.ts +110 -0
- package/src/localisedUrls/resolve.ts +106 -0
- package/src/localisedUrls/routeIdentity.ts +83 -0
- package/src/localisedUrls/routes.ts +451 -0
- package/src/localisedUrls/types.ts +18 -0
- package/src/rendererHead.ts +25 -8
- package/src/request-policy/policyCore.ts +1 -1
- package/src/request-policy/transport.ts +2 -2
- package/src/request-policy/types.ts +1 -1
- package/src/routeHydration.ts +2 -2
- package/src/routerProvider.ts +1 -1
- package/src/routerState.ts +127 -115
- package/src/routerStatePlugin.ts +106 -10
- package/src/routerStateTypes.ts +47 -17
- package/dist/cjs/buildIdentity.js +0 -73
- package/dist/esm/buildIdentity.mjs +0 -35
- package/dist/esm/reactContext.mjs +0 -7
- package/dist/esm-node/buildIdentity.mjs +0 -36
- package/dist/esm-node/reactContext.mjs +0 -8
- package/dist/types/buildIdentity.d.ts +0 -37
- package/dist/types/reactContext.d.ts +0 -6
- package/rslib.config.mts +0 -19
- package/rstest.config.mts +0 -38
- package/src/buildIdentity.ts +0 -61
- package/src/reactContext.ts +0 -16
- package/tests/buildIdentity.test.ts +0 -51
- package/tests/contextExtensions.test.ts +0 -27
- package/tests/headRuntime.test.tsx +0 -229
- package/tests/rendererHead.test.ts +0 -187
- package/tests/request-policy/browser-policy.test.ts +0 -108
- package/tests/request-policy/client-isolation.test.ts +0 -109
- package/tests/request-policy/node-policy.test.ts +0 -447
- package/tests/request-policy/policyCore.test.ts +0 -129
- package/tests/request-policy/requestContext.test.ts +0 -66
- package/tests/request-policy/requestFactory.outbound-contract.test.ts +0 -290
- package/tests/request-policy/traceparent.test.ts +0 -52
- package/tests/request-policy/transport-retry.test.ts +0 -367
- package/tests/routeHydration.test.ts +0 -180
- package/tests/routerPrefetchPolicy.test.ts +0 -102
- package/tests/routerProvider.test.ts +0 -29
- package/tests/routerState.test.ts +0 -78
- package/tests/routerStatePlugin.test.ts +0 -63
- package/tests/runtimeContextProjection.test.ts +0 -83
- package/tests/safeFailure.test.ts +0 -136
- package/tests/shellStream.test.ts +0 -122
- package/tests/workspaceEvents.test.ts +0 -221
- package/tsconfig.json +0 -10
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import { PassThrough, Readable } from 'node:stream';
|
|
2
|
-
import {
|
|
3
|
-
abortHeadRender,
|
|
4
|
-
beginHeadRender,
|
|
5
|
-
collectHeadRecord,
|
|
6
|
-
completeHeadRender,
|
|
7
|
-
createHeadChunkProcessor,
|
|
8
|
-
} from '../src';
|
|
9
|
-
import { createNodeHeadMarkerStripper, pipeNodeHeadStream } from '../src/node';
|
|
10
|
-
|
|
11
|
-
const marker = (props: Record<string, string>) =>
|
|
12
|
-
`<template data-modern-helmet="${props['data-modern-helmet']}"></template>`;
|
|
13
|
-
|
|
14
|
-
describe('renderer head transactions', () => {
|
|
15
|
-
it('commits only markers observed in completed output', () => {
|
|
16
|
-
const context = {};
|
|
17
|
-
let published: string[] = [];
|
|
18
|
-
beginHeadRender(context);
|
|
19
|
-
const committed = collectHeadRecord(
|
|
20
|
-
context,
|
|
21
|
-
() => 'committed',
|
|
22
|
-
records => {
|
|
23
|
-
published = records;
|
|
24
|
-
},
|
|
25
|
-
)!;
|
|
26
|
-
collectHeadRecord(
|
|
27
|
-
context,
|
|
28
|
-
() => 'abandoned',
|
|
29
|
-
records => {
|
|
30
|
-
published = records;
|
|
31
|
-
},
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
expect(completeHeadRender(context, `a${marker(committed)}b`)).toBe('ab');
|
|
35
|
-
expect(published).toEqual(['committed']);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('preserves user templates that are not current transaction markers', () => {
|
|
39
|
-
const context = {};
|
|
40
|
-
beginHeadRender(context);
|
|
41
|
-
const userTemplate =
|
|
42
|
-
'<template data-modern-helmet="h00000000-0000-0000-0000-000000000000000000000000"></template>';
|
|
43
|
-
|
|
44
|
-
expect(completeHeadRender(context, userTemplate)).toBe(userTemplate);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('strips markers split across chunks without corrupting unicode', () => {
|
|
48
|
-
const sampleContext = {};
|
|
49
|
-
beginHeadRender(sampleContext);
|
|
50
|
-
const sampleProps = collectHeadRecord(
|
|
51
|
-
sampleContext,
|
|
52
|
-
() => 'head',
|
|
53
|
-
() => {},
|
|
54
|
-
)!;
|
|
55
|
-
const sampleHtml = `č${marker(sampleProps)}尾`;
|
|
56
|
-
|
|
57
|
-
for (let split = 1; split < sampleHtml.length; split += 1) {
|
|
58
|
-
const context = {};
|
|
59
|
-
beginHeadRender(context);
|
|
60
|
-
const props = collectHeadRecord(
|
|
61
|
-
context,
|
|
62
|
-
() => 'head',
|
|
63
|
-
() => {},
|
|
64
|
-
)!;
|
|
65
|
-
const html = `č${marker(props)}尾`;
|
|
66
|
-
const processor = createHeadChunkProcessor(context);
|
|
67
|
-
expect(
|
|
68
|
-
processor.push(html.slice(0, split)) +
|
|
69
|
-
processor.finish(html.slice(split)),
|
|
70
|
-
).toBe('č尾');
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('clears the previous snapshot while rendering and restores it on abort', () => {
|
|
75
|
-
const context = {};
|
|
76
|
-
let published: string[] = [];
|
|
77
|
-
const publish = (records: string[]) => {
|
|
78
|
-
published = records;
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
beginHeadRender(context);
|
|
82
|
-
const previous = collectHeadRecord(context, () => 'previous', publish)!;
|
|
83
|
-
completeHeadRender(context, marker(previous));
|
|
84
|
-
expect(published).toEqual(['previous']);
|
|
85
|
-
|
|
86
|
-
beginHeadRender(context);
|
|
87
|
-
expect(published).toEqual([]);
|
|
88
|
-
collectHeadRecord(context, () => 'provisional', publish);
|
|
89
|
-
abortHeadRender(context);
|
|
90
|
-
expect(published).toEqual(['previous']);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('strips split markers from a Node stream', async () => {
|
|
94
|
-
const context = {};
|
|
95
|
-
let published: string[] = [];
|
|
96
|
-
beginHeadRender(context);
|
|
97
|
-
const props = collectHeadRecord(
|
|
98
|
-
context,
|
|
99
|
-
() => 'node',
|
|
100
|
-
records => {
|
|
101
|
-
published = records;
|
|
102
|
-
},
|
|
103
|
-
)!;
|
|
104
|
-
const html = `č${marker(props)}尾`;
|
|
105
|
-
const encoded = Buffer.from(html);
|
|
106
|
-
const stripper = createNodeHeadMarkerStripper(context);
|
|
107
|
-
const output = new Promise<string>((resolve, reject) => {
|
|
108
|
-
let rendered = '';
|
|
109
|
-
stripper.setEncoding('utf8');
|
|
110
|
-
stripper.on('data', chunk => {
|
|
111
|
-
rendered += chunk;
|
|
112
|
-
});
|
|
113
|
-
stripper.on('end', () => resolve(rendered));
|
|
114
|
-
stripper.on('error', reject);
|
|
115
|
-
});
|
|
116
|
-
stripper.write(encoded.subarray(0, 1));
|
|
117
|
-
stripper.write(encoded.subarray(1, 17));
|
|
118
|
-
stripper.end(encoded.subarray(17));
|
|
119
|
-
|
|
120
|
-
await expect(output).resolves.toBe('č尾');
|
|
121
|
-
expect(published).toEqual(['node']);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('injects one missing terminal marker without truncating multichunk UTF-8', async () => {
|
|
125
|
-
const context = {};
|
|
126
|
-
const terminalMarker = '<!-- shell stream end -->';
|
|
127
|
-
const prefix = Buffer.from('x'.repeat(9 * 1024));
|
|
128
|
-
const unicodeTail = Buffer.from('č尾');
|
|
129
|
-
const input = Buffer.concat([prefix, unicodeTail]);
|
|
130
|
-
beginHeadRender(context);
|
|
131
|
-
const stripper = createNodeHeadMarkerStripper(context, terminalMarker);
|
|
132
|
-
const output = new Promise<string>((resolve, reject) => {
|
|
133
|
-
let rendered = '';
|
|
134
|
-
stripper.setEncoding('utf8');
|
|
135
|
-
stripper.on('data', chunk => {
|
|
136
|
-
rendered += chunk;
|
|
137
|
-
});
|
|
138
|
-
stripper.on('end', () => resolve(rendered));
|
|
139
|
-
stripper.on('error', reject);
|
|
140
|
-
});
|
|
141
|
-
stripper.write(input.subarray(0, prefix.length + 1));
|
|
142
|
-
stripper.write(input.subarray(prefix.length + 1, prefix.length + 3));
|
|
143
|
-
stripper.end(input.subarray(prefix.length + 3));
|
|
144
|
-
|
|
145
|
-
await expect(output).resolves.toBe(
|
|
146
|
-
`${input.toString('utf8')}${terminalMarker}`,
|
|
147
|
-
);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('does not duplicate a split terminal marker or corrupt its tail', async () => {
|
|
151
|
-
const context = {};
|
|
152
|
-
const terminalMarker = '<!-- shell stream end -->';
|
|
153
|
-
const input = Buffer.from(`shell${terminalMarker}č尾`);
|
|
154
|
-
const markerOffset = Buffer.byteLength('shell') + 7;
|
|
155
|
-
beginHeadRender(context);
|
|
156
|
-
const stripper = createNodeHeadMarkerStripper(context, terminalMarker);
|
|
157
|
-
const output = new Promise<string>((resolve, reject) => {
|
|
158
|
-
let rendered = '';
|
|
159
|
-
stripper.setEncoding('utf8');
|
|
160
|
-
stripper.on('data', chunk => {
|
|
161
|
-
rendered += chunk;
|
|
162
|
-
});
|
|
163
|
-
stripper.on('end', () => resolve(rendered));
|
|
164
|
-
stripper.on('error', reject);
|
|
165
|
-
});
|
|
166
|
-
stripper.write(input.subarray(0, markerOffset));
|
|
167
|
-
stripper.write(input.subarray(markerOffset, input.length - 1));
|
|
168
|
-
stripper.end(input.subarray(input.length - 1));
|
|
169
|
-
|
|
170
|
-
await expect(output).resolves.toBe(input.toString('utf8'));
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('rejects the destination and reports a source error exactly once', async () => {
|
|
174
|
-
const source = new PassThrough();
|
|
175
|
-
const destination = new PassThrough();
|
|
176
|
-
const output = new Response(
|
|
177
|
-
Readable.toWeb(destination) as ReadableStream<Uint8Array>,
|
|
178
|
-
).text();
|
|
179
|
-
const onError = rstest.fn();
|
|
180
|
-
pipeNodeHeadStream({ source, destination, context: {}, onError });
|
|
181
|
-
|
|
182
|
-
source.destroy(new Error('source failed'));
|
|
183
|
-
|
|
184
|
-
await expect(output).rejects.toThrow('source failed');
|
|
185
|
-
expect(onError).toHaveBeenCalledTimes(1);
|
|
186
|
-
});
|
|
187
|
-
});
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
configure,
|
|
3
|
-
createRequest,
|
|
4
|
-
} from '@modern-js/runtime-extensions/request-policy/client';
|
|
5
|
-
import nock from 'nock';
|
|
6
|
-
|
|
7
|
-
describe('configure', () => {
|
|
8
|
-
const path = '/api';
|
|
9
|
-
const method = 'GET';
|
|
10
|
-
const response = {
|
|
11
|
-
code: 200,
|
|
12
|
-
data: {
|
|
13
|
-
message: 'hello Modernjs',
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
test('should allow explicit cross-origin policy and attach envelope header', async () => {
|
|
18
|
-
const producer = 'producer-browser-policy';
|
|
19
|
-
const producerUrl = 'https://producer.internal';
|
|
20
|
-
const previousEnv = process.env.NODE_ENV;
|
|
21
|
-
process.env.NODE_ENV = 'production';
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
nock(producerUrl).get(path).reply(200, response);
|
|
25
|
-
const customRequest = rs.fn(
|
|
26
|
-
(requestPath: RequestInfo, init?: RequestInit) =>
|
|
27
|
-
fetch(requestPath, init),
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
configure({
|
|
31
|
-
request: customRequest,
|
|
32
|
-
requestId: producer,
|
|
33
|
-
operationContract: {
|
|
34
|
-
enabled: false,
|
|
35
|
-
},
|
|
36
|
-
setDomain: () => producerUrl,
|
|
37
|
-
allowCrossOriginEnvelope: true,
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const request = createRequest(
|
|
41
|
-
path,
|
|
42
|
-
method,
|
|
43
|
-
8080,
|
|
44
|
-
undefined,
|
|
45
|
-
undefined,
|
|
46
|
-
producer,
|
|
47
|
-
);
|
|
48
|
-
const res = await request();
|
|
49
|
-
|
|
50
|
-
const headers = customRequest.mock.calls[0][1].headers as Record<
|
|
51
|
-
string,
|
|
52
|
-
string
|
|
53
|
-
>;
|
|
54
|
-
const envelope = JSON.parse(headers['x-modernjs-bff-envelope']);
|
|
55
|
-
expect(envelope.requestId).toBe(producer);
|
|
56
|
-
expect(envelope.target).toBe('browser');
|
|
57
|
-
expect(res instanceof Response).toBe(true);
|
|
58
|
-
} finally {
|
|
59
|
-
process.env.NODE_ENV = previousEnv;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('should not require process to exist in browser runtime', async () => {
|
|
64
|
-
const previousProcess = globalThis.process;
|
|
65
|
-
const customRequest = rs.fn(() =>
|
|
66
|
-
Promise.resolve(
|
|
67
|
-
new Response(
|
|
68
|
-
JSON.stringify({
|
|
69
|
-
code: 200,
|
|
70
|
-
data: {
|
|
71
|
-
message: 'ok',
|
|
72
|
-
},
|
|
73
|
-
}),
|
|
74
|
-
),
|
|
75
|
-
),
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
Object.defineProperty(globalThis, 'process', {
|
|
80
|
-
configurable: true,
|
|
81
|
-
value: undefined,
|
|
82
|
-
});
|
|
83
|
-
configure({
|
|
84
|
-
request: customRequest,
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
const request = createRequest({
|
|
88
|
-
path,
|
|
89
|
-
method,
|
|
90
|
-
port: 8080,
|
|
91
|
-
});
|
|
92
|
-
const response = await request();
|
|
93
|
-
const data = await response.json();
|
|
94
|
-
|
|
95
|
-
expect(data).toStrictEqual({
|
|
96
|
-
code: 200,
|
|
97
|
-
data: {
|
|
98
|
-
message: 'ok',
|
|
99
|
-
},
|
|
100
|
-
});
|
|
101
|
-
} finally {
|
|
102
|
-
Object.defineProperty(globalThis, 'process', {
|
|
103
|
-
configurable: true,
|
|
104
|
-
value: previousProcess,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
});
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { createClient as createNativeClient } from '@modern-js/create-request/server';
|
|
2
|
-
import * as server from '@modern-js/runtime-extensions/request-policy/server';
|
|
3
|
-
|
|
4
|
-
const options = {
|
|
5
|
-
path: '/api',
|
|
6
|
-
method: 'GET',
|
|
7
|
-
port: 8080,
|
|
8
|
-
requestId: 'shared-producer',
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
describe('isolated producer policy clients', () => {
|
|
12
|
-
test('does not share producer initialization or request configuration between instances', async () => {
|
|
13
|
-
const first = server.createClient();
|
|
14
|
-
const second = server.createClient();
|
|
15
|
-
const firstRequest = rs.fn(async () => new Response('first'));
|
|
16
|
-
const secondRequest = rs.fn(async () => new Response('second'));
|
|
17
|
-
first.configure({
|
|
18
|
-
requestId: options.requestId,
|
|
19
|
-
request: firstRequest,
|
|
20
|
-
setDomain: () => 'https://first.example',
|
|
21
|
-
operationContract: { enabled: false },
|
|
22
|
-
});
|
|
23
|
-
expect(() => second.createRequest(options)()).toThrow(
|
|
24
|
-
server.ProducerClientNotInitializedError,
|
|
25
|
-
);
|
|
26
|
-
second.configure({
|
|
27
|
-
requestId: options.requestId,
|
|
28
|
-
request: secondRequest,
|
|
29
|
-
setDomain: () => 'https://second.example',
|
|
30
|
-
operationContract: { enabled: false },
|
|
31
|
-
});
|
|
32
|
-
expect(await (await first.createRequest(options)()).text()).toBe('first');
|
|
33
|
-
expect(await (await second.createRequest(options)()).text()).toBe('second');
|
|
34
|
-
expect(firstRequest).toHaveBeenCalledWith(
|
|
35
|
-
'https://first.example/api',
|
|
36
|
-
expect.any(Object),
|
|
37
|
-
);
|
|
38
|
-
expect(secondRequest).toHaveBeenCalledWith(
|
|
39
|
-
'https://second.example/api',
|
|
40
|
-
expect.any(Object),
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('does not initialize producer policy by configuring a separate native client', () => {
|
|
45
|
-
createNativeClient().configure({
|
|
46
|
-
requestId: options.requestId,
|
|
47
|
-
request: rs.fn(),
|
|
48
|
-
});
|
|
49
|
-
const producer = server.createClient();
|
|
50
|
-
expect(() => producer.createRequest(options)()).toThrow(
|
|
51
|
-
server.ProducerClientNotInitializedError,
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('retains secured behavior for an explicitly empty requestId', () => {
|
|
56
|
-
const client = server.createClient();
|
|
57
|
-
const request = rs.fn();
|
|
58
|
-
client.configure({
|
|
59
|
-
requestId: '',
|
|
60
|
-
request,
|
|
61
|
-
setDomain: () => 'https://producer.example',
|
|
62
|
-
});
|
|
63
|
-
expect(() => client.createRequest({ ...options, requestId: '' })()).toThrow(
|
|
64
|
-
server.OperationContractViolationError,
|
|
65
|
-
);
|
|
66
|
-
expect(request).not.toHaveBeenCalled();
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
test('calls setDomain once after interceptor and keeps native and policy state on rejection', async () => {
|
|
70
|
-
const client = server.createClient();
|
|
71
|
-
const order: string[] = [];
|
|
72
|
-
const request = rs.fn(async () => new Response('original'));
|
|
73
|
-
const setDomain = rs.fn(() => {
|
|
74
|
-
order.push('domain');
|
|
75
|
-
return 'https://original.example';
|
|
76
|
-
});
|
|
77
|
-
client.configure({
|
|
78
|
-
requestId: options.requestId,
|
|
79
|
-
interceptor: () => {
|
|
80
|
-
order.push('interceptor');
|
|
81
|
-
return request;
|
|
82
|
-
},
|
|
83
|
-
setDomain,
|
|
84
|
-
requireEnvelope: false,
|
|
85
|
-
operationContract: { enabled: false },
|
|
86
|
-
});
|
|
87
|
-
const replacement = rs.fn();
|
|
88
|
-
expect(() =>
|
|
89
|
-
client.configure({
|
|
90
|
-
requestId: options.requestId,
|
|
91
|
-
request: replacement,
|
|
92
|
-
setDomain: () => '',
|
|
93
|
-
}),
|
|
94
|
-
).toThrow(server.ProducerDomainNotConfiguredError);
|
|
95
|
-
const response = await client.createRequest(options)();
|
|
96
|
-
expect(await response.text()).toBe('original');
|
|
97
|
-
expect(order).toEqual(['interceptor', 'domain']);
|
|
98
|
-
expect(setDomain).toHaveBeenCalledTimes(1);
|
|
99
|
-
expect(request).toHaveBeenCalledWith(
|
|
100
|
-
'https://original.example/api',
|
|
101
|
-
expect.objectContaining({
|
|
102
|
-
headers: expect.not.objectContaining({
|
|
103
|
-
'x-modernjs-bff-envelope': expect.anything(),
|
|
104
|
-
}),
|
|
105
|
-
}),
|
|
106
|
-
);
|
|
107
|
-
expect(replacement).not.toHaveBeenCalled();
|
|
108
|
-
});
|
|
109
|
-
});
|