@bleedingdev/modern-js-runtime-extensions 3.9.0-ultramodern.4 → 3.9.0-ultramodern.6

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.
Files changed (155) hide show
  1. package/dist/cjs/contextExtensions.js +74 -0
  2. package/dist/cjs/headRuntime.js +91 -0
  3. package/dist/cjs/helmetContext.js +54 -0
  4. package/dist/cjs/index.js +18 -4
  5. package/dist/cjs/prefetchPolicy.js +52 -0
  6. package/dist/cjs/request-policy/browser.js +139 -0
  7. package/dist/cjs/request-policy/client.js +234 -0
  8. package/dist/cjs/request-policy/node.js +149 -0
  9. package/dist/cjs/request-policy/policyCore.js +266 -0
  10. package/dist/cjs/request-policy/requestContext.js +137 -0
  11. package/dist/cjs/request-policy/traceparent.js +56 -0
  12. package/dist/cjs/request-policy/transport.js +234 -0
  13. package/dist/cjs/request-policy/types.js +57 -0
  14. package/dist/cjs/routeHydration.js +127 -0
  15. package/dist/cjs/routerPrefetchPolicy.js +153 -0
  16. package/dist/cjs/routerProvider.js +105 -0
  17. package/dist/cjs/routerState.js +167 -0
  18. package/dist/cjs/routerStatePlugin.js +86 -0
  19. package/dist/cjs/routerStateTypes.js +18 -0
  20. package/dist/cjs/runtimeContextProjection.js +112 -0
  21. package/dist/cjs/server-config/bffRuntime.js +18 -0
  22. package/dist/cjs/server-config/index.js +18 -0
  23. package/dist/cjs/server-config/serverTelemetry.js +18 -0
  24. package/dist/cjs/shellStream.js +34 -2
  25. package/dist/cjs/workspaceEvents.js +159 -0
  26. package/dist/esm/contextExtensions.mjs +33 -0
  27. package/dist/esm/headRuntime.mjs +43 -0
  28. package/dist/esm/helmetContext.mjs +13 -0
  29. package/dist/esm/index.mjs +2 -0
  30. package/dist/esm/prefetchPolicy.mjs +11 -0
  31. package/dist/esm/request-policy/browser.mjs +11 -0
  32. package/dist/esm/request-policy/client.mjs +195 -0
  33. package/dist/esm/request-policy/policyCore.mjs +171 -0
  34. package/dist/esm/request-policy/requestContext.mjs +75 -0
  35. package/dist/esm/request-policy/traceparent.mjs +18 -0
  36. package/dist/esm/request-policy/transport.mjs +196 -0
  37. package/dist/esm/request-policy/types.mjs +10 -0
  38. package/dist/esm/routeHydration.mjs +77 -0
  39. package/dist/esm/routerPrefetchPolicy.mjs +115 -0
  40. package/dist/esm/routerProvider.mjs +58 -0
  41. package/dist/esm/routerState.mjs +105 -0
  42. package/dist/esm/routerStatePlugin.mjs +48 -0
  43. package/dist/esm/routerStateTypes.mjs +0 -0
  44. package/dist/esm/runtimeContextProjection.mjs +74 -0
  45. package/dist/esm/server-config/bffRuntime.mjs +0 -0
  46. package/dist/esm/server-config/index.mjs +0 -0
  47. package/dist/esm/server-config/serverTelemetry.mjs +0 -0
  48. package/dist/esm/shellStream.mjs +34 -2
  49. package/dist/esm/workspaceEvents.mjs +66 -0
  50. package/dist/esm-node/contextExtensions.mjs +34 -0
  51. package/dist/esm-node/headRuntime.mjs +44 -0
  52. package/dist/esm-node/helmetContext.mjs +14 -0
  53. package/dist/esm-node/index.mjs +2 -0
  54. package/dist/esm-node/prefetchPolicy.mjs +12 -0
  55. package/dist/esm-node/request-policy/browser.mjs +12 -0
  56. package/dist/esm-node/request-policy/client.mjs +196 -0
  57. package/dist/esm-node/request-policy/node.mjs +22 -0
  58. package/dist/esm-node/request-policy/policyCore.mjs +172 -0
  59. package/dist/esm-node/request-policy/requestContext.mjs +76 -0
  60. package/dist/esm-node/request-policy/traceparent.mjs +19 -0
  61. package/dist/esm-node/request-policy/transport.mjs +197 -0
  62. package/dist/esm-node/request-policy/types.mjs +11 -0
  63. package/dist/esm-node/routeHydration.mjs +78 -0
  64. package/dist/esm-node/routerPrefetchPolicy.mjs +116 -0
  65. package/dist/esm-node/routerProvider.mjs +59 -0
  66. package/dist/esm-node/routerState.mjs +106 -0
  67. package/dist/esm-node/routerStatePlugin.mjs +49 -0
  68. package/dist/esm-node/routerStateTypes.mjs +1 -0
  69. package/dist/esm-node/runtimeContextProjection.mjs +75 -0
  70. package/dist/esm-node/server-config/bffRuntime.mjs +1 -0
  71. package/dist/esm-node/server-config/index.mjs +1 -0
  72. package/dist/esm-node/server-config/serverTelemetry.mjs +1 -0
  73. package/dist/esm-node/shellStream.mjs +34 -2
  74. package/dist/esm-node/workspaceEvents.mjs +67 -0
  75. package/dist/types/contextExtensions.d.ts +34 -0
  76. package/dist/types/headRuntime.d.ts +12 -0
  77. package/dist/types/helmetContext.d.ts +10 -0
  78. package/dist/types/index.d.ts +2 -0
  79. package/dist/types/prefetchPolicy.d.ts +4 -0
  80. package/dist/types/request-policy/browser.d.ts +10 -0
  81. package/dist/types/request-policy/client.d.ts +14 -0
  82. package/dist/types/request-policy/node.d.ts +10 -0
  83. package/dist/types/request-policy/policyCore.d.ts +107 -0
  84. package/dist/types/request-policy/requestContext.d.ts +22 -0
  85. package/dist/types/request-policy/traceparent.d.ts +10 -0
  86. package/dist/types/request-policy/transport.d.ts +12 -0
  87. package/dist/types/request-policy/types.d.ts +144 -0
  88. package/dist/types/routeHydration.d.ts +24 -0
  89. package/dist/types/routerPrefetchPolicy.d.ts +28 -0
  90. package/dist/types/routerProvider.d.ts +55 -0
  91. package/dist/types/routerState.d.ts +12 -0
  92. package/dist/types/routerStatePlugin.d.ts +19 -0
  93. package/dist/types/routerStateTypes.d.ts +40 -0
  94. package/dist/types/runtimeContextProjection.d.ts +30 -0
  95. package/dist/types/server-config/bffRuntime.d.ts +122 -0
  96. package/dist/types/server-config/index.d.ts +2 -0
  97. package/dist/types/server-config/serverTelemetry.d.ts +322 -0
  98. package/dist/types/workspaceEvents.d.ts +62 -0
  99. package/package.json +198 -13
  100. package/rslib.config.mts +17 -2
  101. package/rstest.config.mts +33 -2
  102. package/src/contextExtensions.ts +81 -0
  103. package/src/headRuntime.tsx +77 -0
  104. package/src/helmetContext.ts +31 -0
  105. package/src/index.ts +2 -0
  106. package/src/prefetchPolicy.ts +33 -0
  107. package/src/request-policy/browser.ts +22 -0
  108. package/src/request-policy/client.ts +404 -0
  109. package/src/request-policy/node.ts +41 -0
  110. package/src/request-policy/policyCore.ts +424 -0
  111. package/src/request-policy/requestContext.ts +149 -0
  112. package/src/request-policy/traceparent.ts +43 -0
  113. package/src/request-policy/transport.ts +349 -0
  114. package/src/request-policy/types.ts +229 -0
  115. package/src/routeHydration.ts +208 -0
  116. package/src/routerPrefetchPolicy.ts +195 -0
  117. package/src/routerProvider.ts +160 -0
  118. package/src/routerState.ts +208 -0
  119. package/src/routerStatePlugin.ts +86 -0
  120. package/src/routerStateTypes.ts +46 -0
  121. package/src/runtimeContextProjection.ts +105 -0
  122. package/src/server-config/bffRuntime.ts +136 -0
  123. package/src/server-config/index.ts +2 -0
  124. package/src/server-config/serverTelemetry.ts +337 -0
  125. package/src/shellStream.ts +55 -25
  126. package/src/workspaceEvents.ts +324 -0
  127. package/tests/buildIdentity.test.ts +2 -4
  128. package/tests/contextExtensions.test.ts +71 -0
  129. package/tests/headRuntime.test.tsx +369 -0
  130. package/tests/nativeSafeFailureCompatibility.test.ts +117 -0
  131. package/tests/prefetchPolicy.test.ts +51 -0
  132. package/tests/rendererHead.test.ts +1 -72
  133. package/tests/request-policy/browser-policy.test.ts +608 -0
  134. package/tests/request-policy/client-isolation.test.ts +149 -0
  135. package/tests/request-policy/identityBinding.test.ts +75 -0
  136. package/tests/request-policy/node-policy.test.ts +741 -0
  137. package/tests/request-policy/policyCore.test.ts +250 -0
  138. package/tests/request-policy/requestContext.test.ts +80 -0
  139. package/tests/request-policy/requestFactory.outbound-contract.test.ts +691 -0
  140. package/tests/request-policy/traceparent.test.ts +55 -0
  141. package/tests/request-policy/transport-retry.test.ts +370 -0
  142. package/tests/routeHydration.test.ts +180 -0
  143. package/tests/routerPrefetchPolicy.test.ts +102 -0
  144. package/tests/routerProvider.test.ts +29 -0
  145. package/tests/routerState.test.ts +157 -0
  146. package/tests/routerStatePlugin.test.ts +108 -0
  147. package/tests/runtimeContextProjection.test.ts +135 -0
  148. package/tests/shellStream.test.ts +37 -0
  149. package/tests/workspaceEvents.test.ts +391 -0
  150. package/dist/cjs/rscHtmlStream.js +0 -128
  151. package/dist/esm/rscHtmlStream.mjs +0 -86
  152. package/dist/esm-node/rscHtmlStream.mjs +0 -87
  153. package/dist/types/rscHtmlStream.d.ts +0 -4
  154. package/src/rscHtmlStream.ts +0 -142
  155. package/tests/rscHtmlStream.test.ts +0 -153
@@ -0,0 +1,149 @@
1
+ import { createClient as createNativeClient } from '@modern-js/create-request/server';
2
+ import * as context from '@modern-js/runtime-extensions/request-context';
3
+ import * as canonical from '@modern-js/runtime-extensions/request-policy';
4
+ import * as server from '@modern-js/runtime-extensions/request-policy/server';
5
+
6
+ const options = {
7
+ path: '/api',
8
+ method: 'GET',
9
+ port: 8080,
10
+ requestId: 'shared-producer',
11
+ };
12
+
13
+ describe('isolated producer policy clients', () => {
14
+ test('does not share producer initialization or request configuration between instances', async () => {
15
+ const first = server.createClient();
16
+ const second = server.createClient();
17
+ const firstRequest = rs.fn(async () => new Response('first'));
18
+ const secondRequest = rs.fn(async () => new Response('second'));
19
+ first.configure({
20
+ requestId: options.requestId,
21
+ request: firstRequest,
22
+ setDomain: () => 'https://first.example',
23
+ operationContract: { enabled: false },
24
+ });
25
+ expect(() => second.createRequest(options)()).toThrow(
26
+ server.ProducerClientNotInitializedError,
27
+ );
28
+ second.configure({
29
+ requestId: options.requestId,
30
+ request: secondRequest,
31
+ setDomain: () => 'https://second.example',
32
+ operationContract: { enabled: false },
33
+ });
34
+ expect(await (await first.createRequest(options)()).text()).toBe('first');
35
+ expect(await (await second.createRequest(options)()).text()).toBe('second');
36
+ expect(firstRequest).toHaveBeenCalledWith(
37
+ 'https://first.example/api',
38
+ expect.any(Object),
39
+ );
40
+ expect(secondRequest).toHaveBeenCalledWith(
41
+ 'https://second.example/api',
42
+ expect.any(Object),
43
+ );
44
+ });
45
+
46
+ test('does not initialize producer policy by configuring a separate native client', () => {
47
+ createNativeClient().configure({
48
+ requestId: options.requestId,
49
+ request: rs.fn(),
50
+ });
51
+ const producer = server.createClient();
52
+ expect(() => producer.createRequest(options)()).toThrow(
53
+ server.ProducerClientNotInitializedError,
54
+ );
55
+ });
56
+
57
+ test('retains secured behavior for an explicitly empty requestId', () => {
58
+ const client = server.createClient();
59
+ const request = rs.fn();
60
+ client.configure({
61
+ requestId: '',
62
+ request,
63
+ setDomain: () => 'https://producer.example',
64
+ });
65
+ expect(() => client.createRequest({ ...options, requestId: '' })()).toThrow(
66
+ server.OperationContractViolationError,
67
+ );
68
+ expect(request).not.toHaveBeenCalled();
69
+ });
70
+
71
+ test('calls setDomain once after interceptor and keeps native and policy state on rejection', async () => {
72
+ const client = server.createClient();
73
+ const order: string[] = [];
74
+ const request = rs.fn(async () => new Response('original'));
75
+ const setDomain = rs.fn(() => {
76
+ order.push('domain');
77
+ return 'https://original.example';
78
+ });
79
+ client.configure({
80
+ requestId: options.requestId,
81
+ interceptor: () => {
82
+ order.push('interceptor');
83
+ return request;
84
+ },
85
+ setDomain,
86
+ requireEnvelope: false,
87
+ operationContract: { enabled: false },
88
+ });
89
+ const replacement = rs.fn();
90
+ expect(() =>
91
+ client.configure({
92
+ requestId: options.requestId,
93
+ request: replacement,
94
+ setDomain: () => '',
95
+ }),
96
+ ).toThrow(server.ProducerDomainNotConfiguredError);
97
+ const response = await client.createRequest(options)();
98
+ expect(await response.text()).toBe('original');
99
+ expect(order).toEqual(['interceptor', 'domain']);
100
+ expect(setDomain).toHaveBeenCalledTimes(1);
101
+ expect(request).toHaveBeenCalledWith(
102
+ 'https://original.example/api',
103
+ expect.objectContaining({
104
+ headers: expect.not.objectContaining({
105
+ 'x-modernjs-bff-envelope': expect.anything(),
106
+ }),
107
+ }),
108
+ );
109
+ expect(replacement).not.toHaveBeenCalled();
110
+ });
111
+
112
+ test('shares source configure across canonical require/import and explicit server', async () => {
113
+ const required: typeof canonical = require('@modern-js/runtime-extensions/request-policy');
114
+ expect(required.configure).toBe(canonical.configure);
115
+ expect(server.configure).toBe(canonical.configure);
116
+ const request = rs.fn(async () => new Response('shared'));
117
+ required.configure({
118
+ requestId: options.requestId,
119
+ request,
120
+ setDomain: () => 'https://shared.example',
121
+ operationContract: { enabled: false },
122
+ });
123
+ expect(await (await canonical.createRequest(options)()).text()).toBe(
124
+ 'shared',
125
+ );
126
+ canonical.configure({
127
+ requestId: options.requestId,
128
+ request,
129
+ setDomain: () => 'https://updated.example',
130
+ operationContract: { enabled: false },
131
+ });
132
+ await required.createRequest(options)();
133
+ expect(request).toHaveBeenLastCalledWith(
134
+ 'https://updated.example/api',
135
+ expect.any(Object),
136
+ );
137
+ });
138
+
139
+ test('exports universal context helpers without a request client', () => {
140
+ expect(context.createRequestContextHeaders).toBe(
141
+ canonical.createRequestContextHeaders,
142
+ );
143
+ expect(context.parseTraceparent).toBe(canonical.parseTraceparent);
144
+ expect(context).not.toHaveProperty('configure');
145
+ expect(context).not.toHaveProperty('createClient');
146
+ expect(context).not.toHaveProperty('createRequest');
147
+ expect(context).not.toHaveProperty('createUploader');
148
+ });
149
+ });
@@ -0,0 +1,75 @@
1
+ import {
2
+ configure,
3
+ createRequest,
4
+ } from '@modern-js/runtime-extensions/request-policy/server';
5
+ import { storage } from '@modern-js/runtime-utils/node';
6
+ import nock from 'nock';
7
+
8
+ describe('identity binding headers', () => {
9
+ const path = '/api';
10
+ const method = 'GET';
11
+ const response = {
12
+ code: 200,
13
+ data: {
14
+ message: 'hello Modernjs',
15
+ },
16
+ };
17
+
18
+ const run = (
19
+ headers: Record<string, string>,
20
+ callback: () => Promise<void> | void,
21
+ ) =>
22
+ storage.run(
23
+ {
24
+ headers,
25
+ monitors: {} as any,
26
+ },
27
+ callback,
28
+ );
29
+
30
+ test('should not forward case-variant protected identity headers beside server-derived binding', async () => {
31
+ const producer = 'producer-identity-case-collision';
32
+ const producerUrl = 'http://127.0.0.1:9088';
33
+
34
+ await run({}, async () => {
35
+ nock(producerUrl).get(path).reply(200, response);
36
+ const customRequest = rs.fn((requestPath: any, init: any) =>
37
+ fetch(requestPath, init),
38
+ );
39
+
40
+ configure({
41
+ request: customRequest as unknown as typeof fetch,
42
+ requestId: producer,
43
+ allowedHeaders: ['X-Tenant-Id'],
44
+ resolveHeaders: () => ({
45
+ 'X-Tenant-Id': 'tenant-resolved',
46
+ }),
47
+ operationContract: {
48
+ enabled: false,
49
+ },
50
+ identityBinding: {
51
+ deriveHeaders: () => ({
52
+ 'x-tenant-id': 'tenant-bound',
53
+ }),
54
+ strict: false,
55
+ },
56
+ setDomain: () => producerUrl,
57
+ });
58
+
59
+ const request = createRequest(
60
+ path,
61
+ method,
62
+ 8080,
63
+ undefined,
64
+ undefined,
65
+ producer,
66
+ );
67
+
68
+ await request();
69
+ const headers = customRequest.mock.calls[0]?.[1]?.headers;
70
+
71
+ expect(headers['X-Tenant-Id']).toBeUndefined();
72
+ expect(headers['x-tenant-id']).toBe('tenant-resolved');
73
+ });
74
+ });
75
+ });