mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-06 03:20:13 +08:00
Refactor packages (#101)
This commit is contained in:
35 files changed
+161
-121
No files matched your search
@@ -40,6 +40,12 @@ module.exports = {
|
||||
'prettier/prettier': ['error', { endOfLine: 'auto', semi: false }],
|
||||
'import/prefer-default-export': 'off',
|
||||
'no-restricted-syntax': ['off', 'ForOfStatement'],
|
||||
'lines-between-class-members': [
|
||||
'error',
|
||||
'always',
|
||||
{ exceptAfterSingleLine: true },
|
||||
],
|
||||
'no-use-before-define': 'off',
|
||||
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
|
||||
@@ -55,4 +61,12 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/tests/**/*.js', '**/tests/**/*.ts'], // Adjust the pattern to match your test files
|
||||
rules: {
|
||||
'import/extensions': 'off', // Turn off the rule for test files
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
+4
-2
@@ -2,6 +2,8 @@
|
||||
// const { jsWithTs: tsjPreset } = require('ts-jest/presets')
|
||||
|
||||
module.exports = {
|
||||
preset: 'ts-jest/presets/js-with-ts',
|
||||
testEnvironment: 'node',
|
||||
preset: 'ts-jest/presets/default-esm',
|
||||
moduleNameMapper: {
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1', // Redirect .js imports to .ts files
|
||||
},
|
||||
}
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
"cli": "yarn workspace client start",
|
||||
"lint": "eslint .",
|
||||
"format": "prettier --ignore-path .prettierignore --write app server",
|
||||
"test": "yarn jest",
|
||||
"test": "yarn node --experimental-vm-modules --no-warnings $(yarn bin jest)",
|
||||
"test:e2e": "yarn workspace tests test",
|
||||
"test:open": "yarn workspace tests test:open",
|
||||
"analytics": "yarn workspace analytics dev",
|
||||
@@ -29,7 +29,7 @@
|
||||
"build:quests": "yarn workspace server build:quests"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^20.10.4",
|
||||
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
||||
"@typescript-eslint/parser": "^6.14.0",
|
||||
|
||||
File renamed without changes.
@@ -1,7 +1,6 @@
|
||||
/* eslint-disable lines-between-class-members */
|
||||
import { basename } from './utils.js'
|
||||
|
||||
interface FileObject {
|
||||
export interface FileObject {
|
||||
path: string
|
||||
type: string
|
||||
discovered: boolean
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { FileObject } from './file.js'
|
||||
import FileNode from './fileNode.js'
|
||||
|
||||
export interface Event {
|
||||
add?: FileObject[]
|
||||
remove?: FileObject[]
|
||||
discover?: FileObject[]
|
||||
}
|
||||
|
||||
export default class FileGraph extends FileNode {
|
||||
add(files) {
|
||||
add(files: FileObject[]) {
|
||||
// Logic to add the file node to the graph
|
||||
// You can implement the logic to find the appropriate location in the file graph
|
||||
// If the file node already exists, throw an error
|
||||
@@ -11,7 +18,7 @@ export default class FileGraph extends FileNode {
|
||||
})
|
||||
}
|
||||
|
||||
remove(files) {
|
||||
remove(files: FileObject[]) {
|
||||
// Logic to remove a file node from the graph
|
||||
// If the file node is a folder, also remove all children
|
||||
// If the file node doesn't exist, throw an error
|
||||
@@ -21,7 +28,7 @@ export default class FileGraph extends FileNode {
|
||||
})
|
||||
}
|
||||
|
||||
discover(eventFiles) {
|
||||
discover(eventFiles: FileObject[]) {
|
||||
// Logic to handle the discover event
|
||||
// Overwrite the file graph with the provided files
|
||||
// Remove file nodes that don't exist anymore and add new ones
|
||||
@@ -35,7 +42,7 @@ export default class FileGraph extends FileNode {
|
||||
this.merge(newNode)
|
||||
}
|
||||
|
||||
handleEvent(event) {
|
||||
handleEvent(event: Event) {
|
||||
// eslint-disable-next-line default-case
|
||||
switch (true) {
|
||||
case !!event.add:
|
||||
@@ -1,19 +1,25 @@
|
||||
import File from './file.js'
|
||||
import File, { FileObject } from './file.js'
|
||||
import {
|
||||
DuplicateItemError,
|
||||
ParentNotExistsError,
|
||||
FileNotExistsError,
|
||||
} from './errors.js'
|
||||
import { basename, dirname } from './utils.js'
|
||||
import { dirname } from './utils.js'
|
||||
|
||||
export default class FileNode extends File {
|
||||
constructor(file) {
|
||||
children: FileNode[]
|
||||
|
||||
constructor(file: FileObject | FileNode) {
|
||||
super(file)
|
||||
this.children = []
|
||||
if (file.children) this.children = file.children.map((f) => new FileNode(f))
|
||||
if ((<FileNode>file).children)
|
||||
this.children = (<FileNode>file).children.map((f) => new FileNode(f))
|
||||
}
|
||||
|
||||
addChild(fileInput, { makeParents } = {}) {
|
||||
addChild(
|
||||
fileInput: FileObject,
|
||||
{ makeParents }: { makeParents?: boolean } = {}
|
||||
) {
|
||||
const file = new FileNode(fileInput)
|
||||
if (file.path === this.path) {
|
||||
throw new DuplicateItemError(
|
||||
@@ -39,7 +45,6 @@ export default class FileNode extends File {
|
||||
} else if (makeParents) {
|
||||
const parent = new FileNode({
|
||||
path: parentPath,
|
||||
name: basename(parentPath),
|
||||
type: 'folder',
|
||||
discovered: false,
|
||||
children: [file],
|
||||
@@ -53,7 +58,7 @@ export default class FileNode extends File {
|
||||
}
|
||||
}
|
||||
|
||||
removeChild(fileToRemove) {
|
||||
removeChild(fileToRemove: FileObject) {
|
||||
const file = new FileNode(fileToRemove)
|
||||
const parentPath = dirname(file.path)
|
||||
|
||||
@@ -73,7 +78,7 @@ export default class FileNode extends File {
|
||||
}
|
||||
}
|
||||
|
||||
merge(fileNode) {
|
||||
merge(fileNode: FileNode) {
|
||||
// Merge the children of the provided file node into this node
|
||||
// If a child already exists, merge the children of that child
|
||||
// If a child does not exist, add it to this node
|
||||
@@ -88,7 +93,7 @@ export default class FileNode extends File {
|
||||
if (existingChild) {
|
||||
existingChild.merge(child)
|
||||
} else {
|
||||
this.children.push(child)
|
||||
this.children.push(new FileNode(child))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -112,14 +117,12 @@ export default class FileNode extends File {
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
'Cannot merge file nodes with different paths',
|
||||
this.path,
|
||||
fileNode.path
|
||||
`Cannot merge file nodes with different paths: ${this.path}, ${fileNode.path}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
toString(level = 0) {
|
||||
toString(level = 0): string {
|
||||
let { name } = this
|
||||
const indent = ' '.repeat(level)
|
||||
name = `${indent}${name}`
|
||||
@@ -1,3 +0,0 @@
|
||||
export { default as File } from './file.js'
|
||||
export { default as FileNode } from './fileNode.js'
|
||||
export { default as FileGraph } from './fileGraph.js'
|
||||
@@ -0,0 +1,3 @@
|
||||
export { default as File, FileObject } from './file.js'
|
||||
export { default as FileNode } from './fileNode.js'
|
||||
export { default as FileGraph, Event } from './fileGraph.js'
|
||||
@@ -1,4 +1,4 @@
|
||||
export function dirname(path) {
|
||||
export function dirname(path: string) {
|
||||
const parts = path.split('/')
|
||||
if (parts.length <= 2) {
|
||||
return '/'
|
||||
@@ -7,7 +7,7 @@ export function dirname(path) {
|
||||
return parts.join('/')
|
||||
}
|
||||
|
||||
export function basename(path) {
|
||||
export function basename(path: string): string {
|
||||
const parts = path.split('/')
|
||||
return parts.pop()
|
||||
return parts.pop() ?? ''
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,10 +6,7 @@ export { default as Session } from './session.js'
|
||||
export { default as Command } from './command.js'
|
||||
export { default as UserProfile } from './userProfile.js'
|
||||
|
||||
export default async function connectDB(uri) {
|
||||
const db = await mongoose.connect(uri, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
})
|
||||
export default async function connectDB(uri: string) {
|
||||
const db = await mongoose.connect(uri)
|
||||
return db.connection.getClient()
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,4 +1,4 @@
|
||||
export function isValidUsername(username) {
|
||||
export function isValidUsername(username: string): boolean {
|
||||
// check if the username is between 1 and 32 characters
|
||||
if (username.length > 32) {
|
||||
return false
|
||||
@@ -29,7 +29,7 @@ export function isValidUsername(username) {
|
||||
return true
|
||||
}
|
||||
|
||||
export function isValidEmail(email) {
|
||||
export function isValidEmail(email: string): boolean {
|
||||
// Define a regular expression pattern for a valid email address.
|
||||
const emailPattern = /^[\w-.+]+@([\w][\w-]*\.)+[\w-]{2,}$/
|
||||
|
||||
@@ -3,14 +3,21 @@ const fileTypes = {
|
||||
folder: '-d',
|
||||
link: '-L',
|
||||
socket: '-S',
|
||||
unknown: '-e',
|
||||
}
|
||||
|
||||
function sanitizePath(path) {
|
||||
export type FileType = keyof typeof fileTypes
|
||||
|
||||
export type File = {
|
||||
path: string
|
||||
type: FileType
|
||||
}
|
||||
|
||||
function sanitizePath(path: string): string {
|
||||
return path.replace(/[^a-zA-Z0-9._/-]/g, '')
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function buildFileCheckCmd(file) {
|
||||
export function buildFileCheckCmd(file: File): string[] {
|
||||
const { path, type } = file
|
||||
return ['test', fileTypes[type] || '-e', sanitizePath(path)]
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
export default class DAG {
|
||||
#nodes = new Map()
|
||||
|
||||
#edges = new Set()
|
||||
|
||||
#layers = []
|
||||
|
||||
constructor(nodes) {
|
||||
this.#nodes = new Map(nodes.map((node) => [node._id, node]))
|
||||
this.#edges = new Set()
|
||||
this.#nodes.forEach((_, id) => {
|
||||
this.#setLayer(id)
|
||||
this.#addEdges(id)
|
||||
})
|
||||
}
|
||||
|
||||
getNode(id) {
|
||||
return this.#nodes.get(id)
|
||||
}
|
||||
|
||||
getNodes() {
|
||||
return Array.from(this.#nodes.values())
|
||||
}
|
||||
|
||||
getEdges() {
|
||||
return this.#edges
|
||||
}
|
||||
|
||||
getEdgesArray() {
|
||||
return Array.from(this.#edges.values())
|
||||
}
|
||||
|
||||
getLayers() {
|
||||
return this.#layers
|
||||
}
|
||||
|
||||
getLayer(id) {
|
||||
const node = this.getNode(id)
|
||||
if (!node) {
|
||||
throw new Error(`Node ${id} not found`)
|
||||
}
|
||||
return this.#layers[node.layer - 1]
|
||||
}
|
||||
|
||||
#setLayer(id) {
|
||||
const node = this.getNode(id)
|
||||
if (!node) {
|
||||
throw new Error(`Node ${id} not found`)
|
||||
}
|
||||
if (node.layer !== undefined) {
|
||||
return node.layer
|
||||
}
|
||||
const previousLayer = node.requirements.map((rId) => this.#setLayer(rId))
|
||||
node.layer = Math.max(...previousLayer, 0) + 1
|
||||
if (this.#layers.length < node.layer) {
|
||||
this.#layers.push(1)
|
||||
} else {
|
||||
this.#layers[node.layer - 1] += 1
|
||||
}
|
||||
node.index = this.#layers[node.layer - 1]
|
||||
return node.layer
|
||||
}
|
||||
|
||||
#addEdges(id) {
|
||||
const node = this.getNode(id)
|
||||
if (!node) {
|
||||
throw new Error(`Node ${id} not found`)
|
||||
}
|
||||
node.requirements.forEach((rId) => {
|
||||
this.#edges.add([rId, id])
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
interface Node {
|
||||
_id: string
|
||||
requirements: string[]
|
||||
}
|
||||
|
||||
export default class DAG {
|
||||
private nodes = new Map()
|
||||
private edges = new Set()
|
||||
private layers: number[] = []
|
||||
|
||||
constructor(nodes: Node[]) {
|
||||
this.nodes = new Map(nodes.map((node) => [node._id, node]))
|
||||
this.edges = new Set()
|
||||
this.nodes.forEach((_, id) => {
|
||||
this.setLayer(id)
|
||||
this.addEdges(id)
|
||||
})
|
||||
}
|
||||
|
||||
getNode(id: string) {
|
||||
return this.nodes.get(id)
|
||||
}
|
||||
|
||||
getNodes() {
|
||||
return Array.from(this.nodes.values())
|
||||
}
|
||||
|
||||
getEdges() {
|
||||
return this.edges
|
||||
}
|
||||
|
||||
getEdgesArray() {
|
||||
return Array.from(this.edges.values())
|
||||
}
|
||||
|
||||
getLayers() {
|
||||
return this.layers
|
||||
}
|
||||
|
||||
getLayer(id: string) {
|
||||
const node = this.getNode(id)
|
||||
if (!node) {
|
||||
throw new Error(`Node ${id} not found`)
|
||||
}
|
||||
return this.layers[node.layer - 1]
|
||||
}
|
||||
|
||||
private setLayer(id: string) {
|
||||
const node = this.getNode(id)
|
||||
if (!node) {
|
||||
throw new Error(`Node ${id} not found`)
|
||||
}
|
||||
if (node.layer !== undefined) {
|
||||
return node.layer
|
||||
}
|
||||
const previousLayer = node.requirements.map((rId: string) =>
|
||||
this.setLayer(rId)
|
||||
)
|
||||
node.layer = Math.max(...previousLayer, 0) + 1
|
||||
if (this.layers.length < node.layer) {
|
||||
this.layers.push(1)
|
||||
} else {
|
||||
this.layers[node.layer - 1] += 1
|
||||
}
|
||||
node.index = this.layers[node.layer - 1]
|
||||
return node.layer
|
||||
}
|
||||
|
||||
addEdges(id: string) {
|
||||
const node = this.getNode(id)
|
||||
if (!node) {
|
||||
throw new Error(`Node ${id} not found`)
|
||||
}
|
||||
node.requirements.forEach((rId: string) => {
|
||||
this.edges.add([rId, id])
|
||||
})
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -1,8 +1,11 @@
|
||||
import { buildFileCheckCmd } from '../src/commands'
|
||||
import { buildFileCheckCmd, File } from '../src/commands'
|
||||
|
||||
describe('buildFileCheckCmd function', () => {
|
||||
it('builds the file check command correctly', () => {
|
||||
const testcases = [
|
||||
const testcases: {
|
||||
input: File
|
||||
output: string[]
|
||||
}[] = [
|
||||
{
|
||||
input: { path: '/etc/passwd', type: 'file' },
|
||||
output: ['test', '-f', '/etc/passwd'],
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "./dist"
|
||||
"outDir": "./dist",
|
||||
"allowJs": false
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
|
||||
@@ -14,9 +14,9 @@ async function deactivateSessions(user, quest) {
|
||||
return deleteContainer(session.containerId)
|
||||
.catch((err) => logger.error('Failed to delete container', err))
|
||||
.finally(() => {
|
||||
session.status = 'inactive'
|
||||
session.containerId = null
|
||||
return session.save()
|
||||
return Session.findByIdAndUpdate(session._id, {
|
||||
$set: { status: 'inactive', containerId: null },
|
||||
}).catch((err) => logger.error('Failed to update session', err))
|
||||
})
|
||||
})
|
||||
)
|
||||
|
||||
+3
-1
@@ -8,6 +8,8 @@
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "dist"
|
||||
"outDir": "dist",
|
||||
"sourceMap": true,
|
||||
"declaration": true
|
||||
}
|
||||
}
|
||||
@@ -1460,7 +1460,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/jest@npm:^29.5.11":
|
||||
"@types/jest@npm:^29.5.12":
|
||||
version: 29.5.12
|
||||
resolution: "@types/jest@npm:29.5.12"
|
||||
dependencies:
|
||||
@@ -6512,7 +6512,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "linux-odyssey@workspace:."
|
||||
dependencies:
|
||||
"@types/jest": "npm:^29.5.11"
|
||||
"@types/jest": "npm:^29.5.12"
|
||||
"@types/node": "npm:^20.10.4"
|
||||
"@typescript-eslint/eslint-plugin": "npm:^6.14.0"
|
||||
"@typescript-eslint/parser": "npm:^6.14.0"
|
||||
|
||||
Reference in new issue
Block a user