0x1
Version:
18 lines (16 loc) • 6.81 kB
JavaScript
var E=new Map,$=new Map;function U(j,B){let z=B||j.name||"anonymous";E.set(z,"client")}function O(j,B){let z=B||j.name||"anonymous";E.set(z,"server"),$.set(z,j)}function R(j){return E.get(j)==="client"}function b(j){return E.get(j)==="server"}async function w(j,...B){let z=$.get(j);if(!z)throw new Error(`Server function "${j}" not found`);if(typeof window!=="undefined")try{let G=await fetch("/__0x1_server_action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({functionName:j,args:B})});if(!G.ok)throw new Error(`Server function failed: ${G.statusText}`);return await G.json()}catch(G){throw console.error(`Error executing server function "${j}":`,G),G}try{return await z(...B)}catch(G){throw console.error(`Error executing server function "${j}":`,G),G}}function q(j,B){let z=B||j.name||"anonymous";return O(j,z),(...G)=>{return w(z,...G)}}function k(j,B){let z=j.split(`
`),G=null,Q=[],K=[],L;for(let M=0;M<Math.min(5,z.length);M++){let W=z[M].trim();if(W==='"use client"'||W==="'use client'"){G="client";break}if(W==='"use server"'||W==="'use server'"){G="server";break}}if(!G){if(L=D(j,B),L)j=`// 0x1 Auto-inferred: This file is treated as "${L}" context
// Add "use ${L}" at the top to make this explicit
`+j}let J=G||L;if(J){let M=_(j,J,B);K.push(...M)}let V=j;if(J==="server"){let M=/(?:export\s+)?async\s+function\s+(\w+)/g,W=/(?:export\s+)?const\s+(\w+)\s*=\s*async\s*\(/g,Z=/(?:export\s+)?function\s+(\w+)/g,Y=/(?:export\s+)?const\s+(\w+)\s*=\s*\([^)]*\)\s*=>/g,X;while((X=M.exec(j))!==null){let T=X[1];Q.push(T)}while((X=W.exec(j))!==null){let T=X[1];Q.push(T)}while((X=Z.exec(j))!==null){let T=X[1];if(!/^[A-Z]/.test(T)){let H=j.substring(0,X.index).split(`
`).length;K.push({type:"server-context-warning",message:`Function '${T}' in server context should typically be async`,line:H,suggestion:"Consider making this function async or move it to a client component if it doesn't need server-side execution"})}}if(Q.length>0)V+=`
// 0x1 Server Action Registration (server-side only)
// Note: Server actions are automatically registered during transpilation
`}if(J==="client"){let M=/export\s+(?:default\s+)?function\s+(\w+)/g,W=/export\s+const\s+(\w+)\s*=\s*\(/g,Z=[],Y;while((Y=M.exec(j))!==null)Z.push(Y[1]);while((Y=W.exec(j))!==null)Z.push(Y[1]);let X=/(?:export\s+)?(?:async\s+function|const\s+\w+\s*=\s*async)/g;while((Y=X.exec(j))!==null){let T=j.substring(0,Y.index).split(`
`).length;K.push({type:"client-context-warning",message:"Async functions in client components should use React hooks like useEffect for async operations",line:T,suggestion:"Use useEffect(() => { async function fetchData() { ... } fetchData(); }, []) for async operations in client components"})}if(Z.length>0){let T=`
// 0x1 Client Component Registration (processed server-side)
// Components: ${Z.join(", ")}
`;V+=T}}return{code:V,directive:G,serverFunctions:Q,errors:K,inferredContext:L}}function D(j,B){let z=[/import.*from\s+['"]fs['"]/,/import.*from\s+['"]path['"]/,/import.*from\s+['"]crypto['"]/,/await\s+fetch\(/g,/process\.env\./g,/import.*from\s+['"]database['"]/,/\.sql\(/g,/\.query\(/g],G=[/import.*useState.*from/,/import.*useEffect.*from/,/useState\(/g,/useEffect\(/g,/window\./g,/document\./g,/localStorage\./g,/sessionStorage\./g,/addEventListener\(/g,/onClick=/g,/onChange=/g],Q=0,K=0;for(let L of z){let J=j.match(L);if(J)Q+=J.length}for(let L of G){let J=j.match(L);if(J)K+=J.length}if(B.includes("action")||B.includes("server"))Q+=2;if(B.includes("component")||B.includes("client")||B.includes("hook"))K+=2;if(Q>K&&Q>0)return"server";else if(K>Q&&K>0)return"client";return}function _(j,B,z){let G=[],Q=j.split(`
`);if(B==="server"){let K=[{pattern:/window\./g,name:"window"},{pattern:/document\./g,name:"document"},{pattern:/localStorage\./g,name:"localStorage"},{pattern:/sessionStorage\./g,name:"sessionStorage"},{pattern:/addEventListener\(/g,name:"addEventListener"}];for(let J of K){let V;while((V=J.pattern.exec(j))!==null){let M=j.substring(0,V.index).split(`
`).length;G.push({type:"server-context-error",message:`Cannot use browser API '${J.name}' in server context`,line:M,suggestion:'Move this code to a client component with "use client" directive'})}}let L=["useState","useEffect","useCallback","useMemo","useRef"];for(let J of L){let V=new RegExp(`\\b${J}\\(`,"g"),M;while((M=V.exec(j))!==null){let W=j.substring(0,M.index).split(`
`).length;G.push({type:"server-context-error",message:`Cannot use React hook '${J}' in server context`,line:W,suggestion:'Move this component to a client file with "use client" directive'})}}}if(B==="client"){let K=[{pattern:/require\(['"]fs['"]\)/g,name:"fs"},{pattern:/import.*from\s+['"]fs['"]/,name:"fs"},{pattern:/require\(['"]path['"]\)/g,name:"path"},{pattern:/process\.env\./g,name:"process.env"}];for(let L of K){let J;while((J=L.pattern.exec(j))!==null){let V=j.substring(0,J.index).split(`
`).length;G.push({type:"client-context-error",message:`Cannot use server API '${L.name}' in client context`,line:V,suggestion:'Move this code to a server action with "use server" directive'})}}}return G}async function I(j,B){try{let z=await import(B+"?t="+Date.now());if(z[j]&&typeof z[j]==="function")return z[j];if(z.default&&typeof z.default==="function"&&z.default.name===j)return z.default;throw new Error(`Function ${j} not found in ${B}`)}catch(z){throw console.error(`Failed to load server function ${j} from ${B}:`,z),z}}async function y(j){if(j.method!=="POST")return new Response("Method not allowed",{status:405});try{let B=await j.json(),{functionName:z,args:G,__filePath:Q}=B;if(!z)return new Response(JSON.stringify({error:"Function name is required"}),{status:400,headers:{"Content-Type":"application/json"}});let K;if($.has(z))K=$.get(z);else if(Q)K=await I(z,Q);else return new Response(JSON.stringify({error:`Server function "${z}" not found and no file path provided`}),{status:404,headers:{"Content-Type":"application/json"}});let L=await K(...G||[]);return new Response(JSON.stringify(L),{status:200,headers:{"Content-Type":"application/json"}})}catch(B){return console.error("Server action error:",B),new Response(JSON.stringify({error:B instanceof Error?B.message:"Unknown error",stack:B instanceof Error?B.stack:void 0}),{status:500,headers:{"Content-Type":"application/json"}})}}function A(j){return q(j)}function P(j){return U(j),j}function S(){if(typeof window!=="undefined")window.addEventListener("unhandledrejection",(j)=>{if(j.reason?.message?.includes("Server function"))console.error("Unhandled server action error:",j.reason)})}export{A as serverAction,k as processDirectives,O as markAsServer,U as markAsClient,b as isServerFunction,R as isClientComponent,S as initializeDirectives,y as handleServerAction,w as executeServerFunction,q as createServerAction,P as clientComponent};