Changelog:
- Added `getGroupByName() getGroupByGid() getUserByName getUserByUid()` methods to the `Bash` class. - Fixed a bug inside the `localStorage` caching logic that saved only 32 characters out of 36 in the signature UUID. - Added support for reverse order sorting in the quick sort implementation. **Commands:** - ls -l -a -A -U -g -G -h -f -n -N -r -Q -p -o - cd
This commit is contained in:
@@ -620,7 +620,7 @@
|
|||||||
"Mtime": "2025-09-13T18:32:08.743+02:00"
|
"Mtime": "2025-09-13T18:32:08.743+02:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Name": "Desktop",
|
"Name": "Desktop Test",
|
||||||
"Type": 16384,
|
"Type": 16384,
|
||||||
"ReadOnly": false,
|
"ReadOnly": false,
|
||||||
"Interactible": false,
|
"Interactible": false,
|
||||||
|
|||||||
1
src/lib/assets/fs/signature
Normal file
1
src/lib/assets/fs/signature
Normal file
@@ -0,0 +1 @@
|
|||||||
|
f6b90e56-2566-47b5-a7df-fb041128929a
|
||||||
@@ -161,4 +161,36 @@ export class Bash {
|
|||||||
|
|
||||||
return `${(bytes / Math.pow(k, i)).toFixed(dp)}${units[i]}`;
|
return `${(bytes / Math.pow(k, i)).toFixed(dp)}${units[i]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getGroupByName(name: string): Group {
|
||||||
|
const out: Group | undefined = this._group.find((group) => group.groupname === name);
|
||||||
|
console.log(out);
|
||||||
|
|
||||||
|
if (out) return out;
|
||||||
|
else throw new Error(`Cannot find a user group named ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserByName(name: string): User {
|
||||||
|
const out: User | undefined = this._passwd.find((user) => user.username === name);
|
||||||
|
console.log(out);
|
||||||
|
|
||||||
|
if (out) return out;
|
||||||
|
else throw new Error(`Cannot find a user named ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroupByGid(gid: number): Group {
|
||||||
|
const out: Group | undefined = this._group.find((group) => group.gid === gid);
|
||||||
|
console.log(out);
|
||||||
|
|
||||||
|
if (out) return out;
|
||||||
|
else throw new Error(`Cannot find a user group named ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserByUid(uid: number): User {
|
||||||
|
const out: User | undefined = this._passwd.find((user) => user.uid === uid);
|
||||||
|
console.log(out);
|
||||||
|
|
||||||
|
if (out) return out;
|
||||||
|
else throw new Error(`Cannot find a user group named ${name}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
src/lib/stores/bash/commands/cd.ts
Normal file
54
src/lib/stores/bash/commands/cd.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { ExitCode, type Bash } from '../bash';
|
||||||
|
import { Type, type TreeNode } from '../fs';
|
||||||
|
import type { CommandArgs, ICommand, Result } from '../static';
|
||||||
|
|
||||||
|
export const cmd_cd = function (this: Bash, args: CommandArgs): Result {
|
||||||
|
let result: Result = { exitCode: ExitCode.ERROR };
|
||||||
|
const path = args.args[0];
|
||||||
|
let targetNode: TreeNode | null;
|
||||||
|
|
||||||
|
if (args.args.length > 1) return result; // Too many args
|
||||||
|
|
||||||
|
// if no args cd into home dir
|
||||||
|
|
||||||
|
if (args.args.length === 0) {
|
||||||
|
this.getFs().cwd = this.getFs().home;
|
||||||
|
result.exitCode = ExitCode.SUCCESS;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the arg is - cd make your current dir the prev dir and vice versa
|
||||||
|
|
||||||
|
if (args.args[0] === '-') {
|
||||||
|
[this.getFs().cwd, this.getFs().pwd] = [this.getFs().pwd, this.getFs().cwd];
|
||||||
|
result.exitCode = ExitCode.SUCCESS;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the input STRING path from relative to absolute by replacing ~ with the home directory path
|
||||||
|
|
||||||
|
//TODO: Change that to a global function inside fs class to parse all possible path formats????? already exists, need to verify
|
||||||
|
|
||||||
|
let resolvedPath = path.startsWith('~')
|
||||||
|
? path.replace('~', this.getFs().pathArrayToString(this.getFs().home))
|
||||||
|
: path;
|
||||||
|
|
||||||
|
this.getFs().pwd = this.getFs().cwd;
|
||||||
|
targetNode = this.getFs()._getNodeByPathArray(this.getFs().resolvePath(resolvedPath)); // Conversion from STRING path to ARRAY
|
||||||
|
|
||||||
|
if (targetNode === null) return result;
|
||||||
|
if (targetNode.type !== Type.Directory) return result;
|
||||||
|
//if () return ExitCode.ERROR; // Check for read permissions on node and user
|
||||||
|
|
||||||
|
this.getFs().cwd = this.getFs().resolvePath(resolvedPath); // CD was successfull, change current dir to the verified target dir
|
||||||
|
result.exitCode = ExitCode.SUCCESS;
|
||||||
|
console.log(this.getCwd());
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const cd: ICommand = {
|
||||||
|
method: cmd_cd,
|
||||||
|
flags: [] as string[],
|
||||||
|
help: 'PATH TO HELP.md',
|
||||||
|
root: false
|
||||||
|
};
|
||||||
@@ -79,11 +79,12 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
|||||||
const f_a: boolean = flagInfo.has('a') || flagInfo.has('f');
|
const f_a: boolean = flagInfo.has('a') || flagInfo.has('f');
|
||||||
const f_h: boolean = flagInfo.has('h');
|
const f_h: boolean = flagInfo.has('h');
|
||||||
|
|
||||||
if (flagInfo.has('l')) {
|
if (flagInfo.has('l') || flagInfo.has('g') || flagInfo.has('o')) {
|
||||||
const w: HTMLElement = document.createElement('div');
|
const w: HTMLElement = document.createElement('div');
|
||||||
|
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
if (!flagInfo.has('U') && !flagInfo.has('f')) asciiByteQSort(node.children);
|
if (!flagInfo.has('U') && !flagInfo.has('f'))
|
||||||
|
asciiByteQSort(node.children, flagInfo.has('r'));
|
||||||
|
|
||||||
const elem: HTMLElement = document.createElement('div');
|
const elem: HTMLElement = document.createElement('div');
|
||||||
const rows: string[] = [];
|
const rows: string[] = [];
|
||||||
@@ -92,11 +93,26 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
|||||||
const sizes = node.children.map((child) => (child.type === Type.Directory ? '4096' : '1'));
|
const sizes = node.children.map((child) => (child.type === Type.Directory ? '4096' : '1'));
|
||||||
const maxSizeWidth = Math.max(...sizes.map((size) => size.length));
|
const maxSizeWidth = Math.max(...sizes.map((size) => size.length));
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
if (child.name.startsWith('.') && !(f_a || flagInfo.has('A'))) continue;
|
||||||
|
|
||||||
|
const cols: LsEntry = {
|
||||||
|
perms: formatPermission(child),
|
||||||
|
children: formatChildren(child),
|
||||||
|
owners: formatOwners.call(this, child, flagInfo),
|
||||||
|
size: formatSize.call(this, f_h, child, maxSizeWidth),
|
||||||
|
modt: formatModtime(child),
|
||||||
|
name: formatName(child, flagInfo)
|
||||||
|
};
|
||||||
|
|
||||||
|
rows.push(LsEntryUtils.toString(cols));
|
||||||
|
}
|
||||||
|
|
||||||
if (f_a && !flagInfo.has('A')) {
|
if (f_a && !flagInfo.has('A')) {
|
||||||
const current: LsEntry = {
|
const current: LsEntry = {
|
||||||
perms: formatPermission(node),
|
perms: formatPermission(node),
|
||||||
children: formatChildren(node),
|
children: formatChildren(node),
|
||||||
owners: formatOwners(node, flagInfo),
|
owners: formatOwners.call(this, node, flagInfo),
|
||||||
size: formatSize.call(this, f_h, node, maxSizeWidth),
|
size: formatSize.call(this, f_h, node, maxSizeWidth),
|
||||||
modt: formatModtime(node),
|
modt: formatModtime(node),
|
||||||
name: '.'
|
name: '.'
|
||||||
@@ -105,7 +121,7 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
|||||||
? {
|
? {
|
||||||
perms: formatPermission(node.parent),
|
perms: formatPermission(node.parent),
|
||||||
children: formatChildren(node.parent),
|
children: formatChildren(node.parent),
|
||||||
owners: formatOwners(node.parent, flagInfo),
|
owners: formatOwners.call(this, node.parent, flagInfo),
|
||||||
size: formatSize.call(this, f_h, node.parent, maxSizeWidth),
|
size: formatSize.call(this, f_h, node.parent, maxSizeWidth),
|
||||||
modt: formatModtime(node.parent),
|
modt: formatModtime(node.parent),
|
||||||
name: '..'
|
name: '..'
|
||||||
@@ -115,24 +131,11 @@ function result_ls(this: Bash, data: any, args: CommandArgs): HTMLElement {
|
|||||||
name: '..'
|
name: '..'
|
||||||
};
|
};
|
||||||
|
|
||||||
rows.push(LsEntryUtils.toString(current), LsEntryUtils.toString(parent));
|
if (flagInfo.has('r')) {
|
||||||
|
rows.push(LsEntryUtils.toString(parent), LsEntryUtils.toString(current));
|
||||||
|
} else {
|
||||||
|
rows.unshift(LsEntryUtils.toString(current), LsEntryUtils.toString(parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const child of node.children) {
|
|
||||||
if (child.name.startsWith('.') && !(f_a || flagInfo.has('A'))) continue;
|
|
||||||
|
|
||||||
const cols: LsEntry = {
|
|
||||||
perms: formatPermission(child),
|
|
||||||
children: formatChildren(child),
|
|
||||||
owners: formatOwners(child, flagInfo),
|
|
||||||
size: formatSize.call(this, f_h, child, maxSizeWidth),
|
|
||||||
modt: formatModtime(child),
|
|
||||||
name: /\s/.test(child.name) ? `'${child.name}'` : `${child.name}`
|
|
||||||
};
|
|
||||||
|
|
||||||
if (flagInfo.has('g')) cols.owners = '';
|
|
||||||
|
|
||||||
rows.push(LsEntryUtils.toString(cols));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Calculate the total size of contents in the node
|
//TODO: Calculate the total size of contents in the node
|
||||||
@@ -170,12 +173,31 @@ function parsePerms(perms: NodePerms): string {
|
|||||||
return parts.join('');
|
return parts.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatOwners(node: TreeNode, flag: any): string {
|
function formatOwners(this: Bash, node: TreeNode, flag: any): string {
|
||||||
const owner: string = node.owner;
|
const owner: string = node.owner;
|
||||||
const group: string = node.group;
|
const group: string = node.group;
|
||||||
|
|
||||||
|
if (flag.has('G') || flag.has('o')) {
|
||||||
|
if (flag.has('n')) {
|
||||||
|
const uid: number = this.getUserByName(owner).uid;
|
||||||
|
return `${uid}`;
|
||||||
|
}
|
||||||
|
return `${owner}`;
|
||||||
|
}
|
||||||
|
|
||||||
if (flag.has('g')) {
|
if (flag.has('g')) {
|
||||||
return '';
|
if (flag.has('n')) {
|
||||||
|
const gid: number = this.getGroupByName(group).gid;
|
||||||
|
return `${gid}`;
|
||||||
|
}
|
||||||
|
return `${group}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag.has('n')) {
|
||||||
|
const uid: number = this.getUserByName(owner).uid;
|
||||||
|
const gid: number = this.getGroupByName(group).gid;
|
||||||
|
|
||||||
|
return `${uid} ${gid}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return `${owner} ${group}`;
|
return `${owner} ${group}`;
|
||||||
@@ -216,6 +238,19 @@ function formatModtime(node: TreeNode): string {
|
|||||||
].join(' ');
|
].join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatName(node: TreeNode, flag: any) {
|
||||||
|
let name: string;
|
||||||
|
const char: string = flag.has('Q') ? '"' : "'";
|
||||||
|
|
||||||
|
if (flag.has('N')) {
|
||||||
|
name = node.name;
|
||||||
|
} else {
|
||||||
|
name = /\s/.test(node.name) ? `${char}${node.name}${char}` : `${node.name}`; //test if any spaces specifically '\s' (escape and 's' for space)
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag.has('p') && node.type === Type.Directory ? `${name}/` : name;
|
||||||
|
}
|
||||||
|
|
||||||
const checkFlags = (pFlags: string[], dFlags: string[]) => {
|
const checkFlags = (pFlags: string[], dFlags: string[]) => {
|
||||||
const flagSet = new Set(pFlags);
|
const flagSet = new Set(pFlags);
|
||||||
|
|
||||||
@@ -245,7 +280,8 @@ export const ls: ICommand = {
|
|||||||
'o',
|
'o',
|
||||||
'n',
|
'n',
|
||||||
'N',
|
'N',
|
||||||
'L'
|
'L',
|
||||||
|
'm'
|
||||||
] as string[],
|
] as string[],
|
||||||
help: 'PATH TO HELP.MD',
|
help: 'PATH TO HELP.MD',
|
||||||
root: false
|
root: false
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import type { TreeNode } from './fs';
|
import type { TreeNode } from './fs';
|
||||||
|
|
||||||
export function asciiByteQSort(array: TreeNode[]) {
|
export function asciiByteQSort(array: TreeNode[], reverse: boolean) {
|
||||||
qSort(array, 0, array.length - 1);
|
qSort(array, 0, array.length - 1, reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
function qSort(array: TreeNode[], start: number, end: number) {
|
function qSort(array: TreeNode[], start: number, end: number, reverse: boolean) {
|
||||||
if (end <= start) return;
|
if (end <= start) return;
|
||||||
|
|
||||||
let pivot: number = partition(array, start, end);
|
let pivot: number = partition(array, start, end, reverse);
|
||||||
qSort(array, start, pivot - 1);
|
qSort(array, start, pivot - 1, reverse);
|
||||||
qSort(array, pivot + 1, end);
|
qSort(array, pivot + 1, end, reverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
function partition(part: TreeNode[], start: number, end: number): number {
|
function partition(part: TreeNode[], start: number, end: number, reverse: boolean): number {
|
||||||
let pivot: TreeNode = part[end];
|
let pivot: TreeNode = part[end];
|
||||||
let i: number = start - 1;
|
let i: number = start - 1;
|
||||||
|
|
||||||
for (let j = start; j <= end; j++) {
|
for (let j = start; j <= end; j++) {
|
||||||
if (compareStrings(part[j].name, pivot.name) < 0) {
|
if (compareStrings(part[j].name, pivot.name, reverse) < 0) {
|
||||||
i++;
|
i++;
|
||||||
let temp = part[i];
|
let temp = part[i];
|
||||||
part[i] = part[j];
|
part[i] = part[j];
|
||||||
@@ -32,7 +32,7 @@ function partition(part: TreeNode[], start: number, end: number): number {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compareStrings(a: string, b: string): number {
|
function compareStrings(a: string, b: string, reverse: boolean): number {
|
||||||
const minLength = Math.min(a.length, b.length);
|
const minLength = Math.min(a.length, b.length);
|
||||||
|
|
||||||
for (let i = 0; i < minLength; i++) {
|
for (let i = 0; i < minLength; i++) {
|
||||||
@@ -40,8 +40,9 @@ function compareStrings(a: string, b: string): number {
|
|||||||
const charCodeB = b.charCodeAt(i);
|
const charCodeB = b.charCodeAt(i);
|
||||||
|
|
||||||
if (charCodeA !== charCodeB) {
|
if (charCodeA !== charCodeB) {
|
||||||
return charCodeA - charCodeB;
|
return reverse ? charCodeB - charCodeA : charCodeA - charCodeB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return a.length - b.length;
|
|
||||||
|
return reverse ? b.length - a.length : a.length - b.length;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Bash, ExitCode, type Group, type User } from './bash';
|
import { Bash, ExitCode, type Group, type User } from './bash';
|
||||||
import { Type, type TreeNode } from './fs';
|
|
||||||
import type { Char } from '../char';
|
|
||||||
import { ls } from './commands/ls';
|
import { ls } from './commands/ls';
|
||||||
|
import { cd } from './commands/cd';
|
||||||
|
|
||||||
export type ICommand = {
|
export type ICommand = {
|
||||||
method: (this: Bash, args: CommandArgs) => Result;
|
method: (this: Bash, args: CommandArgs) => Result;
|
||||||
@@ -63,6 +62,14 @@ export const PASSWD: User[] = [
|
|||||||
gid: 1000,
|
gid: 1000,
|
||||||
home: '/home/user',
|
home: '/home/user',
|
||||||
history: [] //TODO: Delete this and declare a new history array when logging the user in.
|
history: [] //TODO: Delete this and declare a new history array when logging the user in.
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: 'kamil',
|
||||||
|
passwd: '000',
|
||||||
|
uid: 1003,
|
||||||
|
gid: 1000,
|
||||||
|
home: '/home/kamil',
|
||||||
|
history: [] //TODO: Delete this and declare a new history array when logging the user in.
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -71,61 +78,6 @@ export const cmd_return = function (this: Bash, args: CommandArgs): Result {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cmd_cd = function (this: Bash, args: CommandArgs): Result {
|
|
||||||
let result: Result = { exitCode: ExitCode.ERROR };
|
|
||||||
const path = args.args[0];
|
|
||||||
let targetNode: TreeNode | null;
|
|
||||||
|
|
||||||
if (args.args.length > 1) return result; // Too many args
|
|
||||||
|
|
||||||
// if no args cd into home dir
|
|
||||||
|
|
||||||
if (args.args.length === 0) {
|
|
||||||
this.getFs().cwd = this.getFs().home;
|
|
||||||
result.exitCode = ExitCode.SUCCESS;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the arg is - cd make your current dir the prev dir and vice versa
|
|
||||||
|
|
||||||
if (args.args[0] === '-') {
|
|
||||||
[this.getFs().cwd, this.getFs().pwd] = [this.getFs().pwd, this.getFs().cwd];
|
|
||||||
result.exitCode = ExitCode.SUCCESS;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the input STRING path from relative to absolute by replacing ~ with the home directory path
|
|
||||||
|
|
||||||
//TODO: Change that to a global function inside fs class to parse all possible path formats????? already exists, need to verify
|
|
||||||
|
|
||||||
let resolvedPath = path.startsWith('~')
|
|
||||||
? path.replace('~', this.getFs().pathArrayToString(this.getFs().home))
|
|
||||||
: path;
|
|
||||||
|
|
||||||
this.getFs().pwd = this.getFs().cwd;
|
|
||||||
targetNode = this.getFs()._getNodeByPathArray(this.getFs().resolvePath(resolvedPath)); // Conversion from STRING path to ARRAY
|
|
||||||
|
|
||||||
if (targetNode === null) return result;
|
|
||||||
if (targetNode.type !== Type.Directory) return result;
|
|
||||||
//if () return ExitCode.ERROR; // Check for read permissions on node and user
|
|
||||||
|
|
||||||
this.getFs().cwd = this.getFs().resolvePath(resolvedPath); // CD was successfull, change current dir to the verified target dir
|
|
||||||
result.exitCode = ExitCode.SUCCESS;
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* const compareArrays = (A: string[], B: string[]): { value: string; isInB: boolean }[] => {
|
|
||||||
const result = A.map((item) => ({ value: item, isInB: B.includes(item) }));
|
|
||||||
|
|
||||||
// Validate all B items are in A
|
|
||||||
const invalidItems = B.filter((item) => !A.includes(item));
|
|
||||||
if (invalidItems.length > 0) {
|
|
||||||
throw new Error(`Items '${invalidItems.join("', '")}' from B not found in A`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}; */
|
|
||||||
|
|
||||||
export const COMMANDS = {
|
export const COMMANDS = {
|
||||||
return: {
|
return: {
|
||||||
method: cmd_return,
|
method: cmd_return,
|
||||||
@@ -133,12 +85,7 @@ export const COMMANDS = {
|
|||||||
help: 'PATH TO HELP.MD',
|
help: 'PATH TO HELP.MD',
|
||||||
root: false
|
root: false
|
||||||
},
|
},
|
||||||
cd: {
|
cd,
|
||||||
method: cmd_cd,
|
|
||||||
flags: [] as string[],
|
|
||||||
help: 'PATH TO HELP.MD',
|
|
||||||
root: false
|
|
||||||
},
|
|
||||||
ls
|
ls
|
||||||
} as const satisfies Record<string, ICommand>;
|
} as const satisfies Record<string, ICommand>;
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,10 @@ export class Char {
|
|||||||
this.value = char as BrandedChar;
|
this.value = char as BrandedChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public factory method
|
|
||||||
static from(char: string): Char {
|
static from(char: string): Char {
|
||||||
return new Char(char);
|
return new Char(char);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the primitive value
|
|
||||||
valueOf(): string {
|
valueOf(): string {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
@@ -24,7 +22,6 @@ export class Char {
|
|||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Character operations
|
|
||||||
charCode(): number {
|
charCode(): number {
|
||||||
return this.value.charCodeAt(0);
|
return this.value.charCodeAt(0);
|
||||||
}
|
}
|
||||||
@@ -69,7 +66,6 @@ export class Char {
|
|||||||
return this.value.toLowerCase() === other.value.toLowerCase();
|
return this.value.toLowerCase() === other.value.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static constructors
|
|
||||||
static fromCharCode(charCode: number): Char {
|
static fromCharCode(charCode: number): Char {
|
||||||
return Char.from(String.fromCharCode(charCode));
|
return Char.from(String.fromCharCode(charCode));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,28 +48,63 @@ function jsonToTreeNode(data: any, parent?: TreeNode): TreeNode {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchFsJson(sig: string): Promise<any> {
|
||||||
|
const signature: string | null = localStorage.getItem('signature');
|
||||||
|
|
||||||
|
if (signature !== sig || signature === null || localStorage.getItem('fs') === null) {
|
||||||
|
const fs: JSON = await fetchFileSystem('/src/lib/assets/fs/fs.json');
|
||||||
|
localStorage.setItem('signature', sig);
|
||||||
|
localStorage.setItem('fs', JSON.stringify(fs));
|
||||||
|
|
||||||
|
console.info('FS fetched from file, new sinature:', sig);
|
||||||
|
|
||||||
|
return fs;
|
||||||
|
} else {
|
||||||
|
const fs: string | null = localStorage.getItem('fs');
|
||||||
|
if (fs === null) throw new Error('FS in LocalStorage is null!');
|
||||||
|
|
||||||
|
console.info('FS fetched from localStorage with signature:', sig);
|
||||||
|
|
||||||
|
return JSON.parse(fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchFsSignature(path: string): Promise<any> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(path);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.text();
|
||||||
|
return data.slice(0, 36); //32 characters of uuid + 4 dashes
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch the file system signature', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchFileSystem(path: string): Promise<any> {
|
async function fetchFileSystem(path: string): Promise<any> {
|
||||||
const response = await fetch(path);
|
const response = await fetch(path);
|
||||||
if (!response.ok) throw new Error('Failed to fetch the file system json');
|
if (!response.ok) throw new Error('Failed to fetch the file system json');
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
return data;
|
||||||
const node: TreeNode = jsonToTreeNode(data);
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initTerminal(user: User, callbackInit: any): Promise<Terminal> {
|
export async function initTerminal(user: User, callbackInit: any): Promise<Terminal> {
|
||||||
try {
|
try {
|
||||||
let fsJson = await fetchFileSystem('/src/lib/assets/fs/fs.json');
|
const sig = await fetchFsSignature('/src/lib/assets/fs/signature');
|
||||||
|
const fsJson = await fetchFsJson(sig);
|
||||||
|
const fs: TreeNode = jsonToTreeNode(fsJson);
|
||||||
|
|
||||||
let args: TermInitArgs = {
|
const args: TermInitArgs = {
|
||||||
bash: {
|
bash: {
|
||||||
user: user,
|
user,
|
||||||
fs: fsJson
|
fs
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let terminal = new Terminal(args);
|
const terminal = new Terminal(args);
|
||||||
terminal.registerCallbacks(callbackInit);
|
terminal.registerCallbacks(callbackInit);
|
||||||
|
|
||||||
return terminal;
|
return terminal;
|
||||||
|
|||||||
@@ -99,8 +99,7 @@ export class Terminal {
|
|||||||
|
|
||||||
getCwd(): string {
|
getCwd(): string {
|
||||||
const fs: VirtualFS = this.bash.getFs();
|
const fs: VirtualFS = this.bash.getFs();
|
||||||
let temp: string = fs.formatPath(fs.pathArrayToString(this.bash.getCwd()));
|
return fs.formatPath(fs.pathArrayToString(this.bash.getCwd()));
|
||||||
return temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
userLogin(username: string, passwd: string): ExitCode {
|
userLogin(username: string, passwd: string): ExitCode {
|
||||||
|
|||||||
Reference in New Issue
Block a user