@metagptx/web-sdk 0.0.52-beta.11 → 0.0.52-beta.13

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.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import * as axios0 from "axios";
2
2
  import { AxiosRequestConfig } from "axios";
3
- import { Plugin } from "vite";
4
3
 
5
4
  //#region src/utils/request.d.ts
6
5
  /**
@@ -118,31 +117,6 @@ type IntegrationFunction = (params?: IntegrationParams) => Promise<AnyType>;
118
117
  * @param params.requestInstance - Axios instance for making HTTP requests
119
118
  * @returns Proxy object that dynamically creates integration calls
120
119
  */
120
+
121
121
  //#endregion
122
- //#region src/plugins/vite-plugin-404.d.ts
123
- /**
124
- * Vite plugin to create a virtual 404 React component and automatically add a 404 route
125
- */
126
- declare function vitePlugin404(): Plugin;
127
- //#endregion
128
- //#region src/plugins/vite-plugin-routes.d.ts
129
- interface PluginOptions {
130
- /** 路由文件路径,默认 'src/App.tsx' */
131
- routeFile?: string;
132
- /** 入口文件路径,用于自动注入,默认 'src/main.tsx' */
133
- entryFile?: string;
134
- /** 虚拟模块 ID */
135
- moduleId?: string;
136
- /** 是否自动向父级 iframe 发送路由信息,默认 true */
137
- notifyParent?: boolean;
138
- /** 发送给父级的消息类型标识 */
139
- messageType?: string;
140
- /** 要排除的路由路径模式 */
141
- excludePaths?: string[];
142
- }
143
- /**
144
- * Vite 插件:解析 React Router 的 Route 组件,生成路由信息
145
- */
146
- declare function vitePluginRoutes(options?: PluginOptions): Plugin;
147
- //#endregion
148
- export { type AnyType, type ApiCallParams, type ClientConfig, type IntegrationFunction, type IntegrationParams, type RequestConfig, createClient, vitePlugin404, vitePluginRoutes };
122
+ export { type AnyType, type ApiCallParams, type ClientConfig, type IntegrationFunction, type IntegrationParams, type RequestConfig, createClient };
package/dist/index.js CHANGED
@@ -1,82 +1 @@
1
- import e from"axios";import t from"qs";import n from"node:fs";import r from"node:path";import*as i from"@babel/parser";import a from"@babel/traverse";import*as o from"@babel/types";const s=e=>{let t=e.response?.status;if(t&&t>=400&&t!==401)try{typeof window<`u`&&window.top&&window.top?.postMessage({type:`mgx-appview-error`,targetName:window.name,data:{errMsg:e.response?.data?.message||e.response?.data?.detail||`Server Error`,stack:JSON.stringify({url:e.response?.config?.url,data:e.response?.data,status:e.response?.status})}},`*`)}catch(e){console.warn(`Failed to notify parent window about API error:`,e)}},c=(n={})=>{let{onUnauthorized:r,...i}=n,a=typeof globalThis<`u`&&`localStorage`in globalThis&&typeof globalThis.localStorage?.getItem==`function`?globalThis.localStorage.getItem(`token`)??void 0:void 0,o={timeout:6e4,paramsSerializer:e=>t.stringify(e,{arrayFormat:`brackets`}),...i,headers:{"Content-Type":`application/json`,"App-Host":globalThis?.window?.location?.origin??``,...a?{Authorization:`Bearer ${a}`}:{},...i.headers}},c=e.create(o);return c.interceptors.request.use(e=>e,e=>Promise.reject(e)),c.interceptors.response.use(e=>e,e=>{let t=e.response?.status;return t===401&&r&&r(),s(e),Promise.reject(e)}),c},l=[`stripe.com`],u=e=>typeof e==`string`?e.startsWith(`_`)||e.startsWith(`$`)||e===`constructor`||e===`toString`||e===`valueOf`||e===`inspect`||e===`toJSON`:!0,d=()=>{let e=window.location?.href??``,t=``;e.startsWith(`/`)?t=e:e&&(t=e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i,``));let n=new URLSearchParams({from_url:t});window.location.href=`/api/v1/auth/login?${n.toString()}`},f=()=>globalThis?.window?.name?.includes(`devIframe`),p=e=>e?l.some(t=>e.toString().includes(t)):!1,m=e=>{let{requestInstance:t}=e;return{async login(){let e=new URLSearchParams(window.location.search),t=e.get(`token`);return t&&typeof globalThis<`u`&&`localStorage`in globalThis&&(globalThis.localStorage?.setItem(`token`,t),globalThis.localStorage?.setItem(`isLougOutManual`,`false`),console.log(`login success----`,globalThis.localStorage?.getItem(`token`),globalThis.localStorage?.getItem(`isLougOutManual`)),window.location.href=`/`),t},async me(){return t.get(`/api/v1/auth/me`)},async logout(){typeof globalThis<`u`&&`localStorage`in globalThis&&(globalThis.localStorage?.removeItem(`token`),globalThis.localStorage?.setItem(`isLougOutManual`,`true`),console.log(`logout success----`,globalThis.localStorage?.getItem(`token`),globalThis.localStorage?.getItem(`isLougOutManual`)));let e=await t.get(`/api/v1/auth/logout`);return typeof globalThis<`u`&&`window`in globalThis&&(globalThis.window.opener=null),window.location.href=`/`,e},toLogin:d}},h=e=>{let{requestInstance:t,entityName:n}=e,r=`/api/v1/entities/${n}`,i=e=>{if(!e)return;let t={...e};return e.fields&&Array.isArray(e.fields)&&(t.fields=e.fields.join(`,`)),e.query&&typeof e.query==`object`&&(t.query=JSON.stringify(e.query)),t};return{async query(e){let n=i(e);return t.get(r,{params:n})},async queryAll(e){let n=i(e);return t.get(`${r}/all`,{params:n})},async get(e){let{id:n,...a}=e,o=i(a);return t.get(`${r}/${n}`,{params:o})},async create(e){return t.post(r,e.data)},async update(e){return t.put(`${r}/${e.id}`,e.data)},async delete(e){return t.delete(`${r}/${e.id}`)},async deleteBatch(e){return t.delete(`${r}/batch`,{data:{ids:e.ids}})},async createBatch(e){return t.post(`${r}/batch`,e.data)},async updateBatch(e){return t.put(`${r}/batch`,e.data)}}},g=e=>{let{requestInstance:t}=e,n=new Map;return new Proxy({},{get(e,r){if(!u(r))return n.has(r)||n.set(r,h({requestInstance:t,entityName:r})),n.get(r)}})},_=e=>{let{requestInstance:t}=e;return{async invoke(e){let{url:n,method:r=`GET`,data:i,options:a={}}=e;if(typeof window<`u`&&a?.responseType===`stream`){let e;try{typeof globalThis<`u`&&`localStorage`in globalThis&&typeof globalThis.localStorage?.getItem==`function`&&(e=globalThis.localStorage.getItem(`token`)??void 0)}catch{}let t={"Content-Type":`application/json`,"App-Host":globalThis?.window?.location?.origin??``,...e?{Authorization:`Bearer ${e}`}:{},...a.headers||{}},o;i&&[`POST`,`PUT`,`PATCH`].includes(r.toUpperCase())&&(o=JSON.stringify(i));let s=await fetch(n,{method:r.toUpperCase(),headers:t,body:o});return s}let o={method:r.toUpperCase(),url:n,...a};return i&&[`POST`,`PUT`,`PATCH`].includes(o.method)?o.data=i:i&&[`GET`,`DELETE`].includes(o.method)&&(o.params=i),t.request(o)}}},v=e=>{let{requestInstance:t}=e;return new Proxy({},{get(e,n){if(!u(n))return new Proxy({},{get(e,r){if(!u(r))return(e={})=>{let i=`/api/integrations/core/${r}`;n!==`core`&&(i=`/api/integrations/providers/${n}/${r}`);let{payload:a={},option:o={}}=e,s=a instanceof FormData?{...o,headers:{...o.headers,"Content-Type":void 0}}:o;return t.post(i,a,s)}}})}})};let y=null;const b=e=>{if(y)return;let{requestInstance:t}=e,n=async e=>{let n=globalThis?.localStorage?.getItem(`token`);if(n)return;let r=e.token,i=await t.post(`/api/v1/auth/token/exchange`,{platform_token:r});i.status===200&&i.data.token&&(globalThis?.localStorage?.setItem(`token`,i.data.token),window.location.href=`/`)},r=e=>{switch(e.data.type){case`mgx-token-saved`:n(e.data.data);break;default:break}};y={requestInstance:t,handleMessage:r},globalThis?.window?.addEventListener(`message`,r)},x=()=>{let e=(e,t,n,r)=>{if(globalThis?.window===void 0||!globalThis?.window?.top){console.warn(`postMessage: window.top is not available`);return}try{let{targetOrigin:i=`*`,targetName:a=globalThis?.window?.name??``}=n||{},o={type:e,targetName:a,data:t};(r??globalThis?.window?.top)?.postMessage(o,i)}catch(e){console.warn(`Failed to send postMessage:`,e)}};return{postMessage:e}};let S=!1;const C=e=>{b(e);let{postMessage:t}=x(),n=()=>{if(S)return;S=!0;let e=globalThis?.localStorage?.getItem(`token`),n=globalThis?.localStorage?.getItem(`isLougOutManual`)===`true`,r=window.self!==window.top&&window.name?.includes(`devIframe`);console.log(`init----`,e,n,r),!e&&!n&&r&&(console.log(`init----`,`send mgx-token-request`),t(`mgx-token-request`,{domain:globalThis?.window?.location?.href??``},{},globalThis?.window?.opener),t(`mgx-token-request`,{domain:globalThis?.window?.location?.href??``}))};return n(),{createPage(e){let n=e??globalThis?.window?.location?.pathname??``;t(`mgx-create-page`,{path:n})}}},w=()=>{let{postMessage:e}=x(),t=t=>{if(t){if(globalThis?.window===void 0){console.warn(`openUrl: window is not available`);return}if(p(t)&&f()){e(`mgx-open-url`,{url:t.toString()},{},globalThis?.window?.opener);return}globalThis.window.location.href=t.toString()}};return{openUrl:t}},T=(e={})=>{let t=c({baseURL:`/`,...e});console.log(`createClient----`,t);let n=m({requestInstance:t}),r=g({requestInstance:t}),i=_({requestInstance:t}),a=v({requestInstance:t}),o=C({requestInstance:t}),s=w();return{auth:n,entities:r,apiCall:i,integrations:a,frame:o,utils:s}};function E(){let e=`virtual:404-page`,t=`import { Button } from '@/components/ui/button';
2
- import { createClient } from '@metagptx/web-sdk';
3
-
4
- // Create client instance
5
- const client = createClient();
6
-
7
- export default function NotFoundPage() {
8
- const isInMGXIframe =
9
- window.self !== window.top && window.name?.includes('devIframe');
10
- return (
11
- <div className="min-h-screen flex flex-col items-center justify-center bg-gradient-to-br from-gray-50 to-blue-50 p-6 text-center">
12
- <div className="space-y-6 max-w-md">
13
- <div className="space-y-3">
14
- <h1 className="text-5xl font-bold text-primary">404</h1>
15
- <h2 className="text-2xl font-semibold text-gray-800">
16
- Page Not Found
17
- </h2>
18
- <p className="text-muted-foreground">
19
- The page you're looking for doesn't exist or may have been moved.
20
- </p>
21
- </div>
22
-
23
- <div className="flex flex-col sm:flex-row gap-3 justify-center">
24
- <Button asChild>
25
- <a href="/">Return Home</a>
26
- </Button>
27
- {isInMGXIframe ? (
28
- <Button variant="outline" onClick={() => client.frame.createPage()}>
29
- Create page
30
- </Button>
31
- ) : (
32
- <Button
33
- variant="outline"
34
- onClick={() => (window.location.href = 'https://mgx.dev')}
35
- >
36
- Go to MGX
37
- </Button>
38
- )}
39
- </div>
40
- </div>
41
- </div>
42
- );
43
- }
44
- `;return{name:`vite-plugin-404`,enforce:`pre`,resolveId(t){return t===e||t.startsWith(e)?`\0${e}.tsx`:null},load(n){return n===`\0${e}.tsx`||n.includes(`virtual:404-page`)?t:null},transform(e,t){if(!t.includes(`App.tsx`)||!t.endsWith(`.tsx`))return null;let n=e.includes(`virtual:404-page`)||e.includes(`NotFound404`)||e.includes(`NotFoundPage`)||/path\s*=\s*["']\*["']/.test(e);if(n)return null;let r=!1,i=e.includes(`virtual:404-page`);if(!i){let t=/(import\s+AuthError\s+from\s+['"][^'"]+AuthError[^'"]*['"];)/;if(t.test(e))e=e.replace(t,`$1
45
- import NotFoundPage from 'virtual:404-page';`),r=!0;else if(/\/\/\s*MODULE_IMPORTS_END/.test(e))e=e.replace(/(\/\/\s*MODULE_IMPORTS_END)/,`$1
46
- import NotFoundPage from 'virtual:404-page';`),r=!0;else if(/\/\/\s*MODULE_IMPORTS_START/.test(e))e=e.replace(/(\/\/\s*MODULE_IMPORTS_START)/,`import NotFoundPage from 'virtual:404-page';
47
- $1`),r=!0;else{let t=/(^import\s[^;]+;)/gm,n=[...e.matchAll(t)];if(n.length>0){let t=n[n.length-1],i=t.index+t[0].length,a=e.substring(0,i),o=e.substring(i);e=`${a}\nimport NotFoundPage from 'virtual:404-page';${o}`,r=!0}}}let a=/path\s*=\s*["']\*["']/.test(e);if(!a){if(/\/\/\s*MODULE_ROUTES_END/.test(e)){let t=e.match(/(\s*)\/\/\s*MODULE_ROUTES_END/);if(t){let n=t[1];e=e.replace(/(\s*)\/\/\s*MODULE_ROUTES_END/,`${n}<Route path="*" element={<NotFoundPage />} />\n$1// MODULE_ROUTES_END`),r=!0}}else if(/<\/Routes>/.test(e)){let t=e.match(/(\s*)<\/Routes>/);if(t){let n=t[1],i=e.match(/(\s+)<Route\s+path=/),a=i?i[1]:`${n} `;e=e.replace(/(\s*)<\/Routes>/,`${a}<Route path="*" element={<NotFoundPage />} />\n$1</Routes>`),r=!0}}else if(/<Route\s+path=/.test(e)){let t=/<Route\s[^>]*\/>|<Route\s[^>]*>[\s\S]*?<\/Route>/g,n=[...e.matchAll(t)];if(n.length>0){let t=n[n.length-1],i=t.index+t[0].length,a=e.substring(0,i),o=e.substring(i),s=a.split(`
48
- `),c=s[s.length-1],l=c.match(/^(\s*)/)?.[1]||``;e=`${a}\n${l}<Route path="*" element={<NotFoundPage />} />${o}`,r=!0}}}return r?{code:e,map:null}:null}}}const D=a.default||a;function O(e={}){let{routeFile:t=`src/App.tsx`,entryFile:a=`src/main.tsx`,moduleId:s=`virtual:routes-manifest`,notifyParent:c=!0,messageType:l=`ROUTES_MANIFEST`,excludePaths:u=[`*`]}=e,d=`\0${s}`,f=process.cwd();function p(e,t){for(let n of e)if(o.isJSXAttribute(n)&&o.isJSXIdentifier(n.name,{name:t})&&o.isStringLiteral(n.value))return n.value.value}function m(e){for(let t of e)if(o.isJSXAttribute(t)&&o.isJSXIdentifier(t.name,{name:`element`})){let e=t.value;if(o.isJSXExpressionContainer(e)){let t=e.expression;if(o.isJSXElement(t)){let e=t.openingElement;if(o.isJSXIdentifier(e.name))return e.name.name}}}}function h(e){return e.some(e=>o.isJSXAttribute(e)&&o.isJSXIdentifier(e.name,{name:`element`}))}function g(e){return e.some(e=>o.isJSXAttribute(e)&&o.isJSXIdentifier(e.name,{name:`index`}))}function _(e,t){let n=[];for(let r of e)if(o.isJSXElement(r)){let e=r.openingElement;if(o.isJSXIdentifier(e.name,{name:`Route`})){let e=v(r,t);e&&n.push(e)}}return n}function v(e,t){let n=e.openingElement.attributes,r=p(n,`path`),i=g(n),a=h(n),o=m(n),s;if(i)s=t||`/`;else if(r===void 0)return null;else s=r.startsWith(`/`)?r:t===`/`?`/${r}`:`${t}/${r}`;s=s.replace(/\/+/g,`/`),s!==`/`&&s.endsWith(`/`)&&(s=s.slice(0,-1));let c={path:s,hasElement:a,elementName:o,isWildcard:r===`*`,isIndex:i};if(e.children&&e.children.length>0){let t=_(e.children,s);t.length>0&&(c.children=t)}return c}function y(e,t=[]){for(let n of e)n.hasElement&&t.push({path:n.path,elementName:n.elementName}),n.children&&y(n.children,t);return t}function b(e){let t=0;for(let n of e)t++,n.children&&(t+=b(n.children));return t}function x(e){let t={routeTree:[],routes:[],pageCount:0,total:0,generatedAt:new Date().toISOString()};if(!n.existsSync(e))return console.warn(`[routes-scanner] Route file not found: ${e}`),t;let r=n.readFileSync(e,`utf-8`),a;try{a=i.parse(r,{sourceType:`module`,plugins:[`jsx`,`typescript`]})}catch(e){return console.error(`[routes-scanner] Failed to parse route file:`,e),t}let s=[];D(a,{JSXElement(e){let t=e.node.openingElement;if(o.isJSXIdentifier(t.name,{name:`Routes`})){let t=e.node.children;for(let e of t)if(o.isJSXElement(e)){let t=e.openingElement;if(o.isJSXIdentifier(t.name,{name:`Route`})){let t=v(e,``);t&&s.push(t)}}e.stop()}}});let c=y(s),l=c.filter(e=>!u.some(t=>e.path===t||e.path.match(RegExp(`^${t.replace(`*`,`.*`)}$`))));return{routeTree:s,routes:c,pageCount:l.length,total:b(s),generatedAt:new Date().toISOString()}}return{name:`vite-plugin-routes-scanner`,configResolved(e){f=e.root},resolveId(e){if(e===s)return d},load(e){if(e===d){let e=r.resolve(f,t),n=x(e),i=c?`
49
- // 向父级 iframe 发送路由信息
50
- function notifyParentWindow() {
51
- console.log('[routes-scanner] notifyParentWindow', routesManifest);
52
- if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
53
- try {
54
- window.parent.postMessage({
55
- type: '${l}',
56
- payload: routesManifest,
57
- }, '*');
58
- } catch (e) {
59
- console.warn('[routes-scanner] Failed to notify parent window:', e);
60
- }
61
- }
62
- }
63
-
64
- // 页面加载完成后发送
65
- if (typeof window !== 'undefined') {
66
- if (document.readyState === 'complete') {
67
- notifyParentWindow();
68
- } else {
69
- window.addEventListener('load', notifyParentWindow);
70
- }
71
- }
72
-
73
- export { notifyParentWindow };
74
- `:``;return`
75
- export const routesManifest = ${JSON.stringify(n,null,2)};
76
- export const routeTree = routesManifest.routeTree;
77
- export const routes = routesManifest.routes;
78
- export const pageCount = routesManifest.pageCount;
79
- export const total = routesManifest.total;
80
- ${i}
81
- export default routesManifest;
82
- `}},transform(e,t){let n=t.replace(/\\/g,`/`),i=r.resolve(f,a).replace(/\\/g,`/`);if(n===i&&c){let t=`import "${s}";\n`;return e.includes(s)?null:{code:t+e,map:null}}return null},configureServer(e){let n=r.resolve(f,t);e.watcher.add(n),e.watcher.on(`change`,t=>{if(t===n){let t=e.moduleGraph.getModuleById(d);t&&(e.moduleGraph.invalidateModule(t),e.ws.send({type:`full-reload`}))}})}}}export{T as createClient,E as vitePlugin404,O as vitePluginRoutes};
1
+ import e from"axios";import t from"qs";const n=e=>{let t=e.response?.status;if(t&&t>=400&&t!==401)try{typeof window<`u`&&window.top&&window.top?.postMessage({type:`mgx-appview-error`,targetName:window.name,data:{errMsg:e.response?.data?.message||e.response?.data?.detail||`Server Error`,stack:JSON.stringify({url:e.response?.config?.url,data:e.response?.data,status:e.response?.status})}},`*`)}catch(e){console.warn(`Failed to notify parent window about API error:`,e)}},r=(r={})=>{let{onUnauthorized:i,...a}=r,o=typeof globalThis<`u`&&`localStorage`in globalThis&&typeof globalThis.localStorage?.getItem==`function`?globalThis.localStorage.getItem(`token`)??void 0:void 0,s={timeout:6e4,paramsSerializer:e=>t.stringify(e,{arrayFormat:`brackets`}),...a,headers:{"Content-Type":`application/json`,"App-Host":globalThis?.window?.location?.origin??``,...o?{Authorization:`Bearer ${o}`}:{},...a.headers}},c=e.create(s);return c.interceptors.request.use(e=>e,e=>Promise.reject(e)),c.interceptors.response.use(e=>e,e=>{let t=e.response?.status;return t===401&&i&&i(),n(e),Promise.reject(e)}),c},i=[`stripe.com`],a=e=>typeof e==`string`?e.startsWith(`_`)||e.startsWith(`$`)||e===`constructor`||e===`toString`||e===`valueOf`||e===`inspect`||e===`toJSON`:!0,o=()=>{let e=window.location?.href??``,t=``;e.startsWith(`/`)?t=e:e&&(t=e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/]+/i,``));let n=new URLSearchParams({from_url:t});window.location.href=`/api/v1/auth/login?${n.toString()}`},s=()=>globalThis?.window?.name?.includes(`devIframe`),c=e=>e?i.some(t=>e.toString().includes(t)):!1,l=e=>{let{requestInstance:t}=e;return{async login(){let e=new URLSearchParams(window.location.search),t=e.get(`token`);return t&&typeof globalThis<`u`&&`localStorage`in globalThis&&(globalThis.localStorage?.setItem(`token`,t),globalThis.localStorage?.setItem(`isLougOutManual`,`false`),console.log(`login success----`,globalThis.localStorage?.getItem(`token`),globalThis.localStorage?.getItem(`isLougOutManual`)),window.location.href=`/`),t},async me(){return t.get(`/api/v1/auth/me`)},async logout(){typeof globalThis<`u`&&`localStorage`in globalThis&&(globalThis.localStorage?.removeItem(`token`),globalThis.localStorage?.setItem(`isLougOutManual`,`true`),console.log(`logout success----`,globalThis.localStorage?.getItem(`token`),globalThis.localStorage?.getItem(`isLougOutManual`)));let e=await t.get(`/api/v1/auth/logout`);return typeof globalThis<`u`&&`window`in globalThis&&(globalThis.window.opener=null),window.location.href=`/`,e},toLogin:o}},u=e=>{let{requestInstance:t,entityName:n}=e,r=`/api/v1/entities/${n}`,i=e=>{if(!e)return;let t={...e};return e.fields&&Array.isArray(e.fields)&&(t.fields=e.fields.join(`,`)),e.query&&typeof e.query==`object`&&(t.query=JSON.stringify(e.query)),t};return{async query(e){let n=i(e);return t.get(r,{params:n})},async queryAll(e){let n=i(e);return t.get(`${r}/all`,{params:n})},async get(e){let{id:n,...a}=e,o=i(a);return t.get(`${r}/${n}`,{params:o})},async create(e){return t.post(r,e.data)},async update(e){return t.put(`${r}/${e.id}`,e.data)},async delete(e){return t.delete(`${r}/${e.id}`)},async deleteBatch(e){return t.delete(`${r}/batch`,{data:{ids:e.ids}})},async createBatch(e){return t.post(`${r}/batch`,e.data)},async updateBatch(e){return t.put(`${r}/batch`,e.data)}}},d=e=>{let{requestInstance:t}=e,n=new Map;return new Proxy({},{get(e,r){if(!a(r))return n.has(r)||n.set(r,u({requestInstance:t,entityName:r})),n.get(r)}})},f=e=>{let{requestInstance:t}=e;return{async invoke(e){let{url:n,method:r=`GET`,data:i,options:a={}}=e;if(typeof window<`u`&&a?.responseType===`stream`){let e;try{typeof globalThis<`u`&&`localStorage`in globalThis&&typeof globalThis.localStorage?.getItem==`function`&&(e=globalThis.localStorage.getItem(`token`)??void 0)}catch{}let t={"Content-Type":`application/json`,"App-Host":globalThis?.window?.location?.origin??``,...e?{Authorization:`Bearer ${e}`}:{},...a.headers||{}},o;i&&[`POST`,`PUT`,`PATCH`].includes(r.toUpperCase())&&(o=JSON.stringify(i));let s=await fetch(n,{method:r.toUpperCase(),headers:t,body:o});return s}let o={method:r.toUpperCase(),url:n,...a};return i&&[`POST`,`PUT`,`PATCH`].includes(o.method)?o.data=i:i&&[`GET`,`DELETE`].includes(o.method)&&(o.params=i),t.request(o)}}},p=e=>{let{requestInstance:t}=e;return new Proxy({},{get(e,n){if(!a(n))return new Proxy({},{get(e,r){if(!a(r))return(e={})=>{let i=`/api/integrations/core/${r}`;n!==`core`&&(i=`/api/integrations/providers/${n}/${r}`);let{payload:a={},option:o={}}=e,s=a instanceof FormData?{...o,headers:{...o.headers,"Content-Type":void 0}}:o;return t.post(i,a,s)}}})}})};let m=null;const h=e=>{if(m)return;let{requestInstance:t}=e,n=async e=>{let n=globalThis?.localStorage?.getItem(`token`);if(n)return;let r=e.token,i=await t.post(`/api/v1/auth/token/exchange`,{platform_token:r});i.status===200&&i.data.token&&(globalThis?.localStorage?.setItem(`token`,i.data.token),window.location.href=`/`)},r=e=>{switch(e.data.type){case`mgx-token-saved`:n(e.data.data);break;default:break}};m={requestInstance:t,handleMessage:r},globalThis?.window?.addEventListener(`message`,r)},g=()=>{let e=(e,t,n,r)=>{if(globalThis?.window===void 0||!globalThis?.window?.top){console.warn(`postMessage: window.top is not available`);return}try{let{targetOrigin:i=`*`,targetName:a=globalThis?.window?.name??``}=n||{},o={type:e,targetName:a,data:t};(r??globalThis?.window?.top)?.postMessage(o,i)}catch(e){console.warn(`Failed to send postMessage:`,e)}};return{postMessage:e}};let _=!1;const v=e=>{h(e);let{postMessage:t}=g(),n=()=>{if(_)return;_=!0;let e=globalThis?.localStorage?.getItem(`token`),n=globalThis?.localStorage?.getItem(`isLougOutManual`)===`true`,r=window.self!==window.top&&window.name?.includes(`devIframe`);console.log(`init----`,e,n,r),!e&&!n&&r&&(console.log(`init----`,`send mgx-token-request`),t(`mgx-token-request`,{domain:globalThis?.window?.location?.href??``},{},globalThis?.window?.opener),t(`mgx-token-request`,{domain:globalThis?.window?.location?.href??``}))};return n(),{createPage(e){let n=e??globalThis?.window?.location?.pathname??``;t(`mgx-create-page`,{path:n})}}},y=()=>{let{postMessage:e}=g(),t=t=>{if(t){if(globalThis?.window===void 0){console.warn(`openUrl: window is not available`);return}if(c(t)&&s()){e(`mgx-open-url`,{url:t.toString()},{},globalThis?.window?.opener);return}globalThis.window.location.href=t.toString()}};return{openUrl:t}},b=(e={})=>{let t=r({baseURL:`/`,...e});console.log(`createClient----`,t);let n=l({requestInstance:t}),i=d({requestInstance:t}),a=f({requestInstance:t}),o=p({requestInstance:t}),s=v({requestInstance:t}),c=y();return{auth:n,entities:i,apiCall:a,integrations:o,frame:s,utils:c}};export{b as createClient};
@@ -0,0 +1,141 @@
1
+ import { Plugin } from "vite";
2
+
3
+ //#region src/types/plugins.d.ts
4
+
5
+ /**
6
+ * Vite 插件相关类型定义
7
+ */
8
+ // ==================== vite-plugin-routes 类型 ====================
9
+ interface RouteInfo {
10
+ /** 完整路由路径 */
11
+ path: string;
12
+ /** 是否有 element(即是否为可访问页面) */
13
+ hasElement: boolean;
14
+ /** element 组件名称(如果可识别) */
15
+ elementName?: string;
16
+ /** 是否为通配符路由 */
17
+ isWildcard: boolean;
18
+ /** 是否为 index 路由 */
19
+ isIndex: boolean;
20
+ /** 子路由 */
21
+ children?: RouteInfo[];
22
+ }
23
+ interface RoutesManifest {
24
+ /** 所有路由(树形结构) */
25
+ routeTree: RouteInfo[];
26
+ /** 扁平化的路由列表(只包含有 element 的路由) */
27
+ routes: Array<{
28
+ path: string;
29
+ elementName?: string;
30
+ }>;
31
+ /** 可访问页面总数(排除通配符和纯布局路由) */
32
+ pageCount: number;
33
+ /** 所有路由总数 */
34
+ total: number;
35
+ /** 生成时间戳 */
36
+ generatedAt: string;
37
+ }
38
+ interface PluginRoutesOptions {
39
+ /**
40
+ * 路由文件路径
41
+ * @default 'src/App.tsx'
42
+ */
43
+ routeFile?: string;
44
+
45
+ /**
46
+ * 入口文件路径,用于自动注入
47
+ * @default 'src/main.tsx'
48
+ */
49
+ entryFile?: string;
50
+
51
+ /**
52
+ * 虚拟模块 ID
53
+ * @default 'virtual:routes-manifest'
54
+ */
55
+ moduleId?: string;
56
+
57
+ /**
58
+ * 是否自动向父级 iframe 发送路由信息
59
+ * @default true
60
+ */
61
+ notifyParent?: boolean;
62
+
63
+ /**
64
+ * 发送给父级的消息类型标识
65
+ * @default 'ROUTES_MANIFEST'
66
+ */
67
+ messageType?: string;
68
+
69
+ /**
70
+ * 要排除的路由路径模式
71
+ * @default ['*']
72
+ */
73
+ excludePaths?: string[];
74
+ }
75
+
76
+ // ==================== vite-plugin-404 类型 ====================
77
+
78
+ // vite-plugin-404 目前不需要配置选项
79
+
80
+ // ==================== atomsPlugins 容器类型 ====================
81
+
82
+ interface Plugin404Options {
83
+ /**
84
+ * 是否启用 404 插件
85
+ * @default true
86
+ */
87
+ enable?: boolean;
88
+ }
89
+ interface AtomsPluginRoutesOptions extends PluginRoutesOptions {
90
+ /**
91
+ * 是否启用路由扫描插件
92
+ * @default true
93
+ */
94
+ enable?: boolean;
95
+ }
96
+ interface AtomsPluginOptions {
97
+ /**
98
+ * 404 页面插件配置
99
+ */
100
+ '404'?: Plugin404Options;
101
+
102
+ /**
103
+ * 路由扫描插件配置
104
+ */
105
+ routes?: AtomsPluginRoutesOptions;
106
+ }
107
+ //#endregion
108
+ //#region src/plugins/vite-plugin-atoms.d.ts
109
+ /**
110
+ * Atoms Vite 插件容器
111
+ *
112
+ * 整合了 404 页面插件和路由扫描插件
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * // vite.config.ts
117
+ * import { atoms } from '@metagptx/web-sdk/plugins';
118
+ *
119
+ * export default defineConfig({
120
+ * plugins: [
121
+ * atoms(),
122
+ * ],
123
+ * });
124
+ * ```
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * // 自定义配置
129
+ * atomsPlugins({
130
+ * '404': { enable: true },
131
+ * routes: {
132
+ * enable: true,
133
+ * routeFile: 'src/App.tsx',
134
+ * notifyParent: true,
135
+ * },
136
+ * })
137
+ * ```
138
+ */
139
+ declare function atoms(options?: AtomsPluginOptions): Plugin[];
140
+ //#endregion
141
+ export { type AtomsPluginOptions, type AtomsPluginRoutesOptions, type Plugin404Options, type PluginRoutesOptions, type RouteInfo, type RoutesManifest, atoms };
@@ -0,0 +1,82 @@
1
+ import e from"node:fs";import t from"node:path";import*as n from"@babel/parser";import r from"@babel/traverse";import*as i from"@babel/types";function a(){let e=`virtual:404-page`,t=`import { Button } from '@/components/ui/button';
2
+ import { createClient } from '@metagptx/web-sdk';
3
+
4
+ // Create client instance
5
+ const client = createClient();
6
+
7
+ export default function NotFoundPage() {
8
+ const isInMGXIframe =
9
+ window.self !== window.top && window.name?.includes('devIframe');
10
+ return (
11
+ <div className="min-h-screen flex flex-col items-center justify-center bg-gradient-to-br from-gray-50 to-blue-50 p-6 text-center">
12
+ <div className="space-y-6 max-w-md">
13
+ <div className="space-y-3">
14
+ <h1 className="text-5xl font-bold text-primary">404</h1>
15
+ <h2 className="text-2xl font-semibold text-gray-800">
16
+ Page Not Found
17
+ </h2>
18
+ <p className="text-muted-foreground">
19
+ The page you're looking for doesn't exist or may have been moved.
20
+ </p>
21
+ </div>
22
+
23
+ <div className="flex flex-col sm:flex-row gap-3 justify-center">
24
+ <Button asChild>
25
+ <a href="/">Return Home</a>
26
+ </Button>
27
+ {isInMGXIframe ? (
28
+ <Button variant="outline" onClick={() => client.frame.createPage()}>
29
+ Create page
30
+ </Button>
31
+ ) : (
32
+ <Button
33
+ variant="outline"
34
+ onClick={() => (window.location.href = 'https://mgx.dev')}
35
+ >
36
+ Go to MGX
37
+ </Button>
38
+ )}
39
+ </div>
40
+ </div>
41
+ </div>
42
+ );
43
+ }
44
+ `;return{name:`vite-plugin-404`,enforce:`pre`,resolveId(t){return t===e||t.startsWith(e)?`\0${e}.tsx`:null},load(n){return n===`\0${e}.tsx`||n.includes(`virtual:404-page`)?t:null},transform(e,t){if(!t.includes(`App.tsx`)||!t.endsWith(`.tsx`))return null;let n=e.includes(`virtual:404-page`)||e.includes(`NotFound404`)||e.includes(`NotFoundPage`)||/path\s*=\s*["']\*["']/.test(e);if(n)return null;let r=!1,i=e.includes(`virtual:404-page`);if(!i){let t=/(import\s+AuthError\s+from\s+['"][^'"]+AuthError[^'"]*['"];)/;if(t.test(e))e=e.replace(t,`$1
45
+ import NotFoundPage from 'virtual:404-page';`),r=!0;else if(/\/\/\s*MODULE_IMPORTS_END/.test(e))e=e.replace(/(\/\/\s*MODULE_IMPORTS_END)/,`$1
46
+ import NotFoundPage from 'virtual:404-page';`),r=!0;else if(/\/\/\s*MODULE_IMPORTS_START/.test(e))e=e.replace(/(\/\/\s*MODULE_IMPORTS_START)/,`import NotFoundPage from 'virtual:404-page';
47
+ $1`),r=!0;else{let t=/(^import\s[^;]+;)/gm,n=[...e.matchAll(t)];if(n.length>0){let t=n[n.length-1],i=t.index+t[0].length,a=e.substring(0,i),o=e.substring(i);e=`${a}\nimport NotFoundPage from 'virtual:404-page';${o}`,r=!0}}}let a=/path\s*=\s*["']\*["']/.test(e);if(!a){if(/\/\/\s*MODULE_ROUTES_END/.test(e)){let t=e.match(/(\s*)\/\/\s*MODULE_ROUTES_END/);if(t){let n=t[1];e=e.replace(/(\s*)\/\/\s*MODULE_ROUTES_END/,`${n}<Route path="*" element={<NotFoundPage />} />\n$1// MODULE_ROUTES_END`),r=!0}}else if(/<\/Routes>/.test(e)){let t=e.match(/(\s*)<\/Routes>/);if(t){let n=t[1],i=e.match(/(\s+)<Route\s+path=/),a=i?i[1]:`${n} `;e=e.replace(/(\s*)<\/Routes>/,`${a}<Route path="*" element={<NotFoundPage />} />\n$1</Routes>`),r=!0}}else if(/<Route\s+path=/.test(e)){let t=/<Route\s[^>]*\/>|<Route\s[^>]*>[\s\S]*?<\/Route>/g,n=[...e.matchAll(t)];if(n.length>0){let t=n[n.length-1],i=t.index+t[0].length,a=e.substring(0,i),o=e.substring(i),s=a.split(`
48
+ `),c=s[s.length-1],l=c.match(/^(\s*)/)?.[1]||``;e=`${a}\n${l}<Route path="*" element={<NotFoundPage />} />${o}`,r=!0}}}return r?{code:e,map:null}:null}}}const o=r.default||r;function s(r={}){let{routeFile:a=`src/App.tsx`,entryFile:s=`src/main.tsx`,moduleId:c=`virtual:routes-manifest`,notifyParent:l=!0,messageType:u=`ROUTES_MANIFEST`,excludePaths:d=[`*`]}=r,f=`\0${c}`,p=process.cwd();function m(e,t){for(let n of e)if(i.isJSXAttribute(n)&&i.isJSXIdentifier(n.name,{name:t})&&i.isStringLiteral(n.value))return n.value.value}function h(e){for(let t of e)if(i.isJSXAttribute(t)&&i.isJSXIdentifier(t.name,{name:`element`})){let e=t.value;if(i.isJSXExpressionContainer(e)){let t=e.expression;if(i.isJSXElement(t)){let e=t.openingElement;if(i.isJSXIdentifier(e.name))return e.name.name}}}}function g(e){return e.some(e=>i.isJSXAttribute(e)&&i.isJSXIdentifier(e.name,{name:`element`}))}function _(e){return e.some(e=>i.isJSXAttribute(e)&&i.isJSXIdentifier(e.name,{name:`index`}))}function v(e,t){let n=[];for(let r of e)if(i.isJSXElement(r)){let e=r.openingElement;if(i.isJSXIdentifier(e.name,{name:`Route`})){let e=y(r,t);e&&n.push(e)}}return n}function y(e,t){let n=e.openingElement.attributes,r=m(n,`path`),i=_(n),a=g(n),o=h(n),s;if(i)s=t||`/`;else if(r===void 0)return null;else s=r.startsWith(`/`)?r:t===`/`?`/${r}`:`${t}/${r}`;s=s.replace(/\/+/g,`/`),s!==`/`&&s.endsWith(`/`)&&(s=s.slice(0,-1));let c={path:s,hasElement:a,elementName:o,isWildcard:r===`*`,isIndex:i};if(e.children&&e.children.length>0){let t=v(e.children,s);t.length>0&&(c.children=t)}return c}function b(e,t=[]){for(let n of e)n.hasElement&&t.push({path:n.path,elementName:n.elementName}),n.children&&b(n.children,t);return t}function x(e){let t=0;for(let n of e)t++,n.children&&(t+=x(n.children));return t}function S(t){let r={routeTree:[],routes:[],pageCount:0,total:0,generatedAt:new Date().toISOString()};if(!e.existsSync(t))return console.warn(`[routes-scanner] Route file not found: ${t}`),r;let a=e.readFileSync(t,`utf-8`),s;try{s=n.parse(a,{sourceType:`module`,plugins:[`jsx`,`typescript`]})}catch(e){return console.error(`[routes-scanner] Failed to parse route file:`,e),r}let c=[];o(s,{JSXElement(e){let t=e.node.openingElement;if(i.isJSXIdentifier(t.name,{name:`Routes`})){let t=e.node.children;for(let e of t)if(i.isJSXElement(e)){let t=e.openingElement;if(i.isJSXIdentifier(t.name,{name:`Route`})){let t=y(e,``);t&&c.push(t)}}e.stop()}}});let l=b(c),u=l.filter(e=>!d.some(t=>e.path===t||e.path.match(RegExp(`^${t.replace(`*`,`.*`)}$`))));return{routeTree:c,routes:l,pageCount:u.length,total:x(c),generatedAt:new Date().toISOString()}}return{name:`vite-plugin-routes-scanner`,configResolved(e){p=e.root},resolveId(e){if(e===c)return f},load(e){if(e===f){let e=t.resolve(p,a),n=S(e),r=l?`
49
+ // 向父级 iframe 发送路由信息
50
+ function notifyParentWindow() {
51
+ console.log('[routes-scanner] notifyParentWindow', routesManifest);
52
+ if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
53
+ try {
54
+ window.parent.postMessage({
55
+ type: '${u}',
56
+ payload: routesManifest,
57
+ }, '*');
58
+ } catch (e) {
59
+ console.warn('[routes-scanner] Failed to notify parent window:', e);
60
+ }
61
+ }
62
+ }
63
+
64
+ // 页面加载完成后发送
65
+ if (typeof window !== 'undefined') {
66
+ if (document.readyState === 'complete') {
67
+ notifyParentWindow();
68
+ } else {
69
+ window.addEventListener('load', notifyParentWindow);
70
+ }
71
+ }
72
+
73
+ export { notifyParentWindow };
74
+ `:``;return`
75
+ export const routesManifest = ${JSON.stringify(n,null,2)};
76
+ export const routeTree = routesManifest.routeTree;
77
+ export const routes = routesManifest.routes;
78
+ export const pageCount = routesManifest.pageCount;
79
+ export const total = routesManifest.total;
80
+ ${r}
81
+ export default routesManifest;
82
+ `}},transform(e,n){let r=n.replace(/\\/g,`/`),i=t.resolve(p,s).replace(/\\/g,`/`);if(r===i&&l){let t=`import "${c}";\n`;return e.includes(c)?null:{code:t+e,map:null}}return null},configureServer(e){let n=t.resolve(p,a);e.watcher.add(n),e.watcher.on(`change`,t=>{if(t===n){let t=e.moduleGraph.getModuleById(f);t&&(e.moduleGraph.invalidateModule(t),e.ws.send({type:`full-reload`}))}})}}}function c(e={}){let{404:t={},routes:n={}}=e,{enable:r=!0}=t,{enable:i=!0,...o}=n,c=[];return r&&c.push(a()),i&&c.push(s(o)),c}export{c as atoms};
package/package.json CHANGED
@@ -1,13 +1,22 @@
1
1
  {
2
2
  "name": "@metagptx/web-sdk",
3
3
  "type": "module",
4
- "version": "0.0.52-beta.11",
4
+ "version": "0.0.52-beta.13",
5
5
  "packageManager": "pnpm@10.15.0+sha512.486ebc259d3e999a4e8691ce03b5cac4a71cbeca39372a9b762cb500cfdf0873e2cb16abe3d951b1ee2cf012503f027b98b6584e4df22524e0c7450d9ec7aa7b",
6
6
  "description": "TypeScript SDK for interacting with FuncSea API",
7
7
  "author": "MetaGPTX",
8
8
  "license": "MIT",
9
9
  "exports": {
10
- ".": "./dist/index.js",
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./plugins": {
16
+ "types": "./dist/plugins.d.ts",
17
+ "import": "./dist/plugins.js",
18
+ "default": "./dist/plugins.js"
19
+ },
11
20
  "./package.json": "./package.json"
12
21
  },
13
22
  "main": "./dist/index.js",
@@ -31,6 +40,26 @@
31
40
  "precommit": "npm run typecheck && lint-staged && npm run test:coverage",
32
41
  "commit-msg": "echo commit-msg"
33
42
  },
43
+ "peerDependencies": {
44
+ "@babel/parser": "^7.0.0",
45
+ "@babel/traverse": "^7.0.0",
46
+ "@babel/types": "^7.0.0",
47
+ "vite": "^4.0.0 || ^5.0.0 || ^6.0.0"
48
+ },
49
+ "peerDependenciesMeta": {
50
+ "@babel/parser": {
51
+ "optional": true
52
+ },
53
+ "@babel/traverse": {
54
+ "optional": true
55
+ },
56
+ "@babel/types": {
57
+ "optional": true
58
+ },
59
+ "vite": {
60
+ "optional": true
61
+ }
62
+ },
34
63
  "dependencies": {
35
64
  "@types/qs": "^6.14.0",
36
65
  "axios": "^1.12.2",
@@ -38,8 +67,7 @@
38
67
  "eslint-plugin-prettier": "^5.5.4",
39
68
  "lint-staged": "^16.2.3",
40
69
  "qs": "^6.14.0",
41
- "simple-git-hooks": "^2.13.1",
42
- "vite": "^5.4.1"
70
+ "simple-git-hooks": "^2.13.1"
43
71
  },
44
72
  "devDependencies": {
45
73
  "@antfu/eslint-config": "^5.4.1",
@@ -55,6 +83,7 @@
55
83
  "prettier": "^3.6.2",
56
84
  "tsdown": "^0.11.9",
57
85
  "typescript": "^5.8.3",
86
+ "vite": "^5.4.1",
58
87
  "vitest": "^3.1.3"
59
88
  },
60
89
  "simple-git-hooks": {