mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 03:20:12 +08:00
Merge branch 'main' of https://github.com/linux-odyssey/linux-odyssey into ts-analytics
This commit is contained in:
commit
56d07f14b4
96 files changed
+8595
-11761
No files matched your search
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"rootDir": "src",
|
||||
"outDir": "./dist",
|
||||
"esModuleInterop": true,
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
"license": "GPL",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "tsc -w"
|
||||
"dev": "tsc -w"
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "tsc -w",
|
||||
"dev": "tsc -w",
|
||||
"test": "yarn build && jest"
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -1,8 +1,8 @@
|
||||
import FileGraph from '../src/fileGraph'
|
||||
import FileNode from '../src/fileNode'
|
||||
import FileGraph from '../src/fileGraph.js'
|
||||
import FileNode from '../src/fileNode.js'
|
||||
|
||||
describe('FileGraph', () => {
|
||||
let root
|
||||
let root: FileNode
|
||||
|
||||
beforeEach(() => {
|
||||
root = new FileNode({
|
||||
@@ -66,10 +66,12 @@ describe('FileGraph', () => {
|
||||
{
|
||||
path: '/home/user/folder1/file1.txt',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
},
|
||||
{
|
||||
path: '/home/user/folder2',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
},
|
||||
]
|
||||
|
||||
+64
-45
@@ -1,13 +1,18 @@
|
||||
import { DuplicateItemError, ParentNotExistsError } from '../src/errors'
|
||||
import FileNode from '../src/fileNode'
|
||||
import { DuplicateItemError, ParentNotExistsError } from '../src/errors.js'
|
||||
import FileNode from '../src/fileNode.js'
|
||||
import { FileObject } from '../src/file.js'
|
||||
|
||||
function createNodeFromFiles(files) {
|
||||
function createNodeFromFiles(files: FileObject[]) {
|
||||
const node = new FileNode(files[0])
|
||||
files.slice(1).forEach((file) => node.addChild(file))
|
||||
return node
|
||||
}
|
||||
|
||||
function mergeTest(files1, files2, expectedFiles) {
|
||||
function mergeTest(
|
||||
files1: FileObject[],
|
||||
files2: FileObject[],
|
||||
expectedFiles: FileObject[]
|
||||
) {
|
||||
const node1 = createNodeFromFiles(files1)
|
||||
const node2 = createNodeFromFiles(files2)
|
||||
const expectedNode = createNodeFromFiles(expectedFiles)
|
||||
@@ -17,7 +22,11 @@ function mergeTest(files1, files2, expectedFiles) {
|
||||
expect(node1.toString()).toBe(expectedNode.toString())
|
||||
}
|
||||
|
||||
function removeChildTest(files, fileToRemove, expectedFiles) {
|
||||
function removeChildTest(
|
||||
files: FileObject[],
|
||||
fileToRemove: FileObject,
|
||||
expectedFiles: FileObject[]
|
||||
) {
|
||||
const node = createNodeFromFiles(files)
|
||||
const expectedNode = createNodeFromFiles(expectedFiles)
|
||||
|
||||
@@ -27,7 +36,7 @@ function removeChildTest(files, fileToRemove, expectedFiles) {
|
||||
}
|
||||
|
||||
describe('FileNode', () => {
|
||||
let rootNode
|
||||
let rootNode: FileNode
|
||||
|
||||
beforeEach(() => {
|
||||
rootNode = new FileNode({
|
||||
@@ -41,8 +50,8 @@ describe('FileNode', () => {
|
||||
test('should throw error when adding duplicate item', () => {
|
||||
const child = {
|
||||
path: '/home/rudeus/test',
|
||||
name: 'test',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
}
|
||||
|
||||
// Adding the child for the first time
|
||||
@@ -61,6 +70,7 @@ describe('FileNode', () => {
|
||||
path: '/home/rudeus/alphabet/test',
|
||||
name: 'test',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
}
|
||||
|
||||
// Trying to add to a nonexistent parent should throw an error
|
||||
@@ -75,13 +85,13 @@ describe('FileNode', () => {
|
||||
path: '/home/rudeus/forgotten_scroll.txt',
|
||||
name: 'forgotten_scroll.txt',
|
||||
type: 'file',
|
||||
discovered: 'test',
|
||||
discovered: true,
|
||||
},
|
||||
{
|
||||
path: '/home/rudeus/test',
|
||||
name: 'test',
|
||||
type: 'folder',
|
||||
discovered: 'test',
|
||||
discovered: true,
|
||||
},
|
||||
{
|
||||
path: '/home/rudeus/test/a',
|
||||
@@ -121,30 +131,31 @@ describe('FileNode', () => {
|
||||
const root = {
|
||||
path: '/',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
}
|
||||
const files1 = [
|
||||
root,
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/d', type: 'file' },
|
||||
{ path: '/b/c/f', type: 'file' },
|
||||
{ path: '/a', type: 'file', discovered: true },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/c', type: 'folder', discovered: true },
|
||||
{ path: '/b/d', type: 'file', discovered: true },
|
||||
{ path: '/b/c/f', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
const files2 = [
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/e', type: 'file' },
|
||||
{ path: '/b/c/g', type: 'file' },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/c', type: 'folder', discovered: true },
|
||||
{ path: '/b/e', type: 'file', discovered: true },
|
||||
{ path: '/b/c/g', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
const expected = [
|
||||
root,
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/e', type: 'file' },
|
||||
{ path: '/b/c/g', type: 'file' },
|
||||
{ path: '/a', type: 'file', discovered: true },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/c', type: 'folder', discovered: true },
|
||||
{ path: '/b/e', type: 'file', discovered: true },
|
||||
{ path: '/b/c/g', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
mergeTest(files1, files2, expected)
|
||||
@@ -157,29 +168,30 @@ describe('FileNode', () => {
|
||||
const root = {
|
||||
path: '/',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
}
|
||||
const files1 = [
|
||||
root,
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/d', type: 'file' },
|
||||
{ path: '/b/c/f', type: 'file' },
|
||||
{ path: '/a', type: 'file', discovered: true },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/c', type: 'folder', discovered: true },
|
||||
{ path: '/b/d', type: 'file', discovered: true },
|
||||
{ path: '/b/c/f', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
const files2 = [
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/e', type: 'file' },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/c', type: 'folder', discovered: true },
|
||||
{ path: '/b/e', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
const expected = [
|
||||
root,
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/e', type: 'file' },
|
||||
{ path: '/b/c/f', type: 'file' },
|
||||
{ path: '/a', type: 'file', discovered: true },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/c', type: 'folder', discovered: true },
|
||||
{ path: '/b/e', type: 'file', discovered: true },
|
||||
{ path: '/b/c/f', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
mergeTest(files1, files2, expected)
|
||||
@@ -189,6 +201,7 @@ describe('FileNode', () => {
|
||||
const root = {
|
||||
path: '/',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
}
|
||||
const files1 = [
|
||||
root,
|
||||
@@ -218,23 +231,24 @@ describe('FileNode', () => {
|
||||
const root = {
|
||||
path: '/',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
}
|
||||
const files = [
|
||||
root,
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/c', type: 'folder' },
|
||||
{ path: '/b/d', type: 'file' },
|
||||
{ path: '/b/c/f', type: 'file' },
|
||||
{ path: '/a', type: 'file', discovered: true },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/c', type: 'folder', discovered: true },
|
||||
{ path: '/b/d', type: 'file', discovered: true },
|
||||
{ path: '/b/c/f', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
const fileToRemove = { path: '/b/c', type: 'folder' }
|
||||
const fileToRemove = { path: '/b/c', type: 'folder', discovered: true }
|
||||
|
||||
const expected = [
|
||||
root,
|
||||
{ path: '/a', type: 'file' },
|
||||
{ path: '/b', type: 'folder' },
|
||||
{ path: '/b/d', type: 'file' },
|
||||
{ path: '/a', type: 'file', discovered: true },
|
||||
{ path: '/b', type: 'folder', discovered: true },
|
||||
{ path: '/b/d', type: 'file', discovered: true },
|
||||
]
|
||||
|
||||
removeChildTest(files, fileToRemove, expected)
|
||||
@@ -245,22 +259,27 @@ test('load nested fileNode', () => {
|
||||
const data = {
|
||||
path: '/',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
children: [
|
||||
{
|
||||
path: '/a',
|
||||
type: 'file',
|
||||
discovered: true,
|
||||
},
|
||||
{
|
||||
path: '/b',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
children: [
|
||||
{
|
||||
path: '/b/c',
|
||||
type: 'folder',
|
||||
discovered: true,
|
||||
children: [
|
||||
{
|
||||
path: '/b/c/d',
|
||||
type: 'file',
|
||||
discovered: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -8,9 +8,10 @@
|
||||
"exports": "./dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "tsc -w"
|
||||
"dev": "tsc -w"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/mongoose": "^5.11.97",
|
||||
"mongoose": "^8.0.3"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,19 @@
|
||||
import { model, Schema } from 'mongoose'
|
||||
import { model, Schema, Types } from 'mongoose'
|
||||
|
||||
const Command = model(
|
||||
export interface ICommand {
|
||||
session: Types.ObjectId
|
||||
pwd: string
|
||||
command: string
|
||||
output?: string
|
||||
error?: string
|
||||
stage?: string
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export const Command = model<ICommand>(
|
||||
'Command',
|
||||
new Schema(
|
||||
new Schema<ICommand>(
|
||||
{
|
||||
session: {
|
||||
type: Schema.ObjectId,
|
||||
@@ -33,5 +44,3 @@ const Command = model(
|
||||
{ timestamps: true }
|
||||
)
|
||||
)
|
||||
|
||||
export default Command
|
||||
@@ -1,9 +1,14 @@
|
||||
import { Schema } from 'mongoose'
|
||||
import conditionSchema from './condition.js'
|
||||
import responseSchema from './response.js'
|
||||
import hintSchema from './hint.js'
|
||||
import { conditionSchema, ICondition } from './condition.js'
|
||||
import { responseSchema, IResponse } from './response.js'
|
||||
import { hintSchema, IHint } from './hint.js'
|
||||
|
||||
const commandResponderSchema = new Schema({
|
||||
export interface ICommandResponder extends IHint {
|
||||
condition?: ICondition
|
||||
responses: IResponse[]
|
||||
}
|
||||
|
||||
export const commandResponderSchema = new Schema<ICommandResponder>({
|
||||
condition: {
|
||||
type: conditionSchema,
|
||||
required: false,
|
||||
@@ -15,5 +20,3 @@ const commandResponderSchema = new Schema({
|
||||
})
|
||||
|
||||
commandResponderSchema.add(hintSchema)
|
||||
|
||||
export default commandResponderSchema
|
||||
@@ -1,6 +1,22 @@
|
||||
import { Schema } from 'mongoose'
|
||||
|
||||
const fileConditionSchema = new Schema({
|
||||
export interface IFileCondition {
|
||||
path: string
|
||||
type: string
|
||||
exists: boolean
|
||||
}
|
||||
|
||||
export interface ICondition {
|
||||
command?: string[]
|
||||
output?: string[]
|
||||
error?: string[]
|
||||
pwd?: string[]
|
||||
files?: IFileCondition[]
|
||||
or?: ICondition[]
|
||||
not?: ICondition
|
||||
}
|
||||
|
||||
export const fileConditionSchema = new Schema<IFileCondition>({
|
||||
path: {
|
||||
type: String,
|
||||
required: true,
|
||||
@@ -12,7 +28,7 @@ const fileConditionSchema = new Schema({
|
||||
},
|
||||
})
|
||||
|
||||
const conditionSchema = new Schema({
|
||||
export const conditionSchema = new Schema<ICondition>({
|
||||
command: [String],
|
||||
output: [String],
|
||||
error: [String],
|
||||
@@ -24,5 +40,3 @@ conditionSchema.add({
|
||||
or: [conditionSchema],
|
||||
not: conditionSchema,
|
||||
})
|
||||
|
||||
export default conditionSchema
|
||||
@@ -1,8 +1,11 @@
|
||||
import { Schema } from 'mongoose'
|
||||
import commandResponderSchema from './commandResponder.js'
|
||||
import {
|
||||
commandResponderSchema,
|
||||
ICommandResponder,
|
||||
} from './commandResponder.js'
|
||||
|
||||
const exceptionSchema = new Schema({})
|
||||
export interface IException extends ICommandResponder {}
|
||||
|
||||
export const exceptionSchema = new Schema<IException>({})
|
||||
|
||||
exceptionSchema.add(commandResponderSchema)
|
||||
|
||||
export default exceptionSchema
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Schema } from 'mongoose'
|
||||
import exceptionSchema from './exception.js'
|
||||
import requirementSchema from './requirement.js'
|
||||
import { exceptionSchema, IException } from './exception.js'
|
||||
import { requirementSchema, IRequirement } from './requirement.js'
|
||||
|
||||
const globalExceptionSchema = new Schema({})
|
||||
export interface IGlobalException extends IException, IRequirement {}
|
||||
|
||||
export const globalExceptionSchema = new Schema<IGlobalException>({})
|
||||
|
||||
globalExceptionSchema.add(exceptionSchema)
|
||||
globalExceptionSchema.add(requirementSchema)
|
||||
|
||||
export default globalExceptionSchema
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Schema } from 'mongoose'
|
||||
|
||||
const hintSchema = new Schema({
|
||||
export interface IHint {
|
||||
hints: string[]
|
||||
}
|
||||
|
||||
export const hintSchema = new Schema({
|
||||
hints: {
|
||||
type: [String],
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
export default hintSchema
|
||||
@@ -1,10 +1,15 @@
|
||||
import mongoose from 'mongoose'
|
||||
|
||||
export { default as User } from './user.js'
|
||||
export { default as Quest } from './quest.js'
|
||||
export { default as Session } from './session.js'
|
||||
export { default as Command } from './command.js'
|
||||
export { default as UserProfile } from './userProfile.js'
|
||||
export { User, IUser } from './user.js'
|
||||
export { Quest, IQuest } from './quest.js'
|
||||
export { Session, ISession, ITask } from './session.js'
|
||||
export { Command, ICommand } from './command.js'
|
||||
export { UserProfile, IUserProfile } from './userProfile.js'
|
||||
export { IFileCondition, ICondition } from './condition.js'
|
||||
export { IStage } from './stage.js'
|
||||
export { IRequirement } from './requirement.js'
|
||||
export { IResponse } from './response.js'
|
||||
export { IException } from './exception.js'
|
||||
|
||||
export default async function connectDB(uri: string) {
|
||||
const db = await mongoose.connect(uri)
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import { model, Schema } from 'mongoose'
|
||||
import stageSchema from './stage.js'
|
||||
import globalExceptionSchema from './globalException.js'
|
||||
import { IStage, stageSchema } from './stage.js'
|
||||
import { globalExceptionSchema, IGlobalException } from './globalException.js'
|
||||
import { IRequirement } from './requirement.js'
|
||||
|
||||
const Quest = model(
|
||||
export interface IQuest extends IRequirement {
|
||||
_id: string
|
||||
title: string
|
||||
image: string
|
||||
instruction: string
|
||||
stages: IStage[]
|
||||
exceptions: IGlobalException[]
|
||||
}
|
||||
|
||||
export const Quest = model<IQuest>(
|
||||
'Quest',
|
||||
new Schema({
|
||||
new Schema<IQuest>({
|
||||
_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
@@ -40,5 +50,3 @@ const Quest = model(
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
export default Quest
|
||||
@@ -1,6 +1,10 @@
|
||||
import { Schema } from 'mongoose'
|
||||
|
||||
const requirementSchema = new Schema({
|
||||
export interface IRequirement {
|
||||
requirements: string[]
|
||||
}
|
||||
|
||||
export const requirementSchema = new Schema<IRequirement>({
|
||||
requirements: [
|
||||
{
|
||||
type: String,
|
||||
@@ -8,5 +12,3 @@ const requirementSchema = new Schema({
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
export default requirementSchema
|
||||
@@ -1,6 +1,13 @@
|
||||
import { Schema } from 'mongoose'
|
||||
|
||||
const responseSchema = new Schema({
|
||||
export interface IResponse {
|
||||
type: 'narrative' | 'dialogue'
|
||||
content: string[]
|
||||
speaker?: string
|
||||
color?: string
|
||||
}
|
||||
|
||||
export const responseSchema = new Schema<IResponse>({
|
||||
type: {
|
||||
type: String,
|
||||
enum: ['narrative', 'dialogue'],
|
||||
@@ -14,5 +21,3 @@ const responseSchema = new Schema({
|
||||
speaker: { type: String, default: 'Ada' },
|
||||
color: String,
|
||||
})
|
||||
|
||||
export default responseSchema
|
||||
@@ -1,6 +1,13 @@
|
||||
import { model, Schema } from 'mongoose'
|
||||
import { model, Schema, Types } from 'mongoose'
|
||||
|
||||
const nodeSchema = new Schema({
|
||||
export interface INode {
|
||||
path: string
|
||||
type: string
|
||||
discovered: boolean
|
||||
children?: INode[]
|
||||
}
|
||||
|
||||
const nodeSchema = new Schema<INode>({
|
||||
path: String,
|
||||
type: String,
|
||||
discovered: {
|
||||
@@ -13,7 +20,13 @@ nodeSchema.add({
|
||||
children: [nodeSchema],
|
||||
})
|
||||
|
||||
const taskSchema = new Schema({
|
||||
export interface ITask {
|
||||
id: string
|
||||
name: string
|
||||
completed: boolean
|
||||
}
|
||||
|
||||
const taskSchema = new Schema<ITask>({
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
@@ -28,9 +41,24 @@ const taskSchema = new Schema({
|
||||
},
|
||||
})
|
||||
|
||||
const Session = model(
|
||||
export interface ISession {
|
||||
_id: Types.ObjectId
|
||||
user: Types.ObjectId
|
||||
quest: string
|
||||
containerId: string | null
|
||||
status: string
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
finishedAt?: Date
|
||||
lastActivityAt: Date
|
||||
tasks: ITask[]
|
||||
hints: string[][]
|
||||
graph: INode
|
||||
}
|
||||
|
||||
export const Session = model<ISession>(
|
||||
'Session',
|
||||
new Schema(
|
||||
new Schema<ISession>(
|
||||
{
|
||||
user: {
|
||||
type: Schema.ObjectId,
|
||||
@@ -68,5 +96,3 @@ const Session = model(
|
||||
{ timestamps: true }
|
||||
)
|
||||
)
|
||||
|
||||
export default Session
|
||||
@@ -1,9 +1,18 @@
|
||||
import { Schema } from 'mongoose'
|
||||
import commandResponderSchema from './commandResponder.js'
|
||||
import stageExceptionSchema from './stageException.js'
|
||||
import requirementSchema from './requirement.js'
|
||||
import {
|
||||
commandResponderSchema,
|
||||
ICommandResponder,
|
||||
} from './commandResponder.js'
|
||||
import { stageExceptionSchema, IStageException } from './stageException.js'
|
||||
import { requirementSchema, IRequirement } from './requirement.js'
|
||||
|
||||
const stageSchema = new Schema({
|
||||
export interface IStage extends IRequirement, ICommandResponder {
|
||||
id: string
|
||||
task: string
|
||||
exceptions: IStageException[]
|
||||
}
|
||||
|
||||
export const stageSchema = new Schema<IStage>({
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
@@ -20,5 +29,3 @@ const stageSchema = new Schema({
|
||||
|
||||
stageSchema.add(commandResponderSchema)
|
||||
stageSchema.add(requirementSchema)
|
||||
|
||||
export default stageSchema
|
||||
@@ -1,7 +1,11 @@
|
||||
import { Schema } from 'mongoose'
|
||||
import exceptionSchema from './exception.js'
|
||||
import { exceptionSchema, IException } from './exception.js'
|
||||
|
||||
const stageExceptionSchema = new Schema({
|
||||
export interface IStageException extends IException {
|
||||
catchAll: boolean
|
||||
}
|
||||
|
||||
export const stageExceptionSchema = new Schema<IStageException>({
|
||||
catchAll: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
@@ -10,5 +14,3 @@ const stageExceptionSchema = new Schema({
|
||||
})
|
||||
|
||||
stageExceptionSchema.add(exceptionSchema)
|
||||
|
||||
export default stageExceptionSchema
|
||||
@@ -1,6 +1,12 @@
|
||||
import { model, Schema } from 'mongoose'
|
||||
|
||||
const socialLoginSchema = new Schema({
|
||||
export interface ISocialLogin {
|
||||
provider: string
|
||||
id: string
|
||||
displayName?: string
|
||||
}
|
||||
|
||||
const socialLoginSchema = new Schema<ISocialLogin>({
|
||||
provider: {
|
||||
type: String,
|
||||
required: true,
|
||||
@@ -15,9 +21,18 @@ const socialLoginSchema = new Schema({
|
||||
},
|
||||
})
|
||||
|
||||
const User = model(
|
||||
export interface IUser {
|
||||
username: string
|
||||
email: string
|
||||
hashedPassword: string
|
||||
socialLogins: Map<string, ISocialLogin>
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
|
||||
export const User = model<IUser>(
|
||||
'User',
|
||||
new Schema(
|
||||
new Schema<IUser>(
|
||||
{
|
||||
username: {
|
||||
type: String,
|
||||
@@ -42,5 +57,3 @@ const User = model(
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
export default User
|
||||
@@ -1,6 +1,14 @@
|
||||
import { model, Schema } from 'mongoose'
|
||||
import { model, Schema, Types } from 'mongoose'
|
||||
|
||||
const progressSchema = new Schema({
|
||||
export interface IProgress {
|
||||
quest: string
|
||||
sessions: Types.ObjectId[]
|
||||
completed: boolean
|
||||
startedAt: Date
|
||||
finishedAt?: Date
|
||||
}
|
||||
|
||||
const progressSchema = new Schema<IProgress>({
|
||||
quest: {
|
||||
type: String,
|
||||
ref: 'Quest',
|
||||
@@ -25,9 +33,14 @@ const progressSchema = new Schema({
|
||||
finishedAt: Date,
|
||||
})
|
||||
|
||||
const UserProfile = model(
|
||||
export interface IUserProfile {
|
||||
user: Types.ObjectId
|
||||
progress: Map<string, IProgress>
|
||||
}
|
||||
|
||||
export const UserProfile = model<IUserProfile>(
|
||||
'UserProfile',
|
||||
new Schema(
|
||||
new Schema<IUserProfile>(
|
||||
{
|
||||
user: {
|
||||
type: Schema.ObjectId,
|
||||
@@ -47,5 +60,3 @@ const UserProfile = model(
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
export default UserProfile
|
||||
@@ -8,6 +8,6 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"watch": "tsc -w"
|
||||
"dev": "tsc -w"
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
const fileTypes = {
|
||||
file: '-f',
|
||||
folder: '-d',
|
||||
link: '-L',
|
||||
socket: '-S',
|
||||
unknown: '-e',
|
||||
}
|
||||
|
||||
export type FileType = keyof typeof fileTypes
|
||||
|
||||
export type File = {
|
||||
export interface File {
|
||||
path: string
|
||||
type: FileType
|
||||
type: string
|
||||
}
|
||||
|
||||
const fileTypes = new Map([
|
||||
['file', '-f'],
|
||||
['folder', '-d'],
|
||||
['link', '-L'],
|
||||
['socket', '-S'],
|
||||
])
|
||||
|
||||
function sanitizePath(path: string): string {
|
||||
return path.replace(/[^a-zA-Z0-9._/-]/g, '')
|
||||
}
|
||||
|
||||
export function buildFileCheckCmd(file: File): string[] {
|
||||
const { path, type } = file
|
||||
return ['test', fileTypes[type] || '-e', sanitizePath(path)]
|
||||
return ['test', fileTypes.get(type) || '-e', sanitizePath(path)]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isValidEmail, isValidUsername } from '../src/auth'
|
||||
import { isValidEmail, isValidUsername } from '../src/auth.js'
|
||||
|
||||
test('check valid username', () => {
|
||||
const valid = ['alex', 'alex123', 'john_doe', 'john-doe', 'rudeus']
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { buildFileCheckCmd, File } from '../src/commands'
|
||||
import { buildFileCheckCmd, File } from '../src/commands.js'
|
||||
|
||||
describe('buildFileCheckCmd function', () => {
|
||||
it('builds the file check command correctly', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import DAG from '../src/dag'
|
||||
import DAG from '../src/dag.js'
|
||||
|
||||
describe('dag layers', () => {
|
||||
it('two layer', () => {
|
||||
|
||||
Reference in new issue
Block a user