@bleedingdev/modern-js-renderer-core 0.0.0-bootstrap → 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.
Files changed (147) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/abort.js +65 -0
  3. package/dist/cjs/adapter.js +62 -0
  4. package/dist/cjs/data/body.js +78 -0
  5. package/dist/cjs/data/client.js +409 -0
  6. package/dist/cjs/data/codec.js +168 -0
  7. package/dist/cjs/data/index.js +125 -0
  8. package/dist/cjs/data/private.js +77 -0
  9. package/dist/cjs/data/routes.js +149 -0
  10. package/dist/cjs/data/server.js +791 -0
  11. package/dist/cjs/data/static.js +110 -0
  12. package/dist/cjs/data/tree.js +231 -0
  13. package/dist/cjs/data/types.js +56 -0
  14. package/dist/cjs/document.js +184 -0
  15. package/dist/cjs/entry-client.js +142 -0
  16. package/dist/cjs/entry-server.js +253 -0
  17. package/dist/cjs/federation.js +80 -0
  18. package/dist/cjs/identity.js +120 -0
  19. package/dist/cjs/index.js +46 -0
  20. package/dist/cjs/localization.js +48 -0
  21. package/dist/cjs/router.js +293 -0
  22. package/dist/cjs/server/assets.js +56 -0
  23. package/dist/cjs/server/dispatch.js +351 -0
  24. package/dist/cjs/server/index.js +57 -0
  25. package/dist/cjs/server/types.js +18 -0
  26. package/dist/cjs/server/worker.js +73 -0
  27. package/dist/cjs/session/cache.js +172 -0
  28. package/dist/cjs/session/index.js +63 -0
  29. package/dist/cjs/session/request.js +269 -0
  30. package/dist/cjs/session/types.js +18 -0
  31. package/dist/esm/abort.mjs +27 -0
  32. package/dist/esm/adapter.mjs +21 -0
  33. package/dist/esm/data/body.mjs +40 -0
  34. package/dist/esm/data/client.mjs +368 -0
  35. package/dist/esm/data/codec.mjs +112 -0
  36. package/dist/esm/data/index.mjs +7 -0
  37. package/dist/esm/data/private.mjs +39 -0
  38. package/dist/esm/data/routes.mjs +108 -0
  39. package/dist/esm/data/server.mjs +723 -0
  40. package/dist/esm/data/static.mjs +51 -0
  41. package/dist/esm/data/tree.mjs +193 -0
  42. package/dist/esm/data/types.mjs +6 -0
  43. package/dist/esm/document.mjs +131 -0
  44. package/dist/esm/entry-client.mjs +104 -0
  45. package/dist/esm/entry-server.mjs +215 -0
  46. package/dist/esm/federation.mjs +36 -0
  47. package/dist/esm/identity.mjs +63 -0
  48. package/dist/esm/index.mjs +1 -0
  49. package/dist/esm/localization.mjs +10 -0
  50. package/dist/esm/router.mjs +225 -0
  51. package/dist/esm/server/assets.mjs +15 -0
  52. package/dist/esm/server/dispatch.mjs +307 -0
  53. package/dist/esm/server/index.mjs +3 -0
  54. package/dist/esm/server/types.mjs +0 -0
  55. package/dist/esm/server/worker.mjs +35 -0
  56. package/dist/esm/session/cache.mjs +116 -0
  57. package/dist/esm/session/index.mjs +3 -0
  58. package/dist/esm/session/request.mjs +231 -0
  59. package/dist/esm/session/types.mjs +0 -0
  60. package/dist/esm-node/abort.mjs +28 -0
  61. package/dist/esm-node/adapter.mjs +22 -0
  62. package/dist/esm-node/data/body.mjs +41 -0
  63. package/dist/esm-node/data/client.mjs +369 -0
  64. package/dist/esm-node/data/codec.mjs +113 -0
  65. package/dist/esm-node/data/index.mjs +8 -0
  66. package/dist/esm-node/data/private.mjs +40 -0
  67. package/dist/esm-node/data/routes.mjs +109 -0
  68. package/dist/esm-node/data/server.mjs +724 -0
  69. package/dist/esm-node/data/static.mjs +52 -0
  70. package/dist/esm-node/data/tree.mjs +194 -0
  71. package/dist/esm-node/data/types.mjs +7 -0
  72. package/dist/esm-node/document.mjs +132 -0
  73. package/dist/esm-node/entry-client.mjs +105 -0
  74. package/dist/esm-node/entry-server.mjs +216 -0
  75. package/dist/esm-node/federation.mjs +37 -0
  76. package/dist/esm-node/identity.mjs +64 -0
  77. package/dist/esm-node/index.mjs +2 -0
  78. package/dist/esm-node/localization.mjs +11 -0
  79. package/dist/esm-node/router.mjs +226 -0
  80. package/dist/esm-node/server/assets.mjs +16 -0
  81. package/dist/esm-node/server/dispatch.mjs +308 -0
  82. package/dist/esm-node/server/index.mjs +4 -0
  83. package/dist/esm-node/server/types.mjs +1 -0
  84. package/dist/esm-node/server/worker.mjs +36 -0
  85. package/dist/esm-node/session/cache.mjs +117 -0
  86. package/dist/esm-node/session/index.mjs +4 -0
  87. package/dist/esm-node/session/request.mjs +232 -0
  88. package/dist/esm-node/session/types.mjs +1 -0
  89. package/dist/types/abort.d.ts +6 -0
  90. package/dist/types/adapter.d.ts +195 -0
  91. package/dist/types/data/body.d.ts +2 -0
  92. package/dist/types/data/client.d.ts +17 -0
  93. package/dist/types/data/codec.d.ts +14 -0
  94. package/dist/types/data/index.d.ts +8 -0
  95. package/dist/types/data/private.d.ts +6 -0
  96. package/dist/types/data/routes.d.ts +28 -0
  97. package/dist/types/data/server.d.ts +59 -0
  98. package/dist/types/data/static.d.ts +31 -0
  99. package/dist/types/data/tree.d.ts +3 -0
  100. package/dist/types/data/types.d.ts +104 -0
  101. package/dist/types/document.d.ts +76 -0
  102. package/dist/types/entry-client.d.ts +53 -0
  103. package/dist/types/entry-server.d.ts +63 -0
  104. package/dist/types/federation.d.ts +56 -0
  105. package/dist/types/identity.d.ts +27 -0
  106. package/dist/types/index.d.ts +1 -0
  107. package/dist/types/localization.d.ts +58 -0
  108. package/dist/types/router.d.ts +201 -0
  109. package/dist/types/server/assets.d.ts +14 -0
  110. package/dist/types/server/dispatch.d.ts +11 -0
  111. package/dist/types/server/index.d.ts +4 -0
  112. package/dist/types/server/types.d.ts +64 -0
  113. package/dist/types/server/worker.d.ts +25 -0
  114. package/dist/types/session/cache.d.ts +25 -0
  115. package/dist/types/session/index.d.ts +4 -0
  116. package/dist/types/session/request.d.ts +8 -0
  117. package/dist/types/session/types.d.ts +48 -0
  118. package/package.json +159 -4
  119. package/src/abort.ts +40 -0
  120. package/src/adapter.ts +255 -0
  121. package/src/data/body.ts +43 -0
  122. package/src/data/client.ts +501 -0
  123. package/src/data/codec.ts +247 -0
  124. package/src/data/index.ts +8 -0
  125. package/src/data/private.ts +68 -0
  126. package/src/data/routes.ts +201 -0
  127. package/src/data/server.ts +977 -0
  128. package/src/data/static.ts +105 -0
  129. package/src/data/tree.ts +244 -0
  130. package/src/data/types.ts +98 -0
  131. package/src/document.ts +338 -0
  132. package/src/entry-client.ts +236 -0
  133. package/src/entry-server.ts +393 -0
  134. package/src/federation.ts +111 -0
  135. package/src/identity.ts +128 -0
  136. package/src/index.ts +7 -0
  137. package/src/localization.ts +77 -0
  138. package/src/router.ts +475 -0
  139. package/src/server/assets.ts +60 -0
  140. package/src/server/dispatch.ts +523 -0
  141. package/src/server/index.ts +16 -0
  142. package/src/server/types.ts +94 -0
  143. package/src/server/worker.ts +94 -0
  144. package/src/session/cache.ts +177 -0
  145. package/src/session/index.ts +11 -0
  146. package/src/session/request.ts +324 -0
  147. package/src/session/types.ts +60 -0
@@ -0,0 +1,231 @@
1
+ import { identityCacheKey } from "../identity.mjs";
2
+ import { permitsDocumentCache, policyHeaders } from "./cache.mjs";
3
+ function freezeResponsePolicy(policy) {
4
+ if (!Number.isInteger(policy.status) || policy.status < 200 || policy.status > 599) throw new TypeError('A renderer response status must be an integer from 200 to 599.');
5
+ if ('document' !== policy.kind && 'terminal' !== policy.kind) throw new TypeError('A renderer response must identify its document or terminal outcome.');
6
+ const statusText = policy.statusText;
7
+ if (void 0 !== statusText && 'string' != typeof statusText) throw new TypeError('A renderer response status text must be a string.');
8
+ new Response(null, {
9
+ status: policy.status,
10
+ ...void 0 === statusText ? {} : {
11
+ statusText
12
+ }
13
+ });
14
+ if (![
15
+ 'no-store',
16
+ 'private',
17
+ 'public'
18
+ ].includes(policy.cache.mode)) throw new TypeError('A renderer response has an unknown cache policy.');
19
+ if ('public' === policy.cache.mode && (!Number.isInteger(policy.cache.maxAgeSeconds) || policy.cache.maxAgeSeconds < 0)) throw new TypeError('A public document cache lifetime must be a nonnegative integer.');
20
+ const headers = policy.headers.map(([name, value])=>{
21
+ new Headers([
22
+ [
23
+ name,
24
+ value
25
+ ]
26
+ ]);
27
+ return Object.freeze([
28
+ name,
29
+ value
30
+ ]);
31
+ });
32
+ return Object.freeze({
33
+ kind: policy.kind,
34
+ status: policy.status,
35
+ ...void 0 === statusText ? {} : {
36
+ statusText
37
+ },
38
+ headers: Object.freeze(headers),
39
+ cache: Object.freeze({
40
+ ...policy.cache
41
+ })
42
+ });
43
+ }
44
+ function createRequestSession(input) {
45
+ identityCacheKey(input.identity);
46
+ if ('node' !== input.platform.kind && 'worker' !== input.platform.kind) throw new TypeError('A renderer request requires an explicit Node or worker binding.');
47
+ const identity = Object.freeze({
48
+ ...input.identity
49
+ });
50
+ const platform = Object.freeze({
51
+ ...input.platform
52
+ });
53
+ const abortController = new AbortController();
54
+ const disposers = new Set();
55
+ let state = 'matching';
56
+ let policy;
57
+ let committedPolicy;
58
+ let fallback = false;
59
+ let responseCreated = false;
60
+ let hasDocumentBody = false;
61
+ let deliveredResponse;
62
+ let deliveredHeaders;
63
+ let reader;
64
+ let bodyController;
65
+ let cancelPromise;
66
+ let finishPromise;
67
+ let resolveCompletion;
68
+ const completion = new Promise((resolve)=>{
69
+ resolveCompletion = resolve;
70
+ });
71
+ const cancelSource = (reason)=>{
72
+ cancelPromise ??= reader ? reader.cancel(reason).finally(()=>reader?.releaseLock()) : Promise.resolve();
73
+ return cancelPromise;
74
+ };
75
+ const finish = (terminalState, error)=>{
76
+ if (finishPromise) return finishPromise;
77
+ state = terminalState;
78
+ input.request.signal.removeEventListener('abort', onRequestAbort);
79
+ const ownedDisposers = [
80
+ ...disposers
81
+ ].reverse();
82
+ disposers.clear();
83
+ finishPromise = Promise.resolve().then(async ()=>{
84
+ const cleanupErrors = [];
85
+ let recorded = false;
86
+ if ('completed' !== terminalState) cancelSource(error).catch((cancelError)=>{
87
+ if (!recorded) cleanupErrors.push(cancelError);
88
+ });
89
+ for (const dispose of ownedDisposers)try {
90
+ await dispose();
91
+ } catch (cleanupError) {
92
+ cleanupErrors.push(cleanupError);
93
+ }
94
+ await Promise.resolve();
95
+ recorded = true;
96
+ if ('completed' === terminalState && cleanupErrors.length > 0) state = 'failed';
97
+ const result = Object.freeze({
98
+ state: state,
99
+ fallback,
100
+ ...void 0 !== error ? {
101
+ error
102
+ } : {},
103
+ cleanupErrors: Object.freeze(cleanupErrors),
104
+ cacheEligible: 'completed' === state && hasDocumentBody && !fallback && void 0 !== committedPolicy && permitsDocumentCache({
105
+ ...committedPolicy,
106
+ headers: deliveredHeaders ? [
107
+ ...deliveredHeaders.entries()
108
+ ] : committedPolicy.headers
109
+ })
110
+ });
111
+ resolveCompletion(result);
112
+ return result;
113
+ });
114
+ if ('completed' !== terminalState) {
115
+ abortController.abort(error);
116
+ bodyController?.error(error);
117
+ }
118
+ return finishPromise;
119
+ };
120
+ const abort = (reason = new DOMException('The renderer request was aborted.', 'AbortError'))=>{
121
+ finish('aborted', reason);
122
+ };
123
+ function onRequestAbort() {
124
+ abort(input.request.signal.reason);
125
+ }
126
+ const session = {
127
+ request: input.request,
128
+ identity,
129
+ platform,
130
+ signal: abortController.signal,
131
+ get state () {
132
+ return state;
133
+ },
134
+ get responsePolicy () {
135
+ return policy;
136
+ },
137
+ get committedPolicy () {
138
+ return committedPolicy;
139
+ },
140
+ completion,
141
+ resolveResponse (nextPolicy) {
142
+ if (committedPolicy || finishPromise) throw new Error('Renderer response status and headers are already committed or terminated.');
143
+ policy = freezeResponsePolicy(nextPolicy);
144
+ if ('matching' === state) state = 'ready';
145
+ },
146
+ startRendering () {
147
+ if ('ready' !== state) throw new Error('Resolve the blocking HTTP outcome before starting the renderer.');
148
+ state = 'rendering';
149
+ },
150
+ registerCleanup (dispose) {
151
+ if (finishPromise) throw new Error('Cannot register cleanup after a renderer request terminates.');
152
+ disposers.add(dispose);
153
+ return ()=>{
154
+ disposers.delete(dispose);
155
+ };
156
+ },
157
+ markFallback () {
158
+ if (finishPromise) throw new Error('Cannot change fallback disposition after a renderer request terminates.');
159
+ fallback = true;
160
+ },
161
+ respond (body) {
162
+ if (responseCreated || committedPolicy || finishPromise) throw new Error('A renderer request has exactly one response body consumer.');
163
+ if (!policy || 'ready' !== state && 'rendering' !== state) throw new Error('Resolve the blocking HTTP outcome before committing a response.');
164
+ if (null !== body && [
165
+ 204,
166
+ 205,
167
+ 304
168
+ ].includes(policy.status)) throw new TypeError(`HTTP ${policy.status} cannot contain a renderer response body.`);
169
+ reader = body?.getReader();
170
+ hasDocumentBody = null !== body;
171
+ responseCreated = true;
172
+ committedPolicy = policy;
173
+ state = 'committed';
174
+ const headers = policyHeaders(committedPolicy.headers);
175
+ let wrappedBody = null;
176
+ if (reader) {
177
+ const sourceReader = reader;
178
+ wrappedBody = new ReadableStream({
179
+ start (controller) {
180
+ bodyController = controller;
181
+ },
182
+ async pull (controller) {
183
+ try {
184
+ const next = await sourceReader.read();
185
+ if (finishPromise) return;
186
+ if (!next.done) return void controller.enqueue(next.value);
187
+ sourceReader.releaseLock();
188
+ const result = await finish('completed');
189
+ if (result.cleanupErrors.length > 0) controller.error(new AggregateError(result.cleanupErrors, 'Renderer request cleanup failed.'));
190
+ else controller.close();
191
+ } catch (error) {
192
+ if (!finishPromise) {
193
+ await finish('failed', error);
194
+ controller.error(error);
195
+ }
196
+ }
197
+ },
198
+ cancel (reason) {
199
+ abort(reason);
200
+ return completion.then(()=>{});
201
+ }
202
+ }, {
203
+ highWaterMark: 0
204
+ });
205
+ } else finish('completed');
206
+ const response = new Response(wrappedBody, {
207
+ status: committedPolicy.status,
208
+ ...void 0 === committedPolicy.statusText ? {} : {
209
+ statusText: committedPolicy.statusText
210
+ },
211
+ headers
212
+ });
213
+ deliveredResponse = response;
214
+ deliveredHeaders = response.headers;
215
+ return response;
216
+ },
217
+ ownsResponseBody (response) {
218
+ return void 0 !== deliveredResponse && (response === deliveredResponse || null !== deliveredResponse.body && response.body === deliveredResponse.body);
219
+ },
220
+ fail (error) {
221
+ finish('failed', error);
222
+ },
223
+ abort
224
+ };
225
+ if (input.request.signal.aborted) onRequestAbort();
226
+ else input.request.signal.addEventListener('abort', onRequestAbort, {
227
+ once: true
228
+ });
229
+ return session;
230
+ }
231
+ export { createRequestSession };
File without changes
@@ -0,0 +1,28 @@
1
+ import "node:module";
2
+ function untilAborted(handled, signal) {
3
+ const settled = Promise.resolve(handled);
4
+ const discard = ()=>void settled.then((value)=>{
5
+ if (value instanceof Response) value.body?.cancel().catch(()=>{});
6
+ }, ()=>{});
7
+ if (signal.aborted) {
8
+ discard();
9
+ return Promise.reject(signal.reason);
10
+ }
11
+ return new Promise((resolve, reject)=>{
12
+ const onAbort = ()=>{
13
+ discard();
14
+ reject(signal.reason);
15
+ };
16
+ signal.addEventListener('abort', onAbort, {
17
+ once: true
18
+ });
19
+ settled.then((value)=>{
20
+ signal.removeEventListener('abort', onAbort);
21
+ resolve(value);
22
+ }, (error)=>{
23
+ signal.removeEventListener('abort', onAbort);
24
+ reject(error);
25
+ });
26
+ });
27
+ }
28
+ export { untilAborted };
@@ -0,0 +1,22 @@
1
+ import "node:module";
2
+ const adapterError = (name, detail)=>new Error(`Invalid renderer adapter ${String(name)}: ${detail}`);
3
+ function defineRendererAdapter(adapter) {
4
+ const { name, profile } = adapter;
5
+ if (profile.renderer !== name) throw adapterError(name, `profile names ${profile.renderer}`);
6
+ if (!adapter.routerFrameworks.length) throw adapterError(name, 'it declares no router framework');
7
+ if (adapter.worker.rsc !== profile.capabilities.rsc) throw adapterError(name, 'worker RSC support contradicts its profile');
8
+ if ('native' === adapter.kind) {
9
+ if (true !== adapter.worker.nativeDocuments) throw adapterError(name, 'native documents come from its server handler');
10
+ const federation = adapter.federation;
11
+ const capability = profile.capabilities.moduleFederation;
12
+ if (void 0 === federation !== (false === capability) || void 0 !== federation && federation.ssr !== (true === capability)) throw adapterError(name, 'federation support contradicts its profile');
13
+ }
14
+ return Object.freeze(adapter);
15
+ }
16
+ function nativeRendererDependencies(profile) {
17
+ return {
18
+ ...Object.fromEntries(Object.entries(profile.dependencies).filter(([name])=>!name.startsWith('@modern-js/'))),
19
+ [profile.router.coreName]: profile.router.coreVersion
20
+ };
21
+ }
22
+ export { defineRendererAdapter, nativeRendererDependencies };
@@ -0,0 +1,41 @@
1
+ import "node:module";
2
+ import { DataProtocolError, MAX_DATA_BYTES } from "./codec.mjs";
3
+ async function readBoundedDataText(response, signal, maxBytes = MAX_DATA_BYTES) {
4
+ if (signal?.aborted) {
5
+ response.body?.cancel(signal.reason).catch(()=>void 0);
6
+ signal.throwIfAborted();
7
+ }
8
+ if (!response.body) return '';
9
+ const reader = response.body.getReader();
10
+ const decoder = new TextDecoder('utf-8', {
11
+ fatal: true
12
+ });
13
+ let bytes = 0;
14
+ let text = '';
15
+ const abort = ()=>{
16
+ reader.cancel(signal?.reason).catch(()=>void 0);
17
+ };
18
+ signal?.addEventListener('abort', abort, {
19
+ once: true
20
+ });
21
+ try {
22
+ while(true){
23
+ const result = await reader.read();
24
+ signal?.throwIfAborted();
25
+ if (result.done) break;
26
+ bytes += result.value.byteLength;
27
+ if (bytes > maxBytes) throw new DataProtocolError('Public data exceeds its byte limit');
28
+ text += decoder.decode(result.value, {
29
+ stream: true
30
+ });
31
+ }
32
+ return text + decoder.decode();
33
+ } catch (error) {
34
+ reader.cancel(error).catch(()=>void 0);
35
+ throw error;
36
+ } finally{
37
+ signal?.removeEventListener('abort', abort);
38
+ reader.releaseLock();
39
+ }
40
+ }
41
+ export { readBoundedDataText };