@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,96 @@
1
+ import axios from "axios"
2
+ import { clsx, type ClassValue } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ import RPC from "./RPC"
5
+ import API from "./API"
6
+
7
+ export function cn(...inputs: ClassValue[]) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+
11
+ interface UploadFileParams {
12
+ folder: string;
13
+ filedata: any;
14
+ filename: string;
15
+ filetype: string;
16
+ }
17
+
18
+ export const uploadFile = async ({
19
+ folder,
20
+ filedata,
21
+ filename,
22
+ filetype
23
+ }: UploadFileParams) => {
24
+ try {
25
+ const { payload } = await RPC.call('s3', 'upload_url', {
26
+ folder,
27
+ filename,
28
+ filetype,
29
+ toStorage: 'false'
30
+ })
31
+
32
+ const { response } = payload
33
+ const upload = response.uploadUrl
34
+ // console.log('UPLOAD URL: ' + upload)
35
+
36
+ // this returns an empty string ("")
37
+ const { data } = await axios({
38
+ url: upload,
39
+ method: 'PUT',
40
+ data: filedata,
41
+ headers: { 'Content-Type': filetype }
42
+ })
43
+
44
+ return data
45
+ } catch (error) {
46
+ throw error
47
+ }
48
+ }
49
+
50
+ export const updateSpace = async (space: any, updates: Record<string, any>) => {
51
+ try {
52
+ const { payload } = await API.put(
53
+ `/space/${space._id}`,
54
+ updates,
55
+ null,
56
+ false
57
+ )
58
+
59
+ return payload
60
+ } catch (error) {
61
+ throw error
62
+ }
63
+ }
64
+
65
+ export const fetchSpace = async (params: any) => {
66
+ try {
67
+ const url = params._id ? `/space/${params._id}` : '/space'
68
+ const { payload } = await API.get(url, params)
69
+
70
+ // console.log('FETCH SPACE: ' + JSON.stringify(payload))
71
+
72
+ return payload
73
+ } catch (error) {
74
+ throw error
75
+ }
76
+ }
77
+
78
+ export const fetchMessages = async (site: string, threadId: string) => {
79
+ try {
80
+ const url = `/thread/${site}/${threadId}`
81
+ const { data } = await axios({
82
+ url,
83
+ method: 'GET',
84
+ headers: { 'Content-Type': 'application/json' }
85
+ })
86
+
87
+ // console.log('MESSAGES: ' + JSON.stringify(data))
88
+ if (data.error) {
89
+ throw new Error(data.error)
90
+ }
91
+
92
+ return data.payload
93
+ } catch (error) {
94
+ throw error
95
+ }
96
+ }
@@ -0,0 +1,63 @@
1
+ import express, { Request, Response, NextFunction} from 'express'
2
+ import turbo360 from '@turbo360/turbo-sdk'
3
+ import main from './routes/main.js'
4
+ import chat from './routes/chat.js'
5
+ import mcp from './routes/mcp.js'
6
+ import thread from './routes/thread.js'
7
+ import rpc from './routes/rpc.js'
8
+ import api from './routes/api.js'
9
+ import fetchManifest from './utils/fetchManifest.js'
10
+ // import { sessionMiddleware, setupPassport } from './utils/Auth.js'
11
+
12
+ const ONE_DAY = 24 * 60 * 60 * 1000
13
+
14
+ const app = express()
15
+
16
+ turbo360.configureApp(app, {
17
+ views: 'views',
18
+ static: 'public',
19
+ viewEngine: 'mustache' // ejs or mustache
20
+ })
21
+
22
+ // setupPassport(app)
23
+ // app.use(sessionMiddleware)
24
+
25
+ app.use(async (req: any, res: Response, next: NextFunction) => {
26
+ try {
27
+ req._vineyard = await fetchManifest()
28
+ // console.log('MANIFEST: ' + JSON.stringify(req._vineyard))
29
+ } catch (error) {
30
+
31
+ } finally {
32
+ next()
33
+ }
34
+ })
35
+
36
+ // set routes
37
+ app.use('/api/chat', chat)
38
+ app.use('/api/mcp', mcp)
39
+ app.use('/api', api)
40
+ app.use('/thread', thread)
41
+ app.post('/context', (req, res, next) => {
42
+ if (!req.body.context) {
43
+ return next()
44
+ }
45
+
46
+ const domain = (process.env.TURBO_ENV === 'local') ? 'localhost' : '.vinely.ai'
47
+ const token = process.env.VLY_CONTEXT as string
48
+ const cookie = req.body.context
49
+
50
+ res.cookie(token, JSON.stringify(cookie), {
51
+ maxAge: 14 * ONE_DAY,
52
+ httpOnly: true,
53
+ domain,
54
+ })
55
+
56
+ res.json({
57
+ data: 'context set'
58
+ })
59
+ })
60
+ app.use('/rpc', rpc)
61
+ app.use('/', main)
62
+
63
+ export default app
@@ -0,0 +1,38 @@
1
+ import axios from 'axios'
2
+ import { Router } from 'express'
3
+ import APIMgr from '../utils/APIMgr.js'
4
+
5
+ interface ReqParams {
6
+ url: string;
7
+ method: string;
8
+ headers: any;
9
+ data?: any
10
+ }
11
+
12
+ const router = Router()
13
+
14
+ router.get('/:resource', async (req, res, next) => {
15
+ const path = `${req.params.resource}`
16
+ const { payload } = await APIMgr.get(path, req.query, null)
17
+ res.json({ payload })
18
+ })
19
+
20
+ router.get('/:resource/:id', async (req, res, next) => {
21
+ const path = `${req.params.resource}/${req.params.id}`
22
+ const { payload } = await APIMgr.get(path, null, null)
23
+ res.json({ payload })
24
+ })
25
+
26
+ router.post('/:resource', async (req, res, next) => {
27
+ const path = `${req.params.resource}`
28
+ const { payload } = await APIMgr.post(path, req.body, null)
29
+ res.json({ payload })
30
+ })
31
+
32
+ router.put('/:resource/:id', async (req, res, next) => {
33
+ const path = `${req.params.resource}/${req.params.id}`
34
+ const { payload } = await APIMgr.put(path, req.body, null)
35
+ res.json({ payload })
36
+ })
37
+
38
+ export default router
@@ -0,0 +1,133 @@
1
+ import { Router, Response, NextFunction } from "express"
2
+ import { openai } from "@ai-sdk/openai"
3
+ // import { anthropic } from "@ai-sdk/anthropic"
4
+ import { StreamableHTTPClientTransport, StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js"
5
+ import {
6
+ streamText,
7
+ UIMessage,
8
+ stepCountIs,
9
+ convertToModelMessages,
10
+ experimental_createMCPClient as createMCPClient, // https://github.com/vercel/ai/discussions/5257
11
+ experimental_MCPClient as MCPClient
12
+ } from "ai"
13
+ import { hasAuthProvider, getAuthProvider } from "../utils/mcp-auth.js";
14
+
15
+ interface ChatMessages {
16
+ messages: UIMessage[]
17
+ }
18
+
19
+ /*
20
+ const MCP_SERVERS: Record<string, string> = {
21
+ sports: 'https://mcp-sports-server-pbiesp.turbo360-staging.com/mcp',
22
+ population: 'https://mcp-population-server-jz3gg2.turbo360-staging.com/mcp',
23
+ domain: 'https://api.findadomain.dev/mcp',
24
+ notion: 'https://mcp.notion.com/mcp',
25
+ // notion: 'https://api.githubcopilot.com/mcp/', // did not work
26
+ // notion: 'https://server.smithery.ai/@rashidazarang/airtable-mcp/mcp' // did not work
27
+ // notion: 'https://server.smithery.ai/@VeyraX/veyrax-mcp/mcp', // worked
28
+ airtable: 'https://server.smithery.ai/airtable-server/mcp', // worked
29
+ rube: 'https://rube.app/mcp',
30
+ google: 'https://mcp.composio.dev/composio/server/fdb469c6-c700-4014-9827-e3547a2c0240/mcp?include_composio_helper_actions=true',
31
+ // mola: 'http://localhost:3000/mcp',
32
+ mola: 'https://mola-mcp-mdmvrp.turbo360-staging.com/mcp',
33
+ square: 'https://mcp.squareup.com/sse',
34
+ stripe: 'https://mcp.stripe.com',
35
+ // dats2101: 'http://localhost:3000/mcp',
36
+ dats2101: 'https://dats2101-mcp-vw2biy.turbo360-staging.com/mcp',
37
+ econ1012: 'https://hayden-mcp-prsjjh.turbo360-staging.com/mcp',
38
+ levy: 'https://levy-mcp-i5tnpu.turbo360-staging.com/mcp',
39
+ splitLoyalty: 'https://split-loyalty-mcp-qcqbll.turbo360-staging.com/mcp',
40
+ // 'banter-egcda42e': 'http://localhost:3000/mcp',
41
+ 'banter-egcda42e': 'https://banter-mcp-pxmukt.turbo360-staging.com/mcp',
42
+ }
43
+ */
44
+
45
+ const router = Router()
46
+
47
+ router.post('/', async (req: any, res: Response, next: NextFunction) => {
48
+ // console.log('\nMANIFEST: ' + JSON.stringify(req._vineyard))
49
+ const { vly_context } = req.cookies // check if undefined
50
+ // console.log('\nVLY_CONTEXT: ' + vly_context)
51
+ const ctx = JSON.parse(vly_context)
52
+
53
+ const { messages }: ChatMessages = req.body
54
+ console.log('LOG: ' + JSON.stringify(messages))
55
+
56
+ const datasource: Record<string, any> = req._vineyard.datasources[ctx.vine]
57
+ console.log('DATASOURCE: ' + JSON.stringify(datasource))
58
+
59
+ const headers: Record<string, string> = { 'vinely-args': JSON.stringify(datasource) }
60
+ // console.log('HEADERS: ' + JSON.stringify(headers))
61
+
62
+ // if not specified, default to banter:
63
+ const mcps = datasource.mcps || [
64
+ {
65
+ name: 'banter-egcda42e',
66
+ url: 'https://banter-mcp-pxmukt.turbo360-staging.com/mcp'
67
+ }
68
+ ]
69
+
70
+ try {
71
+ const mcpClients = []
72
+ for (const mcp of mcps) {
73
+ let transport;
74
+ const url = new URL(mcp.url)
75
+ const opts: StreamableHTTPClientTransportOptions = {
76
+ requestInit: { headers }
77
+ }
78
+
79
+ if (hasAuthProvider(url)) {
80
+ transport = new StreamableHTTPClientTransport(
81
+ url,
82
+ {
83
+ ...opts,
84
+ authProvider: getAuthProvider(url),
85
+ },
86
+ )
87
+ } else {
88
+ transport = new StreamableHTTPClientTransport(url, opts)
89
+ }
90
+
91
+ const mcpClient = await createMCPClient({ transport, name: process.env.VLY_APP })
92
+ mcpClients.push(mcpClient)
93
+ }
94
+
95
+ const allTools: Record<string, any> = {}
96
+ for (const mcpClient of mcpClients) {
97
+ const tools = await mcpClient.tools() // this is an dictionary NOT an array
98
+ const toolNames: string[] = Object.keys(tools)
99
+
100
+ // TODO: prevent collision of tool names:
101
+ toolNames.forEach((toolName: string) => {
102
+ allTools[toolName] = tools[toolName]
103
+ })
104
+ }
105
+
106
+ const result = streamText({
107
+ // this text will come from the vineyard level (when creating a vineyard):
108
+ system: `
109
+ You are a helpful assistant helping college-level studies review course materials. You have access to tools that allow you to get information from their uploaded content. Use these tools as a primary source when answering questions rather than your inherent knowledge. When answering, always relate your answer to the materials the user uploaded.
110
+
111
+ When appropriate, suggest additional questions the user may ask you to help further their understanding of the subject content. When you have presented a lot of material, offer to ask them a question to confirm their understanding.
112
+ `,
113
+ model: openai("gpt-4o"),
114
+ messages: convertToModelMessages(messages),
115
+ stopWhen: stepCountIs(5), // stop after 5 steps if tools were called
116
+ tools: allTools
117
+ })
118
+
119
+ console.log('RESULT: ' + JSON.stringify(result) + '\n')
120
+
121
+ res.set({
122
+ 'connection': 'keep-alive',
123
+ 'keep-alive': 'timeout=5',
124
+ 'transfer-encoding': 'chunked'
125
+ })
126
+
127
+ result.pipeUIMessageStreamToResponse(res)
128
+ } catch (error: any) {
129
+ console.log('ERR: ' + error)
130
+ }
131
+ })
132
+
133
+ export default router
@@ -0,0 +1,36 @@
1
+ import { Router, Response, NextFunction } from 'express'
2
+
3
+ const router = Router()
4
+
5
+ const isLocal = process.env.TURBO_ENV === 'local'
6
+
7
+ const partials = {
8
+ imports: `partials/imports.${isLocal ? 'dev' : 'prod'}`
9
+ }
10
+
11
+ router.get('/', (req: any, res: Response, next: NextFunction) => {
12
+ res.render('landing', {
13
+ isLocal,
14
+ partials,
15
+ CDN: process.env.CDN,
16
+ context: JSON.stringify({
17
+ vineyard: req._vineyard
18
+ })
19
+ })
20
+ })
21
+
22
+ router.get('/:mcp', (req, res, next) => {
23
+ const mcp = req.params.mcp
24
+ const ONE_DAY = 24 * 60 * 60 * 1000
25
+ const domain = isLocal ? 'localhost' : '.vinely.ai'
26
+
27
+ res.cookie('vly_mcp', mcp, {
28
+ maxAge: 14 * ONE_DAY,
29
+ httpOnly: true,
30
+ domain,
31
+ })
32
+
33
+ res.redirect('/')
34
+ })
35
+
36
+ export default router
@@ -0,0 +1,52 @@
1
+ import { Router, Response, NextFunction } from "express"
2
+ import { handleMCPAuthCallback, setupAuthProvider } from "../utils/mcp-auth.js"
3
+
4
+ const MCP_CLIENT_NAME = "Test MCP Client"
5
+
6
+ const router = Router()
7
+
8
+ router.get('/setup', async (req: any, res: Response, next: NextFunction) => {
9
+ const { mcpUrl } = req.query
10
+ if (!mcpUrl) {
11
+ res.status(400).json({
12
+ data: 'Malformed request: mcpUrl required.'
13
+ })
14
+
15
+ return
16
+ }
17
+
18
+ let url;
19
+ try {
20
+ url = new URL(decodeURIComponent(mcpUrl))
21
+ }
22
+ catch {
23
+ // return new Response("Malformed request.", { status: 400 });
24
+ res.status(400).json({
25
+ data: 'Malformed request.'
26
+ })
27
+
28
+ return
29
+ }
30
+
31
+ try {
32
+ const redirectUrl = await setupAuthProvider(MCP_CLIENT_NAME, new URL(url))
33
+ if (redirectUrl) {
34
+ res.redirect(redirectUrl.toString())
35
+ return
36
+ }
37
+
38
+ // res.send('Authentication initiated')
39
+ }
40
+ catch (error) {
41
+ console.error("Error initiating MCP authentication: ", error)
42
+ res.status(500).json({
43
+ data: 'Failed to initiate MCP authentication.'
44
+ })
45
+ }
46
+ })
47
+
48
+ router.get('/auth', async (req: any, res: Response, next: NextFunction) => {
49
+ return await handleMCPAuthCallback(req, res)
50
+ })
51
+
52
+ export default router
@@ -0,0 +1,64 @@
1
+ import axios from 'axios'
2
+ import { Router } from 'express'
3
+
4
+ const router = Router()
5
+
6
+ router.get('/:service/:action', (req, res, next) => {
7
+ res.json({
8
+ data: `RPC call ${req.params.service}:${req.params.action} must be POST request.`
9
+ })
10
+ })
11
+
12
+ router.post('/:action', async (req, res, next) => {
13
+ try {
14
+ const url = `${process.env.VINELY_RPC}/${req.params.action}`
15
+ const { data } = await axios({
16
+ url,
17
+ method: 'post',
18
+ data: req.body,
19
+ headers: {
20
+ 'Accept': 'application/json',
21
+ 'vinely-client': 'dashboard'
22
+ }
23
+ })
24
+
25
+ if (data.error) {
26
+ throw new Error(data.error)
27
+ }
28
+
29
+ res.json({ payload: data })
30
+ } catch (error: any) {
31
+ res.json({
32
+ error: error.message
33
+ })
34
+ }
35
+ })
36
+
37
+ router.post('/:service/:action', async (req, res, next) => {
38
+ try {
39
+ const url = `${process.env.VINELY_RPC}/${req.params.service}/${req.params.action}`
40
+ const { data } = await axios({
41
+ url,
42
+ method: 'post',
43
+ data: req.body,
44
+ headers: {
45
+ 'Accept': 'application/json',
46
+ 'vinely-client': 'dashboard'
47
+ }
48
+ })
49
+
50
+ // console.log('RPC: ' + JSON.stringify(data))
51
+ if (data.error) {
52
+ throw new Error(data.error)
53
+ }
54
+
55
+
56
+ res.json({ payload: data })
57
+ } catch (error: any) {
58
+ res.json({
59
+ error: error.message
60
+ })
61
+ }
62
+ })
63
+
64
+ export default router
@@ -0,0 +1,44 @@
1
+ import axios from 'axios'
2
+ import { Router, Response, NextFunction } from 'express'
3
+
4
+ const router = Router()
5
+
6
+ const isLocal = process.env.TURBO_ENV === 'local'
7
+
8
+ const partials = {
9
+ imports: `partials/imports.${isLocal ? 'dev' : 'prod'}`
10
+ }
11
+
12
+ router.get('/:thread_id', (req: any, res: Response, next: NextFunction) => {
13
+ res.render('landing', {
14
+ isLocal,
15
+ partials,
16
+ CDN: process.env.CDN,
17
+ context: JSON.stringify({
18
+ vineyard: req._vineyard
19
+ })
20
+ })
21
+ })
22
+
23
+ router.get('/:site/:thread_id', async (req: any, res: Response, next: NextFunction) => {
24
+ try {
25
+ const { site, thread_id } = req.params
26
+ const url = `https://vinely.s3.us-east-1.amazonaws.com/sites/${site}/threads/${thread_id}.json`
27
+
28
+ const { data } = await axios({
29
+ url,
30
+ method: 'get',
31
+ headers: {
32
+ Accept: 'application/json'
33
+ }
34
+ })
35
+
36
+ res.json({ payload: data })
37
+ } catch (error: any) {
38
+ res.json({
39
+ error: error.message
40
+ })
41
+ }
42
+ })
43
+
44
+ export default router
@@ -0,0 +1,156 @@
1
+ import axios from 'axios'
2
+ // import moment from 'moment'
3
+
4
+ const parseError = (err: any) => {
5
+ if (!err.response) {
6
+ return err
7
+ }
8
+
9
+ if (!err.response.data) {
10
+ return err
11
+ }
12
+
13
+ const { status, data } = err.response
14
+ const error = new Error(JSON.stringify({
15
+ ...data,
16
+ status,
17
+ }))
18
+
19
+ error.name = data.type
20
+ return error
21
+ }
22
+
23
+ const queryParamsToString = (query: any) => {
24
+ const keys = Object.keys(query)
25
+ const lastIndex = keys.length - 1
26
+ let queryString = ''
27
+ keys.forEach((key, i) => {
28
+ queryString += `${key}=${query[key]}`
29
+ if (i !== lastIndex)
30
+ queryString += '&'
31
+ })
32
+
33
+ return queryString
34
+ }
35
+
36
+ const API_VERSION = process.env.VLY_API_BASE
37
+ // const API_VERSION = `http://localhost:3000/rest`
38
+
39
+ const DEFAULT_HEADERS = {
40
+ 'Accept': 'application/json',
41
+ 'Content-Type': 'application/json',
42
+ 'X-Requested-With': 'XMLHttpRequest',
43
+ // 'Cache-Control': 'no-cache',
44
+ // 'Pragma': 'no-cache',
45
+ }
46
+
47
+ class APIMgr {
48
+ constructor() {
49
+
50
+ }
51
+
52
+ defaultHeaders(reqHeaders: any) {
53
+ const headers: any = {
54
+ ...DEFAULT_HEADERS,
55
+ // 'Client-TzOffset': tzOffsetHeader(),
56
+ }
57
+
58
+ if (!reqHeaders)
59
+ return headers
60
+
61
+ Object.keys(reqHeaders).forEach((headerName: string) => {
62
+ headers[headerName] = reqHeaders[headerName]
63
+ })
64
+
65
+ return headers
66
+ }
67
+
68
+ async get(endpoint: string, params: any, reqHeaders: any) {
69
+ const headers = this.defaultHeaders(reqHeaders)
70
+ // console.log('HEADERS: ' + JSON.stringify(headers))
71
+
72
+ const url = params
73
+ ? `${API_VERSION}/${endpoint}?${queryParamsToString(params)}`
74
+ : `${API_VERSION}/${endpoint}`
75
+
76
+ // console.log('API MGR GET: ' + url)
77
+ try {
78
+ const { data } = await axios({
79
+ // url: `${API_VERSION}/${endpoint}`,
80
+ url,
81
+ method: 'get',
82
+ headers,
83
+ })
84
+
85
+ return data
86
+ } catch (error) {
87
+ throw parseError(error)
88
+ }
89
+ }
90
+
91
+ async post(endpoint: string, body: any, reqHeaders: any) {
92
+ const headers = this.defaultHeaders(reqHeaders)
93
+
94
+ try {
95
+ const { data } = await axios({
96
+ url: `${API_VERSION}/${endpoint}`,
97
+ method: 'post',
98
+ data: body,
99
+ headers,
100
+ })
101
+
102
+ return data
103
+ } catch (error) {
104
+ throw parseError(error)
105
+ }
106
+ }
107
+
108
+ async put(endpoint: string, body: any, reqHeaders: any, isFormData = false) {
109
+ try {
110
+ const headers = this.defaultHeaders(reqHeaders)
111
+
112
+ if (isFormData === true) {
113
+ const resp = await axios.put(`${API_VERSION}/${endpoint}`, body, {
114
+ responseType: 'blob',
115
+ headers: {
116
+ ...headers,
117
+ 'content-type': 'multipart/form-data',
118
+ },
119
+ })
120
+
121
+ return resp
122
+ }
123
+
124
+ const { data } = await axios({
125
+ url: `${API_VERSION}/${endpoint}`,
126
+ method: 'put',
127
+ data: body,
128
+ headers,
129
+ })
130
+
131
+ return data
132
+ } catch (error) {
133
+ throw parseError(error)
134
+ }
135
+ }
136
+
137
+ /*
138
+ async delete(endpoint, body, reqHeaders) {
139
+ const headers = this.defaultHeaders(reqHeaders)
140
+
141
+ try {
142
+ const { data } = await axios({
143
+ url: `${API_VERSION}/${endpoint}`,
144
+ method: 'delete',
145
+ headers,
146
+ })
147
+
148
+ return data
149
+ } catch (error) {
150
+ throw parseError(error)
151
+ }
152
+ }
153
+ */
154
+ }
155
+
156
+ export default new APIMgr()