@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.
- package/auth/index.js +147 -0
- package/base/vinely-base/.nvmrc +1 -0
- package/base/vinely-base/README.md +30 -0
- package/base/vinely-base/app.js +5 -0
- package/base/vinely-base/declarations.d.ts +1 -0
- package/base/vinely-base/package.json +103 -0
- package/base/vinely-base/public/css/globals-2.css +3699 -0
- package/base/vinely-base/public/css/globals.css +3695 -0
- package/base/vinely-base/public/js/app.js +1 -0
- package/base/vinely-base/public/js/jquery.js +2 -0
- package/base/vinely-base/scratch.js +21 -0
- package/base/vinely-base/src/client/components/app-sidebar.tsx +59 -0
- package/base/vinely-base/src/client/components/assistant-ui/markdown-text.tsx +153 -0
- package/base/vinely-base/src/client/components/assistant-ui/thread-list.tsx +67 -0
- package/base/vinely-base/src/client/components/assistant-ui/thread.tsx +666 -0
- package/base/vinely-base/src/client/components/assistant-ui/tool-fallback.tsx +44 -0
- package/base/vinely-base/src/client/components/assistant-ui/tooltip-icon-button.tsx +44 -0
- package/base/vinely-base/src/client/components/ui/breadcrumb.tsx +109 -0
- package/base/vinely-base/src/client/components/ui/button.tsx +59 -0
- package/base/vinely-base/src/client/components/ui/input.tsx +21 -0
- package/base/vinely-base/src/client/components/ui/separator.tsx +28 -0
- package/base/vinely-base/src/client/components/ui/sheet.tsx +139 -0
- package/base/vinely-base/src/client/components/ui/sidebar.tsx +726 -0
- package/base/vinely-base/src/client/components/ui/skeleton.tsx +14 -0
- package/base/vinely-base/src/client/components/ui/tooltip.tsx +61 -0
- package/base/vinely-base/src/client/components/vines-sidebar.tsx +182 -0
- package/base/vinely-base/src/client/contexts/SessionContext.tsx +28 -0
- package/base/vinely-base/src/client/contexts/SessionReducer.tsx +32 -0
- package/base/vinely-base/src/client/hooks/use-mobile.ts +19 -0
- package/base/vinely-base/src/client/index.tsx +154 -0
- package/base/vinely-base/src/client/lib/API.ts +155 -0
- package/base/vinely-base/src/client/lib/RPC.ts +49 -0
- package/base/vinely-base/src/client/lib/utils.ts +96 -0
- package/base/vinely-base/src/server/index.ts +63 -0
- package/base/vinely-base/src/server/routes/api.ts +38 -0
- package/base/vinely-base/src/server/routes/chat.ts +133 -0
- package/base/vinely-base/src/server/routes/main.ts +36 -0
- package/base/vinely-base/src/server/routes/mcp.ts +52 -0
- package/base/vinely-base/src/server/routes/rpc.ts +64 -0
- package/base/vinely-base/src/server/routes/thread.ts +44 -0
- package/base/vinely-base/src/server/utils/APIMgr.ts +156 -0
- package/base/vinely-base/src/server/utils/Auth.ts +235 -0
- package/base/vinely-base/src/server/utils/fetchManifest.ts +15 -0
- package/base/vinely-base/src/server/utils/mcp-auth.ts +251 -0
- package/base/vinely-base/tsconfig.json +16 -0
- package/base/vinely-base/views/landing.html +187 -0
- package/base/vinely-base/views/partials/imports.dev.html +3 -0
- package/base/vinely-base/webpack.config.js +112 -0
- package/deploy/Dockerfile +9 -0
- package/deploy/index.js +244 -0
- package/index.js +266 -0
- package/package.json +28 -0
- package/scaffold/app/gulpfile.js +12 -0
- package/scaffold/app/package.json +24 -0
- package/scaffold/app/src/index.js +14 -0
- package/scaffold/index.js +171 -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/utils/Realm.js +60 -0
- package/utils/http.js +22 -0
- package/utils/index.js +276 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import webpack from 'webpack'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import HtmlWebpackPlugin from 'html-webpack-plugin'
|
|
4
|
+
import TerserPlugin from 'terser-webpack-plugin'
|
|
5
|
+
import { fileURLToPath } from 'url'
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url) // get the resolved path to the file
|
|
8
|
+
const __dirname = path.dirname(__filename) // get the name of the directory
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
entry: {
|
|
12
|
+
app: `./src/client/index.tsx`
|
|
13
|
+
},
|
|
14
|
+
output: {
|
|
15
|
+
path: `${__dirname.replace('webpack', '')}/public/dist`,
|
|
16
|
+
filename: (process.env.NODE_ENV === 'production') ? 'prod/[name].[chunkhash].js' : 'dev/[name].js',
|
|
17
|
+
chunkFilename: (process.env.NODE_ENV === 'production') ? 'prod/[name].[chunkhash].js' : 'dev/[name].js',
|
|
18
|
+
sourceMapFilename: 'dev/[name].map',
|
|
19
|
+
publicPath: `{{{ CDN }}}/dist/`
|
|
20
|
+
},
|
|
21
|
+
devtool: 'inline-source-map',
|
|
22
|
+
module: {
|
|
23
|
+
rules: [
|
|
24
|
+
{
|
|
25
|
+
test: /\.jsx?$/,
|
|
26
|
+
exclude: /node_modules/,
|
|
27
|
+
loader: 'babel-loader'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
test: /\.json$/,
|
|
31
|
+
loader: 'json-loader',
|
|
32
|
+
type: 'javascript/auto'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
test: /\.tsx?$/,
|
|
36
|
+
exclude: /node_modules/,
|
|
37
|
+
// use: 'ts-loader',
|
|
38
|
+
use: [
|
|
39
|
+
{
|
|
40
|
+
loader: 'ts-loader',
|
|
41
|
+
options: {
|
|
42
|
+
transpileOnly: true
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
// TODO: inject loaded CSS URI into templates rather than inject like this
|
|
48
|
+
// {
|
|
49
|
+
// test: /^(?!.*katex.*).*\.(gif|svg|jpg|png|css)$/, // add whatever files you wanna use within this regEx
|
|
50
|
+
// use: ["file-loader"]
|
|
51
|
+
// },
|
|
52
|
+
{
|
|
53
|
+
test: /\.(gif|svg|jpg|png|css)$/, // add whatever files you wanna use within this regEx
|
|
54
|
+
use: ["file-loader"]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
test: /katex.*\.css$/,
|
|
58
|
+
loader: 'file-loader',
|
|
59
|
+
options: {
|
|
60
|
+
name: "[name].css",
|
|
61
|
+
outputPath: "css"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
performance: process.env.NODE_ENV === 'production' ? { hints: false } : {},
|
|
67
|
+
plugins: process.env.NODE_ENV === 'production'
|
|
68
|
+
? [
|
|
69
|
+
new HtmlWebpackPlugin({
|
|
70
|
+
template: `./public/dist/build.html`,
|
|
71
|
+
filename: `../../views/partials/imports.prod.html`,
|
|
72
|
+
inject: 'body'
|
|
73
|
+
}),
|
|
74
|
+
new webpack.DefinePlugin({
|
|
75
|
+
'process.env': {
|
|
76
|
+
NODE_ENV: JSON.stringify('production')
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
]
|
|
80
|
+
: [],
|
|
81
|
+
optimization: process.env.NODE_ENV === 'production'
|
|
82
|
+
? {
|
|
83
|
+
minimize: true,
|
|
84
|
+
minimizer: [new TerserPlugin()],
|
|
85
|
+
splitChunks: {
|
|
86
|
+
cacheGroups: {
|
|
87
|
+
vendor: {
|
|
88
|
+
test: /node_modules/,
|
|
89
|
+
chunks: 'initial',
|
|
90
|
+
name: 'commons',
|
|
91
|
+
enforce: true
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
: {
|
|
97
|
+
minimize: false,
|
|
98
|
+
splitChunks: {
|
|
99
|
+
cacheGroups: {
|
|
100
|
+
vendor: {
|
|
101
|
+
test: /node_modules/,
|
|
102
|
+
chunks: 'initial',
|
|
103
|
+
name: 'commons',
|
|
104
|
+
enforce: true
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
resolve: {
|
|
110
|
+
extensions: ['.js', '.jsx', '.tsx', '.ts'] // add .tsx and .ts as file extensions to be resolved
|
|
111
|
+
}
|
|
112
|
+
}
|
package/deploy/index.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const axios = require('axios')
|
|
4
|
+
const shell = require('shelljs')
|
|
5
|
+
const colors = require('colors/safe') // https://www.npmjs.com/package/colors
|
|
6
|
+
const bestzip = require('bestzip')
|
|
7
|
+
|
|
8
|
+
// const PORTAL_URL = 'https://portal.turbo360.co'
|
|
9
|
+
|
|
10
|
+
const RPC_URL = 'https://e3lunom2hka3u6iiotrlzrcez40uwdnk.lambda-url.us-east-1.on.aws'
|
|
11
|
+
const ZIP_NAME = 'LATEST.zip'
|
|
12
|
+
const STATIC_ARCHIVE_NAME = 'Archive.zip'
|
|
13
|
+
const DEFAULT_HEADERS = {
|
|
14
|
+
'Content-Type': 'application/json',
|
|
15
|
+
'Accept': 'application/json'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const rpcCall = async (action, args, headers = DEFAULT_HEADERS) => {
|
|
19
|
+
try {
|
|
20
|
+
const resp = await axios({
|
|
21
|
+
url: RPC_URL,
|
|
22
|
+
method: 'post',
|
|
23
|
+
headers,
|
|
24
|
+
data: {
|
|
25
|
+
action,
|
|
26
|
+
args
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
return resp
|
|
31
|
+
} catch (error) {
|
|
32
|
+
throw error
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const getUploadUrl = async (folder, filename, filetype = 'application/zip') => {
|
|
37
|
+
const resp = await rpcCall('uploadUrl', { folder, filename, filetype })
|
|
38
|
+
|
|
39
|
+
if (resp.data.confirmation !== 'success') {
|
|
40
|
+
throw new Error(resp.data.message)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const uploadUrl = resp.data.data.upload
|
|
44
|
+
return uploadUrl
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
// 09/17/2019 - this did not cover all scenarios. Windows worked fine (confirmed
|
|
49
|
+
// by Marianne) but if on a funky linux distro, the "else" block failed.
|
|
50
|
+
var zipDirectory = function(){
|
|
51
|
+
// console.log('PLT == ' + process.platform)
|
|
52
|
+
if (process.platform == 'win32'){ // fuck windows:
|
|
53
|
+
return bestzip.nodeZip({source:'*', destination: '../package.zip'})
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return new Promise(function(resolve, reject){
|
|
57
|
+
shell.exec('zip -r -q package.zip *')
|
|
58
|
+
resolve(true)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
} */
|
|
62
|
+
|
|
63
|
+
const zipDirectory = (name = 'package.zip') => {
|
|
64
|
+
// the package.zip file has to be created in another directory
|
|
65
|
+
// otherwise it will include "package.zip" itself with nothing
|
|
66
|
+
// inside. This is sloppy so we create the package.zip file in
|
|
67
|
+
// one level up then bring it back into the deploy folder
|
|
68
|
+
|
|
69
|
+
if (process.platform === 'win32'){ // fuck windows:
|
|
70
|
+
return bestzip.nodeZip({
|
|
71
|
+
source: '*',
|
|
72
|
+
destination: `../${name}`
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return bestzip.nodeZip({
|
|
77
|
+
source: '*',
|
|
78
|
+
destination: `../${name}`
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const compile = async (deployDir, name = 'package.zip', dir = null) => {
|
|
84
|
+
// let data = utils.readFile('package.json')
|
|
85
|
+
// const json = JSON.parse(data)
|
|
86
|
+
|
|
87
|
+
// delete json.devDependencies // prevent these from deploying
|
|
88
|
+
|
|
89
|
+
shell.mkdir('-p', `${deployDir}/`)
|
|
90
|
+
|
|
91
|
+
if (dir === null) {
|
|
92
|
+
shell.cp('-R', '!(node_modules|deploy)', `${deployDir}/`) // copy everything but node_modules and deploy
|
|
93
|
+
} else {
|
|
94
|
+
// compress contents of specified directory:
|
|
95
|
+
shell.cd(dir)
|
|
96
|
+
shell.cp('-R', '!(node_modules|deploy)', `../${deployDir}/`)
|
|
97
|
+
shell.cd('..')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
shell.cd(deployDir)
|
|
101
|
+
|
|
102
|
+
await zipDirectory(name) // package it up!
|
|
103
|
+
|
|
104
|
+
// the zip file has to be created in another directory
|
|
105
|
+
// otherwise it will include "*.zip" itself with nothing
|
|
106
|
+
// inside. This is sloppy so we create the zip file in
|
|
107
|
+
// one level up then bring it back into the deploy folder
|
|
108
|
+
shell.cd('..')
|
|
109
|
+
shell.mv([name], `${deployDir}/`)
|
|
110
|
+
shell.cd(deployDir)
|
|
111
|
+
|
|
112
|
+
shell.mv([name], '..') // place package in root directory
|
|
113
|
+
shell.cd('..')
|
|
114
|
+
shell.rm('-rf', deployDir) // remove hidden deploy dir
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
module.exports = {
|
|
118
|
+
project: async ({ TURBO_PROJECT_SLUG }) => {
|
|
119
|
+
if (!TURBO_PROJECT_SLUG) {
|
|
120
|
+
throw new Error(colors.white('Project undefined. Please check .env file.'))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
shell.cp('-R', path.join(__dirname, 'Dockerfile'), 'Dockerfile')
|
|
124
|
+
|
|
125
|
+
const uploadUrl = await getUploadUrl('projects', `${TURBO_PROJECT_SLUG}/container/${ZIP_NAME}`)
|
|
126
|
+
|
|
127
|
+
console.log(`\n${colors.white('Deploying project code. This usually takes a few minutes...')}\n`)
|
|
128
|
+
await compile('.deploy', ZIP_NAME)
|
|
129
|
+
|
|
130
|
+
await axios({
|
|
131
|
+
url: uploadUrl,
|
|
132
|
+
method: 'put',
|
|
133
|
+
data: fs.readFileSync(ZIP_NAME),
|
|
134
|
+
headers: {
|
|
135
|
+
'Content-Type': 'application/zip'
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
shell.rm('-rf', ZIP_NAME)
|
|
140
|
+
shell.rm('-rf', 'Dockerfile')
|
|
141
|
+
|
|
142
|
+
// trigger docker build in the cloud:
|
|
143
|
+
await rpcCall('deploy', { project: TURBO_PROJECT_SLUG })
|
|
144
|
+
|
|
145
|
+
// connect container image to function:
|
|
146
|
+
await rpcCall('bind-image', { project: TURBO_PROJECT_SLUG })
|
|
147
|
+
|
|
148
|
+
console.log(colors.white('\nDeploy complete! To view your site, navigate to\n'))
|
|
149
|
+
console.log(colors.white(`https://${TURBO_PROJECT_SLUG}.vinely.site\n\n`))
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
static: async ({ TURBO_PROJECT_SLUG }) => {
|
|
153
|
+
if (!TURBO_PROJECT_SLUG) {
|
|
154
|
+
throw new Error(colors.white('Project undefined. Please check .env file.'))
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const uploadUrl = await getUploadUrl('projects', `${TURBO_PROJECT_SLUG}/static/${STATIC_ARCHIVE_NAME}`)
|
|
158
|
+
await compile('.deploy', STATIC_ARCHIVE_NAME, 'public')
|
|
159
|
+
|
|
160
|
+
await axios({
|
|
161
|
+
url: uploadUrl,
|
|
162
|
+
method: 'put',
|
|
163
|
+
data: fs.readFileSync(STATIC_ARCHIVE_NAME),
|
|
164
|
+
headers: {
|
|
165
|
+
'Content-Type': 'application/zip'
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
shell.rm('-rf', STATIC_ARCHIVE_NAME)
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
await rpcCall('sync', {
|
|
173
|
+
project: TURBO_PROJECT_SLUG,
|
|
174
|
+
folder: 'static',
|
|
175
|
+
file: STATIC_ARCHIVE_NAME
|
|
176
|
+
})
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.warn('FAIL: ' + error)
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
console.log(colors.white('\nStatic deployment complete! To view, navigate to\n'))
|
|
183
|
+
console.log(colors.white(`https://${TURBO_PROJECT_SLUG}.turbo360-static-sites.com\n\n`))
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
/*
|
|
187
|
+
// deploy app:
|
|
188
|
+
app: async ({ TURBO_APP_SLUG }) => {
|
|
189
|
+
let resp = await axios({
|
|
190
|
+
url: RPC_URL,
|
|
191
|
+
method: 'post',
|
|
192
|
+
data: {
|
|
193
|
+
action: 'appDeployments',
|
|
194
|
+
args: {
|
|
195
|
+
app: TURBO_APP_SLUG
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
headers: { Accept: 'application/json' }
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
const { confirmation, message, data } = resp.data
|
|
202
|
+
if (confirmation !== 'success') {
|
|
203
|
+
throw new Error(message)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const { deployments } = data
|
|
207
|
+
const deployment = `${deployments.length + 1}.zip`
|
|
208
|
+
|
|
209
|
+
resp = await axios({
|
|
210
|
+
url: RPC_URL,
|
|
211
|
+
method: 'post',
|
|
212
|
+
data: {
|
|
213
|
+
action: 'uploadUrl',
|
|
214
|
+
args: {
|
|
215
|
+
folder: 'apps',
|
|
216
|
+
// filename: `${TURBO_APP_SLUG}/${deployment}`,
|
|
217
|
+
filename: `${TURBO_APP_SLUG}/builds/${deployment}`,
|
|
218
|
+
filetype: 'application/zip'
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
if (resp.data.confirmation !== 'success') {
|
|
224
|
+
throw new Error(resp.data.message)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const uploadUrl = resp.data.data.upload
|
|
228
|
+
|
|
229
|
+
console.log('\nUploading app code...\n')
|
|
230
|
+
await compile('.deploy', deployment)
|
|
231
|
+
|
|
232
|
+
await axios({
|
|
233
|
+
url: uploadUrl,
|
|
234
|
+
method: 'put',
|
|
235
|
+
data: fs.readFileSync(deployment),
|
|
236
|
+
headers: {
|
|
237
|
+
'Content-Type': 'application/zip'
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
shell.rm('-rf', deployment)
|
|
242
|
+
}
|
|
243
|
+
*/
|
|
244
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// REFERENCE:
|
|
4
|
+
// https://developer.atlassian.com/blog/2015/11/scripting-with-node/
|
|
5
|
+
// https://www.npmjs.com/package/shelljs
|
|
6
|
+
// https://github.com/expressjs/generator/blob/master/bin/express-cli.js
|
|
7
|
+
// https://developer.atlassian.com/blog/2015/11/scripting-with-node/
|
|
8
|
+
|
|
9
|
+
const path = require('path')
|
|
10
|
+
const dotenv = require('dotenv')
|
|
11
|
+
const axios = require('axios')
|
|
12
|
+
const prompt = require('prompt')
|
|
13
|
+
const { Command } = require('commander')
|
|
14
|
+
const shell = require('shelljs')
|
|
15
|
+
const colors = require('colors/safe')
|
|
16
|
+
const AdmZip = require('adm-zip')
|
|
17
|
+
const auth = require('./auth')
|
|
18
|
+
const deploy = require('./deploy')
|
|
19
|
+
const scaffold = require('./scaffold')
|
|
20
|
+
const utils = require('./utils')
|
|
21
|
+
const Realm = require('./utils/Realm')
|
|
22
|
+
const packageJson = require('./package.json')
|
|
23
|
+
|
|
24
|
+
const VERSION = packageJson.version
|
|
25
|
+
|
|
26
|
+
const PORTAL_URL = 'https://portal.turbo360.co'
|
|
27
|
+
// const RPC_URL = 'https://e3lunom2hka3u6iiotrlzrcez40uwdnk.lambda-url.us-east-1.on.aws'
|
|
28
|
+
|
|
29
|
+
// FUTURE: Export as a referenceable type
|
|
30
|
+
const ERRORS = {
|
|
31
|
+
// General errors
|
|
32
|
+
UNSPECIFIED: { exitCode: 1 },
|
|
33
|
+
INVALID_PARAMS: { exitCode: 2 },
|
|
34
|
+
NOT_LOGGED_IN: { exitCode: 3 },
|
|
35
|
+
|
|
36
|
+
// Deploy-specific errors
|
|
37
|
+
PROJECT_NOT_CONNECTED: { exitCode: 100 },
|
|
38
|
+
PROJECT_NOT_FOUND: { exitCode: 101 },
|
|
39
|
+
NOT_AUTHORIZED: { exitCode: 102 },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const program = new Command()
|
|
43
|
+
|
|
44
|
+
program.version(VERSION, '-v, --version', 'output the current version')
|
|
45
|
+
|
|
46
|
+
program.command('help')
|
|
47
|
+
.description('help')
|
|
48
|
+
.action(() => {
|
|
49
|
+
console.log('HELP!')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
program.command('version')
|
|
53
|
+
.description('show current version')
|
|
54
|
+
.action((cmd, options) => {
|
|
55
|
+
try {
|
|
56
|
+
const text = `${colors.cyan(`\nVinely CLI Version: `)} ${colors.brightGreen(`${VERSION}`)}\n`
|
|
57
|
+
console.log(text)
|
|
58
|
+
} catch (error) {
|
|
59
|
+
// console.log(colors.red('\nError: '+err.message+'\n'))
|
|
60
|
+
utils.printError(error)
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
program.command('profile')
|
|
65
|
+
.description('Current Vinely user')
|
|
66
|
+
.action(async (cmd, options) => {
|
|
67
|
+
const user = await auth.currentUser()
|
|
68
|
+
if (user === false) {
|
|
69
|
+
program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
|
|
70
|
+
ERRORS.NOT_LOGGED_IN);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const text = `${colors.cyan(`\nLogged in as: `)} ${colors.brightGreen(`${user.username}`)}\n`
|
|
74
|
+
console.log(text)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
program.command('login')
|
|
78
|
+
.description('login to Vinely')
|
|
79
|
+
.action(async (cmd, options) => {
|
|
80
|
+
try {
|
|
81
|
+
const credentials = await auth.showPrompt()
|
|
82
|
+
|
|
83
|
+
const resp = await axios({
|
|
84
|
+
url: `${PORTAL_URL}/auth/login`,
|
|
85
|
+
method: 'post',
|
|
86
|
+
data: credentials,
|
|
87
|
+
headers: { Accept: 'application/json'}
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
const { data } = resp.data
|
|
91
|
+
const user = { id: data._id, username: data.username }
|
|
92
|
+
|
|
93
|
+
shell.cd('')
|
|
94
|
+
utils.write('.vinely_user', JSON.stringify(user, null, 2) + '\n')
|
|
95
|
+
|
|
96
|
+
const successText = `${colors.cyan(`\nSuccess! `)} ${colors.brightGreen(`Currently Logged In As ${user.username}\n`)}`
|
|
97
|
+
console.log(successText)
|
|
98
|
+
} catch (error) {
|
|
99
|
+
utils.printError(error)
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
program.command('dev')
|
|
104
|
+
.description('run dev server')
|
|
105
|
+
.action(async (cmd, options) => {
|
|
106
|
+
try {
|
|
107
|
+
// shell.cp('-R', path.join(__dirname, '../default/lambda/js/index.js'), 'vectors/js/index.js')
|
|
108
|
+
shell.cd(path.join(__dirname, 'base/vinely-base'))
|
|
109
|
+
shell.exec('npm run dev')
|
|
110
|
+
// shell.cd('vinely-base')
|
|
111
|
+
|
|
112
|
+
// shell.exec('gulp build --gulpfile node_modules/@turbo360/turbo-sdk/src/gulpfile.js --silent')
|
|
113
|
+
|
|
114
|
+
} catch (error) {
|
|
115
|
+
utils.printError(error)
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
program.command('new <name>')
|
|
120
|
+
.description('create new Vinely app')
|
|
121
|
+
.action(name => scaffold(name, 'project'))
|
|
122
|
+
|
|
123
|
+
program.command('connect')
|
|
124
|
+
.description('Connect to Vinely project')
|
|
125
|
+
.action(async (cmd, options) => {
|
|
126
|
+
try {
|
|
127
|
+
const user = await auth.currentUser() // must be logged in.
|
|
128
|
+
if (user === false) {
|
|
129
|
+
program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
|
|
130
|
+
ERRORS.NOT_LOGGED_IN);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const projects = await Realm.restQuery('project', 'get', { 'members.id': user.id })
|
|
134
|
+
if (projects.length === 0) {
|
|
135
|
+
throw new Error(`No Projects not found.`)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// console.log('PROJECTS: ' + JSON.stringify(projects))
|
|
139
|
+
|
|
140
|
+
const _projects = projects.map(({ name }, idx) => `${idx + 1}. ${name}`)
|
|
141
|
+
|
|
142
|
+
const schema = {
|
|
143
|
+
properties: {
|
|
144
|
+
framework: {
|
|
145
|
+
message: `\n\n${_projects.join('\n')}\n\nSelect project number then press "enter"\n`,
|
|
146
|
+
required: true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
prompt.start()
|
|
152
|
+
|
|
153
|
+
prompt.get(schema, (err, result) => {
|
|
154
|
+
if (err) {
|
|
155
|
+
console.log('\n')
|
|
156
|
+
return
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const selected = result.framework.trim()
|
|
160
|
+
const index = parseInt(selected - 1)
|
|
161
|
+
|
|
162
|
+
if (index < 0) {
|
|
163
|
+
utils.printError(new Error('Invalid entry.'))
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (_projects.length < (index + 1)) {
|
|
168
|
+
utils.printError(new Error('Invalid entry.'))
|
|
169
|
+
return
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const selectedApp = projects[index]
|
|
173
|
+
if (!selectedApp) {
|
|
174
|
+
utils.printError(new Error('Invalid entry.'))
|
|
175
|
+
return
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// console.log('SELECTED: ' + JSON.stringify(selectedApp))
|
|
179
|
+
const { name, slug } = selectedApp
|
|
180
|
+
const envFile = utils.readFile('.env') || '{}'
|
|
181
|
+
const envJson = dotenv.parse(envFile)
|
|
182
|
+
|
|
183
|
+
const env = {
|
|
184
|
+
...envJson,
|
|
185
|
+
'TURBO_PROJECT': name,
|
|
186
|
+
'TURBO_PROJECT_SLUG': slug
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
let envString = ''
|
|
190
|
+
Object.keys(env).forEach((key, i) => {
|
|
191
|
+
if (env[key] !== null) {
|
|
192
|
+
envString += key+'='+env[key]+'\n'
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
utils.write('.env', envString)
|
|
197
|
+
console.log('\nApp Connected!\nto deploy:\n\n$ vly deploy\n\n')
|
|
198
|
+
})
|
|
199
|
+
} catch (error) {
|
|
200
|
+
utils.printError(error)
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
program.command('build')
|
|
205
|
+
.description('compile Vinely app')
|
|
206
|
+
.action(name => {
|
|
207
|
+
shell.exec('gulp build --gulpfile node_modules/@turbo360/turbo-sdk/src/gulpfile.js --silent')
|
|
208
|
+
|
|
209
|
+
console.log('BUILD COMPLETE')
|
|
210
|
+
// const gulpfilePath = path.join(__dirname, 'scaffold/app/gulpfile.js')
|
|
211
|
+
// shell.exec(`gulp build --gulpfile ${gulpfilePath}`)
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
program.command('deploy')
|
|
216
|
+
.option('-t, --type <default_or_static>', 'deployment type | static or default', 'default') // https://www.npmjs.com/package/commander#default-option-value
|
|
217
|
+
.description('Deploy to Vinely')
|
|
218
|
+
.action(async (cmd, options) => {
|
|
219
|
+
try {
|
|
220
|
+
const { type } = cmd
|
|
221
|
+
if (type !== 'default' && type !== 'static') {
|
|
222
|
+
const msg = colors.red(`\nError: Invalid deployment type ${type}.\n`) +
|
|
223
|
+
colors.white(`Please select type "static" or omit type flag.\n`);
|
|
224
|
+
program.error(msg, ERRORS.INVALID_PARAMS)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const user = await auth.currentUser() // must be logged in.
|
|
228
|
+
if (user === false) {
|
|
229
|
+
program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
|
|
230
|
+
ERRORS.NOT_LOGGED_IN);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const {
|
|
234
|
+
TURBO_PROJECT = null,
|
|
235
|
+
TURBO_PROJECT_SLUG = null
|
|
236
|
+
} = dotenv.parse(utils.readFile('.env') ?? '')
|
|
237
|
+
|
|
238
|
+
if (TURBO_PROJECT === null || TURBO_PROJECT_SLUG === null) {
|
|
239
|
+
program.error('Vinely project not connected. To connect, run:\n\n$ vly connect',
|
|
240
|
+
ERRORS.PROJECT_NOT_CONNECTED)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const apps = await Realm.restQuery('project', 'get', { slug: TURBO_PROJECT_SLUG })
|
|
244
|
+
if (apps.length === 0) {
|
|
245
|
+
program.error(`App ${TURBO_PROJECT} not found.`, ERRORS.PROJECT_NOT_FOUND)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const { members } = apps[0]
|
|
249
|
+
if (!members.find(member => (member.id === user.id))) {
|
|
250
|
+
program.error('Unauthorized', ERRORS.NOT_AUTHORIZED)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// console.log('DEPLOY: ' + type)
|
|
254
|
+
// if (type === 'static') {
|
|
255
|
+
// await deploy.static({ TURBO_PROJECT_SLUG })
|
|
256
|
+
// return
|
|
257
|
+
// }
|
|
258
|
+
|
|
259
|
+
await deploy.project({ TURBO_PROJECT_SLUG })
|
|
260
|
+
} catch (error) {
|
|
261
|
+
utils.printError(error)
|
|
262
|
+
program.error(`Unexpected error: ${error}`, ERRORS.UNSPECIFIED)
|
|
263
|
+
}
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
program.parse(process.argv)
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@surph_ai/sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"bin": {
|
|
13
|
+
"surph": "./index.js"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [],
|
|
16
|
+
"author": "SurphAI",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"adm-zip": "^0.5.10",
|
|
20
|
+
"axios": "^1.12.2",
|
|
21
|
+
"bestzip": "^2.2.1",
|
|
22
|
+
"colors": "^1.4.0",
|
|
23
|
+
"commander": "^14.0.1",
|
|
24
|
+
"dotenv": "^16.0.3",
|
|
25
|
+
"prompt": "^1.3.0",
|
|
26
|
+
"shelljs": "^0.8.5"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const gulp = require('gulp')
|
|
2
|
+
const babel = require('gulp-babel')
|
|
3
|
+
|
|
4
|
+
gulp.task('build', () => {
|
|
5
|
+
return gulp.src(['../src/**'])
|
|
6
|
+
.pipe(babel({
|
|
7
|
+
presets: ['@babel/preset-env']
|
|
8
|
+
}))
|
|
9
|
+
.pipe(gulp.dest('../dist'))
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
gulp.task('default', gulp.series('build'))
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"description": "",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
7
|
+
"build": "turbo build"
|
|
8
|
+
},
|
|
9
|
+
"babel": {
|
|
10
|
+
"presets": ["@babel/env"]
|
|
11
|
+
},
|
|
12
|
+
"keywords": [],
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@turbo360/turbo-sdk": "^0.0.7"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@babel/cli": "^7.21.5",
|
|
19
|
+
"@babel/core": "^7.0.0",
|
|
20
|
+
"@babel/preset-env": "^7.21.5",
|
|
21
|
+
"gulp": "^4.0.2",
|
|
22
|
+
"gulp-babel": "^8.0.0"
|
|
23
|
+
}
|
|
24
|
+
}
|