@surph_ai/sdk 0.0.1

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.
Files changed (70) hide show
  1. package/auth/index.js +147 -0
  2. package/base/vinely-base/.nvmrc +1 -0
  3. package/base/vinely-base/README.md +30 -0
  4. package/base/vinely-base/app.js +5 -0
  5. package/base/vinely-base/declarations.d.ts +1 -0
  6. package/base/vinely-base/package.json +103 -0
  7. package/base/vinely-base/public/css/globals-2.css +3699 -0
  8. package/base/vinely-base/public/css/globals.css +3695 -0
  9. package/base/vinely-base/public/js/app.js +1 -0
  10. package/base/vinely-base/public/js/jquery.js +2 -0
  11. package/base/vinely-base/scratch.js +21 -0
  12. package/base/vinely-base/src/client/components/app-sidebar.tsx +59 -0
  13. package/base/vinely-base/src/client/components/assistant-ui/markdown-text.tsx +153 -0
  14. package/base/vinely-base/src/client/components/assistant-ui/thread-list.tsx +67 -0
  15. package/base/vinely-base/src/client/components/assistant-ui/thread.tsx +666 -0
  16. package/base/vinely-base/src/client/components/assistant-ui/tool-fallback.tsx +44 -0
  17. package/base/vinely-base/src/client/components/assistant-ui/tooltip-icon-button.tsx +44 -0
  18. package/base/vinely-base/src/client/components/ui/breadcrumb.tsx +109 -0
  19. package/base/vinely-base/src/client/components/ui/button.tsx +59 -0
  20. package/base/vinely-base/src/client/components/ui/input.tsx +21 -0
  21. package/base/vinely-base/src/client/components/ui/separator.tsx +28 -0
  22. package/base/vinely-base/src/client/components/ui/sheet.tsx +139 -0
  23. package/base/vinely-base/src/client/components/ui/sidebar.tsx +726 -0
  24. package/base/vinely-base/src/client/components/ui/skeleton.tsx +14 -0
  25. package/base/vinely-base/src/client/components/ui/tooltip.tsx +61 -0
  26. package/base/vinely-base/src/client/components/vines-sidebar.tsx +182 -0
  27. package/base/vinely-base/src/client/contexts/SessionContext.tsx +28 -0
  28. package/base/vinely-base/src/client/contexts/SessionReducer.tsx +32 -0
  29. package/base/vinely-base/src/client/hooks/use-mobile.ts +19 -0
  30. package/base/vinely-base/src/client/index.tsx +154 -0
  31. package/base/vinely-base/src/client/lib/API.ts +155 -0
  32. package/base/vinely-base/src/client/lib/RPC.ts +49 -0
  33. package/base/vinely-base/src/client/lib/utils.ts +96 -0
  34. package/base/vinely-base/src/server/index.ts +63 -0
  35. package/base/vinely-base/src/server/routes/api.ts +38 -0
  36. package/base/vinely-base/src/server/routes/chat.ts +133 -0
  37. package/base/vinely-base/src/server/routes/main.ts +36 -0
  38. package/base/vinely-base/src/server/routes/mcp.ts +52 -0
  39. package/base/vinely-base/src/server/routes/rpc.ts +64 -0
  40. package/base/vinely-base/src/server/routes/thread.ts +44 -0
  41. package/base/vinely-base/src/server/utils/APIMgr.ts +156 -0
  42. package/base/vinely-base/src/server/utils/Auth.ts +235 -0
  43. package/base/vinely-base/src/server/utils/fetchManifest.ts +15 -0
  44. package/base/vinely-base/src/server/utils/mcp-auth.ts +251 -0
  45. package/base/vinely-base/tsconfig.json +16 -0
  46. package/base/vinely-base/views/landing.html +187 -0
  47. package/base/vinely-base/views/partials/imports.dev.html +3 -0
  48. package/base/vinely-base/webpack.config.js +112 -0
  49. package/deploy/Dockerfile +9 -0
  50. package/deploy/index.js +244 -0
  51. package/index.js +266 -0
  52. package/package.json +28 -0
  53. package/scaffold/app/gulpfile.js +12 -0
  54. package/scaffold/app/package.json +24 -0
  55. package/scaffold/app/src/index.js +14 -0
  56. package/scaffold/index.js +171 -0
  57. package/scaffold/project/README.md +28 -0
  58. package/scaffold/project/app.js +20 -0
  59. package/scaffold/project/apps/README.md +1 -0
  60. package/scaffold/project/env.txt +4 -0
  61. package/scaffold/project/package-lock.json +2459 -0
  62. package/scaffold/project/package.json +21 -0
  63. package/scaffold/project/public/css/bootstrap.css +5926 -0
  64. package/scaffold/project/public/js/app.js +1 -0
  65. package/scaffold/project/public/js/jquery.js +2 -0
  66. package/scaffold/project/routes/index.js +8 -0
  67. package/scaffold/project/templates/index.mustache +20 -0
  68. package/utils/Realm.js +60 -0
  69. package/utils/http.js +22 -0
  70. package/utils/index.js +276 -0
@@ -0,0 +1,14 @@
1
+ import React from "react"
2
+ import { cn } from "../../lib/utils"
3
+
4
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
5
+ return (
6
+ <div
7
+ data-slot="skeleton"
8
+ className={cn("bg-accent animate-pulse rounded-md", className)}
9
+ {...props}
10
+ />
11
+ )
12
+ }
13
+
14
+ export { Skeleton }
@@ -0,0 +1,61 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
5
+
6
+ import { cn } from "../../lib/utils";
7
+
8
+ function TooltipProvider({
9
+ delayDuration = 0,
10
+ ...props
11
+ }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
12
+ return (
13
+ <TooltipPrimitive.Provider
14
+ data-slot="tooltip-provider"
15
+ delayDuration={delayDuration}
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ function Tooltip({
22
+ ...props
23
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
24
+ return (
25
+ <TooltipProvider>
26
+ <TooltipPrimitive.Root data-slot="tooltip" {...props} />
27
+ </TooltipProvider>
28
+ );
29
+ }
30
+
31
+ function TooltipTrigger({
32
+ ...props
33
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
34
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
35
+ }
36
+
37
+ function TooltipContent({
38
+ className,
39
+ sideOffset = 0,
40
+ children,
41
+ ...props
42
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
43
+ return (
44
+ <TooltipPrimitive.Portal>
45
+ <TooltipPrimitive.Content
46
+ data-slot="tooltip-content"
47
+ sideOffset={sideOffset}
48
+ className={cn(
49
+ "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
50
+ className
51
+ )}
52
+ {...props}
53
+ >
54
+ {children}
55
+ <TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
56
+ </TooltipPrimitive.Content>
57
+ </TooltipPrimitive.Portal>
58
+ );
59
+ }
60
+
61
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
@@ -0,0 +1,182 @@
1
+ import axios from 'axios'
2
+ import React, { useContext, useState, useEffect } from "react"
3
+ import { MessagesSquare } from "lucide-react"
4
+ import {
5
+ Sidebar,
6
+ SidebarContent,
7
+ SidebarFooter,
8
+ SidebarHeader,
9
+ SidebarMenu,
10
+ SidebarMenuButton,
11
+ SidebarMenuItem,
12
+ SidebarRail,
13
+ } from "./ui/sidebar"
14
+ import { SessionContext } from '../contexts/SessionContext'
15
+ import { useAssistantRuntime } from '@assistant-ui/react'
16
+
17
+ const convertToArray = (data: Record<string, any> | undefined): any[] => {
18
+ if (!data) {
19
+ return []
20
+ }
21
+
22
+ const _array: any[] = []
23
+ for (const key of Object.keys(data)) {
24
+ const datasource = data[key]
25
+ if (datasource.index === '') {
26
+ continue
27
+ }
28
+
29
+ _array.push(datasource)
30
+ }
31
+
32
+ return _array
33
+ }
34
+
35
+ const contextRequest = async (datasource: Record<string, any>): Promise<void> => {
36
+ try {
37
+ await axios({
38
+ url: '/context',
39
+ method: 'post',
40
+ // data: { context: datasource },
41
+ headers: { Accept: 'application/json' },
42
+ data: {
43
+ context: {
44
+ vine: datasource.slug
45
+ }
46
+ },
47
+ })
48
+ } catch (error) {
49
+
50
+ }
51
+ }
52
+
53
+ const VinesSidebar = ({ items }: any) => {
54
+ const { context, dispatch } = useContext(SessionContext)
55
+ const { currentSpace, currentDatasource } = context
56
+ const [ indexed, setIndexed ] = useState<Record<string, any>[] | null>(null)
57
+
58
+ const assistantRuntime = useAssistantRuntime() as any
59
+
60
+ useEffect(() => {
61
+ if (indexed) {
62
+ return
63
+ }
64
+
65
+ if (!items) {
66
+ return
67
+ }
68
+
69
+ const _indexed = convertToArray(items).filter(datasource => datasource.index !== '')
70
+ setIndexed(_indexed)
71
+
72
+ if (currentDatasource) {
73
+ return
74
+ }
75
+
76
+ const datasource = _indexed[0]
77
+ dispatch({ type: 'SET_CURRENT_DATASOURCE', data: datasource })
78
+ }, [])
79
+
80
+ useEffect(() => {
81
+ if (!currentDatasource) {
82
+ return
83
+ }
84
+
85
+ contextRequest(currentDatasource)
86
+ }, [currentDatasource])
87
+
88
+ const selectItem = async (e: any): Promise<void> => {
89
+ if (e) {
90
+ e.preventDefault()
91
+ }
92
+
93
+ const threadId = e.target.getAttribute('data-thread')
94
+ const datasourceSlug = e.target.getAttribute('data-source')
95
+ const datasource = items[datasourceSlug]
96
+
97
+ if (currentDatasource.slug === datasource.slug) { // ignore
98
+ return
99
+ }
100
+
101
+ const { threadIds } = assistantRuntime.threads._core._state._baseValue
102
+ if (threadIds.length === 0) { // no conversation started, user toggling between options.
103
+ dispatch({ type: 'SET_CURRENT_DATASOURCE', data: datasource })
104
+ return
105
+ }
106
+
107
+ const previous = document.getElementById(`menu-${currentDatasource.slug}`)
108
+ if (previous?.getAttribute('data-thread') === '-1') {
109
+ const _threadId = threadIds[0]
110
+ const items = Array.from(document.getElementsByClassName('datasource-menu-item'))
111
+ let found = false
112
+ for (const item of items) {
113
+ const dataThread = item.getAttribute('data-thread')
114
+ if (dataThread === _threadId) {
115
+ found = true
116
+ break
117
+ }
118
+ }
119
+
120
+ if (found === false)
121
+ previous?.setAttribute('data-thread', _threadId)
122
+ }
123
+
124
+ if (threadId === '-1') {
125
+ // console.log('Assign thread id: ' + JSON.stringify(threadIds))
126
+ await assistantRuntime.threads.switchToNewThread()
127
+ dispatch({ type: 'SET_CURRENT_DATASOURCE', data: datasource })
128
+ return
129
+ }
130
+
131
+ await assistantRuntime.threads.switchToThread(threadId)
132
+ dispatch({ type: 'SET_CURRENT_DATASOURCE', data: datasource })
133
+ }
134
+
135
+ return (
136
+ <Sidebar>
137
+ <SidebarContent>
138
+ {/* <ThreadList /> */}
139
+ <div className="p-4">
140
+ <ul className="sidebar-list">
141
+ {indexed ? indexed.map((ds: any) => (
142
+ <li key={ds.slug}>
143
+ <a
144
+ href="#"
145
+ className="datasource-menu-item"
146
+ onClick={selectItem}
147
+ id={`menu-${ds.slug}`}
148
+ data-source={ds.slug}
149
+ data-thread="-1"
150
+ style={{
151
+ color: currentDatasource
152
+ ? (ds.slug === currentDatasource.slug) ? '#fff' : '#555'
153
+ : '#333'
154
+ }}
155
+ >
156
+ {ds.name}
157
+ </a>
158
+ </li>
159
+ )): null}
160
+ </ul>
161
+ </div>
162
+ </SidebarContent>
163
+
164
+ <SidebarRail />
165
+ <SidebarFooter>
166
+ <SidebarMenu>
167
+ <SidebarMenuItem style={{ paddingLeft: 10, paddingBottom: 6 }}>
168
+ <a
169
+ href="https://vinely.ai"
170
+ style={{ fontSize: 12, color: '#fff' }}
171
+ target="_blank"
172
+ >
173
+ Powered by <span className="color-accent">Vinely</span>
174
+ </a>
175
+ </SidebarMenuItem>
176
+ </SidebarMenu>
177
+ </SidebarFooter>
178
+ </Sidebar>
179
+ )
180
+ }
181
+
182
+ export { VinesSidebar }
@@ -0,0 +1,28 @@
1
+ import React, { createContext, useReducer } from 'react'
2
+ import sessionReducer from './SessionReducer'
3
+
4
+ interface ContextProps {
5
+ children: any,
6
+ initial: any
7
+ }
8
+
9
+ export const SessionContext: React.Context<any> = createContext({})
10
+
11
+ const SessionContextProvider = ({ children, initial }: ContextProps) => {
12
+ const initialContext = {
13
+ ...initial,
14
+ settings: initial.config
15
+ }
16
+
17
+ const [context, dispatch] = useReducer(sessionReducer, {
18
+ ...initialContext
19
+ })
20
+
21
+ return (
22
+ <SessionContext.Provider value={{context, dispatch}}>
23
+ {children}
24
+ </SessionContext.Provider>
25
+ )
26
+ }
27
+
28
+ export default SessionContextProvider
@@ -0,0 +1,32 @@
1
+ export default (context: any, action: any) => {
2
+ const { data, type } = action;
3
+ switch (type) {
4
+ // case 'SET_CURRENT_USER': {
5
+ // console.log('SET_CURRENT_USER: ' + JSON.stringify(data))
6
+ // return {
7
+ // ...context,
8
+ // user: data
9
+ // }
10
+ // }
11
+
12
+ case 'SET_CURRENT_SPACE': {
13
+ console.log('SET_CURRENT_SPACE: ' + JSON.stringify(data))
14
+ return {
15
+ ...context,
16
+ currentSpace: data,
17
+ currentDatasource: null
18
+ }
19
+ }
20
+
21
+ case 'SET_CURRENT_DATASOURCE': {
22
+ console.log('SET_CURRENT_DATASOURCE: ' + JSON.stringify(data))
23
+ return {
24
+ ...context,
25
+ currentDatasource: data
26
+ }
27
+ }
28
+
29
+ default:
30
+ return context;
31
+ }
32
+ }
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,154 @@
1
+ import React, { useMemo, useEffect, useState } from 'react'
2
+ import ReactDOM from 'react-dom/client'
3
+ import Markdown from 'react-markdown'
4
+ import { BrowserRouter as Router, Route, Switch, useParams } from 'react-router-dom'
5
+ import { AssistantRuntimeProvider } from "@assistant-ui/react"
6
+ import { useChatRuntime } from "@assistant-ui/react-ai-sdk"
7
+ import { Thread } from "./components/assistant-ui/thread"
8
+ import {
9
+ SidebarInset,
10
+ SidebarProvider,
11
+ // SidebarTrigger,
12
+ } from "./components/ui/sidebar"
13
+ import { VinesSidebar } from "./components/vines-sidebar"
14
+ import SessionContextProvider from './contexts/SessionContext'
15
+ import { fetchMessages } from './lib/utils'
16
+ import "katex/dist/katex.min.css";
17
+
18
+ declare global {
19
+ interface Window {
20
+ __CONTEXT__: Record<string, any>
21
+ }
22
+ }
23
+
24
+ const { vineyard } = window.__CONTEXT__
25
+
26
+ const PlainText = () => {
27
+ const [ messages, setMessages ] = useState<Record<string, string>[] | null>(null)
28
+ const { thread_id } = useParams() as any
29
+
30
+ useEffect(() => {
31
+ const _fetchMessages = async () => {
32
+ try {
33
+ const payload = await fetchMessages(vineyard.slug, thread_id)
34
+ setMessages(payload.messages)
35
+ } catch (error: any) {
36
+ console.log('FETCH MESSAGES ERR: ' + error.message)
37
+ }
38
+ }
39
+
40
+ _fetchMessages()
41
+ }, [])
42
+
43
+ return (
44
+ <div className="markdown" style={{ overflow: 'scroll' }}>
45
+ {messages?.map(msg => {
46
+ if (msg.role === 'user') {
47
+ return (
48
+ <div key={msg.id} className="message-user">
49
+ <div style={{ textAlign: 'right'}}>
50
+ <small>{msg.createdAt}</small>
51
+ <p>{msg.text}</p>
52
+ </div>
53
+ </div>
54
+ )
55
+ }
56
+
57
+ return (
58
+ <Markdown key={msg.id}>
59
+ {msg.text}
60
+ </Markdown>
61
+ )
62
+ })}
63
+ </div>
64
+ )
65
+ }
66
+
67
+ const Entry = () => {
68
+ const runtime = useChatRuntime()
69
+
70
+ const metadata = useMemo(() => (vineyard.metadata || {}), [])
71
+
72
+ // useEffect(() => {
73
+ // console.log('THREAD: ' + JSON.stringify(thread))
74
+ // }, [thread])
75
+
76
+ return (
77
+ <Router>
78
+ <AssistantRuntimeProvider runtime={runtime}>
79
+ <SidebarProvider>
80
+ <div className="flex h-dvh w-full pr-0.5">
81
+ <VinesSidebar items={vineyard.datasources} />
82
+ <SidebarInset>
83
+ <header id="nav-header" className="flex h-16 shrink-0 items-center px-4 header">
84
+ <div style={{ flex: 1 }}></div>
85
+ <div style={{ flex: 1, textAlign: 'center', color: '#e8e8e3', paddingTop: 12 }}>
86
+ {metadata.logo
87
+ ? <img
88
+ src={metadata.logo}
89
+ style={{ maxWidth: 220, margin: 'auto', transition: 'all 0.25s linear' }}
90
+ onMouseEnter={(e: any) => {
91
+ e.target.style.opacity = '0.6'
92
+ if (e.target.classList.contains('effect-shine')) {
93
+ return
94
+ }
95
+
96
+ setTimeout(() => {
97
+ e.target.style.transition = 'none'
98
+ e.target.style.opacity = '1'
99
+ e.target.classList.add('effect-shine')
100
+ }, 750)
101
+ }}
102
+ onMouseLeave={(e: any) => {
103
+ e.target.style.transition = 'all 0.25s linear'
104
+ e.target.style.opacity = '0.6'
105
+
106
+ if (!e.target.classList.contains('effect-shine')) {
107
+ return
108
+ }
109
+
110
+ setTimeout(() => {
111
+ e.target.style.opacity = '1'
112
+ e.target.classList.remove('effect-shine')
113
+ }, (350))
114
+ }}
115
+ />
116
+ : vineyard.name
117
+ }
118
+ </div>
119
+ <div style={{ flex: 1 }}></div>
120
+ </header>
121
+ {/* <div className="flex-1 overflow-hidden"> */}
122
+ <Switch>
123
+ <Route exact path="/">
124
+ <Thread />
125
+ </Route>
126
+
127
+ <Route exact path="/thread/:thread_id">
128
+ <PlainText />
129
+ </Route>
130
+ </Switch>
131
+ {/* </div> */}
132
+ </SidebarInset>
133
+ </div>
134
+ </SidebarProvider>
135
+ </AssistantRuntimeProvider>
136
+ </Router>
137
+ )
138
+ }
139
+
140
+ const RootLayout = ({ children }: any) => {
141
+ return (
142
+ <SessionContextProvider
143
+ initial={{
144
+ currentSpace: vineyard,
145
+ currentDatasource: null
146
+ }}
147
+ >
148
+ <Entry />
149
+ </SessionContextProvider>
150
+ )
151
+ }
152
+
153
+ const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
154
+ root.render(<RootLayout children={null} />)
@@ -0,0 +1,155 @@
1
+ import axios from 'axios'
2
+
3
+ type ReqHeaders = Record<string, string>
4
+ type ReqBody = Record<string, any>
5
+
6
+ const queryParamsToString = (query: any) => {
7
+ const keys = Object.keys(query)
8
+ const lastIndex = keys.length - 1
9
+ let queryString = ''
10
+ keys.forEach((key, i) => {
11
+ queryString += `${key}=${query[key]}`
12
+ if (i !== lastIndex)
13
+ queryString += '&'
14
+ })
15
+
16
+ return queryString
17
+ }
18
+
19
+ const parseError = (err: any) => {
20
+ if (!err.response) {
21
+ return err
22
+ }
23
+
24
+ if (!err.response.data) {
25
+ return err
26
+ }
27
+
28
+ const { status, data } = err.response
29
+ const error = new Error(JSON.stringify({
30
+ ...data,
31
+ status,
32
+ }))
33
+
34
+ error.name = data.type
35
+ return error
36
+ }
37
+
38
+ const API_VERSION = '/api'
39
+ // const API_VERSION = `http://localhost:3000/rest`
40
+
41
+ const DEFAULT_HEADERS = {
42
+ 'Accept': 'application/json',
43
+ 'Content-Type': 'application/json',
44
+ 'X-Requested-With': 'XMLHttpRequest',
45
+ // 'Cache-Control': 'no-cache',
46
+ // 'Pragma': 'no-cache',
47
+ }
48
+
49
+ class API {
50
+ constructor() {
51
+
52
+ }
53
+
54
+ defaultHeaders(reqHeaders: any) {
55
+ const headers: any = {
56
+ ...DEFAULT_HEADERS,
57
+ // 'Client-TzOffset': tzOffsetHeader(),
58
+ }
59
+
60
+ if (!reqHeaders)
61
+ return headers
62
+
63
+ Object.keys(reqHeaders).forEach((headerName: string) => {
64
+ headers[headerName] = reqHeaders[headerName]
65
+ })
66
+
67
+ return headers
68
+ }
69
+
70
+ async get(endpoint: string, query?: ReqBody, reqHeaders?: ReqHeaders) {
71
+ const headers = this.defaultHeaders(reqHeaders)
72
+
73
+ const url = query === null
74
+ ? `${API_VERSION}${endpoint}`
75
+ : `${API_VERSION}${endpoint}?${queryParamsToString(query)}`
76
+
77
+ try {
78
+ const { data } = await axios({
79
+ url,
80
+ method: 'get',
81
+ headers,
82
+ })
83
+
84
+ return data
85
+ } catch (error) {
86
+ throw parseError(error)
87
+ }
88
+ }
89
+
90
+ async post(endpoint: string, body: ReqBody, reqHeaders?: ReqHeaders) {
91
+ const headers = this.defaultHeaders(reqHeaders)
92
+
93
+ try {
94
+ const { data } = await axios({
95
+ url: `${API_VERSION}${endpoint}`,
96
+ method: 'post',
97
+ data: body,
98
+ headers,
99
+ })
100
+
101
+ return data
102
+ } catch (error) {
103
+ throw parseError(error)
104
+ }
105
+ }
106
+
107
+ async put(endpoint: string, body: ReqBody, reqHeaders: ReqHeaders | null, isFormData?: boolean) {
108
+ try {
109
+ const headers = this.defaultHeaders(reqHeaders)
110
+
111
+ if (isFormData === true) {
112
+ const resp = await axios.put(`${API_VERSION}${endpoint}`, body, {
113
+ responseType: 'blob',
114
+ headers: {
115
+ ...headers,
116
+ 'content-type': 'multipart/form-data',
117
+ },
118
+ })
119
+
120
+ return resp.data
121
+ }
122
+
123
+ const { data } = await axios({
124
+ url: `${API_VERSION}${endpoint}`,
125
+ method: 'put',
126
+ data: body,
127
+ headers,
128
+ })
129
+
130
+ return data
131
+ } catch (error) {
132
+ throw parseError(error)
133
+ }
134
+ }
135
+
136
+ /*
137
+ async delete(endpoint, body, reqHeaders) {
138
+ const headers = this.defaultHeaders(reqHeaders)
139
+
140
+ try {
141
+ const { data } = await axios({
142
+ url: `${API_VERSION}${endpoint}`,
143
+ method: 'delete',
144
+ headers,
145
+ })
146
+
147
+ return data
148
+ } catch (error) {
149
+ throw parseError(error)
150
+ }
151
+ }
152
+ */
153
+ }
154
+
155
+ export default new API()
@@ -0,0 +1,49 @@
1
+ import axios from 'axios'
2
+
3
+ class RPC {
4
+ constructor() {
5
+
6
+ }
7
+
8
+ /*
9
+ defaultHeaders(reqHeaders: any) {
10
+ const headers: any = {
11
+ ...DEFAULT_HEADERS,
12
+ // 'Client-TzOffset': tzOffsetHeader(),
13
+ }
14
+
15
+ if (!reqHeaders)
16
+ return headers
17
+
18
+ Object.keys(reqHeaders).forEach((headerName: string) => {
19
+ headers[headerName] = reqHeaders[headerName]
20
+ })
21
+
22
+ return headers
23
+ }
24
+ */
25
+
26
+ async call(
27
+ service: string,
28
+ action: string | null,
29
+ args: Record<any, any>
30
+ ): Promise<Record<any, any>> {
31
+
32
+ const url = action === null
33
+ ? `/rpc/${service}`
34
+ : `/rpc/${service}/${action}`
35
+
36
+ const { data } = await axios({
37
+ url,
38
+ method: 'post',
39
+ data: args,
40
+ headers: {
41
+ Accept: 'application/json'
42
+ }
43
+ })
44
+
45
+ return data
46
+ }
47
+ }
48
+
49
+ export default new RPC()