superuser.app 0.0.0

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 (45) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +296 -0
  3. package/commands/domains/add.js +102 -0
  4. package/commands/domains/list.js +71 -0
  5. package/commands/domains/remove.js +97 -0
  6. package/commands/domains/verify.js +130 -0
  7. package/commands/g/endpoint.js +32 -0
  8. package/commands/g/test.js +42 -0
  9. package/commands/init.js +220 -0
  10. package/commands/login.js +123 -0
  11. package/commands/me.js +54 -0
  12. package/commands/organizations/create.js +68 -0
  13. package/commands/profile.js +58 -0
  14. package/commands/register.js +127 -0
  15. package/commands/run.js +194 -0
  16. package/commands/serve.js +35 -0
  17. package/commands/test.js +68 -0
  18. package/commands/up.js +257 -0
  19. package/commands/update.js +84 -0
  20. package/commands/version.js +31 -0
  21. package/helpers/constants.js +3 -0
  22. package/helpers/draw_box.js +38 -0
  23. package/helpers/draw_table.js +144 -0
  24. package/helpers/file_writer.js +101 -0
  25. package/helpers/generate/endpoint/_index.js +44 -0
  26. package/helpers/generate/test/_index.js +112 -0
  27. package/helpers/load_package.js +62 -0
  28. package/helpers/local_server.js +72 -0
  29. package/helpers/settings_manager.js +108 -0
  30. package/helpers/verify_packages.js +85 -0
  31. package/index.js +7 -0
  32. package/package.json +31 -0
  33. package/src/endpoint/functions/index.js +35 -0
  34. package/src/init/__.env +1 -0
  35. package/src/init/__.env.production +1 -0
  36. package/src/init/__.env.staging +1 -0
  37. package/src/init/__.gitignore +6 -0
  38. package/src/init/functions/index.js +15 -0
  39. package/src/init/instant.package.json +3 -0
  40. package/src/init/package.json +16 -0
  41. package/src/init/serve.instant.js +52 -0
  42. package/src/init/test/run.js +45 -0
  43. package/src/init/test/tests/_index.js +53 -0
  44. package/src/test/blank.mjs +16 -0
  45. package/src/test/endpoint.mjs +20 -0
@@ -0,0 +1,58 @@
1
+ const { Command } = require('cmnd');
2
+ const colors = require('colors/safe');
3
+ const inquirer = require('inquirer');
4
+
5
+ const SettingsManager = require('../helpers/settings_manager.js');
6
+ const DrawTable = require('../helpers/draw_table.js');
7
+
8
+ class ProfileCommand extends Command {
9
+
10
+ constructor() {
11
+ super('profile');
12
+ }
13
+
14
+ help () {
15
+ return {
16
+ description: 'Change your active profile',
17
+ args: [],
18
+ flags: {},
19
+ vflags: {}
20
+ };
21
+ }
22
+
23
+ async run (params) {
24
+
25
+ const settings = SettingsManager.read(true);
26
+ const profiles = settings.profileList;
27
+
28
+ console.log();
29
+
30
+ const columns = ['email', 'host', 'active'];
31
+ const rows = profiles.map((p, i) => {
32
+ return {
33
+ email: p.email,
34
+ host: p.host || '',
35
+ active: i === 0
36
+ ? colors.bold.green('yes')
37
+ : ''
38
+ };
39
+ });
40
+
41
+ const index = await DrawTable.selectIndexFromTable(
42
+ 'Choose your active profile',
43
+ columns,
44
+ rows
45
+ );
46
+
47
+ console.log();
48
+ if (index !== -1) {
49
+ SettingsManager.write(profiles[index]);
50
+ }
51
+
52
+ return void 0;
53
+
54
+ }
55
+
56
+ }
57
+
58
+ module.exports = ProfileCommand;
@@ -0,0 +1,127 @@
1
+ const { Command } = require('cmnd');
2
+ const io = require('io');
3
+ const colors = require('colors/safe');
4
+ const inquirer = require('inquirer');
5
+
6
+ const constants = require('../helpers/constants.js');
7
+
8
+ const LoginCommand = require('./login.js');
9
+
10
+ class RegisterCommand extends Command {
11
+
12
+ constructor() {
13
+ super('register');
14
+ }
15
+
16
+ help () {
17
+ return {
18
+ description: 'Registers a new user account with the Superuser Package Registry',
19
+ args: [],
20
+ flags: {},
21
+ vflags: {}
22
+ };
23
+ }
24
+
25
+ async run (params) {
26
+
27
+ let host = (params.flags.h || [])[0] || constants.BASE_URL;
28
+ if (!host.startsWith('http://') && !host.startsWith('https://')) {
29
+ host = host.startsWith('localhost')
30
+ ? `http://${host}`
31
+ : `https://${host}`
32
+ }
33
+
34
+ let registerResult = await inquirer.prompt([
35
+ {
36
+ name: 'email',
37
+ type: 'input',
38
+ message: `E-mail`,
39
+ validate: e => {
40
+ if (!e.match(/^[^@]+@[^@]+\.[a-z0-9\-]+$/gi)) {
41
+ return 'Must be a valid e-mail address';
42
+ } else {
43
+ return true;
44
+ }
45
+ }
46
+ },
47
+ {
48
+ name: 'organization_name',
49
+ type: 'input',
50
+ message: `Username`,
51
+ validate: v => {
52
+ if (
53
+ v.match(/[a-z][a-z0-9\-]*[a-z0-9]/i) &&
54
+ v.indexOf('--') === -1
55
+ ) {
56
+ return true;
57
+ } else {
58
+ return 'must start with a letter, end with a letter or number, and contain only A-Z, a-z, 0-9 or -';
59
+ }
60
+ }
61
+ },
62
+ {
63
+ name: 'password',
64
+ type: 'password',
65
+ message: `Password`
66
+ },
67
+ {
68
+ name: 'repeat_password',
69
+ type: 'password',
70
+ message: `Repeat password`
71
+ }
72
+ ]);
73
+
74
+ let result = await io.post(
75
+ `${host}/users`,
76
+ null,
77
+ null,
78
+ registerResult
79
+ );
80
+
81
+ if (result.statusCode !== 200) {
82
+ const e = result.data.error;
83
+ const message = e.message;
84
+ const details = e.details || {};
85
+ const more = [];
86
+ if (Object.keys(details).length) {
87
+ for (const key in details) {
88
+ more.push(`- ${colors.bold(key)}: ${details[key].message}`);
89
+ }
90
+ }
91
+ throw new Error(
92
+ message +
93
+ (
94
+ more.length
95
+ ? '\n\n' + more.join('\n')
96
+ : ''
97
+ )
98
+ );
99
+ }
100
+
101
+ const user = result.data; // grab json {data:}
102
+
103
+ console.log();
104
+ console.log(colors.bold(`${colors.blue(`Registered`)} for ${colors.green('Superuser')} successfully!`));
105
+ console.log(`${colors.bold(`email`)}: ${user.email}`);
106
+ console.log(`${colors.bold(`username`)}: ${user.memberships[0].organization.name}`);
107
+ console.log(`${colors.bold(`created at`)}: ${user.created_at}`);
108
+
109
+ return LoginCommand.prototype.run.call(
110
+ this,
111
+ {
112
+ args: [],
113
+ flags: {
114
+ h: params.flags.h
115
+ },
116
+ vflags: {
117
+ email: [user.email],
118
+ password: [registerResult.password]
119
+ }
120
+ }
121
+ );
122
+
123
+ }
124
+
125
+ }
126
+
127
+ module.exports = RegisterCommand;
@@ -0,0 +1,194 @@
1
+ const { Command } = require('cmnd');
2
+ const colors = require('colors/safe');
3
+ const io = require('io');
4
+ const kill = require('tree-kill');
5
+
6
+ const loadPackage = require('../helpers/load_package.js');
7
+ const localServer = require('../helpers/local_server.js');
8
+
9
+ const sleep = t => new Promise(r => setTimeout(() => r(1), t));
10
+ const killProcess = pid => {
11
+ return new Promise((resolve, reject) => {
12
+ kill(pid, (err) => {
13
+ if (err) {
14
+ reject(err);
15
+ } else {
16
+ resolve(true);
17
+ }
18
+ });
19
+ });
20
+ };
21
+
22
+ class RunCommand extends Command {
23
+
24
+ constructor() {
25
+ super('run');
26
+ }
27
+
28
+ help() {
29
+ return {
30
+ description: 'Runs a function in the local project',
31
+ args: [],
32
+ flags: {
33
+ 'm': 'Specify method, default is "get"',
34
+ 'v': 'Verbose mode: shows URL, status code and arguments'
35
+ },
36
+ vflags: {
37
+ '*': 'Used to populate query and / or body parameters'
38
+ }
39
+ };
40
+ }
41
+
42
+ async run(params) {
43
+
44
+ // Use 8199 for test runs
45
+ const InstantPackage = await loadPackage(params, true);
46
+ const port = 8199;
47
+ const timeout = 5000;
48
+ const url = `http://localhost:${port}`;
49
+
50
+ // Validate arguments, default method is "get"
51
+ const method = ((params.flags['m'] || [])[0] || 'get').toLowerCase();
52
+ if (['get', 'post', 'put', 'delete', 'del'].indexOf(method) === -1) {
53
+ throw new Error(`Method "${method}" not supported.`);
54
+ }
55
+ if (method === 'del') {
56
+ method = 'delete';
57
+ }
58
+ const functionParams = Object.keys(params.vflags).reduce((functionParams, key) => {
59
+ functionParams[key] = params.vflags[key].join(' ');
60
+ return functionParams;
61
+ }, {});
62
+ let pathname = params.args[0] || '';
63
+ if (!pathname) {
64
+ throw new Error(
65
+ `Please provide a pathname as the first argument.\n` +
66
+ `Use "/" to execute the root method (index.js)`
67
+ );
68
+ }
69
+ if (pathname.startsWith('..')) {
70
+ throw new Error(`Invalid pathname: "${pathname}"`);
71
+ }
72
+ if (pathname.startsWith('.')) {
73
+ pathname = pathname.slice(1);
74
+ }
75
+ if (pathname.startsWith('/')) {
76
+ pathname = pathname.slice(1);
77
+ }
78
+
79
+ const proc = localServer.run({ port, isBackground: true });
80
+ let isConnected = false;
81
+ proc.stdout.on('data', data => {
82
+ const message = data.toString();
83
+
84
+ if (message.includes(`*** Listening on localhost:${port}`)) {
85
+ isConnected = true;
86
+ } else if (message.includes(`Unable to spawn HTTP Workers, listening on port ${port}`)) {
87
+ isConnected = true;
88
+ }
89
+ });
90
+
91
+ // Wait for connection or timeout
92
+ let isTimedOut = false
93
+ await Promise.race([
94
+ (async () => {
95
+ await sleep(timeout);
96
+ if (!isConnected) {
97
+ isTimedOut = true;
98
+ await killProcess(proc.pid);
99
+ throw new Error(
100
+ `Timed out waiting for development server.\n` +
101
+ `Are you sure you're not running another server on :${port}?\n` +
102
+ `To kill any processes running on this port on a unix system, use:\n` +
103
+ `$ lsof -ti :${port} | xargs kill -9`
104
+ );
105
+ }
106
+ })(),
107
+ (async () => {
108
+ while (!isConnected && !isTimedOut) {
109
+ await sleep(1);
110
+ }
111
+ return true;
112
+ })()
113
+ ]);
114
+
115
+ const queryParams = (method === 'get' || method === 'delete')
116
+ ? { ...functionParams }
117
+ : {};
118
+ queryParams._debug = true;
119
+ const bodyParams = (method === 'post' || method === 'put')
120
+ ? JSON.stringify(functionParams)
121
+ : '';
122
+
123
+ let result;
124
+ const streamResult = await io.request(
125
+ method.toUpperCase(),
126
+ `${url}/${pathname}`,
127
+ queryParams,
128
+ {},
129
+ bodyParams,
130
+ ({id, event, data}) => {
131
+ if (event === '@response') {
132
+ let json = JSON.parse(data);
133
+ result = json;
134
+ } else if (event === '@stdout') {
135
+ let json = JSON.parse(data);
136
+ json.split('\n').forEach(line => {
137
+ console.log(colors.grey(`${params.flags.v ? colors.bold(`stdout> `) : ''}${line}`));
138
+ });
139
+ } else if (event === '@stderr') {
140
+ let json = JSON.parse(data);
141
+ json.split('\n').forEach(line => {
142
+ console.log(colors.yellow(`${params.flags.v ? colors.bold(`stderr> `) : ''}${line}`));
143
+ });
144
+ } else {
145
+ console.log(colors.blue(`${colors.bold(`${event}> `)}${data}`));
146
+ }
147
+ }
148
+ );
149
+
150
+ // Handle non-event errors given by server
151
+ if (streamResult.statusCode === 500) {
152
+ const errorBody = streamResult.body.toString();
153
+ let errorMessage = errorBody;
154
+ // cut out the "Application Error: " prefix and only capture the first line
155
+ if (errorBody.startsWith('Application Error:')) {
156
+ errorMessage = errorBody.slice('Application Error: '.length);
157
+ }
158
+ // ignore the stack trace
159
+ errorMessage = errorMessage.split('\n')[0];
160
+ throw new Error(errorMessage);
161
+ }
162
+
163
+ // retrieve details
164
+ const body = result.body.toString();
165
+ let json;
166
+ try {
167
+ json = JSON.parse(body);
168
+ } catch (e) {
169
+ // do nothing
170
+ }
171
+
172
+ // Terminate process
173
+ await killProcess(proc.pid);
174
+ if (params.flags.v) {
175
+ console.log(colors.bold.green('location: ') + `${url}/${pathname}`);
176
+ console.log(colors.bold.green('method: ') + method.toUpperCase());
177
+ console.log(colors.bold.green('status: ') + result.statusCode);
178
+ console.log(colors.bold.green('arguments: '));
179
+ console.log(JSON.stringify(functionParams, null, 2));
180
+ console.log(colors.bold.green('result:'));
181
+ }
182
+ if (json) {
183
+ console.log(JSON.stringify(json, null, 2));
184
+ } else {
185
+ console.log(body);
186
+ }
187
+
188
+ return void 0;
189
+
190
+ }
191
+
192
+ }
193
+
194
+ module.exports = RunCommand;
@@ -0,0 +1,35 @@
1
+ const { Command } = require('cmnd');
2
+
3
+ const loadPackage = require('../helpers/load_package.js');
4
+ const localServer = require('../helpers/local_server.js');
5
+
6
+ class ServeCommand extends Command {
7
+
8
+ constructor() {
9
+ super('serve');
10
+ }
11
+
12
+ help () {
13
+ return {
14
+ description: 'Starts a development server using package.json["scripts"]["start"]',
15
+ args: [],
16
+ flags: {},
17
+ vflags: {
18
+ port: 'specify a port to run on'
19
+ }
20
+ };
21
+ }
22
+
23
+ async run (params) {
24
+
25
+ const InstantPackage = await loadPackage(params, true);
26
+
27
+ localServer.run({ port: 8100 });
28
+
29
+ return void 0;
30
+
31
+ }
32
+
33
+ }
34
+
35
+ module.exports = ServeCommand;
@@ -0,0 +1,68 @@
1
+ const { Command } = require('cmnd');
2
+ const colors = require('colors/safe');
3
+ const fs = require('fs');
4
+ const childProcess = require('child_process');
5
+
6
+ const loadPackage = require('../helpers/load_package.js');
7
+
8
+ class TestCommand extends Command {
9
+
10
+ constructor() {
11
+ super('test');
12
+ }
13
+
14
+ help () {
15
+ return {
16
+ description: 'Runs tests using package.json["scripts"]["test"]',
17
+ args: [],
18
+ flags: {},
19
+ vflags: {}
20
+ };
21
+ }
22
+
23
+ async run (params) {
24
+
25
+ const InstantPackage = await loadPackage(params, true);
26
+
27
+ console.log();
28
+ console.log(`Running tests ...`);
29
+ const pkgExists = fs.existsSync('package.json');
30
+ if (pkgExists) {
31
+ let pkg;
32
+ try {
33
+ pkg = JSON.parse(fs.readFileSync('package.json').toString());
34
+ } catch (e) {
35
+ throw new Error(`Could not read "package.json"`);
36
+ }
37
+ if (pkg?.scripts?.test) {
38
+ console.log(`Running script: ${colors.blue.bold(pkg.scripts.test)} ...`);
39
+ console.log();
40
+ const result = childProcess.spawnSync(
41
+ `${pkg.scripts.test} ${params.args.join(' ')}`,
42
+ {
43
+ stdio: 'inherit',
44
+ shell: true,
45
+ env: {...process.env, PATH: process.env.PATH + ':./node_modules/.bin'}
46
+ }
47
+ );
48
+ if (result.status === 0) {
49
+ console.log(colors.bold.green(`Success!`) + ` All tests passed.`);
50
+ console.log();
51
+ } else {
52
+ console.log(colors.bold.red(`Failure:`) + ` One or more of your tests failed.`);
53
+ console.log();
54
+ }
55
+ } else {
56
+ throw new Error(`Could not find "package.json"["scripts"]["test"]`);
57
+ }
58
+ } else {
59
+ throw new Error(`No "package.json" in this directory`);
60
+ }
61
+
62
+ return void 0;
63
+
64
+ }
65
+
66
+ }
67
+
68
+ module.exports = TestCommand;