-
-
Notifications
You must be signed in to change notification settings - Fork 120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: edge case when rsa depends on another rsa #785
Changes from 17 commits
b4fcfa5
2f720a4
4a5266d
9900d74
adfeec3
93efe90
ac345cf
6d46f2e
4db6361
4132469
944b44c
32ea016
4c56b7d
d037dc3
c45f2cc
65c8c2d
93320d0
ed9d708
e660f9d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "ai", | ||
"type": "module", | ||
"version": "1.0.0", | ||
"description": "Vercel AI mockup", | ||
"exports": { | ||
"./rsc": { | ||
"types": "./src/index.d.ts", | ||
"react-server": "./src/server.js", | ||
"import": "./src/client.js" | ||
} | ||
}, | ||
"devDependencies": { | ||
"react-dom": "^18", | ||
"react-server-dom-webpack": "18.3.0-canary-eb33bd747-20240312" | ||
}, | ||
"peerDependencies": { | ||
"react": "^18 || ^19" | ||
}, | ||
"private": true | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
'use client'; | ||
import { useActions } from './shared.js'; | ||
|
||
export { useActions }; | ||
|
||
export function createAI() { | ||
throw new Error('You should not call createAI in the client side'); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import type { ReactNode } from 'react'; | ||
|
||
declare function createAI( | ||
actions: Record<string, (...args: any[]) => any>, | ||
): (props: { children: ReactNode }) => ReactNode; | ||
|
||
declare function useActions(): Record<string, any>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
'use server'; | ||
import { InternalProvider } from './shared.js'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
|
||
async function innerAction({ action }, state, ...args) { | ||
'use server'; | ||
return action(...args); | ||
} | ||
|
||
function wrapAction(action, options) { | ||
return innerAction.bind(null, { action, options }); | ||
} | ||
|
||
export function createAI(actions) { | ||
const wrappedActions = {}; | ||
for (const name in actions) { | ||
wrappedActions[name] = wrapAction(actions[name]); | ||
} | ||
return function AI(props) { | ||
return jsx(InternalProvider, { | ||
actions: wrappedActions, | ||
children: props.children, | ||
}); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
'use client'; | ||
import { createContext, useContext } from 'react'; | ||
import { jsx } from 'react/jsx-runtime'; | ||
|
||
const ActionContext = createContext(null); | ||
|
||
export function useActions() { | ||
return useContext(ActionContext); | ||
} | ||
|
||
export function InternalProvider(props) { | ||
return jsx('div', { | ||
'data-testid': 'ai-internal-provider', | ||
children: jsx(ActionContext.Provider, { | ||
value: props.actions, | ||
children: props.children, | ||
}), | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
'use client'; | ||
|
||
import { useActions } from 'ai/rsc'; | ||
import { useEffect } from 'react'; | ||
|
||
export const ClientActionsConsumer = () => { | ||
const actions = useActions(); | ||
useEffect(() => { | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-expect-error | ||
globalThis.actions = actions; | ||
}, [actions]); | ||
return <div>globalThis.actions: {JSON.stringify(Object.keys(actions))}</div>; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { ReactNode } from 'react'; | ||
import { createAI } from 'ai/rsc'; | ||
|
||
const AI = createAI({ | ||
foo: async () => { | ||
'use server'; | ||
return 0; | ||
}, | ||
}); | ||
|
||
export function ServerProvider({ children }: { children: ReactNode }) { | ||
return <AI>{children}</AI>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -189,9 +189,9 @@ export async function renderRsc( | |
) { | ||
// XXX This doesn't support streaming unlike busboy | ||
const formData = parseFormData(bodyStr, contentType); | ||
args = await decodeReply(formData); | ||
args = await decodeReply(formData, bundlerConfig); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I actually wonder why this works. This is basically resolving client entry. Can it be used for server entry? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's also resolving the server entry, yes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check react test case, they have cases to load server modules There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In |
||
} else if (bodyStr) { | ||
args = await decodeReply(bodyStr); | ||
args = await decodeReply(bodyStr, bundlerConfig); | ||
} | ||
const [fileId, name] = rsfId.split('#') as [string, string]; | ||
let mod: any; | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this won't work because node condition is not including
react-server
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's why you need a vite server to load the module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and import() doesn't support .ts(x) file in dev side
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, but it should work on PRD, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, but ID is not correct; it is now like
/path/to/file
which is presented as HTTP resource