@surph_ai/cli 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.
- package/cli.js +447 -0
- package/deploy/index.js +153 -0
- package/deploy/tool-handler.js +16 -0
- package/index.js +3 -0
- package/package.json +35 -0
- package/scaffold/index.js +137 -0
- package/scaffold/project/README.md +28 -0
- package/scaffold/project/app.js +20 -0
- package/scaffold/project/apps/README.md +1 -0
- package/scaffold/project/env.txt +4 -0
- package/scaffold/project/package-lock.json +2459 -0
- package/scaffold/project/package.json +21 -0
- package/scaffold/project/public/css/bootstrap.css +5926 -0
- package/scaffold/project/public/js/app.js +1 -0
- package/scaffold/project/public/js/jquery.js +2 -0
- package/scaffold/project/routes/index.js +8 -0
- package/scaffold/project/templates/index.mustache +20 -0
- package/scaffold/tool/README.md +25 -0
- package/scaffold/tool/env.txt +2 -0
- package/scaffold/tool/example.txt +1 -0
- package/scaffold/tool/package.json +27 -0
- package/scaffold/tool/tools/index.ts +13 -0
- package/toolserver/app.js +25 -0
- package/toolserver/chat.js +95222 -0
- package/toolserver/routes/index.js +8 -0
- package/toolserver/routes/tool.js +118 -0
- package/toolserver/templates/index.html +20 -0
- package/types.d.ts +73 -0
- package/utils/index.js +275 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
const os = require('os')
|
|
4
|
+
const { Router, response } = require('express')
|
|
5
|
+
const { pathToFileURL } = require('url')
|
|
6
|
+
const manifest = require('../../../../../manifest.json')
|
|
7
|
+
|
|
8
|
+
const SESSION_DIR = path.resolve(__dirname, '../../../../../.surph')
|
|
9
|
+
const SESSION_FILE = path.join(SESSION_DIR, 'session.json')
|
|
10
|
+
|
|
11
|
+
const toolsPath = pathToFileURL(
|
|
12
|
+
path.resolve(__dirname, '../../../../../dist/tools/index.js')
|
|
13
|
+
).href
|
|
14
|
+
|
|
15
|
+
const loadTool = () => import(toolsPath).then((mod) => mod.default)
|
|
16
|
+
|
|
17
|
+
const router = Router()
|
|
18
|
+
|
|
19
|
+
const handler = async (event, tool) => {
|
|
20
|
+
const { args, context, user } = event
|
|
21
|
+
let payload = null
|
|
22
|
+
let errorMsg = null
|
|
23
|
+
try {
|
|
24
|
+
payload = await tool({ args, context, user })
|
|
25
|
+
} catch (error) {
|
|
26
|
+
errorMsg = error instanceof Error ? error.message : String(error)
|
|
27
|
+
} finally {
|
|
28
|
+
const resp = { success: errorMsg === null ? true : false }
|
|
29
|
+
|
|
30
|
+
if (payload)
|
|
31
|
+
resp.payload = payload
|
|
32
|
+
|
|
33
|
+
if (errorMsg !== null)
|
|
34
|
+
resp.error = errorMsg
|
|
35
|
+
|
|
36
|
+
return resp
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
router.get('/', async (req, res, next) => {
|
|
41
|
+
const surphUser = req.headers['x-surph-user']
|
|
42
|
+
if (surphUser) {
|
|
43
|
+
try {
|
|
44
|
+
// console.log('SAVE SURPH USER: ' + surphUser)
|
|
45
|
+
fs.mkdirSync(SESSION_DIR, { recursive: true, mode: 0o700 })
|
|
46
|
+
fs.writeFileSync(
|
|
47
|
+
SESSION_FILE,
|
|
48
|
+
JSON.stringify({
|
|
49
|
+
userId: surphUser,
|
|
50
|
+
updatedAt: new Date().toISOString()
|
|
51
|
+
}, null, 2),
|
|
52
|
+
{ mode: 0o600 }
|
|
53
|
+
)
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.warn('[sdk] session write failed:', error.message)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
res.json({ response: manifest })
|
|
61
|
+
} catch (error) {
|
|
62
|
+
res.json({
|
|
63
|
+
response: {
|
|
64
|
+
success: false,
|
|
65
|
+
error: error.message
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
router.get('/test', async (req, res, next) => {
|
|
72
|
+
try {
|
|
73
|
+
if (Object.keys(req.query).length === 0) {
|
|
74
|
+
throw new Error('No arguments provided.')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const context = req.query._context || null
|
|
78
|
+
const user = req.query._user || null
|
|
79
|
+
const params = { args: req.query, context, user }
|
|
80
|
+
|
|
81
|
+
const toolRunner = await loadTool()
|
|
82
|
+
const response = await handler(params, toolRunner)
|
|
83
|
+
res.json({ response })
|
|
84
|
+
} catch (error) {
|
|
85
|
+
res.json({
|
|
86
|
+
response: {
|
|
87
|
+
success: false,
|
|
88
|
+
error: error.message
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
router.post('/custom', async (req, res, next) => {
|
|
95
|
+
try {
|
|
96
|
+
const { name, args, tool, user = null, context = null } = req.body;
|
|
97
|
+
if (process.env.SURPH_TOOL !== tool.slug) {
|
|
98
|
+
throw new Error(`Invalid tool ${tool.slug}. Check .env file.`)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const toolRunner = await loadTool()
|
|
102
|
+
const response = await handler({ args, context, user }, toolRunner)
|
|
103
|
+
if (response.error) {
|
|
104
|
+
throw new Error(response.error);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
res.json({ response })
|
|
108
|
+
} catch (error) {
|
|
109
|
+
res.json({
|
|
110
|
+
response: {
|
|
111
|
+
success: false,
|
|
112
|
+
error: error.message
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
module.exports = router
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html dir="ltr" lang="en-US">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
7
|
+
<meta http-equiv="Content-Language" content="en" />
|
|
8
|
+
|
|
9
|
+
<title>Surph AI</title>
|
|
10
|
+
<link rel="shortcut icon" href="https://lh3.googleusercontent.com/MpnmfR3zYPTojA03QbhGgwIHucmH5s4G2vbIlADYhODL488MQt_BuVztv9LYmJbhwkScYN0DIXuh4d10YMsLbWXT">
|
|
11
|
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
|
12
|
+
<link rel="stylesheet" href="https://cdn.turbo360-dev.com/admin/assets/scaffold/css/style.min.css" />
|
|
13
|
+
</head>
|
|
14
|
+
|
|
15
|
+
<body>
|
|
16
|
+
<div class="container pt-5">
|
|
17
|
+
<h1>Welcome to Surph AI</h1>
|
|
18
|
+
</div>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Type definitions for @surph_ai/sdk
|
|
2
|
+
// These describe the runtime contract the tool server hands to each tool's default export.
|
|
3
|
+
|
|
4
|
+
export type OAuthProvider = 'google' | 'github' | (string & {});
|
|
5
|
+
|
|
6
|
+
export interface GoogleOAuth {
|
|
7
|
+
accessToken: string;
|
|
8
|
+
refreshToken?: string;
|
|
9
|
+
/** ISO-8601 timestamp for when accessToken expires. */
|
|
10
|
+
expiresAt: string;
|
|
11
|
+
/** OAuth scopes granted by the user. */
|
|
12
|
+
scopes: string[];
|
|
13
|
+
/** ISO-8601 timestamp for when the user first connected the provider. */
|
|
14
|
+
connectedAt: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface UserOAuth {
|
|
18
|
+
google?: GoogleOAuth;
|
|
19
|
+
[provider: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UserAuth {
|
|
23
|
+
type: OAuthProvider;
|
|
24
|
+
/** Provider-issued stable identifier for the user (e.g. Google 'sub'). */
|
|
25
|
+
id: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface User {
|
|
29
|
+
_id: string;
|
|
30
|
+
firstName?: string;
|
|
31
|
+
lastName?: string;
|
|
32
|
+
email: string;
|
|
33
|
+
username: string;
|
|
34
|
+
avatar?: string;
|
|
35
|
+
tags?: string[];
|
|
36
|
+
following?: string[];
|
|
37
|
+
notifications?: unknown[];
|
|
38
|
+
type?: 'claimed' | 'anonymous' | (string & {});
|
|
39
|
+
auth?: UserAuth;
|
|
40
|
+
timestamp?: string;
|
|
41
|
+
lastVisit?: string;
|
|
42
|
+
identifiers?: string[];
|
|
43
|
+
tools?: string[];
|
|
44
|
+
oauth?: UserOAuth;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Per-invocation context. Currently opaque — populated by the caller (chat
|
|
49
|
+
* server, deployed harness, etc.). Cast to a more specific shape inside the
|
|
50
|
+
* tool if you know what your caller sends.
|
|
51
|
+
*/
|
|
52
|
+
export type ToolContext = Record<string, unknown> | null;
|
|
53
|
+
|
|
54
|
+
export interface ToolHandlerInput<TArgs = Record<string, unknown>> {
|
|
55
|
+
args: TArgs;
|
|
56
|
+
context: ToolContext;
|
|
57
|
+
user: User;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type ToolHandler<
|
|
61
|
+
TArgs = Record<string, unknown>,
|
|
62
|
+
TResult = unknown,
|
|
63
|
+
> = (input: ToolHandlerInput<TArgs>) => Promise<TResult> | TResult;
|
|
64
|
+
|
|
65
|
+
export interface Surph {
|
|
66
|
+
fetchUser(username: string): Promise<User>;
|
|
67
|
+
fetchContext(slug: string | ToolContext): Promise<unknown>;
|
|
68
|
+
searchContext(ctxSlug: string, query: string): Promise<unknown>;
|
|
69
|
+
search(query: string, ctxSlug?: string | null): Promise<unknown>;
|
|
70
|
+
toolHandler(tool: string, args?: Record<string, unknown>): Promise<unknown>;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export declare const surph: Surph;
|
package/utils/index.js
ADDED
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const colors = require('colors/safe')
|
|
3
|
+
const dotenv = require('dotenv')
|
|
4
|
+
const MODE_0666 = parseInt('0666', 8)
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
isTurboApp: function(){
|
|
10
|
+
var packageJson = null
|
|
11
|
+
var env = null
|
|
12
|
+
try {
|
|
13
|
+
packageJson = fs.readFileSync('package.json', 'utf8')
|
|
14
|
+
var json = JSON.parse(packageJson)
|
|
15
|
+
var dependencies = json.dependencies
|
|
16
|
+
if (dependencies.turbo360==null || dependencies.vertex360==null){
|
|
17
|
+
return {
|
|
18
|
+
isTurboApp: false,
|
|
19
|
+
missing: 'turbo360 and/or vertex 360',
|
|
20
|
+
reason: 'Missing turbo360 and/or vertex 360 dependencies'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var envData = fs.readFileSync('.env', 'utf8')
|
|
25
|
+
env = dotenv.parse(envData)
|
|
26
|
+
var turboEnv = env['TURBO_ENV']
|
|
27
|
+
if (turboEnv == null){
|
|
28
|
+
return {
|
|
29
|
+
isTurboApp: false,
|
|
30
|
+
missing: 'TURBO_ENV environment variable',
|
|
31
|
+
reason: 'Missing TURBO_ENV environment variable. Please set "TURBO_ENV=dev" in the .env file'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// this is definitely a turbo project
|
|
36
|
+
return {
|
|
37
|
+
isTurboApp: true,
|
|
38
|
+
turboEnv: turboEnv,
|
|
39
|
+
turbo360: dependencies.turbo360,
|
|
40
|
+
vertex360: dependencies.vertex360
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch(err){
|
|
44
|
+
// console.log('ERR - ' + err.message)
|
|
45
|
+
var missing = (packageJson == null) ? 'package.json' : '.env'
|
|
46
|
+
var reason = (packageJson == null) ? 'Missing package.json file' : 'Missing .env file. Please add .env file with "TURBO_ENV=dev" variable set.'
|
|
47
|
+
return {
|
|
48
|
+
isTurboApp: false,
|
|
49
|
+
missing: missing,
|
|
50
|
+
reason: reason
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
defaultTurboDeploy: function() {
|
|
56
|
+
var turboDeployString = '## Do NOT check this file into version control\n'
|
|
57
|
+
turboDeployString += '\nBUCKET=<AWS_HOST_BUCKET>'
|
|
58
|
+
turboDeployString += '\nAWS_KEY=<AWS_KEY>'
|
|
59
|
+
turboDeployString += '\nAWS_SECRET=<AWS_SECRET>'
|
|
60
|
+
turboDeployString += '\nAWS_ACCT=<AWS_ACCT>'
|
|
61
|
+
turboDeployString += '\nAWS_ROLE=<AWS_ROLE>'
|
|
62
|
+
turboDeployString += '\nAWS_REGION=<AWS_REGION>'
|
|
63
|
+
return turboDeployString
|
|
64
|
+
},
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
defaultEnv: function() {
|
|
68
|
+
var envString = '## Do NOT check this file into version control\n'
|
|
69
|
+
envString += '\nTURBO_ENV=dev'
|
|
70
|
+
envString += '\nTURBO_CDN=https://cdn.turbo360-vertex.com'
|
|
71
|
+
envString += '\nSESSION_SECRET=YOUR_SESSION_SECRET'
|
|
72
|
+
envString += '\nTURBO_APP_ID=<TURBO_APP_ID>'
|
|
73
|
+
envString += '\nTMP_DIR=/tmp'
|
|
74
|
+
envString += '\nTURBO_API_KEY=<TURBO_API_KEY>'
|
|
75
|
+
envString += '\nTURBO_APP_SLUG=<TURBO_APP_SLUG>'
|
|
76
|
+
return envString
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
validateEnv: function(env, fields) { // fields is an array
|
|
80
|
+
if (!fields) {
|
|
81
|
+
// required env values to deploy:
|
|
82
|
+
fields = [
|
|
83
|
+
{text:'TURBO_CDN', min:20, placeholder:'https://cdn.turbo360-vertex.com'},
|
|
84
|
+
{text:'TURBO_APP_SLUG', min:6, placeholder:'<TURBO_APP_SLUG>'},
|
|
85
|
+
{text:'TURBO_API_KEY', min:20, placeholder:'<TURBO_API_KEY>'},
|
|
86
|
+
{text:'TURBO_APP_ID', min:20, placeholder:'<TURBO_APP_ID>'}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
var missing = null
|
|
91
|
+
fields.forEach(function(field){
|
|
92
|
+
// e.g. - {text:"TURBO_APP_ID", min:20}
|
|
93
|
+
var key = field.text
|
|
94
|
+
if (env[key] == null){
|
|
95
|
+
missing = key
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (env[key] == field.placeholder){ // still default placeholder string
|
|
100
|
+
missing = key
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (env[key].length < field.min){ // doesn't meet min str length
|
|
105
|
+
missing = key
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
return missing
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
write: (path, str, mode = MODE_0666) => {
|
|
114
|
+
fs.writeFileSync(path, str, { mode })
|
|
115
|
+
// console.log(' \x1b[36mcreate\x1b[0m : ' + path)
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
// readFile: function(filepath, errMessage){
|
|
119
|
+
// return new Promise(function(resolve, reject){
|
|
120
|
+
// fs.readFile(filepath, 'utf8', function(err, data) {
|
|
121
|
+
// if (err) {
|
|
122
|
+
// var error = (errMessage) ? Error(errMessage) : err
|
|
123
|
+
// reject(error)
|
|
124
|
+
// return
|
|
125
|
+
// }
|
|
126
|
+
|
|
127
|
+
// resolve(data)
|
|
128
|
+
// })
|
|
129
|
+
// })
|
|
130
|
+
// },
|
|
131
|
+
|
|
132
|
+
readFile: (filepath, encoding = 'utf8') => {
|
|
133
|
+
// if (!encoding)
|
|
134
|
+
// encoding = 'utf8'
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
const file = fs.readFileSync(filepath, encoding)
|
|
138
|
+
return file
|
|
139
|
+
} catch (error) {
|
|
140
|
+
return null
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
printError: (error) => {
|
|
145
|
+
if (error.response) {
|
|
146
|
+
const { data } = error.response
|
|
147
|
+
const errorText = `${colors.red(`\nError: `)} ${colors.white(`${data.error}\n`)}`
|
|
148
|
+
console.log(errorText)
|
|
149
|
+
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const errorText = `${colors.red(`\nError: `)} ${colors.white(`${error.message}\n`)}`
|
|
154
|
+
console.log(errorText)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
postRequest: function(endpoint, params){
|
|
159
|
+
return new Promise(function(resolve, reject){
|
|
160
|
+
superagent
|
|
161
|
+
.post(endpoint)
|
|
162
|
+
.send(params)
|
|
163
|
+
.set('Accept', 'application/json')
|
|
164
|
+
.end(function(err, response){
|
|
165
|
+
// console.log('POST CALLBACK: ' + JSON.stringify(response))
|
|
166
|
+
if (err){
|
|
167
|
+
// console.log('err 1: ' + err)
|
|
168
|
+
if (!response){
|
|
169
|
+
reject(err)
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (response.text){
|
|
174
|
+
try {
|
|
175
|
+
var parsed = JSON.parse(response.text)
|
|
176
|
+
var message = parsed.message || 'Something went wrong. Please try again.'
|
|
177
|
+
reject(new Error(message))
|
|
178
|
+
return
|
|
179
|
+
} catch(parseError){
|
|
180
|
+
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
reject(err)
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (response.body.confirmation != 'success'){
|
|
189
|
+
// console.log('POST ERROR: ' + JSON.stringify(response))
|
|
190
|
+
reject(new Error(response.body.message))
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
resolve(response.body)
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
putRequest: function(endpoint, params){
|
|
200
|
+
return new Promise(function(resolve, reject){
|
|
201
|
+
superagent
|
|
202
|
+
.put(endpoint)
|
|
203
|
+
.send(params)
|
|
204
|
+
.set('Accept', 'application/json')
|
|
205
|
+
.end(function(err, response){
|
|
206
|
+
if (err){
|
|
207
|
+
if (!response){
|
|
208
|
+
reject(err)
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (response.text){
|
|
213
|
+
try {
|
|
214
|
+
var parsed = JSON.parse(response.text)
|
|
215
|
+
var message = parsed.message || 'Something went wrong. Please try again.'
|
|
216
|
+
reject(new Error(message))
|
|
217
|
+
return
|
|
218
|
+
} catch(parseError){
|
|
219
|
+
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
reject(err)
|
|
224
|
+
return
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (response.body.confirmation != 'success'){
|
|
228
|
+
// console.log('POST ERROR: ' + JSON.stringify(response))
|
|
229
|
+
reject(new Error(response.body.message))
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
resolve(response.body)
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
getRequest: function(endpoint){
|
|
239
|
+
return new Promise(function(resolve, reject){
|
|
240
|
+
superagent
|
|
241
|
+
.get(endpoint)
|
|
242
|
+
.set('Accept', 'application/json')
|
|
243
|
+
.end(function(err, response){
|
|
244
|
+
if (err){
|
|
245
|
+
if (!response){
|
|
246
|
+
reject(err)
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (response.text){
|
|
251
|
+
try {
|
|
252
|
+
var parsed = JSON.parse(response.text)
|
|
253
|
+
var message = parsed.message || 'Something went wrong. Please try again.'
|
|
254
|
+
reject(new Error(message))
|
|
255
|
+
return
|
|
256
|
+
} catch(parseError){
|
|
257
|
+
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
reject(err)
|
|
262
|
+
return
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (response.body.confirmation != 'success'){
|
|
266
|
+
reject(new Error(response.body.message))
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
resolve(response.body)
|
|
271
|
+
})
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
*/
|
|
275
|
+
}
|