1
1
import opts from 'astro:react:opts' ;
2
+ import type { AstroComponentMetadata } from 'astro' ;
2
3
import React from 'react' ;
3
4
import ReactDOM from 'react-dom/server' ;
4
5
import { incrementId } from './context.js' ;
5
6
import StaticHtml from './static-html.js' ;
7
+ import type { RendererContext } from './types.js' ;
6
8
7
- const slotName = ( str ) => str . trim ( ) . replace ( / [ - _ ] ( [ a - z ] ) / g, ( _ , w ) => w . toUpperCase ( ) ) ;
9
+ const slotName = ( str : string ) => str . trim ( ) . replace ( / [ - _ ] ( [ a - z ] ) / g, ( _ , w ) => w . toUpperCase ( ) ) ;
8
10
const reactTypeof = Symbol . for ( 'react.element' ) ;
9
11
const reactTransitionalTypeof = Symbol . for ( 'react.transitional.element' ) ;
10
12
11
- async function check ( Component , props , children ) {
13
+ async function check (
14
+ this : RendererContext ,
15
+ Component : any ,
16
+ props : Record < string , any > ,
17
+ children : any ,
18
+ ) {
12
19
// Note: there are packages that do some unholy things to create "components".
13
20
// Checking the $$typeof property catches most of these patterns.
14
21
if ( typeof Component === 'object' ) {
@@ -26,7 +33,7 @@ async function check(Component, props, children) {
26
33
}
27
34
28
35
let isReactComponent = false ;
29
- function Tester ( ...args ) {
36
+ function Tester ( ...args : Array < any > ) {
30
37
try {
31
38
const vnode = Component ( ...args ) ;
32
39
if (
@@ -40,31 +47,37 @@ async function check(Component, props, children) {
40
47
return React . createElement ( 'div' ) ;
41
48
}
42
49
43
- await renderToStaticMarkup ( Tester , props , children , { } ) ;
50
+ await renderToStaticMarkup . call ( this , Tester , props , children , { } as any ) ;
44
51
45
52
return isReactComponent ;
46
53
}
47
54
48
- async function getNodeWritable ( ) {
55
+ async function getNodeWritable ( ) : Promise < typeof import ( 'node:stream' ) . Writable > {
49
56
let nodeStreamBuiltinModuleName = 'node:stream' ;
50
57
let { Writable } = await import ( /* @vite -ignore */ nodeStreamBuiltinModuleName ) ;
51
58
return Writable ;
52
59
}
53
60
54
- function needsHydration ( metadata ) {
61
+ function needsHydration ( metadata : AstroComponentMetadata ) {
55
62
// Adjust how this is hydrated only when the version of Astro supports `astroStaticSlot`
56
63
return metadata . astroStaticSlot ? ! ! metadata . hydrate : true ;
57
64
}
58
65
59
- async function renderToStaticMarkup ( Component , props , { default : children , ...slotted } , metadata ) {
66
+ async function renderToStaticMarkup (
67
+ this : RendererContext ,
68
+ Component : any ,
69
+ props : Record < string , any > ,
70
+ { default : children , ...slotted } : Record < string , any > ,
71
+ metadata : AstroComponentMetadata ,
72
+ ) {
60
73
let prefix ;
61
74
if ( this && this . result ) {
62
75
prefix = incrementId ( this . result ) ;
63
76
}
64
- const attrs = { prefix } ;
77
+ const attrs : Record < string , any > = { prefix } ;
65
78
66
79
delete props [ 'class' ] ;
67
- const slots = { } ;
80
+ const slots : Record < string , any > = { } ;
68
81
for ( const [ key , value ] of Object . entries ( slotted ) ) {
69
82
const name = slotName ( key ) ;
70
83
slots [ name ] = React . createElement ( StaticHtml , {
@@ -111,10 +124,11 @@ async function renderToStaticMarkup(Component, props, { default: children, ...sl
111
124
return { html, attrs } ;
112
125
}
113
126
114
- /**
115
- * @returns {Promise<[actionResult: any, actionKey: string, actionName: string] | undefined> }
116
- */
117
- async function getFormState ( { result } ) {
127
+ async function getFormState ( {
128
+ result,
129
+ } : RendererContext ) : Promise <
130
+ [ actionResult : any , actionKey : string , actionName : string ] | undefined
131
+ > {
118
132
const { request, actionResult } = result ;
119
133
120
134
if ( ! actionResult ) return undefined ;
@@ -139,7 +153,7 @@ async function getFormState({ result }) {
139
153
return [ actionResult , actionKey , actionName ] ;
140
154
}
141
155
142
- async function renderToPipeableStreamAsync ( vnode , options ) {
156
+ async function renderToPipeableStreamAsync ( vnode : any , options : Record < string , any > ) {
143
157
const Writable = await getNodeWritable ( ) ;
144
158
let html = '' ;
145
159
return new Promise ( ( resolve , reject ) => {
@@ -171,7 +185,7 @@ async function renderToPipeableStreamAsync(vnode, options) {
171
185
* Use a while loop instead of "for await" due to cloudflare and Vercel Edge issues
172
186
* See https://github.com/facebook/react/issues/24169
173
187
*/
174
- async function readResult ( stream ) {
188
+ async function readResult ( stream : ReactDOM . ReactDOMServerReadableStream ) {
175
189
const reader = stream . getReader ( ) ;
176
190
let result = '' ;
177
191
const decoder = new TextDecoder ( 'utf-8' ) ;
@@ -191,13 +205,13 @@ async function readResult(stream) {
191
205
}
192
206
}
193
207
194
- async function renderToReadableStreamAsync ( vnode , options ) {
208
+ async function renderToReadableStreamAsync ( vnode : any , options : Record < string , any > ) {
195
209
return await readResult ( await ReactDOM . renderToReadableStream ( vnode , options ) ) ;
196
210
}
197
211
198
212
const formContentTypes = [ 'application/x-www-form-urlencoded' , 'multipart/form-data' ] ;
199
213
200
- function isFormRequest ( contentType ) {
214
+ function isFormRequest ( contentType : string | null ) {
201
215
// Split off parameters like charset or boundary
202
216
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type#content-type_in_html_forms
203
217
const type = contentType ?. split ( ';' ) [ 0 ] . toLowerCase ( ) ;
0 commit comments