@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,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
+ }
@@ -0,0 +1,9 @@
1
+ FROM public.ecr.aws/lambda/nodejs:22
2
+
3
+ ARG TURBO_PROJECT
4
+
5
+ COPY app.js . /var/task/
6
+
7
+ RUN npm install --production
8
+
9
+ CMD [ "app.entry" ]
@@ -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
+ }