better error handling & messaging
parent
33f81c848d
commit
67a9a9715d
16
.system
16
.system
|
|
@ -1,21 +1,17 @@
|
|||
{
|
||||
"handoff": "",
|
||||
"instances": {
|
||||
"72C17CDFC5F943E0A41155D892419843": {
|
||||
"50C60F4EF04D41B38A2EB573788829DA": {
|
||||
"config": {},
|
||||
"module": "systemd"
|
||||
},
|
||||
"D2A1E19739BB4CC08DD7192164CD4D67": {
|
||||
"config": {},
|
||||
"module": "sshd"
|
||||
},
|
||||
"768C13637962402D803215C97D8F04CD": {
|
||||
"config": {},
|
||||
"module": "systemd"
|
||||
},
|
||||
"0CEB261DB70A4A51BC80E15D782D8D98": {
|
||||
"C34D0DE00AB3454195E9249BF3596610": {
|
||||
"config": {},
|
||||
"module": "sshd"
|
||||
}
|
||||
},
|
||||
"aliases": {
|
||||
"systemd": "50C60F4EF04D41B38A2EB573788829DA",
|
||||
"sshd": "C34D0DE00AB3454195E9249BF3596610"
|
||||
}
|
||||
}
|
||||
20
loader.mjs
20
loader.mjs
|
|
@ -16,6 +16,7 @@ let echo = true;
|
|||
export async function resolve(specifier, context, defaultResolver) {
|
||||
if(echo === false) {
|
||||
} else if(imports === 0) {
|
||||
console.log(chalk.black.bgAnsi256(204)(' Welcome to Vogue System Runtime '));
|
||||
console.log(chalk.green('#'), chalk.ansi256(242)('@kernel'))
|
||||
} else {
|
||||
console.log(chalk.green('#'), chalk.ansi256(242)(specifier));
|
||||
|
|
@ -26,13 +27,20 @@ export async function resolve(specifier, context, defaultResolver) {
|
|||
}
|
||||
|
||||
const maps = {
|
||||
'file:///boot': pathResolve(__dirname, 'src', 'index.ts'),
|
||||
'@kernel:base': pathResolve(__dirname, 'src', 'index.ts'),
|
||||
'@kernel:log-hook': pathResolve(__dirname, 'src', 'logHook.ts'),
|
||||
'file:///boot': pathResolve(__dirname, 'src', 'index.ts'),
|
||||
|
||||
'@kernel:base': pathResolve(__dirname, 'src', 'index.ts'),
|
||||
'@kernel:log-hook': pathResolve(__dirname, 'src', 'logHook.ts'),
|
||||
|
||||
'@commands:executor': pathResolve(__dirname, 'src', 'commands', 'executor.ts'),
|
||||
'@builtin:systemd': pathResolve(__dirname, 'src', 'modules', 'systemd.ts'),
|
||||
'@builtin:sshd': pathResolve(__dirname, 'src', 'modules', 'sshd.ts'),
|
||||
'@echo off': pathResolve(__dirname, 'src', 'noop.ts')
|
||||
'@commands:create': pathResolve(__dirname, 'src', 'commands', 'create.ts'),
|
||||
'@commands:ls': pathResolve(__dirname, 'src', 'commands', 'ls.ts'),
|
||||
'@commands:save': pathResolve(__dirname, 'src', 'commands', 'save.ts'),
|
||||
|
||||
'@builtin:systemd': pathResolve(__dirname, 'src', 'modules', 'systemd.ts'),
|
||||
'@builtin:sshd': pathResolve(__dirname, 'src', 'modules', 'sshd.ts'),
|
||||
|
||||
'@echo off': pathResolve(__dirname, 'src', 'noop.ts')
|
||||
};
|
||||
|
||||
const matches = Object.keys(maps).filter(map => specifier.startsWith(map));
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@
|
|||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "(clear || cls) && node --no-warnings --loader ./loader.mjs /boot",
|
||||
"start": "(clear || cls) && node --no-warnings --unhandled-rejections=strict --loader ./loader.mjs /boot",
|
||||
"tsc": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/md5": "^2.3.1",
|
||||
"@types/node": "^16.11.12",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"chalk": "^5.0.0",
|
||||
"md5": "^2.3.0",
|
||||
"serverline": "^1.5.0",
|
||||
"ssh2": "^1.5.0",
|
||||
"telnet": "^0.0.1",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,33 @@
|
|||
import createExecutor from "./executor.js";
|
||||
|
||||
export const create = createExecutor({
|
||||
pawn() {
|
||||
import { system, autoColorString } from '@kernel:base';
|
||||
import * as uuid from 'uuid';
|
||||
|
||||
export default async function create(module: string, name: string, id: string) {
|
||||
if(!module || typeof module !== 'string' || module.trim() === '') {
|
||||
throw new Error('INVALID_MODULE_NAME');
|
||||
}
|
||||
})
|
||||
if(name && (typeof name !== 'string' || name.trim() === '')) {
|
||||
throw new Error('IVALID_MODULE_ALIAS');
|
||||
}
|
||||
name ??= module;
|
||||
if(system.aliases.has(name)) {
|
||||
if(name === module) {
|
||||
throw new Error('DEFAULT_MODULE_ALREADY_EXISTS');
|
||||
} else {
|
||||
throw new Error('MODULE_ALIAS_TAKEN');
|
||||
}
|
||||
}
|
||||
const imported = (await import('@builtin:' + module));
|
||||
const functions = 'default' in imported ? imported.default : imported;
|
||||
id ??= uuid.v4().replace(/-/g, '').toUpperCase();
|
||||
system.instances.set(id, {
|
||||
config: {},
|
||||
ram: {},
|
||||
module: module,
|
||||
functions
|
||||
});
|
||||
if(name) {
|
||||
system.aliases.set(name, id);
|
||||
}
|
||||
console.log('Created instance of', autoColorString(module))
|
||||
return id;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { system, autoColorString } from '@kernel:base';
|
||||
import chalk from 'chalk';
|
||||
|
||||
export default function ls(flags: any) {
|
||||
// if(flags) console.log(flags)
|
||||
|
||||
console.log('Instances', chalk.ansi256(242)('(' + system.instances.size + ')'));
|
||||
for(const [k, v] of system.instances) {
|
||||
console.log(
|
||||
' '
|
||||
+ autoColorString(k.substring(0, 4))
|
||||
+ ':', JSON.stringify(v.config, null, 2).replace('\n', ' ').trim()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import { system } from '@kernel:base';
|
||||
import { resolve } from 'path';
|
||||
import { writeFileSync } from 'fs';
|
||||
|
||||
export default function save() {
|
||||
const timeStart = new Date().getTime();
|
||||
const obj: any = {
|
||||
handoff: system.handoff,
|
||||
instances: {},
|
||||
aliases: {}
|
||||
};
|
||||
for(const [id, info] of system.instances.entries()) {
|
||||
obj.instances[id] = {
|
||||
config: info.config,
|
||||
module: info.module
|
||||
}
|
||||
}
|
||||
for(const [alias, id] of system.aliases.entries()) {
|
||||
obj.aliases[alias] = id;
|
||||
}
|
||||
const systemString = JSON.stringify(obj, null, 2);
|
||||
const fullPath = resolve('.system');
|
||||
writeFileSync(fullPath, systemString);
|
||||
const elapsed = new Date().getTime() - timeStart;
|
||||
console.log('System saved to ' + fullPath + ' in ' + elapsed + ' ms')
|
||||
}
|
||||
|
|
@ -2,6 +2,9 @@ declare module "serverline";
|
|||
declare module "telnet";
|
||||
declare module "@kernel:base";
|
||||
declare module "@commands:executor";
|
||||
declare module "@commands:create";
|
||||
declare module "@commands:ls";
|
||||
declare module "@commands:save";
|
||||
declare module "@builtin:systemd";
|
||||
declare module "@builtin:sshd";
|
||||
declare module "@echo off";
|
||||
127
src/index.ts
127
src/index.ts
|
|
@ -1,14 +1,16 @@
|
|||
/// <reference path="./externals.d.ts" />
|
||||
|
||||
// console.clear();
|
||||
|
||||
import '@kernel:log-hook';
|
||||
import createExecutor from '@commands:executor';
|
||||
import create from '@commands:create';
|
||||
import ls from '@commands:ls';
|
||||
import save from '@commands:save';
|
||||
import * as uuid from 'uuid';
|
||||
import serverline from 'serverline';
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||
import { resolve } from 'path'
|
||||
import chalk from 'chalk';
|
||||
import md5 from 'md5';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const [ startupFile ] = args;
|
||||
|
|
@ -20,9 +22,22 @@ type Instance = {
|
|||
functions: any;
|
||||
};
|
||||
|
||||
const system = {
|
||||
export const system = {
|
||||
instances: new Map<string, Instance>(),
|
||||
handoff: ''
|
||||
handoff: '',
|
||||
aliases: new Map<string, string>()
|
||||
}
|
||||
|
||||
function checkpoint(string: string) {
|
||||
console.log(chalk.black.bgAnsi256(204)(' ' + string + ' '));
|
||||
}
|
||||
|
||||
export function autoColorString(string: string) {
|
||||
let colorCode = 0;
|
||||
for(const char of md5(string)) colorCode += char.charCodeAt(0);
|
||||
colorCode %= 6 ** 3;
|
||||
colorCode += 16;
|
||||
return chalk.ansi256(colorCode)(string);
|
||||
}
|
||||
|
||||
export const exec = async (s: string, echo = true) => {
|
||||
|
|
@ -30,71 +45,18 @@ export const exec = async (s: string, echo = true) => {
|
|||
await executor(...(s.split(' ')));
|
||||
};
|
||||
|
||||
serverline.init({
|
||||
prompt: chalk.cyan('λ ')
|
||||
});
|
||||
|
||||
const kernel = {
|
||||
async create(module: string, name: string) {
|
||||
// TODO assert module.
|
||||
try {
|
||||
const imported = (await import('@builtin:' + module));
|
||||
const functions = 'default' in imported ? imported.default : imported;
|
||||
const id = name ?? uuid.v4().replace(/-/g, '').toUpperCase();
|
||||
system.instances.set(id, {
|
||||
config: {},
|
||||
ram: {},
|
||||
module: module,
|
||||
functions
|
||||
});
|
||||
return id;
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
e.trace();
|
||||
}
|
||||
},
|
||||
export const kernel = {
|
||||
create: create,
|
||||
quit() {
|
||||
console.log('Shutting down');
|
||||
serverline.close();
|
||||
setTimeout(() => process.exit(0), 0);
|
||||
},
|
||||
ls(flags: any) {
|
||||
if(flags) console.log(flags)
|
||||
|
||||
console.log('Instances', chalk.ansi256(242)('(' + system.instances.size + ')'));
|
||||
for(const [k, v] of system.instances) {
|
||||
let colorCode = 0;
|
||||
for(const char of k) colorCode += char.charCodeAt(0);
|
||||
colorCode %= 6 ** 3;
|
||||
colorCode += 16;
|
||||
console.log(
|
||||
' '
|
||||
+ chalk.ansi256(colorCode)(k.substring(0, 8))
|
||||
+ ':', JSON.stringify(v.config, null, 2).replace('\n', ' ').trim()
|
||||
);
|
||||
}
|
||||
},
|
||||
save() {
|
||||
const timeStart = new Date().getTime();
|
||||
const obj: any = {
|
||||
handoff: system.handoff,
|
||||
instances: {}
|
||||
};
|
||||
for(const [id, info] of system.instances.entries()) {
|
||||
obj.instances[id] = {
|
||||
config: info.config,
|
||||
module: info.module
|
||||
}
|
||||
}
|
||||
const systemString = JSON.stringify(obj, null, 2);
|
||||
const fullPath = resolve('.system');
|
||||
writeFileSync(fullPath, systemString);
|
||||
const elapsed = new Date().getTime() - timeStart;
|
||||
console.log('System saved to ' + fullPath + ' in ' + elapsed + ' ms')
|
||||
},
|
||||
ls: ls,
|
||||
save: save,
|
||||
reset() {
|
||||
system.handoff = '';
|
||||
system.instances = new Map();
|
||||
system.aliases = new Map();
|
||||
console.log('System has been reset.');
|
||||
},
|
||||
exec: exec,
|
||||
|
|
@ -112,35 +74,44 @@ const kernel = {
|
|||
|
||||
const executor = createExecutor(kernel);
|
||||
|
||||
serverline.on('line', (a: string) => {
|
||||
if(a.trim() === "") return;
|
||||
exec(a, false);
|
||||
})
|
||||
|
||||
serverline.on('SIGINT', () => {
|
||||
exec('quit');
|
||||
});
|
||||
|
||||
|
||||
|
||||
(async () => {
|
||||
|
||||
if(existsSync('.system')) {
|
||||
const state: any = JSON.parse(readFileSync('.system').toString());
|
||||
system.handoff = state.handoff;
|
||||
for(const [id, info] of Object.entries<any>(state.instances)) {
|
||||
await kernel.create(info.module, id);
|
||||
const [alias] =
|
||||
Object.entries(state.aliases)
|
||||
.find(([,tryId]) => tryId === id)
|
||||
?? [undefined];
|
||||
await kernel.create(info.module, alias, id);
|
||||
system.instances.get(id).config = info.config;
|
||||
}
|
||||
checkpoint('System State Restored');
|
||||
}
|
||||
|
||||
if(startupFile) {
|
||||
await exec('script ' + startupFile);
|
||||
console.log(chalk.green('Script finished, exitting...'));
|
||||
checkpoint('Script Finished');
|
||||
await exec('quit');
|
||||
} else {
|
||||
}
|
||||
})()
|
||||
|
||||
serverline.init({
|
||||
prompt: chalk.cyan('λ ')
|
||||
});
|
||||
serverline.setCompletion(Object.keys(kernel));
|
||||
serverline.on('line', (a: string) => {
|
||||
if(a.trim() === "") return;
|
||||
exec(a, false);
|
||||
});
|
||||
|
||||
serverline.on('SIGINT', () => {
|
||||
exec('quit');
|
||||
});
|
||||
|
||||
})().catch((e: Error) => {
|
||||
console.error(e);
|
||||
});
|
||||
checkpoint('Kernel Loaded');
|
||||
import '@echo off';
|
||||
|
||||
serverline.setCompletion(Object.keys(kernel))
|
||||
|
|
@ -6,7 +6,8 @@
|
|||
"moduleResolution": "Node",
|
||||
"baseUrl": "./src",
|
||||
"outDir": "./dist",
|
||||
"declaration": true
|
||||
"declaration": true,
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"paths": {
|
||||
"@commands:executor": [""]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
reset
|
||||
create systemd
|
||||
create sshd
|
||||
invoke systemd add sshd invoke sshd start
|
||||
|
|
|
|||
33
yarn.lock
33
yarn.lock
|
|
@ -39,7 +39,14 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/node@^16.11.12":
|
||||
"@types/md5@^2.3.1":
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/md5/-/md5-2.3.1.tgz#010bcf3bb50a2cff3a574cb1c0b4051a9c67d6bc"
|
||||
integrity sha512-OK3oe+ALIoPSo262lnhAYwpqFNXbiwH2a+0+Z5YBnkQEwWD8fk5+PIeRhYA48PzvX9I4SGNpWy+9bLj8qz92RQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*", "@types/node@^16.11.12":
|
||||
version "16.11.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.12.tgz#ac7fb693ac587ee182c3780c26eb65546a1a3c10"
|
||||
integrity sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==
|
||||
|
|
@ -103,6 +110,11 @@ chalk@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.0.tgz#bd96c6bb8e02b96e08c0c3ee2a9d90e050c7b832"
|
||||
integrity sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==
|
||||
|
||||
charenc@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||
|
||||
cpu-features@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cpu-features/-/cpu-features-0.0.2.tgz#9f636156f1155fd04bdbaa028bb3c2fbef3cea7a"
|
||||
|
|
@ -115,6 +127,11 @@ create-require@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||
|
||||
crypt@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
debug@*:
|
||||
version "4.3.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
|
||||
|
|
@ -127,6 +144,11 @@ diff@^4.0.1:
|
|||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
is-buffer@~1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
|
||||
json5@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
|
||||
|
|
@ -139,6 +161,15 @@ make-error@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||
|
||||
md5@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
|
||||
integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
|
||||
dependencies:
|
||||
charenc "0.0.2"
|
||||
crypt "0.0.2"
|
||||
is-buffer "~1.1.6"
|
||||
|
||||
minimist@^1.2.0:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
|
|
|
|||
Loading…
Reference in New Issue