Skip to content

Commit a19a185

Browse files
feat: convert integrations to TS (#13663)
1 parent 620d15d commit a19a185

32 files changed

Lines changed: 222 additions & 158 deletions
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@astrojs/svelte': patch
3+
'@astrojs/react': patch
4+
'@astrojs/vue': patch
5+
---
6+
7+
Improves type-safety of renderers
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
declare module 'astro:react:opts' {
2+
type Options = Pick<
3+
import('./src/index.js').ReactIntegrationOptions,
4+
'experimentalDisableStreaming' | 'experimentalReactChildren'
5+
>;
6+
const options: Options;
7+
export = options;
8+
}

packages/integrations/react/package.json

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,15 @@
2222
"exports": {
2323
".": "./dist/index.js",
2424
"./actions": "./dist/actions.js",
25-
"./client.js": "./client.js",
26-
"./client-v17.js": "./client-v17.js",
27-
"./server.js": "./server.js",
28-
"./server-v17.js": "./server-v17.js",
25+
"./client.js": "./dist/client.js",
26+
"./client-v17.js": "./dist/client-v17.js",
27+
"./server.js": "./dist/server.js",
28+
"./server-v17.js": "./dist/server-v17.js",
2929
"./package.json": "./package.json",
30-
"./jsx-runtime": "./jsx-runtime.js"
30+
"./jsx-runtime": "./dist/jsx-runtime.js"
3131
},
3232
"files": [
33-
"dist",
34-
"client.js",
35-
"client-v17.js",
36-
"context.js",
37-
"jsx-runtime.js",
38-
"server.js",
39-
"server.d.ts",
40-
"server-v17.js",
41-
"server-v17.d.ts",
42-
"static-html.js",
43-
"vnode-children.js"
33+
"dist"
4434
],
4535
"scripts": {
4636
"build": "astro-scripts build \"src/**/*.ts\" && tsc",

packages/integrations/react/server.d.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/integrations/react/server17.d.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

packages/integrations/react/client-v17.js renamed to packages/integrations/react/src/client-v17.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ import { createElement } from 'react';
22
import { hydrate, render, unmountComponentAtNode } from 'react-dom';
33
import StaticHtml from './static-html.js';
44

5-
export default (element) =>
6-
(Component, props, { default: children, ...slotted }, { client }) => {
5+
export default (element: HTMLElement) =>
6+
(
7+
Component: any,
8+
props: Record<string, any>,
9+
{ default: children, ...slotted }: Record<string, any>,
10+
{ client }: Record<string, string>,
11+
) => {
712
for (const [key, value] of Object.entries(slotted)) {
813
props[key] = createElement(StaticHtml, { value, name: key });
914
}
Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { createElement, startTransition } from 'react';
2-
import { createRoot, hydrateRoot } from 'react-dom/client';
2+
import { type Root, createRoot, hydrateRoot } from 'react-dom/client';
33
import StaticHtml from './static-html.js';
44

5-
function isAlreadyHydrated(element) {
5+
function isAlreadyHydrated(element: HTMLElement) {
66
for (const key in element) {
77
if (key.startsWith('__reactContainer')) {
8-
return key;
8+
return key as keyof HTMLElement;
99
}
1010
}
1111
}
1212

13-
function createReactElementFromDOMElement(element) {
14-
let attrs = {};
13+
function createReactElementFromDOMElement(element: any): any {
14+
let attrs: Record<string, string> = {};
1515
for (const attr of element.attributes) {
1616
attrs[attr.name] = attr.value;
1717
}
@@ -24,7 +24,7 @@ function createReactElementFromDOMElement(element) {
2424
element.localName,
2525
attrs,
2626
Array.from(element.childNodes)
27-
.map((c) => {
27+
.map((c: any) => {
2828
if (c.nodeType === Node.TEXT_NODE) {
2929
return c.data;
3030
} else if (c.nodeType === Node.ELEMENT_NODE) {
@@ -37,7 +37,7 @@ function createReactElementFromDOMElement(element) {
3737
);
3838
}
3939

40-
function getChildren(childString, experimentalReactChildren) {
40+
function getChildren(childString: string, experimentalReactChildren: boolean) {
4141
if (experimentalReactChildren && childString) {
4242
let children = [];
4343
let template = document.createElement('template');
@@ -54,8 +54,8 @@ function getChildren(childString, experimentalReactChildren) {
5454
}
5555

5656
// Keep a map of roots so we can reuse them on re-renders
57-
let rootMap = new WeakMap();
58-
const getOrCreateRoot = (element, creator) => {
57+
let rootMap = new WeakMap<HTMLElement, Root>();
58+
const getOrCreateRoot = (element: HTMLElement, creator: () => Root) => {
5959
let root = rootMap.get(element);
6060
if (!root) {
6161
root = creator();
@@ -64,8 +64,13 @@ const getOrCreateRoot = (element, creator) => {
6464
return root;
6565
};
6666

67-
export default (element) =>
68-
(Component, props, { default: children, ...slotted }, { client }) => {
67+
export default (element: HTMLElement) =>
68+
(
69+
Component: any,
70+
props: Record<string, any>,
71+
{ default: children, ...slotted }: Record<string, any>,
72+
{ client }: Record<string, string>,
73+
) => {
6974
if (!element.hasAttribute('ssr')) return;
7075

7176
const actionKey = element.getAttribute('data-action-key');
@@ -107,7 +112,7 @@ export default (element) =>
107112
}
108113
startTransition(() => {
109114
const root = getOrCreateRoot(element, () => {
110-
const r = hydrateRoot(element, componentEl, renderOptions);
115+
const r = hydrateRoot(element, componentEl, renderOptions as any);
111116
element.addEventListener('astro:unmount', () => r.unmount(), { once: true });
112117
return r;
113118
});

packages/integrations/react/context.js renamed to packages/integrations/react/src/context.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
const contexts = new WeakMap();
1+
import type { SSRResult } from 'astro';
2+
3+
const contexts = new WeakMap<SSRResult, { currentIndex: number; readonly id: string }>();
24

35
const ID_PREFIX = 'r';
46

5-
function getContext(rendererContextResult) {
7+
function getContext(rendererContextResult: SSRResult) {
68
if (contexts.has(rendererContextResult)) {
79
return contexts.get(rendererContextResult);
810
}
@@ -16,8 +18,8 @@ function getContext(rendererContextResult) {
1618
return ctx;
1719
}
1820

19-
export function incrementId(rendererContextResult) {
20-
const ctx = getContext(rendererContextResult);
21+
export function incrementId(rendererContextResult: SSRResult) {
22+
const ctx = getContext(rendererContextResult)!;
2123
const id = ctx.id;
2224
ctx.currentIndex++;
2325
return id;

packages/integrations/react/jsx-runtime.js renamed to packages/integrations/react/src/jsx-runtime.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// it can run in Node ESM. 'react' doesn't declare this module as an export map
33
// So we have to use the .js. The .js is not added via the babel automatic JSX transform
44
// hence this module as a workaround.
5-
import jsxr from 'react/jsx-runtime.js';
5+
import jsxr from 'react/jsx-runtime';
66
const { jsx, jsxs, Fragment } = jsxr;
77

88
export { jsx, jsxs, Fragment };

packages/integrations/react/server-v17.js renamed to packages/integrations/react/src/server-v17.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import type { AstroComponentMetadata } from 'astro';
12
import React from 'react';
2-
import ReactDOM from 'react-dom/server.js';
3+
import ReactDOM from 'react-dom/server';
34
import StaticHtml from './static-html.js';
45

5-
const slotName = (str) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase());
6+
const slotName = (str: string) => str.trim().replace(/[-_]([a-z])/g, (_, w) => w.toUpperCase());
67
const reactTypeof = Symbol.for('react.element');
78

8-
function check(Component, props, children) {
9+
function check(Component: any, props: Record<string, any>, children: any) {
910
// Note: there are packages that do some unholy things to create "components".
1011
// Checking the $$typeof property catches most of these patterns.
1112
if (typeof Component === 'object') {
@@ -19,7 +20,7 @@ function check(Component, props, children) {
1920
}
2021

2122
let isReactComponent = false;
22-
function Tester(...args) {
23+
function Tester(...args: Array<any>) {
2324
try {
2425
const vnode = Component(...args);
2526
if (vnode && vnode['$$typeof'] === reactTypeof) {
@@ -30,14 +31,19 @@ function check(Component, props, children) {
3031
return React.createElement('div');
3132
}
3233

33-
renderToStaticMarkup(Tester, props, children, {});
34+
renderToStaticMarkup(Tester, props, children, {} as any);
3435

3536
return isReactComponent;
3637
}
3738

38-
function renderToStaticMarkup(Component, props, { default: children, ...slotted }, metadata) {
39+
function renderToStaticMarkup(
40+
Component: any,
41+
props: Record<string, any>,
42+
{ default: children, ...slotted }: Record<string, any>,
43+
metadata: AstroComponentMetadata,
44+
) {
3945
delete props['class'];
40-
const slots = {};
46+
const slots: Record<string, any> = {};
4147
for (const [key, value] of Object.entries(slotted)) {
4248
const name = slotName(key);
4349
slots[name] = React.createElement(StaticHtml, { value, name });

0 commit comments

Comments
 (0)