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,44 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const colors = require('colors/safe');
5
+
6
+ const fileWriter = require('../../file_writer.js');
7
+
8
+ const generateTest = require('../test/_index.js');
9
+
10
+ module.exports = async (InstantPackage, params) => {
11
+
12
+ let writePathname = params.args[0] || '';
13
+ writePathname = writePathname.split('/').filter(v => !!v).join('/');
14
+
15
+ let newFilename;
16
+
17
+ const pathname = path.join(__dirname, '..', '..', '..', 'src', 'endpoint');
18
+ if (!fs.existsSync(pathname)) {
19
+ throw new Error(`No endpoint template found.`);
20
+ }
21
+
22
+ console.log();
23
+ console.log(colors.bold.black(`Generating:`) + ` Endpoint file ...`);
24
+ console.log();
25
+
26
+ const files = fileWriter.readRecursive(pathname);
27
+ for (const filename in files) {
28
+ newFilename = filename;
29
+ newFilename = newFilename.replace(/^\/functions\//gi, $0 => $0 + (writePathname ? `${writePathname}/` : ``));
30
+ let fileData = files[filename];
31
+ fileWriter.writeFile(newFilename, fileData, false);
32
+ }
33
+
34
+ console.log();
35
+ console.log(colors.bold.green(`Success!`) + ` Created blank endpoint at "${newFilename}"!`);
36
+ console.log();
37
+
38
+ if (!params.vflags.hasOwnProperty('no-tests')) {
39
+ await generateTest(InstantPackage, {args: [], flags: {}, vflags: {endpoint: [newFilename]}});
40
+ }
41
+
42
+ return true;
43
+
44
+ };
@@ -0,0 +1,112 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const colors = require('colors/safe');
5
+
6
+ const fileWriter = require('../../file_writer.js');
7
+
8
+ module.exports = async (InstantPackage, params) => {
9
+
10
+ let testName = params.args[0] || '';
11
+ testName = testName.split('/').filter(v => !!v).join('/');
12
+ testName = testName.replace(/\.m?js$/gi, '');
13
+
14
+ let endpointFor = ((params.vflags.endpoint || [])[0] || '');
15
+
16
+ if (testName) {
17
+
18
+ const pathname = path.join(__dirname, '..', '..', '..', 'src', 'test', 'blank.js');
19
+ if (!fs.existsSync(pathname)) {
20
+ throw new Error(`No test template found for model.`);
21
+ }
22
+
23
+ let fileString = fs.readFileSync(pathname).toString();
24
+ fileString = fileString.replaceAll('Name', testName);
25
+
26
+ let newFilename = `test/tests/${testName}.js`;
27
+ const fileData = Buffer.from(fileString);
28
+ fileWriter.writeFile(newFilename, fileData, false);
29
+
30
+ console.log();
31
+ console.log(colors.bold.green(`Success!`) + ` Created tests for "${colors.bold.green(testName)}"!`);
32
+ console.log();
33
+
34
+ } else if (endpointFor) {
35
+
36
+ const pathname = path.join(__dirname, '..', '..', '..', 'src', 'test', 'endpoint.js');
37
+ if (!fs.existsSync(pathname)) {
38
+ throw new Error(`No test template found for endpoint.`);
39
+ }
40
+ if (!endpointFor.startsWith('/')) {
41
+ endpointFor = `/${endpointFor}`;
42
+ }
43
+ if (endpointFor.startsWith('/functions/')) {
44
+ endpointFor = endpointFor.slice('/functions'.length);
45
+ }
46
+ endpointFor = endpointFor.replace(/\.m?js$/, '');
47
+ let functionPathname = path.join(process.cwd(), `functions`, `${endpointFor}.js`);
48
+ if (!fs.existsSync(functionPathname)) {
49
+ functionPathname = path.join(process.cwd(), `functions`, `${endpointFor}.js`);
50
+ if (!fs.existsSync(functionPathname)) {
51
+ throw new Error(`Could not find matching endpoint "${endpointFor}" in "./functions" directory`);
52
+ }
53
+ }
54
+
55
+ let methods = [];
56
+ let endpointPath;
57
+ if (endpointFor.endsWith('/index')) {
58
+ endpointPath = endpointFor.slice(0, -('/index').length) + '/';
59
+ } else if (endpointFor.endsWith('/__main__')) {
60
+ endpointPath = endpointFor.slice(0, -('/__main__').length) + '/';
61
+ } else if (endpointFor.endsWith('/__notfound__')) {
62
+ endpointPath = endpointFor.slice(0, -('/__notfound__').length) + '/*/';
63
+ } else if (endpointFor.endsWith('/404')) {
64
+ endpointPath = endpointFor.slice(0, -('/404').length) + '/*/';
65
+ } else {
66
+ endpointPath = endpointFor + '/';
67
+ }
68
+
69
+ const file = fs.readFileSync(pathname);
70
+ let fileString = file.toString();
71
+ let template = '';
72
+ fileString = fileString.replaceAll('Pathname', endpointPath);
73
+ fileString = fileString.replace(/(\n)([ \t]*)\/\/ Method Begin\s*?\n([\s\S]*?)\/\/ Method End[ \t]*(\n)/gi, ($0, $1, $2, $3, $4) => {
74
+ template = $2 + $3.trim();
75
+ return `${$1}/* *** */${$4}`;
76
+ });
77
+
78
+ const dotenv = require(path.join(process.cwd(), `node_modules`, `dotenv`));
79
+ dotenv.config();
80
+ const endpoint = await import(functionPathname);
81
+
82
+ if ('default' in endpoint) {
83
+ methods.push('POST');
84
+ } else {
85
+ ('GET' in endpoint) && methods.push('GET');
86
+ ('POST' in endpoint) && methods.push('POST');
87
+ ('PUT' in endpoint) && methods.push('PUT');
88
+ ('DELETE' in endpoint) && methods.push('DELETE');
89
+ }
90
+
91
+ fileString = fileString.replace(
92
+ '/* *** */',
93
+ methods.map(method => {
94
+ return template
95
+ .replaceAll('Method', method)
96
+ .replaceAll('__method__', method === `DELETE` ? `del` : method.toLowerCase());
97
+ }).join('\n\n')
98
+ );
99
+
100
+ let newFilename = `test/tests/functions${endpointFor}.js`;
101
+ const fileData = Buffer.from(fileString);
102
+ fileWriter.writeFile(newFilename, fileData, false);
103
+
104
+ console.log();
105
+ console.log(colors.bold.green(`Success!`) + ` Created tests for "${colors.bold.green(endpointFor)}"!`);
106
+ console.log();
107
+
108
+ }
109
+
110
+ return true;
111
+
112
+ };
@@ -0,0 +1,62 @@
1
+ const https = require('https');
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+
5
+ const verifyPackages = require('./verify_packages.js');
6
+
7
+ module.exports = async (params = null, validate = false) => {
8
+
9
+ if (validate) {
10
+ await verifyPackages(true);
11
+ }
12
+
13
+ let toolpkg;
14
+ const toolPathname = path.join(process.cwd(), 'superuser.json');
15
+ if (!fs.existsSync(toolPathname)) {
16
+ if (validate) {
17
+ throw new Error(
18
+ `No "superuser.json" in this directory. Are you sure you meant to do this?\n` +
19
+ `Run \`$ ibot init\` to initialize a project here if you are.`
20
+ );
21
+ }
22
+ } else {
23
+ toolpkg = JSON.parse(fs.readFileSync(toolPathname));
24
+ }
25
+
26
+ let dotenv;
27
+ const dotenvPathname = path.join(process.cwd(), 'node_modules', 'dotenv');
28
+ if (!fs.existsSync(dotenvPathname)) {
29
+ if (validate) {
30
+ throw new Error(
31
+ `dotenv should be installed in this directory to use Superuser Package locally.\n` +
32
+ `Run \`$ npm i dotenv --save-dev\` to install the latest version`
33
+ );
34
+ }
35
+ } else {
36
+ dotenv = require(dotenvPathname);
37
+ }
38
+
39
+ let InstantAPI;
40
+ const pathname = path.join(process.cwd(), 'node_modules', '@instant.dev/api');
41
+ if (!fs.existsSync(pathname)) {
42
+ if (validate) {
43
+ throw new Error(
44
+ `@instant.dev/api should be installed in this directory to use Superuser Package locally.\n` +
45
+ `Run \`$ npm i @instant.dev/api --save-dev\` to install the latest version`
46
+ );
47
+ }
48
+ } else {
49
+ InstantAPI = require(pathname);
50
+ }
51
+
52
+ if (
53
+ toolpkg &&
54
+ dotenv &&
55
+ InstantAPI
56
+ ) {
57
+ return { toolpkg, dotenv, InstantAPI };
58
+ } else {
59
+ return null;
60
+ }
61
+
62
+ };
@@ -0,0 +1,72 @@
1
+ const colors = require('colors/safe');
2
+ const fs = require('fs');
3
+ const childProcess = require('child_process');
4
+
5
+ module.exports = {
6
+ run: ({port = null, isBackground = false} = {}) => {
7
+ const consoleLog = (...args) => !isBackground && console.log(...args);
8
+ consoleLog();
9
+ consoleLog(`Running ${colors.green.bold('Superuser Package')} development server ...`);
10
+ const pkgExists = fs.existsSync('package.json');
11
+ if (pkgExists) {
12
+ let pkg;
13
+ try {
14
+ pkg = JSON.parse(fs.readFileSync('package.json').toString());
15
+ } catch (e) {
16
+ throw new Error(`Could not read "package.json"`);
17
+ }
18
+ if (pkg?.scripts?.start) {
19
+ consoleLog(`Running script: ${colors.blue.bold(pkg.scripts.start)} ...`);
20
+ const envVars = {...process.env};
21
+ if (!fs.existsSync('.env')) {
22
+ consoleLog(
23
+ colors.bold.yellow(`Warn: `) +
24
+ `No envFile found in ".env", no environment variables loaded ...`
25
+ );
26
+ } else {
27
+ const lines = fs.readFileSync(`.env`)
28
+ .toString()
29
+ .split('\n')
30
+ .filter(line => !!line.trim() && !line.trim().startsWith('#'));
31
+ for (const line of lines) {
32
+ const key = line.split('=')[0];
33
+ const value = line.split('=').slice(1).join('=');
34
+ envVars[key] = value;
35
+ consoleLog(`Loading environment variable: ${colors.grey.bold(key)} ...`);
36
+ }
37
+ }
38
+ consoleLog();
39
+ if (isBackground) {
40
+ return childProcess.spawn(
41
+ pkg.scripts.start,
42
+ {
43
+ stdio: 'pipe',
44
+ shell: true,
45
+ env: {
46
+ ...envVars,
47
+ PORT: port || envVars.PORT || '',
48
+ DISABLE_HOT_RELOAD: 'true'
49
+ }
50
+ }
51
+ );
52
+ } else {
53
+ return childProcess.spawnSync(
54
+ pkg.scripts.start,
55
+ {
56
+ stdio: 'inherit',
57
+ shell: true,
58
+ env: {
59
+ ...envVars,
60
+ PORT: port || envVars.PORT || ''
61
+ }
62
+ }
63
+ );
64
+ }
65
+ } else {
66
+ throw new Error(`Could not find "package.json"["scripts"]["start"]`);
67
+ }
68
+ } else {
69
+ throw new Error(`No "package.json" in this directory`);
70
+ }
71
+ }
72
+ };
@@ -0,0 +1,108 @@
1
+ const os = require('os');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const SETTINGS_FILENAME = '~/.ibotrc';
6
+
7
+ const parsePathname = (pathname) => {
8
+ if (!pathname) {
9
+ pathname = './';
10
+ }
11
+ if (
12
+ !pathname.startsWith('~/') &&
13
+ !pathname.startsWith('./') &&
14
+ !pathname.startsWith('/')
15
+ ) {
16
+ pathname = './' + pathname;
17
+ }
18
+ if (pathname.startsWith('~/')) {
19
+ pathname = os.homedir().split(path.sep).join('/') + pathname.slice(1);
20
+ } else if (pathname.startsWith('./') || pathname.startsWith('../')) {
21
+ pathname = process.cwd().split(path.sep).join('/') + '/' + pathname;
22
+ }
23
+ return path.resolve(pathname);
24
+ }
25
+
26
+ function readSettings (validate = false) {
27
+ const pathname = parsePathname(SETTINGS_FILENAME);
28
+ if (!fs.existsSync(pathname)) {
29
+ fs.writeFileSync(pathname, '');
30
+ }
31
+ if (fs.statSync(pathname).isDirectory()) {
32
+ throw new Error(`Invalid settings file, is a directory: "${pathname}"`);
33
+ }
34
+ const file = fs.readFileSync(pathname);
35
+ const fileString = file.toString().replace(/\r/gi, '').trim();
36
+ const profileList = [];
37
+ if (fileString) {
38
+ const lines = fileString.split('\n');
39
+ for (const line of lines) {
40
+ if (line === '[profile]') {
41
+ profileList.push({});
42
+ } else if (!profileList.length) {
43
+ throw new Error(`Settings must start with [profile]`);
44
+ } else {
45
+ const values = line.split('=');
46
+ const key = values[0];
47
+ const value = values.slice(1).join('=');
48
+ profileList[profileList.length - 1][key] = value;
49
+ }
50
+ }
51
+ }
52
+ let curProfile;
53
+ let i = 0;
54
+ for (const profile of profileList) {
55
+ if (!profile.email) {
56
+ throw new Error(`Profile index ${i} missing "email"`);
57
+ }
58
+ if (!profile.key) {
59
+ throw new Error(`Profile index ${i} missing "key"`);
60
+ }
61
+ i++;
62
+ }
63
+ if (validate && !profileList[0]) {
64
+ throw new Error(`You are not logged in. Try \`ibot login\` to log in first.`);
65
+ }
66
+ return {
67
+ activeProfile: profileList[0],
68
+ profileList
69
+ }
70
+ }
71
+
72
+ function writeSettings (newProfile) {
73
+ if (!newProfile.email) {
74
+ throw new Error(`Must specify newProfile "email"`);
75
+ } else if (!newProfile.key) {
76
+ throw new Error(`Must specify newProfile "key"`);
77
+ }
78
+ const settings = readSettings();
79
+ const activeProfile = newProfile;
80
+ const profileList = [].concat(
81
+ activeProfile,
82
+ settings.profileList.filter(p => p.email !== newProfile.email)
83
+ );
84
+ const pathname = parsePathname(SETTINGS_FILENAME);
85
+ fs.writeFileSync(
86
+ pathname,
87
+ profileList.map(p => {
88
+ return [
89
+ `[profile]`,
90
+ `email=${p.email}`,
91
+ `key=${p.key}`,
92
+ p.host ? `host=${p.host}` : ''
93
+ ].filter(line => !!line.trim()).join('\n');
94
+ }).join('\n') + '\n'
95
+ );
96
+ console.log(`Settings: Set profile(email=${activeProfile.email}) as active in "${pathname}"`);
97
+ console.log(`Settings: Total of ${profileList.length} saved profiles`);
98
+ console.log();
99
+ return {
100
+ activeProfile,
101
+ profileList
102
+ };
103
+ }
104
+
105
+ module.exports = {
106
+ read: readSettings,
107
+ write: writeSettings
108
+ };
@@ -0,0 +1,85 @@
1
+ const colors = require('colors/safe');
2
+ const semver = require('semver');
3
+
4
+ const path = require('path');
5
+ const https = require('https');
6
+
7
+ const drawBox = require('./draw_box.js');
8
+
9
+ module.exports = async (print = false) => {
10
+
11
+ const pkgs = {self: require('../package.json')};
12
+ try {
13
+ pkgs.api = require(path.join(process.cwd(), '/node_modules/@instant.dev/api/package.json'));
14
+ } catch (e) {
15
+ // do nothing:
16
+ // @instant.dev/api not installed locally
17
+ }
18
+ const packages = [
19
+ {
20
+ title: 'Superuser Package CLI',
21
+ name: pkgs.self.name,
22
+ version: pkgs.self.version,
23
+ global: true
24
+ },
25
+ {
26
+ title: 'Superuser Package Gateway (Instant API)',
27
+ name: pkgs.api ? pkgs.api.name : null,
28
+ version: pkgs.api ? pkgs.api.version : null,
29
+ dev: true
30
+ }
31
+ ];
32
+ const checkPackages = packages.filter(pkg => !!pkg.name);
33
+ const verifiedPackages = await Promise.all(
34
+ checkPackages.map(pkg => {
35
+ return (async () => {
36
+ try {
37
+ const response = await new Promise((resolve, reject) => {
38
+ const req = https.request(`https://registry.npmjs.org/${pkg.name}/latest`, res => {
39
+ const buffers = [];
40
+ res.on('data', data => buffers.push(data));
41
+ res.on('end', () => resolve(Buffer.concat(buffers)));
42
+ })
43
+ req.on('error', err => reject(err));
44
+ req.end();
45
+ });
46
+ const json = JSON.parse(response.toString());
47
+ pkg.latest = json.version;
48
+ return pkg;
49
+ } catch (e) {
50
+ // we want to be able to use CLI offline
51
+ // or if NPM is down / returning bad data
52
+ // so just set latest equal to version
53
+ pkg.latest = pkg.version;
54
+ return pkg;
55
+ }
56
+ })();
57
+ })
58
+ );
59
+ const updatePackages = verifiedPackages.filter(pkg => pkg.latest && semver.gt(pkg.latest, pkg.version));
60
+ if (updatePackages.length && print) {
61
+ console.log();
62
+ console.log(
63
+ drawBox.center(
64
+ `yellow`,
65
+ ``,
66
+ `Updates are available for ${colors.bold('ibot')}:`,
67
+ ``,
68
+ ...updatePackages.map(pkg => {
69
+ return [
70
+ pkg.title,
71
+ `${pkg.version} -> ${colors.bold.green(pkg.latest)}`,
72
+ `${colors.bold.grey(`npm i ${pkg.name}@latest${pkg.dev ? ' --save-dev' : ''}${pkg.global ? ' -g' : ''}`)}`,
73
+ ``
74
+ ].join('\n')
75
+ }),
76
+ `Install all with:`,
77
+ `${colors.bold.grey(`ibot update`)}`,
78
+ ``
79
+ )
80
+ );
81
+ }
82
+
83
+ return verifiedPackages;
84
+
85
+ };
package/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { CommandLineInterface } = require('cmnd');
4
+ const CLI = new CommandLineInterface('Superuser Package CLI');
5
+
6
+ CLI.load(__dirname, './commands');
7
+ CLI.run(process.argv.slice(2));
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "superuser.app",
3
+ "version": "0.0.0",
4
+ "description": "Superuser package manager: command line interface for building toolkits for your agents",
5
+ "main": "index.js",
6
+ "files": [
7
+ "/commands",
8
+ "/helpers",
9
+ "/src"
10
+ ],
11
+ "scripts": {
12
+ "test": "echo \"Error: no test specified\" && exit 1"
13
+ },
14
+ "bin": {
15
+ "sup": "index.js"
16
+ },
17
+ "author": "Keith Horwood",
18
+ "license": "MIT",
19
+ "dependencies": {
20
+ "cmnd": "^0.4.1",
21
+ "colors": "^1.4.0",
22
+ "i": "^0.3.7",
23
+ "inquirer": "^8.2.6",
24
+ "io": "^1.5.0",
25
+ "minimatch": "^9.0.4",
26
+ "semver": "^7.5.4",
27
+ "tar-stream": "^3.1.7",
28
+ "tree-kill": "^1.2.2"
29
+ },
30
+ "keywords": []
31
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * GET
3
+ */
4
+ export async function GET (context) {
5
+
6
+ return `HTTP GET!`;
7
+
8
+ };
9
+
10
+ /**
11
+ * POST
12
+ */
13
+ export async function POST (context) {
14
+
15
+ return `HTTP POST!`;
16
+
17
+ }
18
+
19
+ /**
20
+ * PUT
21
+ */
22
+ export async function PUT (context) {
23
+
24
+ return `HTTP PUT!`;
25
+
26
+ };
27
+
28
+ /**
29
+ * DELETE
30
+ */
31
+ export async function DELETE (context) {
32
+
33
+ return `HTTP DELETE!`;
34
+
35
+ };
@@ -0,0 +1 @@
1
+ MY_SECRET=development_secret
@@ -0,0 +1 @@
1
+ MY_SECRET=production_secret
@@ -0,0 +1 @@
1
+ MY_SECRET=staging_secret
@@ -0,0 +1,6 @@
1
+ node_modules/
2
+ .DS_Store
3
+ .env
4
+ .env.staging
5
+ .env.production
6
+ package-lock.json
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Sample welcome API
3
+ * We can provide types to our APIs to enforce type-safety
4
+ * at the HTTP request (@param) and response (@returns) layer
5
+ * @param {string} username
6
+ * @returns {object} welcomeMessage
7
+ * @returns {string} welcomeMessage.message
8
+ */
9
+ export async function GET (username = 'new user') {
10
+
11
+ return {
12
+ message: `Welcome to Superuser, ${username}!`
13
+ };
14
+
15
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "name": "@user/project"
3
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@/not_npm_project",
3
+ "private": false,
4
+ "type": "module",
5
+ "scripts": {
6
+ "start": "node serve.instant.js",
7
+ "test": "mocha test/run.js"
8
+ },
9
+ "dependencies": {},
10
+ "devDependencies": {
11
+ "@instant.dev/api": "latest",
12
+ "dotenv": "latest",
13
+ "mocha": "latest",
14
+ "chai": "latest"
15
+ }
16
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * This file is ** NOT ** used in production on the Superuser Package Registry
3
+ * Any code you change here ** WILL NOT ** run when hosted with Superuser Package
4
+ *
5
+ * However, it used for local development and allows you to ship your Superuser Package
6
+ * service to any host which relies on `package.json["scripts"]["start"]`.
7
+ */
8
+
9
+ // Third-party imports
10
+ import InstantAPI from '@instant.dev/api';
11
+ import dotenv from 'dotenv';
12
+
13
+ // Native imports
14
+ import cluster from 'cluster';
15
+ import os from 'os';
16
+
17
+ // Shorthand references
18
+ const Daemon = InstantAPI.Daemon;
19
+ const Gateway = InstantAPI.Daemon.Gateway;
20
+ const EncryptionTools = InstantAPI.EncryptionTools;
21
+
22
+ // Constants
23
+ const ENVIRONMENT = process.env.NODE_ENV || 'development';
24
+ const PORT = process.env.PORT || 8100;
25
+
26
+ if (cluster.isPrimary) {
27
+
28
+ // Multi-process daemon
29
+ const daemon = new Daemon(
30
+ ENVIRONMENT !== 'development'
31
+ ? os.cpus().length
32
+ : 1,
33
+ 'SuperuserDaemon'
34
+ );
35
+ daemon.start(PORT);
36
+
37
+ } else {
38
+
39
+ // Individual webserver startup
40
+ const gateway = new Gateway({
41
+ name: 'SuperuserDaemon.Gateway',
42
+ debug: ENVIRONMENT !== 'production'
43
+ });
44
+ // Optional: Enable Sentry or another error reporting tool
45
+ // gateway.setErrorHandler(err => Sentry.captureException(err));
46
+ const et = new EncryptionTools();
47
+ dotenv.config(); // load env vars
48
+ et.decryptProcessEnv(process.env); // decrypt env vars, if necessary
49
+ gateway.load(process.cwd()); // load routes from filesystem
50
+ gateway.listen(PORT); // start server
51
+
52
+ }