From 0644783cc42064ea0568ceabd83778f8757d81cc Mon Sep 17 00:00:00 2001
From: wancat
Date: Tue, 27 Feb 2024 12:27:54 +0800
Subject: [PATCH 01/82] feat: use project references to build dependencies
efficiently
---
app/tsconfig.json | 7 ++++++-
package.json | 4 +---
packages/constants/tsconfig.json | 1 +
packages/file-graph/tsconfig.json | 1 +
packages/models/src/index.ts | 2 ++
packages/models/tsconfig.json | 1 +
packages/utils/tsconfig.json | 1 +
server/package.json | 4 ++--
server/tsconfig.json | 8 +++++++-
tsconfig.json | 3 ++-
10 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/app/tsconfig.json b/app/tsconfig.json
index b17c94a..dc7801a 100644
--- a/app/tsconfig.json
+++ b/app/tsconfig.json
@@ -22,5 +22,10 @@
"noFallthroughCasesInSwitch": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*.js"],
- "references": [{ "path": "./tsconfig.node.json" }]
+ "references": [
+ { "path": "./tsconfig.node.json" },
+ { "path": "../packages/utils" },
+ { "path": "../packages/constants" },
+ { "path": "../packages/file-graph" }
+ ]
}
diff --git a/package.json b/package.json
index 04954b1..3888742 100644
--- a/package.json
+++ b/package.json
@@ -13,9 +13,7 @@
],
"scripts": {
"app": "yarn workspace app dev",
- "build:deps": "concurrently \"yarn workspace @linux-odyssey/constants build\" \"yarn workspace @linux-odyssey/file-graph build\" \"yarn workspace @linux-odyssey/models build\" \"yarn workspace @linux-odyssey/utils build\"",
- "build:apps": "concurrently \"yarn workspace app build\" \"yarn workspace server build\" \"yarn workspace analytics build\"",
- "build": "yarn build:deps && yarn build:apps",
+ "build": "yarn workspace server build && yarn workspace app build && yarn workspace analytics build",
"dev": "concurrently -n \"App,Server\" -c \"bgBlue.bold,bgGreen.bold\" \"yarn workspace app dev\" \"yarn workspace server dev\"",
"server": "yarn workspace server dev",
"cli": "yarn workspace client start",
diff --git a/packages/constants/tsconfig.json b/packages/constants/tsconfig.json
index bd29af9..318a4cf 100644
--- a/packages/constants/tsconfig.json
+++ b/packages/constants/tsconfig.json
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
+ "composite": true,
"outDir": "./dist"
},
"include": ["*.js", "*.ts"],
diff --git a/packages/file-graph/tsconfig.json b/packages/file-graph/tsconfig.json
index bf649ac..ccaf320 100644
--- a/packages/file-graph/tsconfig.json
+++ b/packages/file-graph/tsconfig.json
@@ -2,6 +2,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
+ "composite": true,
"outDir": "./dist"
},
"include": ["src"],
diff --git a/packages/models/src/index.ts b/packages/models/src/index.ts
index efdfd11..59332a0 100644
--- a/packages/models/src/index.ts
+++ b/packages/models/src/index.ts
@@ -15,3 +15,5 @@ export default async function connectDB(uri: string) {
const db = await mongoose.connect(uri)
return db.connection.getClient()
}
+
+console.log('Loaded models package')
diff --git a/packages/models/tsconfig.json b/packages/models/tsconfig.json
index bf649ac..ccaf320 100644
--- a/packages/models/tsconfig.json
+++ b/packages/models/tsconfig.json
@@ -2,6 +2,7 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
+ "composite": true,
"outDir": "./dist"
},
"include": ["src"],
diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json
index 8f50229..b1b8f57 100644
--- a/packages/utils/tsconfig.json
+++ b/packages/utils/tsconfig.json
@@ -3,6 +3,7 @@
"compilerOptions": {
"rootDir": "src",
"outDir": "./dist",
+ "composite": true,
"allowJs": false
},
"include": ["src"],
diff --git a/server/package.json b/server/package.json
index c6383ad..02b10c7 100644
--- a/server/package.json
+++ b/server/package.json
@@ -7,8 +7,8 @@
"start": "node dist/index.js",
"setup": "node dist/cli/setup.js",
"clean": "node dist/cli/clean.js",
- "build": "tsc",
- "dev": "concurrently \"tsc -w\" \"sleep 5 && nodemon\"",
+ "build": "tsc -b",
+ "dev": "concurrently \"tsc -b --watch\" \"sleep 5 && nodemon\"",
"build:quests": "node dist/cli/build.js"
},
"dependencies": {
diff --git a/server/tsconfig.json b/server/tsconfig.json
index efc3d54..321fdda 100644
--- a/server/tsconfig.json
+++ b/server/tsconfig.json
@@ -4,5 +4,11 @@
"outDir": "./dist"
},
"include": ["src"],
- "exclude": ["node_modules", "src/*.test.js", "dist"]
+ "exclude": ["node_modules", "src/*.test.js", "dist"],
+ "references": [
+ { "path": "../packages/constants" },
+ { "path": "../packages/file-graph" },
+ { "path": "../packages/models" },
+ { "path": "../packages/utils" }
+ ]
}
diff --git a/tsconfig.json b/tsconfig.json
index 2cd1c93..862aad0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -8,6 +8,7 @@
"strict": true,
"skipLibCheck": true,
"sourceMap": true,
- "declaration": true
+ "declaration": true,
+ "declarationMap": true
}
}
From 15278dfab25bf40dfb6f1e526f7acaa315d545e8 Mon Sep 17 00:00:00 2001
From: wancat
Date: Tue, 27 Feb 2024 12:53:44 +0800
Subject: [PATCH 02/82] fix: docker
---
app/Dockerfile | 4 +---
app/package.json | 1 +
app/tsconfig.json | 1 -
app/tsconfig.node.json | 10 ----------
server/Dockerfile | 4 ----
5 files changed, 2 insertions(+), 18 deletions(-)
delete mode 100644 app/tsconfig.node.json
diff --git a/app/Dockerfile b/app/Dockerfile
index 506854c..e5e4888 100644
--- a/app/Dockerfile
+++ b/app/Dockerfile
@@ -20,9 +20,7 @@ COPY packages/file-graph ./packages/file-graph
COPY packages/utils ./packages/utils
COPY packages/constants ./packages/constants
COPY app ./app
-RUN yarn workspace @linux-odyssey/file-graph build
-RUN yarn workspace @linux-odyssey/utils build
-RUN yarn workspace @linux-odyssey/constants build
+RUN yarn workspace app build:refs
RUN yarn workspace app build
# Production stage
diff --git a/app/package.json b/app/package.json
index 0e605f5..920e658 100644
--- a/app/package.json
+++ b/app/package.json
@@ -7,6 +7,7 @@
"dev": "vite",
"dev:docker": "API_TARGET=http://backend:3000 vite",
"build": "vite build",
+ "build:refs": "tsc --build",
"preview": "vite preview"
},
"dependencies": {
diff --git a/app/tsconfig.json b/app/tsconfig.json
index dc7801a..9a196d6 100644
--- a/app/tsconfig.json
+++ b/app/tsconfig.json
@@ -23,7 +23,6 @@
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*.js"],
"references": [
- { "path": "./tsconfig.node.json" },
{ "path": "../packages/utils" },
{ "path": "../packages/constants" },
{ "path": "../packages/file-graph" }
diff --git a/app/tsconfig.node.json b/app/tsconfig.node.json
deleted file mode 100644
index 42872c5..0000000
--- a/app/tsconfig.node.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "compilerOptions": {
- "composite": true,
- "skipLibCheck": true,
- "module": "ESNext",
- "moduleResolution": "bundler",
- "allowSyntheticDefaultImports": true
- },
- "include": ["vite.config.ts"]
-}
diff --git a/server/Dockerfile b/server/Dockerfile
index 70d5145..32361c6 100644
--- a/server/Dockerfile
+++ b/server/Dockerfile
@@ -26,10 +26,6 @@ COPY server ./server
COPY quests ./quests
ENV NODE_ENV=production
-RUN yarn workspace @linux-odyssey/file-graph build
-RUN yarn workspace @linux-odyssey/utils build
-RUN yarn workspace @linux-odyssey/models build
-RUN yarn workspace @linux-odyssey/constants build
RUN yarn workspace server build
WORKDIR /app/server
CMD [ "yarn", "start" ]
From 6c111a4475cf87a2b73753c85eeab043eafd56ba Mon Sep 17 00:00:00 2001
From: wancat
Date: Wed, 28 Feb 2024 22:17:14 +0800
Subject: [PATCH 03/82] feat: use babel to replace ts-jest (improve
performance)
---
babel.config.js | 6 +
jest.config.ts | 1 -
package.json | 5 +-
yarn.lock | 928 +++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 895 insertions(+), 45 deletions(-)
create mode 100644 babel.config.js
diff --git a/babel.config.js b/babel.config.js
new file mode 100644
index 0000000..befbdd1
--- /dev/null
+++ b/babel.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ presets: [
+ ['@babel/preset-env', { targets: { node: 'current' } }],
+ '@babel/preset-typescript',
+ ],
+}
diff --git a/jest.config.ts b/jest.config.ts
index 32104f4..65e41ea 100644
--- a/jest.config.ts
+++ b/jest.config.ts
@@ -6,7 +6,6 @@
import type { Config } from 'jest'
const config: Config = {
- preset: 'ts-jest/presets/default-esm',
// All imported modules in your tests should be mocked automatically
// automock: false,
diff --git a/package.json b/package.json
index 3888742..e1d0906 100644
--- a/package.json
+++ b/package.json
@@ -28,12 +28,16 @@
"build:quests": "yarn workspace server build:quests"
},
"devDependencies": {
+ "@babel/core": "^7.24.0",
+ "@babel/preset-env": "^7.24.0",
+ "@babel/preset-typescript": "^7.23.3",
"@jest/globals": "^29.7.0",
"@types/jest": "^29.5.12",
"@types/node": "^20.10.4",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@vue/eslint-config-prettier": "^7.1.0",
+ "babel-jest": "^29.7.0",
"concurrently": "^8.2.2",
"eslint": "^8.44.0",
"eslint-config-airbnb-base": "^15.0.0",
@@ -46,7 +50,6 @@
"eslint-plugin-vue": "^9.15.1",
"jest": "^29.7.0",
"prettier": "^3.0.0",
- "ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
diff --git a/yarn.lock b/yarn.lock
index 26908b8..01f5d1d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -28,7 +28,7 @@
"@babel/highlight" "^7.23.4"
chalk "^2.4.2"
-"@babel/compat-data@^7.23.5":
+"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5":
version "7.23.5"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98"
integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==
@@ -54,6 +54,27 @@
json5 "^2.2.3"
semver "^6.3.1"
+"@babel/core@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b"
+ integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==
+ dependencies:
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.23.5"
+ "@babel/generator" "^7.23.6"
+ "@babel/helper-compilation-targets" "^7.23.6"
+ "@babel/helper-module-transforms" "^7.23.3"
+ "@babel/helpers" "^7.24.0"
+ "@babel/parser" "^7.24.0"
+ "@babel/template" "^7.24.0"
+ "@babel/traverse" "^7.24.0"
+ "@babel/types" "^7.24.0"
+ convert-source-map "^2.0.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.3"
+ semver "^6.3.1"
+
"@babel/generator@^7.23.6", "@babel/generator@^7.7.2":
version "7.23.6"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e"
@@ -64,7 +85,21 @@
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
-"@babel/helper-compilation-targets@^7.23.6":
+"@babel/helper-annotate-as-pure@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882"
+ integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.15":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz#5426b109cf3ad47b91120f8328d8ab1be8b0b956"
+ integrity sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==
+ dependencies:
+ "@babel/types" "^7.22.15"
+
+"@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6":
version "7.23.6"
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991"
integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==
@@ -75,12 +110,47 @@
lru-cache "^5.1.1"
semver "^6.3.1"
+"@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.6":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.0.tgz#fc7554141bdbfa2d17f7b4b80153b9b090e5d158"
+ integrity sha512-QAH+vfvts51BCsNZ2PhY6HAggnlS6omLLFTsIpeqZk/MmJ6cW7tgz5yRv0fMJThcr6FmbMrENh1RgrWPTYA76g==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-function-name" "^7.23.0"
+ "@babel/helper-member-expression-to-functions" "^7.23.0"
+ "@babel/helper-optimise-call-expression" "^7.22.5"
+ "@babel/helper-replace-supers" "^7.22.20"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ semver "^6.3.1"
+
+"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.15", "@babel/helper-create-regexp-features-plugin@^7.22.5":
+ version "7.22.15"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz#5ee90093914ea09639b01c711db0d6775e558be1"
+ integrity sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ regexpu-core "^5.3.1"
+ semver "^6.3.1"
+
+"@babel/helper-define-polyfill-provider@^0.5.0":
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz#465805b7361f461e86c680f1de21eaf88c25901b"
+ integrity sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.22.6"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ debug "^4.1.1"
+ lodash.debounce "^4.0.8"
+ resolve "^1.14.2"
+
"@babel/helper-environment-visitor@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
-"@babel/helper-function-name@^7.23.0":
+"@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
@@ -95,6 +165,13 @@
dependencies:
"@babel/types" "^7.22.5"
+"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0":
+ version "7.23.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366"
+ integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==
+ dependencies:
+ "@babel/types" "^7.23.0"
+
"@babel/helper-module-imports@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0"
@@ -113,11 +190,41 @@
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/helper-validator-identifier" "^7.22.20"
+"@babel/helper-optimise-call-expression@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e"
+ integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295"
integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
+"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.3":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a"
+ integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==
+
+"@babel/helper-remap-async-to-generator@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0"
+ integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-wrap-function" "^7.22.20"
+
+"@babel/helper-replace-supers@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793"
+ integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-member-expression-to-functions" "^7.22.15"
+ "@babel/helper-optimise-call-expression" "^7.22.5"
+
"@babel/helper-simple-access@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de"
@@ -125,6 +232,13 @@
dependencies:
"@babel/types" "^7.22.5"
+"@babel/helper-skip-transparent-expression-wrappers@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847"
+ integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
"@babel/helper-split-export-declaration@^7.22.6":
version "7.22.6"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
@@ -142,11 +256,20 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
-"@babel/helper-validator-option@^7.23.5":
+"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5":
version "7.23.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==
+"@babel/helper-wrap-function@^7.22.20":
+ version "7.22.20"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569"
+ integrity sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==
+ dependencies:
+ "@babel/helper-function-name" "^7.22.5"
+ "@babel/template" "^7.22.15"
+ "@babel/types" "^7.22.19"
+
"@babel/helpers@^7.23.9":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d"
@@ -156,6 +279,15 @@
"@babel/traverse" "^7.23.9"
"@babel/types" "^7.23.9"
+"@babel/helpers@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b"
+ integrity sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==
+ dependencies:
+ "@babel/template" "^7.24.0"
+ "@babel/traverse" "^7.24.0"
+ "@babel/types" "^7.24.0"
+
"@babel/highlight@^7.23.4":
version "7.23.4"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b"
@@ -170,6 +302,40 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b"
integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==
+"@babel/parser@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac"
+ integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==
+
+"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a"
+ integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d"
+ integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+ "@babel/plugin-transform-optional-chaining" "^7.23.3"
+
+"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7":
+ version "7.23.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b"
+ integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2":
+ version "7.21.0-placeholder-for-preset-env.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
+ integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
+
"@babel/plugin-syntax-async-generators@^7.8.4":
version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
@@ -184,14 +350,49 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
-"@babel/plugin-syntax-class-properties@^7.8.3":
+"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
-"@babel/plugin-syntax-import-meta@^7.8.3":
+"@babel/plugin-syntax-class-static-block@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406"
+ integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-dynamic-import@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
+ integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-export-namespace-from@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a"
+ integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.3"
+
+"@babel/plugin-syntax-import-assertions@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc"
+ integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-import-attributes@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz#992aee922cf04512461d7dae3ff6951b90a2dc06"
+ integrity sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==
@@ -205,14 +406,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
-"@babel/plugin-syntax-jsx@^7.7.2":
+"@babel/plugin-syntax-jsx@^7.23.3", "@babel/plugin-syntax-jsx@^7.7.2":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473"
integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
-"@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
+"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
@@ -226,7 +427,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
-"@babel/plugin-syntax-numeric-separator@^7.8.3":
+"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
@@ -254,20 +455,544 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
-"@babel/plugin-syntax-top-level-await@^7.8.3":
+"@babel/plugin-syntax-private-property-in-object@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad"
+ integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
-"@babel/plugin-syntax-typescript@^7.7.2":
+"@babel/plugin-syntax-typescript@^7.23.3", "@babel/plugin-syntax-typescript@^7.7.2":
version "7.23.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f"
integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==
dependencies:
"@babel/helper-plugin-utils" "^7.22.5"
+"@babel/plugin-syntax-unicode-sets-regex@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357"
+ integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-arrow-functions@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b"
+ integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-async-generator-functions@^7.23.9":
+ version "7.23.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz#9adaeb66fc9634a586c5df139c6240d41ed801ce"
+ integrity sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-remap-async-to-generator" "^7.22.20"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+
+"@babel/plugin-transform-async-to-generator@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa"
+ integrity sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-remap-async-to-generator" "^7.22.20"
+
+"@babel/plugin-transform-block-scoped-functions@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77"
+ integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-block-scoping@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5"
+ integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-class-properties@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz#35c377db11ca92a785a718b6aa4e3ed1eb65dc48"
+ integrity sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-class-static-block@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz#2a202c8787a8964dd11dfcedf994d36bfc844ab5"
+ integrity sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+
+"@babel/plugin-transform-classes@^7.23.8":
+ version "7.23.8"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92"
+ integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-compilation-targets" "^7.23.6"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-function-name" "^7.23.0"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-replace-supers" "^7.22.20"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474"
+ integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/template" "^7.22.15"
+
+"@babel/plugin-transform-destructuring@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311"
+ integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-dotall-regex@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50"
+ integrity sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-duplicate-keys@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce"
+ integrity sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-dynamic-import@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz#c7629e7254011ac3630d47d7f34ddd40ca535143"
+ integrity sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+
+"@babel/plugin-transform-exponentiation-operator@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18"
+ integrity sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==
+ dependencies:
+ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-export-namespace-from@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz#084c7b25e9a5c8271e987a08cf85807b80283191"
+ integrity sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+
+"@babel/plugin-transform-for-of@^7.23.6":
+ version "7.23.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e"
+ integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+
+"@babel/plugin-transform-function-name@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc"
+ integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.22.15"
+ "@babel/helper-function-name" "^7.23.0"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-json-strings@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz#a871d9b6bd171976efad2e43e694c961ffa3714d"
+ integrity sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+
+"@babel/plugin-transform-literals@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4"
+ integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-logical-assignment-operators@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz#e599f82c51d55fac725f62ce55d3a0886279ecb5"
+ integrity sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+
+"@babel/plugin-transform-member-expression-literals@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc"
+ integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-modules-amd@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d"
+ integrity sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.23.3"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-modules-commonjs@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4"
+ integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.23.3"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-simple-access" "^7.22.5"
+
+"@babel/plugin-transform-modules-systemjs@^7.23.9":
+ version "7.23.9"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz#105d3ed46e4a21d257f83a2f9e2ee4203ceda6be"
+ integrity sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.22.5"
+ "@babel/helper-module-transforms" "^7.23.3"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.20"
+
+"@babel/plugin-transform-modules-umd@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9"
+ integrity sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.23.3"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f"
+ integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-new-target@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980"
+ integrity sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-nullish-coalescing-operator@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz#45556aad123fc6e52189ea749e33ce090637346e"
+ integrity sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+
+"@babel/plugin-transform-numeric-separator@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz#03d08e3691e405804ecdd19dd278a40cca531f29"
+ integrity sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+
+"@babel/plugin-transform-object-rest-spread@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.0.tgz#7b836ad0088fdded2420ce96d4e1d3ed78b71df1"
+ integrity sha512-y/yKMm7buHpFFXfxVFS4Vk1ToRJDilIa6fKRioB9Vjichv58TDGXTvqV0dN7plobAmTW5eSEGXDngE+Mm+uO+w==
+ dependencies:
+ "@babel/compat-data" "^7.23.5"
+ "@babel/helper-compilation-targets" "^7.23.6"
+ "@babel/helper-plugin-utils" "^7.24.0"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-transform-parameters" "^7.23.3"
+
+"@babel/plugin-transform-object-super@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd"
+ integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-replace-supers" "^7.22.20"
+
+"@babel/plugin-transform-optional-catch-binding@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz#318066de6dacce7d92fa244ae475aa8d91778017"
+ integrity sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+
+"@babel/plugin-transform-optional-chaining@^7.23.3", "@babel/plugin-transform-optional-chaining@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017"
+ integrity sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+
+"@babel/plugin-transform-parameters@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af"
+ integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-private-methods@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz#b2d7a3c97e278bfe59137a978d53b2c2e038c0e4"
+ integrity sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-private-property-in-object@^7.23.4":
+ version "7.23.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz#3ec711d05d6608fd173d9b8de39872d8dbf68bf5"
+ integrity sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-create-class-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+
+"@babel/plugin-transform-property-literals@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875"
+ integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-regenerator@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz#141afd4a2057298602069fce7f2dc5173e6c561c"
+ integrity sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ regenerator-transform "^0.15.2"
+
+"@babel/plugin-transform-reserved-words@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8"
+ integrity sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-shorthand-properties@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210"
+ integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-spread@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c"
+ integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+
+"@babel/plugin-transform-sticky-regex@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04"
+ integrity sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-template-literals@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07"
+ integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-typeof-symbol@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4"
+ integrity sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-typescript@^7.23.3":
+ version "7.23.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.6.tgz#aa36a94e5da8d94339ae3a4e22d40ed287feb34c"
+ integrity sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-create-class-features-plugin" "^7.23.6"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-typescript" "^7.23.3"
+
+"@babel/plugin-transform-unicode-escapes@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925"
+ integrity sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-unicode-property-regex@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz#19e234129e5ffa7205010feec0d94c251083d7ad"
+ integrity sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-unicode-regex@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc"
+ integrity sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-unicode-sets-regex@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz#4fb6f0a719c2c5859d11f6b55a050cc987f3799e"
+ integrity sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.15"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/preset-env@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.0.tgz#11536a7f4b977294f0bdfad780f01a8ac8e183fc"
+ integrity sha512-ZxPEzV9IgvGn73iK0E6VB9/95Nd7aMFpbE0l8KQFDG70cOV9IxRP7Y2FUPmlK0v6ImlLqYX50iuZ3ZTVhOF2lA==
+ dependencies:
+ "@babel/compat-data" "^7.23.5"
+ "@babel/helper-compilation-targets" "^7.23.6"
+ "@babel/helper-plugin-utils" "^7.24.0"
+ "@babel/helper-validator-option" "^7.23.5"
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.23.3"
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.23.3"
+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.23.7"
+ "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-class-properties" "^7.12.13"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+ "@babel/plugin-syntax-import-assertions" "^7.23.3"
+ "@babel/plugin-syntax-import-attributes" "^7.23.3"
+ "@babel/plugin-syntax-import-meta" "^7.10.4"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+ "@babel/plugin-syntax-top-level-await" "^7.14.5"
+ "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6"
+ "@babel/plugin-transform-arrow-functions" "^7.23.3"
+ "@babel/plugin-transform-async-generator-functions" "^7.23.9"
+ "@babel/plugin-transform-async-to-generator" "^7.23.3"
+ "@babel/plugin-transform-block-scoped-functions" "^7.23.3"
+ "@babel/plugin-transform-block-scoping" "^7.23.4"
+ "@babel/plugin-transform-class-properties" "^7.23.3"
+ "@babel/plugin-transform-class-static-block" "^7.23.4"
+ "@babel/plugin-transform-classes" "^7.23.8"
+ "@babel/plugin-transform-computed-properties" "^7.23.3"
+ "@babel/plugin-transform-destructuring" "^7.23.3"
+ "@babel/plugin-transform-dotall-regex" "^7.23.3"
+ "@babel/plugin-transform-duplicate-keys" "^7.23.3"
+ "@babel/plugin-transform-dynamic-import" "^7.23.4"
+ "@babel/plugin-transform-exponentiation-operator" "^7.23.3"
+ "@babel/plugin-transform-export-namespace-from" "^7.23.4"
+ "@babel/plugin-transform-for-of" "^7.23.6"
+ "@babel/plugin-transform-function-name" "^7.23.3"
+ "@babel/plugin-transform-json-strings" "^7.23.4"
+ "@babel/plugin-transform-literals" "^7.23.3"
+ "@babel/plugin-transform-logical-assignment-operators" "^7.23.4"
+ "@babel/plugin-transform-member-expression-literals" "^7.23.3"
+ "@babel/plugin-transform-modules-amd" "^7.23.3"
+ "@babel/plugin-transform-modules-commonjs" "^7.23.3"
+ "@babel/plugin-transform-modules-systemjs" "^7.23.9"
+ "@babel/plugin-transform-modules-umd" "^7.23.3"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5"
+ "@babel/plugin-transform-new-target" "^7.23.3"
+ "@babel/plugin-transform-nullish-coalescing-operator" "^7.23.4"
+ "@babel/plugin-transform-numeric-separator" "^7.23.4"
+ "@babel/plugin-transform-object-rest-spread" "^7.24.0"
+ "@babel/plugin-transform-object-super" "^7.23.3"
+ "@babel/plugin-transform-optional-catch-binding" "^7.23.4"
+ "@babel/plugin-transform-optional-chaining" "^7.23.4"
+ "@babel/plugin-transform-parameters" "^7.23.3"
+ "@babel/plugin-transform-private-methods" "^7.23.3"
+ "@babel/plugin-transform-private-property-in-object" "^7.23.4"
+ "@babel/plugin-transform-property-literals" "^7.23.3"
+ "@babel/plugin-transform-regenerator" "^7.23.3"
+ "@babel/plugin-transform-reserved-words" "^7.23.3"
+ "@babel/plugin-transform-shorthand-properties" "^7.23.3"
+ "@babel/plugin-transform-spread" "^7.23.3"
+ "@babel/plugin-transform-sticky-regex" "^7.23.3"
+ "@babel/plugin-transform-template-literals" "^7.23.3"
+ "@babel/plugin-transform-typeof-symbol" "^7.23.3"
+ "@babel/plugin-transform-unicode-escapes" "^7.23.3"
+ "@babel/plugin-transform-unicode-property-regex" "^7.23.3"
+ "@babel/plugin-transform-unicode-regex" "^7.23.3"
+ "@babel/plugin-transform-unicode-sets-regex" "^7.23.3"
+ "@babel/preset-modules" "0.1.6-no-external-plugins"
+ babel-plugin-polyfill-corejs2 "^0.4.8"
+ babel-plugin-polyfill-corejs3 "^0.9.0"
+ babel-plugin-polyfill-regenerator "^0.5.5"
+ core-js-compat "^3.31.0"
+ semver "^6.3.1"
+
+"@babel/preset-modules@0.1.6-no-external-plugins":
+ version "0.1.6-no-external-plugins"
+ resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a"
+ integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/types" "^7.4.4"
+ esutils "^2.0.2"
+
+"@babel/preset-typescript@^7.23.3":
+ version "7.23.3"
+ resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz#14534b34ed5b6d435aa05f1ae1c5e7adcc01d913"
+ integrity sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-validator-option" "^7.22.15"
+ "@babel/plugin-syntax-jsx" "^7.23.3"
+ "@babel/plugin-transform-modules-commonjs" "^7.23.3"
+ "@babel/plugin-transform-typescript" "^7.23.3"
+
+"@babel/regjsgen@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
+ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
+
"@babel/runtime@^7.12.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.21.0":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
@@ -275,6 +1000,13 @@
dependencies:
regenerator-runtime "^0.14.0"
+"@babel/runtime@^7.8.4":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.0.tgz#584c450063ffda59697021430cb47101b085951e"
+ integrity sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
"@babel/template@^7.22.15", "@babel/template@^7.23.9", "@babel/template@^7.3.3":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a"
@@ -284,6 +1016,15 @@
"@babel/parser" "^7.23.9"
"@babel/types" "^7.23.9"
+"@babel/template@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
+ integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==
+ dependencies:
+ "@babel/code-frame" "^7.23.5"
+ "@babel/parser" "^7.24.0"
+ "@babel/types" "^7.24.0"
+
"@babel/traverse@^7.23.9":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950"
@@ -300,6 +1041,22 @@
debug "^4.3.1"
globals "^11.1.0"
+"@babel/traverse@^7.24.0":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e"
+ integrity sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==
+ dependencies:
+ "@babel/code-frame" "^7.23.5"
+ "@babel/generator" "^7.23.6"
+ "@babel/helper-environment-visitor" "^7.22.20"
+ "@babel/helper-function-name" "^7.23.0"
+ "@babel/helper-hoist-variables" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.6"
+ "@babel/parser" "^7.24.0"
+ "@babel/types" "^7.24.0"
+ debug "^4.3.1"
+ globals "^11.1.0"
+
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.3.3":
version "7.23.9"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002"
@@ -309,6 +1066,15 @@
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
+"@babel/types@^7.22.19", "@babel/types@^7.24.0", "@babel/types@^7.4.4":
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf"
+ integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==
+ dependencies:
+ "@babel/helper-string-parser" "^7.23.4"
+ "@babel/helper-validator-identifier" "^7.22.20"
+ to-fast-properties "^2.0.0"
+
"@balena/dockerignore@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@balena/dockerignore/-/dockerignore-1.0.2.tgz#9ffe4726915251e8eb69f44ef3547e0da2c03e0d"
@@ -1926,6 +2692,30 @@ babel-plugin-jest-hoist@^29.6.3:
"@types/babel__core" "^7.1.14"
"@types/babel__traverse" "^7.0.6"
+babel-plugin-polyfill-corejs2@^0.4.8:
+ version "0.4.8"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz#dbcc3c8ca758a290d47c3c6a490d59429b0d2269"
+ integrity sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==
+ dependencies:
+ "@babel/compat-data" "^7.22.6"
+ "@babel/helper-define-polyfill-provider" "^0.5.0"
+ semver "^6.3.1"
+
+babel-plugin-polyfill-corejs3@^0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz#9eea32349d94556c2ad3ab9b82ebb27d4bf04a81"
+ integrity sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.5.0"
+ core-js-compat "^3.34.0"
+
+babel-plugin-polyfill-regenerator@^0.5.5:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz#8b0c8fc6434239e5d7b8a9d1f832bb2b0310f06a"
+ integrity sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.5.0"
+
babel-preset-current-node-syntax@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
@@ -2068,7 +2858,7 @@ braces@^3.0.2, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
-browserslist@^4.22.2:
+browserslist@^4.22.2, browserslist@^4.22.3:
version "4.23.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab"
integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
@@ -2078,13 +2868,6 @@ browserslist@^4.22.2:
node-releases "^2.0.14"
update-browserslist-db "^1.0.13"
-bs-logger@0.x:
- version "0.2.6"
- resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
- integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==
- dependencies:
- fast-json-stable-stringify "2.x"
-
bser@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
@@ -2469,6 +3252,13 @@ cookie@~0.4.1:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
+core-js-compat@^3.31.0, core-js-compat@^3.34.0:
+ version "3.36.0"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.0.tgz#087679119bc2fdbdefad0d45d8e5d307d45ba190"
+ integrity sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==
+ dependencies:
+ browserslist "^4.22.3"
+
core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -3500,7 +4290,7 @@ fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1:
merge2 "^1.3.0"
micromatch "^4.0.4"
-fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
+fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
@@ -4665,7 +5455,7 @@ jest-snapshot@^29.7.0:
pretty-format "^29.7.0"
semver "^7.5.3"
-jest-util@^29.0.0, jest-util@^29.7.0:
+jest-util@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc"
integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==
@@ -4758,6 +5548,11 @@ jsesc@^2.5.1:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+jsesc@~0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+ integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
+
json-buffer@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
@@ -4947,6 +5742,11 @@ lodash-es@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+lodash.debounce@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+ integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
+
lodash.includes@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
@@ -4977,11 +5777,6 @@ lodash.isstring@^4.0.1:
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
-lodash.memoize@4.x:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
- integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==
-
lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -5094,7 +5889,7 @@ make-dir@^4.0.0:
dependencies:
semver "^7.5.3"
-make-error@1.x, make-error@^1.1.1:
+make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
@@ -5995,11 +6790,30 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"
+regenerate-unicode-properties@^10.1.0:
+ version "10.1.1"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480"
+ integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==
+ dependencies:
+ regenerate "^1.4.2"
+
+regenerate@^1.4.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
+ integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
+
regenerator-runtime@^0.14.0:
version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
+regenerator-transform@^0.15.2:
+ version "0.15.2"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4"
+ integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==
+ dependencies:
+ "@babel/runtime" "^7.8.4"
+
regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334"
@@ -6015,6 +6829,25 @@ regexpp@^3.0.0:
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
+regexpu-core@^5.3.1:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b"
+ integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==
+ dependencies:
+ "@babel/regjsgen" "^0.8.0"
+ regenerate "^1.4.2"
+ regenerate-unicode-properties "^10.1.0"
+ regjsparser "^0.9.1"
+ unicode-match-property-ecmascript "^2.0.0"
+ unicode-match-property-value-ecmascript "^2.1.0"
+
+regjsparser@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709"
+ integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==
+ dependencies:
+ jsesc "~0.5.0"
+
request-progress@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe"
@@ -6059,7 +6892,7 @@ resolve.exports@^2.0.0:
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800"
integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==
-resolve@^1.1.7, resolve@^1.10.1, resolve@^1.20.0, resolve@^1.22.2, resolve@^1.22.4:
+resolve@^1.1.7, resolve@^1.10.1, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.2, resolve@^1.22.4:
version "1.22.8"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
@@ -6792,20 +7625,6 @@ ts-interface-checker@^0.1.9:
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
-ts-jest@^29.1.1:
- version "29.1.2"
- resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09"
- integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==
- dependencies:
- bs-logger "0.x"
- fast-json-stable-stringify "2.x"
- jest-util "^29.0.0"
- json5 "^2.2.3"
- lodash.memoize "4.x"
- make-error "1.x"
- semver "^7.5.3"
- yargs-parser "^21.0.1"
-
ts-node@^10.9.2:
version "10.9.2"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
@@ -6978,6 +7797,29 @@ undici-types@~5.26.4:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+unicode-canonical-property-names-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
+ integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==
+
+unicode-match-property-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3"
+ integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==
+ dependencies:
+ unicode-canonical-property-names-ecmascript "^2.0.0"
+ unicode-property-aliases-ecmascript "^2.0.0"
+
+unicode-match-property-value-ecmascript@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0"
+ integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==
+
+unicode-property-aliases-ecmascript@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"
+ integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==
+
universalify@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
@@ -7341,7 +8183,7 @@ yaml@^2.3.1, yaml@^2.3.4:
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2"
integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==
-yargs-parser@^21.0.1, yargs-parser@^21.1.1:
+yargs-parser@^21.1.1:
version "21.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
From 6967e230d0caf3e8811569fc48bbab99e69d7057 Mon Sep 17 00:00:00 2001
From: wancat
Date: Thu, 29 Feb 2024 00:33:41 +0800
Subject: [PATCH 04/82] feat: enable swc and ts-node in server dev
---
server/nodemon.json | 5 +--
server/package.json | 6 ++-
server/tsconfig.json | 5 ++-
yarn.lock | 90 +++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 99 insertions(+), 7 deletions(-)
diff --git a/server/nodemon.json b/server/nodemon.json
index c61d2d2..0fdaf66 100644
--- a/server/nodemon.json
+++ b/server/nodemon.json
@@ -1,6 +1,5 @@
{
- "watch": ["dist", "swagger.yaml", "../quests", "../packages"],
+ "watch": ["src", "swagger.yaml", "../quests", "../packages"],
"ext": "js,ts,yaml,yml",
- "exec": "node -r source-map-support/register dist/index.js",
- "delay": 200
+ "exec": "node --loader ts-node/esm src/index.js"
}
diff --git a/server/package.json b/server/package.json
index 02b10c7..884d244 100644
--- a/server/package.json
+++ b/server/package.json
@@ -8,7 +8,7 @@
"setup": "node dist/cli/setup.js",
"clean": "node dist/cli/clean.js",
"build": "tsc -b",
- "dev": "concurrently \"tsc -b --watch\" \"sleep 5 && nodemon\"",
+ "dev": "nodemon",
"build:quests": "node dist/cli/build.js"
},
"dependencies": {
@@ -44,6 +44,8 @@
"yaml": "^2.3.1"
},
"devDependencies": {
+ "@swc/core": "^1.4.2",
+ "@swc/helpers": "^0.5.6",
"@types/bcrypt": "^5.0.2",
"@types/dockerode": "^3.3.23",
"@types/express": "^4.17.21",
@@ -62,7 +64,9 @@
"concurrently": "^8.2.2",
"jest": "^29.6.1",
"nodemon": "^3.0.1",
+ "regenerator-runtime": "^0.14.1",
"source-map-support": "^0.5.21",
+ "ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}
diff --git a/server/tsconfig.json b/server/tsconfig.json
index 321fdda..6868620 100644
--- a/server/tsconfig.json
+++ b/server/tsconfig.json
@@ -10,5 +10,8 @@
{ "path": "../packages/file-graph" },
{ "path": "../packages/models" },
{ "path": "../packages/utils" }
- ]
+ ],
+ "ts-node": {
+ "swc": true
+ }
}
diff --git a/yarn.lock b/yarn.lock
index 01f5d1d..e4ed895 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1679,6 +1679,92 @@
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
+"@swc/core-darwin-arm64@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.2.tgz#3b5677c5b9c5a7a91d953b96cd603c94064e2835"
+ integrity sha512-1uSdAn1MRK5C1m/TvLZ2RDvr0zLvochgrZ2xL+lRzugLlCTlSA+Q4TWtrZaOz+vnnFVliCpw7c7qu0JouhgQIw==
+
+"@swc/core-darwin-x64@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.4.2.tgz#bbc8bbf420389b12541151255a50f319cc17ef96"
+ integrity sha512-TYD28+dCQKeuxxcy7gLJUCFLqrwDZnHtC2z7cdeGfZpbI2mbfppfTf2wUPzqZk3gEC96zHd4Yr37V3Tvzar+lQ==
+
+"@swc/core-linux-arm-gnueabihf@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.2.tgz#aa9a18f130820717df08c9dd882043fc47e8d35a"
+ integrity sha512-Eyqipf7ZPGj0vplKHo8JUOoU1un2sg5PjJMpEesX0k+6HKE2T8pdyeyXODN0YTFqzndSa/J43EEPXm+rHAsLFQ==
+
+"@swc/core-linux-arm64-gnu@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.2.tgz#5ef1de0ca7cc3a034aa3a1c3c1794b78e6ca207e"
+ integrity sha512-wZn02DH8VYPv3FC0ub4my52Rttsus/rFw+UUfzdb3tHMHXB66LqN+rR0ssIOZrH6K+VLN6qpTw9VizjyoH0BxA==
+
+"@swc/core-linux-arm64-musl@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.2.tgz#5dfd2a8c0483770a307de0ccb6019a082ff0d902"
+ integrity sha512-3G0D5z9hUj9bXNcwmA1eGiFTwe5rWkuL3DsoviTj73TKLpk7u64ND0XjEfO0huVv4vVu9H1jodrKb7nvln/dlw==
+
+"@swc/core-linux-x64-gnu@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.2.tgz#314aa76b7c1208e315e3156ab57b7188fb605bc2"
+ integrity sha512-LFxn9U8cjmYHw3jrdPNqPAkBGglKE3tCZ8rA7hYyp0BFxuo7L2ZcEnPm4RFpmSCCsExFH+LEJWuMGgWERoktvg==
+
+"@swc/core-linux-x64-musl@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.2.tgz#b2b226657f6a8d48f561cb3dbe2d414cfbafe467"
+ integrity sha512-dp0fAmreeVVYTUcb4u9njTPrYzKnbIH0EhH2qvC9GOYNNREUu2GezSIDgonjOXkHiTCvopG4xU7y56XtXj4VrQ==
+
+"@swc/core-win32-arm64-msvc@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.2.tgz#582f79fa328ce0f426ab8313b3d881e7315fab2f"
+ integrity sha512-HlVIiLMQkzthAdqMslQhDkoXJ5+AOLUSTV6fm6shFKZKqc/9cJvr4S8UveNERL9zUficA36yM3bbfo36McwnvQ==
+
+"@swc/core-win32-ia32-msvc@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.2.tgz#15c8289e1c18857f79b9b888100ab1f871bf58f6"
+ integrity sha512-WCF8faPGjCl4oIgugkp+kL9nl3nUATlzKXCEGFowMEmVVCFM0GsqlmGdPp1pjZoWc9tpYanoXQDnp5IvlDSLhA==
+
+"@swc/core-win32-x64-msvc@1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.2.tgz#c999ca7b68124d058b40a1431cdd6f56779670d5"
+ integrity sha512-oV71rwiSpA5xre2C5570BhCsg1HF97SNLsZ/12xv7zayGzqr3yvFALFJN8tHKpqUdCB4FGPjoP3JFdV3i+1wUw==
+
+"@swc/core@^1.4.2":
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.2.tgz#310b0d5e93e47ca72f54150c8f9efcb434c39b17"
+ integrity sha512-vWgY07R/eqj1/a0vsRKLI9o9klGZfpLNOVEnrv4nrccxBgYPjcf22IWwAoaBJ+wpA7Q4fVjCUM8lP0m01dpxcg==
+ dependencies:
+ "@swc/counter" "^0.1.2"
+ "@swc/types" "^0.1.5"
+ optionalDependencies:
+ "@swc/core-darwin-arm64" "1.4.2"
+ "@swc/core-darwin-x64" "1.4.2"
+ "@swc/core-linux-arm-gnueabihf" "1.4.2"
+ "@swc/core-linux-arm64-gnu" "1.4.2"
+ "@swc/core-linux-arm64-musl" "1.4.2"
+ "@swc/core-linux-x64-gnu" "1.4.2"
+ "@swc/core-linux-x64-musl" "1.4.2"
+ "@swc/core-win32-arm64-msvc" "1.4.2"
+ "@swc/core-win32-ia32-msvc" "1.4.2"
+ "@swc/core-win32-x64-msvc" "1.4.2"
+
+"@swc/counter@^0.1.2":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9"
+ integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==
+
+"@swc/helpers@^0.5.6":
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.6.tgz#d16d8566b7aea2bef90d059757e2d77f48224160"
+ integrity sha512-aYX01Ke9hunpoCexYAgQucEpARGQ5w/cqHFrIR+e9gdKb1QWTsVJuTJ2ozQzIAxLyRQe/m+2RqzkyOOGiMKRQA==
+ dependencies:
+ tslib "^2.4.0"
+
+"@swc/types@^0.1.5":
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.5.tgz#043b731d4f56a79b4897a3de1af35e75d56bc63a"
+ integrity sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==
+
"@testing-library/cypress@^10.0.1":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-10.0.1.tgz#15abae0edb83237316ec6d07e152b71a50b38387"
@@ -6802,7 +6888,7 @@ regenerate@^1.4.2:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
-regenerator-runtime@^0.14.0:
+regenerator-runtime@^0.14.0, regenerator-runtime@^0.14.1:
version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
@@ -7659,7 +7745,7 @@ tslib@2.3.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
-tslib@^2.1.0, tslib@^2.6.2:
+tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
From 3b4a808131d806a07ba02c203443184d02b37a0a Mon Sep 17 00:00:00 2001
From: wancat
Date: Wed, 6 Mar 2024 23:06:52 +0800
Subject: [PATCH 05/82] feat: create pattern and command matcher
---
.eslintrc.js | 2 ++
packages/game/src/command.ts | 6 ++++
packages/game/src/condition.ts | 36 +++++++++++++++++++++++
packages/game/src/matcher.ts | 5 ++++
packages/game/test/condition.test.ts | 43 ++++++++++++++++++++++++++++
5 files changed, 92 insertions(+)
create mode 100644 packages/game/src/command.ts
create mode 100644 packages/game/src/condition.ts
create mode 100644 packages/game/src/matcher.ts
create mode 100644 packages/game/test/condition.test.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index d177747..b323dbd 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -60,6 +60,8 @@ module.exports = {
tsx: 'never',
},
],
+ 'no-unused-vars': 'off',
+ '@typescript-eslint/no-unused-vars': 'error',
},
overrides: [
{
diff --git a/packages/game/src/command.ts b/packages/game/src/command.ts
new file mode 100644
index 0000000..6faf783
--- /dev/null
+++ b/packages/game/src/command.ts
@@ -0,0 +1,6 @@
+export interface Command {
+ command: string
+ output: string
+ error: string
+ pwd: string
+}
diff --git a/packages/game/src/condition.ts b/packages/game/src/condition.ts
new file mode 100644
index 0000000..7a050b2
--- /dev/null
+++ b/packages/game/src/condition.ts
@@ -0,0 +1,36 @@
+/* eslint-disable max-classes-per-file */
+import { Command } from './command'
+import { Matcher } from './matcher'
+
+export class PatternMatcher {
+ protected matcher: RegExp | null
+ constructor(pattern?: string, args?: string) {
+ this.matcher = pattern ? new RegExp(pattern, args) : null
+ }
+
+ test(input: string): boolean {
+ if (!this.matcher) {
+ return true
+ }
+ return this.matcher.test(input)
+ }
+}
+
+export class CommandMatcher extends PatternMatcher implements Matcher {
+ match(command: Partial): boolean {
+ return !!command.command && this.test(command.command)
+ }
+}
+
+export class ErrorMatcher extends PatternMatcher implements Matcher {
+ match(command: Partial): boolean {
+ if (!this.matcher) {
+ return command.error === ''
+ }
+ return !!command.error && this.test(command.error)
+ }
+}
+
+export class Condition {
+ private matchers: Matcher[] = []
+}
diff --git a/packages/game/src/matcher.ts b/packages/game/src/matcher.ts
new file mode 100644
index 0000000..b1de51d
--- /dev/null
+++ b/packages/game/src/matcher.ts
@@ -0,0 +1,5 @@
+import { Command } from './command'
+
+export interface Matcher {
+ match(command: Partial): boolean
+}
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
new file mode 100644
index 0000000..e6a9f6c
--- /dev/null
+++ b/packages/game/test/condition.test.ts
@@ -0,0 +1,43 @@
+import { test, expect } from '@jest/globals'
+import { PatternMatcher, CommandMatcher, ErrorMatcher } from '../src/condition'
+import { Command } from '../src/command'
+
+test('pattern match', () => {
+ const matcher = new PatternMatcher('^echo start$')
+
+ expect(matcher.test('echo start')).toBe(true)
+ expect(matcher.test('echo start ')).toBe(false)
+})
+
+test('pattern match with flag', () => {
+ const matcher = new PatternMatcher('^echo start$', 'i')
+
+ expect(matcher.test('echo start')).toBe(true)
+ expect(matcher.test('echo Start')).toBe(true)
+ expect(matcher.test('echo Start ')).toBe(false)
+})
+
+test('empty pattern return true', () => {
+ const matcher = new PatternMatcher('')
+ expect(matcher.test('echo start')).toBe(true)
+})
+
+test('empty error return false', () => {
+ const matcher = new ErrorMatcher()
+ expect(matcher.match({ error: '' })).toBe(true)
+ expect(matcher.match({ error: 'permission denied' })).toBe(false)
+})
+
+test('command match', () => {
+ const command: Command = {
+ command: 'echo start',
+ output: 'start',
+ error: '',
+ pwd: '/home/user',
+ }
+
+ const matcher = new CommandMatcher('^echo start$', 'i')
+ expect(matcher.match(command)).toBe(true)
+})
+
+test('condition match', () => {})
From 9eb08b45f4b4e3ff5dcfb4feaad8ab1be7498f00 Mon Sep 17 00:00:00 2001
From: wancat
Date: Wed, 6 Mar 2024 23:28:28 +0800
Subject: [PATCH 06/82] feat: add pwdmatcher and update error matcher
---
.eslintrc.js | 2 +
packages/game/src/condition.ts | 37 ++++++++++++++----
packages/game/test/condition.test.ts | 57 ++++++++++++++++++++++++----
3 files changed, 81 insertions(+), 15 deletions(-)
diff --git a/.eslintrc.js b/.eslintrc.js
index b323dbd..c8110a1 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -62,6 +62,8 @@ module.exports = {
],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'error',
+ 'no-useless-constructor': 'off',
+ '@typescript-eslint/no-useless-constructor': 'error',
},
overrides: [
{
diff --git a/packages/game/src/condition.ts b/packages/game/src/condition.ts
index 7a050b2..b3d65f0 100644
--- a/packages/game/src/condition.ts
+++ b/packages/game/src/condition.ts
@@ -3,15 +3,12 @@ import { Command } from './command'
import { Matcher } from './matcher'
export class PatternMatcher {
- protected matcher: RegExp | null
- constructor(pattern?: string, args?: string) {
- this.matcher = pattern ? new RegExp(pattern, args) : null
+ protected matcher: RegExp
+ constructor(pattern: string, args?: string) {
+ this.matcher = new RegExp(pattern, args)
}
test(input: string): boolean {
- if (!this.matcher) {
- return true
- }
return this.matcher.test(input)
}
}
@@ -23,14 +20,40 @@ export class CommandMatcher extends PatternMatcher implements Matcher {
}
export class ErrorMatcher extends PatternMatcher implements Matcher {
+ constructor(private errorPattern?: string) {
+ super(errorPattern || '')
+ }
+
match(command: Partial): boolean {
- if (!this.matcher) {
+ if (!this.errorPattern) {
return command.error === ''
}
return !!command.error && this.test(command.error)
}
}
+export class PwdMatcher implements Matcher {
+ constructor(private pwd: string) {}
+
+ match(command: Partial): boolean {
+ return command.pwd === this.pwd
+ }
+}
+
+export interface ICondition {
+ command?: string
+ output?: string
+ error?: string
+ pwd?: string
+}
+
export class Condition {
private matchers: Matcher[] = []
+
+ constructor({ command, output, error, pwd }: ICondition) {
+ if (command) this.matchers.push(new CommandMatcher(command))
+ // if (output) this.matchers.push(new OutputMatcher(output))
+ if (pwd) this.matchers.push(new PwdMatcher(pwd))
+ this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
+ }
}
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index e6a9f6c..e513de6 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -1,5 +1,11 @@
import { test, expect } from '@jest/globals'
-import { PatternMatcher, CommandMatcher, ErrorMatcher } from '../src/condition'
+import {
+ PatternMatcher,
+ CommandMatcher,
+ ErrorMatcher,
+ PwdMatcher,
+ Condition,
+} from '../src/condition'
import { Command } from '../src/command'
test('pattern match', () => {
@@ -22,12 +28,6 @@ test('empty pattern return true', () => {
expect(matcher.test('echo start')).toBe(true)
})
-test('empty error return false', () => {
- const matcher = new ErrorMatcher()
- expect(matcher.match({ error: '' })).toBe(true)
- expect(matcher.match({ error: 'permission denied' })).toBe(false)
-})
-
test('command match', () => {
const command: Command = {
command: 'echo start',
@@ -40,4 +40,45 @@ test('command match', () => {
expect(matcher.match(command)).toBe(true)
})
-test('condition match', () => {})
+test('error matcher', () => {
+ const matcher = new ErrorMatcher()
+ expect(matcher.match({ error: '' })).toBe(true)
+ expect(matcher.match({ error: 'permission denied' })).toBe(false)
+})
+
+test('error matcher with specific error', () => {
+ const matcher = new ErrorMatcher('permission denied')
+ expect(matcher.match({ error: '' })).toBe(false)
+ expect(matcher.match({ error: 'file not found' })).toBe(false)
+ expect(matcher.match({ error: 'cannot open files: permission denied' })).toBe(
+ true
+ )
+})
+
+test('pwd matcher', () => {
+ const matcher = new PwdMatcher('/home/user')
+ expect(matcher.match({ pwd: '/home/user' })).toBe(true)
+ expect(matcher.match({ pwd: '/home/user1' })).toBe(false)
+ expect(matcher.match({ pwd: '/home/user/anotherpath' })).toBe(false)
+ expect(matcher.match({ pwd: '/var/home/user' })).toBe(false)
+})
+
+// test('condition match', () => {
+// const condition = new Condition({
+// command: '^echo start$',
+// pwd: '/home/user',
+// })
+
+// expect(
+// condition.match({
+// command: 'echo start',
+// pwd: '/home/user',
+// })
+// ).toBe(true)
+// expect(
+// condition.match({
+// command: 'echo start',
+// pwd: '/home/user1',
+// })
+// ).toBe(false)
+// })
From cb26e1dcb0cc250e165faefa2461ab77489009fa Mon Sep 17 00:00:00 2001
From: wancat
Date: Wed, 6 Mar 2024 23:32:23 +0800
Subject: [PATCH 07/82] feat: add output matcher
---
packages/game/src/condition.ts | 6 ++++++
packages/game/test/condition.test.ts | 8 ++++++++
2 files changed, 14 insertions(+)
diff --git a/packages/game/src/condition.ts b/packages/game/src/condition.ts
index b3d65f0..c5febc9 100644
--- a/packages/game/src/condition.ts
+++ b/packages/game/src/condition.ts
@@ -40,6 +40,12 @@ export class PwdMatcher implements Matcher {
}
}
+export class OutputMatcher extends PatternMatcher implements Matcher {
+ match(command: Partial): boolean {
+ return command.output ? this.test(command.output.trim()) : false
+ }
+}
+
export interface ICondition {
command?: string
output?: string
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index e513de6..358f388 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -4,6 +4,7 @@ import {
CommandMatcher,
ErrorMatcher,
PwdMatcher,
+ OutputMatcher,
Condition,
} from '../src/condition'
import { Command } from '../src/command'
@@ -63,6 +64,13 @@ test('pwd matcher', () => {
expect(matcher.match({ pwd: '/var/home/user' })).toBe(false)
})
+test('output matcher', () => {
+ const matcher = new OutputMatcher('^start$')
+ expect(matcher.match({ output: 'start' })).toBe(true)
+ expect(matcher.match({ output: 'start1' })).toBe(false)
+ expect(matcher.match({ output: 'start\n' })).toBe(true)
+})
+
// test('condition match', () => {
// const condition = new Condition({
// command: '^echo start$',
From 4f3752060da216cfa6117e273862abf2131cf81b Mon Sep 17 00:00:00 2001
From: wancat
Date: Wed, 6 Mar 2024 23:54:03 +0800
Subject: [PATCH 08/82] feat: condition matcher
---
.eslintrc.js | 2 ++
packages/game/src/condition.ts | 25 ++++++++++++-------
packages/game/test/condition.test.ts | 36 ++++++++++++++--------------
3 files changed, 37 insertions(+), 26 deletions(-)
diff --git a/.eslintrc.js b/.eslintrc.js
index c8110a1..d53065a 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -64,6 +64,8 @@ module.exports = {
'@typescript-eslint/no-unused-vars': 'error',
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': 'error',
+ 'no-empty-function': 'off',
+ '@typescript-eslint/no-empty-function': 'error',
},
overrides: [
{
diff --git a/packages/game/src/condition.ts b/packages/game/src/condition.ts
index c5febc9..7d9c9bf 100644
--- a/packages/game/src/condition.ts
+++ b/packages/game/src/condition.ts
@@ -3,7 +3,7 @@ import { Command } from './command'
import { Matcher } from './matcher'
export class PatternMatcher {
- protected matcher: RegExp
+ private matcher: RegExp
constructor(pattern: string, args?: string) {
this.matcher = new RegExp(pattern, args)
}
@@ -19,16 +19,19 @@ export class CommandMatcher extends PatternMatcher implements Matcher {
}
}
-export class ErrorMatcher extends PatternMatcher implements Matcher {
- constructor(private errorPattern?: string) {
- super(errorPattern || '')
+export class ErrorMatcher implements Matcher {
+ private matcher?: PatternMatcher
+ constructor(errorPattern?: string) {
+ if (errorPattern) {
+ this.matcher = new PatternMatcher(errorPattern)
+ }
}
match(command: Partial): boolean {
- if (!this.errorPattern) {
- return command.error === ''
+ if (!this.matcher) {
+ return !command.error
}
- return !!command.error && this.test(command.error)
+ return this.matcher.test(command.error || '')
}
}
@@ -58,8 +61,14 @@ export class Condition {
constructor({ command, output, error, pwd }: ICondition) {
if (command) this.matchers.push(new CommandMatcher(command))
- // if (output) this.matchers.push(new OutputMatcher(output))
+ if (output) this.matchers.push(new OutputMatcher(output))
if (pwd) this.matchers.push(new PwdMatcher(pwd))
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
}
+
+ match(command: Partial): boolean {
+ return this.matchers.every((matcher) => {
+ return matcher.match(command)
+ })
+ }
}
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index 358f388..69368eb 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -71,22 +71,22 @@ test('output matcher', () => {
expect(matcher.match({ output: 'start\n' })).toBe(true)
})
-// test('condition match', () => {
-// const condition = new Condition({
-// command: '^echo start$',
-// pwd: '/home/user',
-// })
+test('condition match', () => {
+ const condition = new Condition({
+ command: '^echo start$',
+ })
-// expect(
-// condition.match({
-// command: 'echo start',
-// pwd: '/home/user',
-// })
-// ).toBe(true)
-// expect(
-// condition.match({
-// command: 'echo start',
-// pwd: '/home/user1',
-// })
-// ).toBe(false)
-// })
+ expect(
+ condition.match({
+ command: 'echo start',
+ })
+ ).toBe(true)
+ expect(
+ condition.match({
+ command: 'echo hello',
+ })
+ ).toBe(false)
+ expect(
+ condition.match({ command: 'echo start', error: 'permission denied' })
+ ).toBe(false)
+})
From 8280f7073d69e5dc4bde28c76964c1d6b35d2bc9 Mon Sep 17 00:00:00 2001
From: wancat
Date: Wed, 6 Mar 2024 23:57:35 +0800
Subject: [PATCH 09/82] refactor: remove unnecessary patter matcher
---
packages/game/src/condition.ts | 23 +++++++++++------------
packages/game/test/condition.test.ts | 21 ---------------------
2 files changed, 11 insertions(+), 33 deletions(-)
diff --git a/packages/game/src/condition.ts b/packages/game/src/condition.ts
index 7d9c9bf..9b4857d 100644
--- a/packages/game/src/condition.ts
+++ b/packages/game/src/condition.ts
@@ -2,28 +2,22 @@
import { Command } from './command'
import { Matcher } from './matcher'
-export class PatternMatcher {
+export class CommandMatcher implements Matcher {
private matcher: RegExp
constructor(pattern: string, args?: string) {
this.matcher = new RegExp(pattern, args)
}
- test(input: string): boolean {
- return this.matcher.test(input)
- }
-}
-
-export class CommandMatcher extends PatternMatcher implements Matcher {
match(command: Partial): boolean {
- return !!command.command && this.test(command.command)
+ return !!command.command && this.matcher.test(command.command)
}
}
export class ErrorMatcher implements Matcher {
- private matcher?: PatternMatcher
+ private matcher?: RegExp
constructor(errorPattern?: string) {
if (errorPattern) {
- this.matcher = new PatternMatcher(errorPattern)
+ this.matcher = new RegExp(errorPattern)
}
}
@@ -43,9 +37,14 @@ export class PwdMatcher implements Matcher {
}
}
-export class OutputMatcher extends PatternMatcher implements Matcher {
+export class OutputMatcher implements Matcher {
+ private matcher: RegExp
+ constructor(pattern: string, args?: string) {
+ this.matcher = new RegExp(pattern, args)
+ }
+
match(command: Partial): boolean {
- return command.output ? this.test(command.output.trim()) : false
+ return !!command.output && this.matcher.test(command.output.trim())
}
}
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index 69368eb..53c8922 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -1,6 +1,5 @@
import { test, expect } from '@jest/globals'
import {
- PatternMatcher,
CommandMatcher,
ErrorMatcher,
PwdMatcher,
@@ -9,26 +8,6 @@ import {
} from '../src/condition'
import { Command } from '../src/command'
-test('pattern match', () => {
- const matcher = new PatternMatcher('^echo start$')
-
- expect(matcher.test('echo start')).toBe(true)
- expect(matcher.test('echo start ')).toBe(false)
-})
-
-test('pattern match with flag', () => {
- const matcher = new PatternMatcher('^echo start$', 'i')
-
- expect(matcher.test('echo start')).toBe(true)
- expect(matcher.test('echo Start')).toBe(true)
- expect(matcher.test('echo Start ')).toBe(false)
-})
-
-test('empty pattern return true', () => {
- const matcher = new PatternMatcher('')
- expect(matcher.test('echo start')).toBe(true)
-})
-
test('command match', () => {
const command: Command = {
command: 'echo start',
From e83d91385243024955ff8f7395cca328ed63a3b5 Mon Sep 17 00:00:00 2001
From: wancat
Date: Thu, 7 Mar 2024 00:25:50 +0800
Subject: [PATCH 10/82] refactor: separate matchers
---
packages/game/package.json | 10 +++
packages/game/src/condition.ts | 73 -------------------
packages/game/src/condition/commandMatcher.ts | 13 ++++
packages/game/src/condition/condition.ts | 30 ++++++++
packages/game/src/condition/errorMatcher.ts | 18 +++++
packages/game/src/{ => condition}/matcher.ts | 2 +-
packages/game/src/condition/outputMatcher.ts | 13 ++++
packages/game/src/condition/pwdMatcher.ts | 10 +++
packages/game/test/condition.test.ts | 29 +++-----
packages/game/tsconfig.json | 8 ++
10 files changed, 114 insertions(+), 92 deletions(-)
create mode 100644 packages/game/package.json
delete mode 100644 packages/game/src/condition.ts
create mode 100644 packages/game/src/condition/commandMatcher.ts
create mode 100644 packages/game/src/condition/condition.ts
create mode 100644 packages/game/src/condition/errorMatcher.ts
rename packages/game/src/{ => condition}/matcher.ts (64%)
create mode 100644 packages/game/src/condition/outputMatcher.ts
create mode 100644 packages/game/src/condition/pwdMatcher.ts
create mode 100644 packages/game/tsconfig.json
diff --git a/packages/game/package.json b/packages/game/package.json
new file mode 100644
index 0000000..7e6a856
--- /dev/null
+++ b/packages/game/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "@linux-odyssey/game",
+ "version": "1.0.0",
+ "main": "dist/index.ts",
+ "license": "MIT",
+ "scripts": {
+ "build": "tsc -b"
+ },
+ "dependencies": {}
+}
diff --git a/packages/game/src/condition.ts b/packages/game/src/condition.ts
deleted file mode 100644
index 9b4857d..0000000
--- a/packages/game/src/condition.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-/* eslint-disable max-classes-per-file */
-import { Command } from './command'
-import { Matcher } from './matcher'
-
-export class CommandMatcher implements Matcher {
- private matcher: RegExp
- constructor(pattern: string, args?: string) {
- this.matcher = new RegExp(pattern, args)
- }
-
- match(command: Partial): boolean {
- return !!command.command && this.matcher.test(command.command)
- }
-}
-
-export class ErrorMatcher implements Matcher {
- private matcher?: RegExp
- constructor(errorPattern?: string) {
- if (errorPattern) {
- this.matcher = new RegExp(errorPattern)
- }
- }
-
- match(command: Partial): boolean {
- if (!this.matcher) {
- return !command.error
- }
- return this.matcher.test(command.error || '')
- }
-}
-
-export class PwdMatcher implements Matcher {
- constructor(private pwd: string) {}
-
- match(command: Partial): boolean {
- return command.pwd === this.pwd
- }
-}
-
-export class OutputMatcher implements Matcher {
- private matcher: RegExp
- constructor(pattern: string, args?: string) {
- this.matcher = new RegExp(pattern, args)
- }
-
- match(command: Partial): boolean {
- return !!command.output && this.matcher.test(command.output.trim())
- }
-}
-
-export interface ICondition {
- command?: string
- output?: string
- error?: string
- pwd?: string
-}
-
-export class Condition {
- private matchers: Matcher[] = []
-
- constructor({ command, output, error, pwd }: ICondition) {
- if (command) this.matchers.push(new CommandMatcher(command))
- if (output) this.matchers.push(new OutputMatcher(output))
- if (pwd) this.matchers.push(new PwdMatcher(pwd))
- this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
- }
-
- match(command: Partial): boolean {
- return this.matchers.every((matcher) => {
- return matcher.match(command)
- })
- }
-}
diff --git a/packages/game/src/condition/commandMatcher.ts b/packages/game/src/condition/commandMatcher.ts
new file mode 100644
index 0000000..2d102b3
--- /dev/null
+++ b/packages/game/src/condition/commandMatcher.ts
@@ -0,0 +1,13 @@
+import { Command } from '../command.js'
+import { Matcher } from './matcher.js'
+
+export class CommandMatcher implements Matcher {
+ private matcher: RegExp
+ constructor(command: string, flags?: string) {
+ this.matcher = new RegExp(command, flags)
+ }
+
+ match(command: Partial): boolean {
+ return !!command.command && this.matcher.test(command.command)
+ }
+}
diff --git a/packages/game/src/condition/condition.ts b/packages/game/src/condition/condition.ts
new file mode 100644
index 0000000..f65d9b8
--- /dev/null
+++ b/packages/game/src/condition/condition.ts
@@ -0,0 +1,30 @@
+import { Command } from '../command.js'
+import { PwdMatcher } from './pwdMatcher.js'
+import { CommandMatcher } from './commandMatcher.js'
+import { ErrorMatcher } from './errorMatcher.js'
+import { Matcher } from './matcher.js'
+import { OutputMatcher } from './outputMatcher.js'
+
+export interface ICondition {
+ command?: string
+ output?: string
+ error?: string
+ pwd?: string
+}
+
+export class Condition {
+ private matchers: Matcher[] = []
+
+ constructor({ command, output, error, pwd }: ICondition) {
+ if (command) this.matchers.push(new CommandMatcher(command))
+ if (output) this.matchers.push(new OutputMatcher(output))
+ if (pwd) this.matchers.push(new PwdMatcher(pwd))
+ this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
+ }
+
+ match(command: Partial): boolean {
+ return this.matchers.every((matcher) => {
+ return matcher.match(command)
+ })
+ }
+}
diff --git a/packages/game/src/condition/errorMatcher.ts b/packages/game/src/condition/errorMatcher.ts
new file mode 100644
index 0000000..53898fb
--- /dev/null
+++ b/packages/game/src/condition/errorMatcher.ts
@@ -0,0 +1,18 @@
+import { Matcher } from './matcher.js'
+import { Command } from '../command.js'
+
+export class ErrorMatcher implements Matcher {
+ private matcher?: RegExp
+ constructor(errorPattern?: string) {
+ if (errorPattern) {
+ this.matcher = new RegExp(errorPattern)
+ }
+ }
+
+ match(command: Partial): boolean {
+ if (!this.matcher) {
+ return !command.error
+ }
+ return this.matcher.test(command.error || '')
+ }
+}
diff --git a/packages/game/src/matcher.ts b/packages/game/src/condition/matcher.ts
similarity index 64%
rename from packages/game/src/matcher.ts
rename to packages/game/src/condition/matcher.ts
index b1de51d..29afe3f 100644
--- a/packages/game/src/matcher.ts
+++ b/packages/game/src/condition/matcher.ts
@@ -1,4 +1,4 @@
-import { Command } from './command'
+import { Command } from '../command.js'
export interface Matcher {
match(command: Partial): boolean
diff --git a/packages/game/src/condition/outputMatcher.ts b/packages/game/src/condition/outputMatcher.ts
new file mode 100644
index 0000000..3bedb55
--- /dev/null
+++ b/packages/game/src/condition/outputMatcher.ts
@@ -0,0 +1,13 @@
+import { Command } from '../command.js'
+import { Matcher } from './matcher.js'
+
+export class OutputMatcher implements Matcher {
+ private matcher: RegExp
+ constructor(pattern: string, args?: string) {
+ this.matcher = new RegExp(pattern, args)
+ }
+
+ match(command: Partial): boolean {
+ return !!command.output && this.matcher.test(command.output.trim())
+ }
+}
diff --git a/packages/game/src/condition/pwdMatcher.ts b/packages/game/src/condition/pwdMatcher.ts
new file mode 100644
index 0000000..f4e276a
--- /dev/null
+++ b/packages/game/src/condition/pwdMatcher.ts
@@ -0,0 +1,10 @@
+import { Command } from '../command.js'
+import { Matcher } from './matcher.js'
+
+export class PwdMatcher implements Matcher {
+ constructor(private pwd: string) {}
+
+ match(command: Partial): boolean {
+ return command.pwd === this.pwd
+ }
+}
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index 53c8922..0310331 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -1,23 +1,16 @@
import { test, expect } from '@jest/globals'
-import {
- CommandMatcher,
- ErrorMatcher,
- PwdMatcher,
- OutputMatcher,
- Condition,
-} from '../src/condition'
-import { Command } from '../src/command'
+import { Condition } from '../src/condition/condition'
+import { OutputMatcher } from '../src/condition/outputMatcher'
+import { PwdMatcher } from '../src/condition/pwdMatcher'
+import { CommandMatcher } from '../src/condition/commandMatcher'
+import { ErrorMatcher } from '../src/condition/errorMatcher.js'
test('command match', () => {
- const command: Command = {
- command: 'echo start',
- output: 'start',
- error: '',
- pwd: '/home/user',
- }
-
- const matcher = new CommandMatcher('^echo start$', 'i')
- expect(matcher.match(command)).toBe(true)
+ const matcher = new CommandMatcher('^echo start$')
+ expect(matcher.match({ command: 'echo start' })).toBe(true)
+ expect(matcher.match({ command: 'echo start1' })).toBe(false)
+ // Currently not supported
+ expect(matcher.match({ command: 'echo "start"' })).toBe(false)
})
test('error matcher', () => {
@@ -50,7 +43,7 @@ test('output matcher', () => {
expect(matcher.match({ output: 'start\n' })).toBe(true)
})
-test('condition match', () => {
+test('condition match command', () => {
const condition = new Condition({
command: '^echo start$',
})
diff --git a/packages/game/tsconfig.json b/packages/game/tsconfig.json
new file mode 100644
index 0000000..49e05ce
--- /dev/null
+++ b/packages/game/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "rootDir": "./src"
+ },
+ "include": ["src"]
+}
From e5f5590a67860113bcb7faf8c88f2df834cb728b Mon Sep 17 00:00:00 2001
From: wancat
Date: Thu, 7 Mar 2024 00:42:49 +0800
Subject: [PATCH 11/82] feat: add "or" and "not" matchers
---
packages/game/src/condition/condition.ts | 12 +++++++++++-
packages/game/src/condition/notMatcher.ts | 10 ++++++++++
packages/game/src/condition/orMatcher.ts | 10 ++++++++++
packages/game/test/condition.test.ts | 18 ++++++++++++++++++
4 files changed, 49 insertions(+), 1 deletion(-)
create mode 100644 packages/game/src/condition/notMatcher.ts
create mode 100644 packages/game/src/condition/orMatcher.ts
diff --git a/packages/game/src/condition/condition.ts b/packages/game/src/condition/condition.ts
index f65d9b8..6188ef3 100644
--- a/packages/game/src/condition/condition.ts
+++ b/packages/game/src/condition/condition.ts
@@ -1,24 +1,34 @@
+/* eslint-disable max-classes-per-file */
import { Command } from '../command.js'
import { PwdMatcher } from './pwdMatcher.js'
import { CommandMatcher } from './commandMatcher.js'
import { ErrorMatcher } from './errorMatcher.js'
import { Matcher } from './matcher.js'
import { OutputMatcher } from './outputMatcher.js'
+import { OrMatcher } from './orMatcher.js'
+import { NotMatcher } from './notMatcher.js'
export interface ICondition {
command?: string
output?: string
error?: string
pwd?: string
+ or?: ICondition[]
+ not?: ICondition
}
export class Condition {
private matchers: Matcher[] = []
- constructor({ command, output, error, pwd }: ICondition) {
+ constructor({ command, output, error, pwd, or, not }: ICondition) {
if (command) this.matchers.push(new CommandMatcher(command))
if (output) this.matchers.push(new OutputMatcher(output))
if (pwd) this.matchers.push(new PwdMatcher(pwd))
+ if (or) {
+ const conditions = or.map((condition) => new Condition(condition))
+ this.matchers.push(new OrMatcher(conditions))
+ }
+ if (not) this.matchers.push(new NotMatcher(new Condition(not)))
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
}
diff --git a/packages/game/src/condition/notMatcher.ts b/packages/game/src/condition/notMatcher.ts
new file mode 100644
index 0000000..ac3ae99
--- /dev/null
+++ b/packages/game/src/condition/notMatcher.ts
@@ -0,0 +1,10 @@
+import { Command } from '../command.js'
+import { Matcher } from './matcher.js'
+
+export class NotMatcher implements Matcher {
+ constructor(private condition: Matcher) {}
+
+ match(command: Partial): boolean {
+ return !this.condition.match(command)
+ }
+}
diff --git a/packages/game/src/condition/orMatcher.ts b/packages/game/src/condition/orMatcher.ts
new file mode 100644
index 0000000..1703c6c
--- /dev/null
+++ b/packages/game/src/condition/orMatcher.ts
@@ -0,0 +1,10 @@
+import { Command } from '../command.js'
+import { Matcher } from './matcher.js'
+
+export class OrMatcher implements Matcher {
+ constructor(private conditions: Matcher[]) {}
+
+ match(command: Partial): boolean {
+ return this.conditions.some((condition) => condition.match(command))
+ }
+}
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index 0310331..554a0ab 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -62,3 +62,21 @@ test('condition match command', () => {
condition.match({ command: 'echo start', error: 'permission denied' })
).toBe(false)
})
+
+test('condition with OR', () => {
+ const condition = new Condition({
+ or: [{ command: '^echo start$' }, { command: '^echo hello$' }],
+ })
+ expect(condition.match({ command: 'echo start' })).toBe(true)
+ expect(condition.match({ command: 'echo hello' })).toBe(true)
+ expect(condition.match({ command: 'echo start1' })).toBe(false)
+})
+
+test('condition with NOT', () => {
+ const condition = new Condition({
+ not: { command: '^echo start$' },
+ })
+
+ expect(condition.match({ command: 'echo start' })).toBe(false)
+ expect(condition.match({ command: 'echo hello' })).toBe(true)
+})
From b5e20766a35d8635b13f140144a70cab61d76f7d Mon Sep 17 00:00:00 2001
From: wancat
Date: Thu, 7 Mar 2024 00:50:42 +0800
Subject: [PATCH 12/82] refactor: rename paths
---
packages/game/src/command.ts | 6 -----
.../{commandMatcher.ts => CommandMatcher.ts} | 6 ++---
.../condition/{condition.ts => Condition.ts} | 27 +++++++------------
.../{errorMatcher.ts => ErrorMatcher.ts} | 6 ++---
packages/game/src/condition/Matcher.ts | 5 ++++
.../{notMatcher.ts => NotMatcher.ts} | 6 ++---
.../condition/{orMatcher.ts => OrMatcher.ts} | 6 ++---
.../{outputMatcher.ts => OutputMatcher.ts} | 6 ++---
.../{pwdMatcher.ts => PwdMatcher.ts} | 6 ++---
packages/game/src/condition/matcher.ts | 5 ----
packages/game/src/types.ts | 15 +++++++++++
packages/game/test/condition.test.ts | 10 +++----
12 files changed, 52 insertions(+), 52 deletions(-)
delete mode 100644 packages/game/src/command.ts
rename packages/game/src/condition/{commandMatcher.ts => CommandMatcher.ts} (66%)
rename packages/game/src/condition/{condition.ts => Condition.ts} (57%)
rename packages/game/src/condition/{errorMatcher.ts => ErrorMatcher.ts} (71%)
create mode 100644 packages/game/src/condition/Matcher.ts
rename packages/game/src/condition/{notMatcher.ts => NotMatcher.ts} (52%)
rename packages/game/src/condition/{orMatcher.ts => OrMatcher.ts} (58%)
rename packages/game/src/condition/{outputMatcher.ts => OutputMatcher.ts} (66%)
rename packages/game/src/condition/{pwdMatcher.ts => PwdMatcher.ts} (50%)
delete mode 100644 packages/game/src/condition/matcher.ts
create mode 100644 packages/game/src/types.ts
diff --git a/packages/game/src/command.ts b/packages/game/src/command.ts
deleted file mode 100644
index 6faf783..0000000
--- a/packages/game/src/command.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export interface Command {
- command: string
- output: string
- error: string
- pwd: string
-}
diff --git a/packages/game/src/condition/commandMatcher.ts b/packages/game/src/condition/CommandMatcher.ts
similarity index 66%
rename from packages/game/src/condition/commandMatcher.ts
rename to packages/game/src/condition/CommandMatcher.ts
index 2d102b3..1387403 100644
--- a/packages/game/src/condition/commandMatcher.ts
+++ b/packages/game/src/condition/CommandMatcher.ts
@@ -1,5 +1,5 @@
-import { Command } from '../command.js'
-import { Matcher } from './matcher.js'
+import { Command } from '../types.js'
+import { Matcher } from './Matcher.js'
export class CommandMatcher implements Matcher {
private matcher: RegExp
@@ -7,7 +7,7 @@ export class CommandMatcher implements Matcher {
this.matcher = new RegExp(command, flags)
}
- match(command: Partial): boolean {
+ match(command: Command): boolean {
return !!command.command && this.matcher.test(command.command)
}
}
diff --git a/packages/game/src/condition/condition.ts b/packages/game/src/condition/Condition.ts
similarity index 57%
rename from packages/game/src/condition/condition.ts
rename to packages/game/src/condition/Condition.ts
index 6188ef3..5227413 100644
--- a/packages/game/src/condition/condition.ts
+++ b/packages/game/src/condition/Condition.ts
@@ -1,21 +1,12 @@
/* eslint-disable max-classes-per-file */
-import { Command } from '../command.js'
-import { PwdMatcher } from './pwdMatcher.js'
-import { CommandMatcher } from './commandMatcher.js'
-import { ErrorMatcher } from './errorMatcher.js'
-import { Matcher } from './matcher.js'
-import { OutputMatcher } from './outputMatcher.js'
-import { OrMatcher } from './orMatcher.js'
-import { NotMatcher } from './notMatcher.js'
-
-export interface ICondition {
- command?: string
- output?: string
- error?: string
- pwd?: string
- or?: ICondition[]
- not?: ICondition
-}
+import { Command, ICondition } from '../types.js'
+import { PwdMatcher } from './PwdMatcher.js'
+import { CommandMatcher } from './CommandMatcher.js'
+import { ErrorMatcher } from './ErrorMatcher.js'
+import { Matcher } from './Matcher.js'
+import { OutputMatcher } from './OutputMatcher.js'
+import { OrMatcher } from './OrMatcher.js'
+import { NotMatcher } from './NotMatcher.js'
export class Condition {
private matchers: Matcher[] = []
@@ -32,7 +23,7 @@ export class Condition {
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
}
- match(command: Partial): boolean {
+ match(command: Command): boolean {
return this.matchers.every((matcher) => {
return matcher.match(command)
})
diff --git a/packages/game/src/condition/errorMatcher.ts b/packages/game/src/condition/ErrorMatcher.ts
similarity index 71%
rename from packages/game/src/condition/errorMatcher.ts
rename to packages/game/src/condition/ErrorMatcher.ts
index 53898fb..b77a2a8 100644
--- a/packages/game/src/condition/errorMatcher.ts
+++ b/packages/game/src/condition/ErrorMatcher.ts
@@ -1,5 +1,5 @@
-import { Matcher } from './matcher.js'
-import { Command } from '../command.js'
+import { Matcher } from './Matcher.js'
+import { Command } from '../types.js'
export class ErrorMatcher implements Matcher {
private matcher?: RegExp
@@ -9,7 +9,7 @@ export class ErrorMatcher implements Matcher {
}
}
- match(command: Partial): boolean {
+ match(command: Command): boolean {
if (!this.matcher) {
return !command.error
}
diff --git a/packages/game/src/condition/Matcher.ts b/packages/game/src/condition/Matcher.ts
new file mode 100644
index 0000000..862942a
--- /dev/null
+++ b/packages/game/src/condition/Matcher.ts
@@ -0,0 +1,5 @@
+import { Command } from '../types.js'
+
+export interface Matcher {
+ match(command: Command): boolean
+}
diff --git a/packages/game/src/condition/notMatcher.ts b/packages/game/src/condition/NotMatcher.ts
similarity index 52%
rename from packages/game/src/condition/notMatcher.ts
rename to packages/game/src/condition/NotMatcher.ts
index ac3ae99..f37f746 100644
--- a/packages/game/src/condition/notMatcher.ts
+++ b/packages/game/src/condition/NotMatcher.ts
@@ -1,10 +1,10 @@
-import { Command } from '../command.js'
-import { Matcher } from './matcher.js'
+import { Command } from '../types.js'
+import { Matcher } from './Matcher.js'
export class NotMatcher implements Matcher {
constructor(private condition: Matcher) {}
- match(command: Partial): boolean {
+ match(command: Command): boolean {
return !this.condition.match(command)
}
}
diff --git a/packages/game/src/condition/orMatcher.ts b/packages/game/src/condition/OrMatcher.ts
similarity index 58%
rename from packages/game/src/condition/orMatcher.ts
rename to packages/game/src/condition/OrMatcher.ts
index 1703c6c..eb51286 100644
--- a/packages/game/src/condition/orMatcher.ts
+++ b/packages/game/src/condition/OrMatcher.ts
@@ -1,10 +1,10 @@
-import { Command } from '../command.js'
-import { Matcher } from './matcher.js'
+import { Command } from '../types.js'
+import { Matcher } from './Matcher.js'
export class OrMatcher implements Matcher {
constructor(private conditions: Matcher[]) {}
- match(command: Partial): boolean {
+ match(command: Command): boolean {
return this.conditions.some((condition) => condition.match(command))
}
}
diff --git a/packages/game/src/condition/outputMatcher.ts b/packages/game/src/condition/OutputMatcher.ts
similarity index 66%
rename from packages/game/src/condition/outputMatcher.ts
rename to packages/game/src/condition/OutputMatcher.ts
index 3bedb55..643c558 100644
--- a/packages/game/src/condition/outputMatcher.ts
+++ b/packages/game/src/condition/OutputMatcher.ts
@@ -1,5 +1,5 @@
-import { Command } from '../command.js'
-import { Matcher } from './matcher.js'
+import { Command } from '../types.js'
+import { Matcher } from './Matcher.js'
export class OutputMatcher implements Matcher {
private matcher: RegExp
@@ -7,7 +7,7 @@ export class OutputMatcher implements Matcher {
this.matcher = new RegExp(pattern, args)
}
- match(command: Partial): boolean {
+ match(command: Command): boolean {
return !!command.output && this.matcher.test(command.output.trim())
}
}
diff --git a/packages/game/src/condition/pwdMatcher.ts b/packages/game/src/condition/PwdMatcher.ts
similarity index 50%
rename from packages/game/src/condition/pwdMatcher.ts
rename to packages/game/src/condition/PwdMatcher.ts
index f4e276a..dac9c78 100644
--- a/packages/game/src/condition/pwdMatcher.ts
+++ b/packages/game/src/condition/PwdMatcher.ts
@@ -1,10 +1,10 @@
-import { Command } from '../command.js'
-import { Matcher } from './matcher.js'
+import { Command } from '../types.js'
+import { Matcher } from './Matcher.js'
export class PwdMatcher implements Matcher {
constructor(private pwd: string) {}
- match(command: Partial): boolean {
+ match(command: Command): boolean {
return command.pwd === this.pwd
}
}
diff --git a/packages/game/src/condition/matcher.ts b/packages/game/src/condition/matcher.ts
deleted file mode 100644
index 29afe3f..0000000
--- a/packages/game/src/condition/matcher.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { Command } from '../command.js'
-
-export interface Matcher {
- match(command: Partial): boolean
-}
diff --git a/packages/game/src/types.ts b/packages/game/src/types.ts
new file mode 100644
index 0000000..8227198
--- /dev/null
+++ b/packages/game/src/types.ts
@@ -0,0 +1,15 @@
+export interface Command {
+ command?: string
+ output?: string
+ error?: string
+ pwd?: string
+}
+
+export interface ICondition {
+ command?: string
+ output?: string
+ error?: string
+ pwd?: string
+ or?: ICondition[]
+ not?: ICondition
+}
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index 554a0ab..11dd056 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -1,9 +1,9 @@
import { test, expect } from '@jest/globals'
-import { Condition } from '../src/condition/condition'
-import { OutputMatcher } from '../src/condition/outputMatcher'
-import { PwdMatcher } from '../src/condition/pwdMatcher'
-import { CommandMatcher } from '../src/condition/commandMatcher'
-import { ErrorMatcher } from '../src/condition/errorMatcher.js'
+import { Condition } from '../src/condition/Condition'
+import { OutputMatcher } from '../src/condition/OutputMatcher'
+import { PwdMatcher } from '../src/condition/PwdMatcher'
+import { CommandMatcher } from '../src/condition/CommandMatcher'
+import { ErrorMatcher } from '../src/condition/ErrorMatcher.js'
test('command match', () => {
const matcher = new CommandMatcher('^echo start$')
From d612b2d6af69516e1d1909972c9c94632df8510a Mon Sep 17 00:00:00 2001
From: wancat
Date: Fri, 8 Mar 2024 00:13:38 +0800
Subject: [PATCH 13/82] feat: add file matcher
---
.eslintrc.js | 2 +
packages/game/src/condition/FileMatcher.ts | 15 ++++
packages/game/src/types.ts | 14 ++++
packages/game/test/asyncCondition.test.ts | 92 ++++++++++++++++++++++
4 files changed, 123 insertions(+)
create mode 100644 packages/game/src/condition/FileMatcher.ts
create mode 100644 packages/game/test/asyncCondition.test.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index d53065a..f1ee5a6 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -66,6 +66,8 @@ module.exports = {
'@typescript-eslint/no-useless-constructor': 'error',
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': 'error',
+ 'no-shadow': 'off',
+ '@typescript-eslint/no-shadow': 'error',
},
overrides: [
{
diff --git a/packages/game/src/condition/FileMatcher.ts b/packages/game/src/condition/FileMatcher.ts
new file mode 100644
index 0000000..ac9f709
--- /dev/null
+++ b/packages/game/src/condition/FileMatcher.ts
@@ -0,0 +1,15 @@
+import { FileInput, IFileExistenceChecker } from '../types'
+
+interface FileExistenceInput extends FileInput {
+ exists: boolean
+}
+
+export async function checkFiles(
+ checker: IFileExistenceChecker,
+ files: FileExistenceInput[]
+) {
+ const existences = await Promise.all(
+ files.map((file) => checker.exists(file))
+ )
+ return existences.every((exists, index) => exists === files[index].exists)
+}
diff --git a/packages/game/src/types.ts b/packages/game/src/types.ts
index 8227198..57724a9 100644
--- a/packages/game/src/types.ts
+++ b/packages/game/src/types.ts
@@ -13,3 +13,17 @@ export interface ICondition {
or?: ICondition[]
not?: ICondition
}
+
+export enum FileType {
+ FILE = 'file',
+ FOLDER = 'folder',
+}
+
+export interface FileInput {
+ path: string
+ type: FileType
+}
+
+export interface IFileExistenceChecker {
+ exists(file: FileInput): Promise
+}
diff --git a/packages/game/test/asyncCondition.test.ts b/packages/game/test/asyncCondition.test.ts
new file mode 100644
index 0000000..1a6503a
--- /dev/null
+++ b/packages/game/test/asyncCondition.test.ts
@@ -0,0 +1,92 @@
+import { test, expect } from '@jest/globals'
+import { IFileExistenceChecker, FileType, FileInput } from '../src/types.js'
+import { checkFiles } from '../src/condition/FileMatcher.js'
+
+class MockFileChecker implements IFileExistenceChecker {
+ private files: FileInput[] = [
+ {
+ path: '/home/user/hello.txt',
+ type: FileType.FILE,
+ },
+ {
+ path: '/home/user/world.txt',
+ type: FileType.FILE,
+ },
+ {
+ path: '/home/user/Downloads',
+ type: FileType.FOLDER,
+ },
+ ]
+
+ async exists(file: FileInput): Promise {
+ return this.files.some((f) => f.path === file.path && f.type === file.type)
+ }
+}
+
+test('file matcher', async () => {
+ const checker = new MockFileChecker()
+ expect(
+ await checkFiles(checker, [
+ {
+ path: '/home/user/hello.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ ])
+ ).toBe(true)
+ expect(
+ await checkFiles(checker, [
+ {
+ path: '/home/user/not-exists.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ ])
+ ).toBe(false)
+ expect(
+ await checkFiles(checker, [
+ {
+ path: '/home/user/not-exists.txt',
+ type: FileType.FILE,
+ exists: false,
+ },
+ ])
+ ).toBe(true)
+ expect(
+ await checkFiles(checker, [
+ {
+ path: '/home/user/Downloads',
+ type: FileType.FOLDER,
+ exists: true,
+ },
+ ])
+ ).toBe(true)
+ expect(
+ await checkFiles(checker, [
+ {
+ path: '/home/user/hello.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ {
+ path: '/home/user/Downloads',
+ type: FileType.FOLDER,
+ exists: true,
+ },
+ ])
+ ).toBe(true)
+ expect(
+ await checkFiles(checker, [
+ {
+ path: '/home/user/hello.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ {
+ path: '/home/user/not-exist.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ ])
+ ).toBe(false)
+})
From 65ad72223ba291d0aa8fa19b5371ad9f68eb95b1 Mon Sep 17 00:00:00 2001
From: wancat
Date: Fri, 8 Mar 2024 00:24:51 +0800
Subject: [PATCH 14/82] feat: add checkfiles into Condition
---
packages/game/src/condition/Condition.ts | 18 +++++++++++++++---
packages/game/src/condition/FileMatcher.ts | 6 +-----
packages/game/src/types.ts | 5 +++++
packages/game/test/asyncCondition.test.ts | 15 +++++++++++++++
4 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/packages/game/src/condition/Condition.ts b/packages/game/src/condition/Condition.ts
index 5227413..fc8aea4 100644
--- a/packages/game/src/condition/Condition.ts
+++ b/packages/game/src/condition/Condition.ts
@@ -1,5 +1,9 @@
-/* eslint-disable max-classes-per-file */
-import { Command, ICondition } from '../types.js'
+import {
+ Command,
+ ICondition,
+ IFileExistenceChecker,
+ FileExistenceInput,
+} from '../types.js'
import { PwdMatcher } from './PwdMatcher.js'
import { CommandMatcher } from './CommandMatcher.js'
import { ErrorMatcher } from './ErrorMatcher.js'
@@ -7,11 +11,13 @@ import { Matcher } from './Matcher.js'
import { OutputMatcher } from './OutputMatcher.js'
import { OrMatcher } from './OrMatcher.js'
import { NotMatcher } from './NotMatcher.js'
+import { checkFiles } from './FileMatcher.js'
export class Condition {
+ private files: FileExistenceInput[] = []
private matchers: Matcher[] = []
- constructor({ command, output, error, pwd, or, not }: ICondition) {
+ constructor({ command, output, error, pwd, or, not, files }: ICondition) {
if (command) this.matchers.push(new CommandMatcher(command))
if (output) this.matchers.push(new OutputMatcher(output))
if (pwd) this.matchers.push(new PwdMatcher(pwd))
@@ -20,6 +26,7 @@ export class Condition {
this.matchers.push(new OrMatcher(conditions))
}
if (not) this.matchers.push(new NotMatcher(new Condition(not)))
+ if (files) this.files = files
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
}
@@ -28,4 +35,9 @@ export class Condition {
return matcher.match(command)
})
}
+
+ async check(checker: IFileExistenceChecker): Promise {
+ if (this.matchers.length === 0) return true
+ return checkFiles(checker, this.files)
+ }
}
diff --git a/packages/game/src/condition/FileMatcher.ts b/packages/game/src/condition/FileMatcher.ts
index ac9f709..c364e09 100644
--- a/packages/game/src/condition/FileMatcher.ts
+++ b/packages/game/src/condition/FileMatcher.ts
@@ -1,8 +1,4 @@
-import { FileInput, IFileExistenceChecker } from '../types'
-
-interface FileExistenceInput extends FileInput {
- exists: boolean
-}
+import { FileExistenceInput, IFileExistenceChecker } from '../types'
export async function checkFiles(
checker: IFileExistenceChecker,
diff --git a/packages/game/src/types.ts b/packages/game/src/types.ts
index 57724a9..4bcbb1a 100644
--- a/packages/game/src/types.ts
+++ b/packages/game/src/types.ts
@@ -12,6 +12,7 @@ export interface ICondition {
pwd?: string
or?: ICondition[]
not?: ICondition
+ files: FileExistenceInput[]
}
export enum FileType {
@@ -24,6 +25,10 @@ export interface FileInput {
type: FileType
}
+export interface FileExistenceInput extends FileInput {
+ exists: boolean
+}
+
export interface IFileExistenceChecker {
exists(file: FileInput): Promise
}
diff --git a/packages/game/test/asyncCondition.test.ts b/packages/game/test/asyncCondition.test.ts
index 1a6503a..da4399d 100644
--- a/packages/game/test/asyncCondition.test.ts
+++ b/packages/game/test/asyncCondition.test.ts
@@ -1,6 +1,7 @@
import { test, expect } from '@jest/globals'
import { IFileExistenceChecker, FileType, FileInput } from '../src/types.js'
import { checkFiles } from '../src/condition/FileMatcher.js'
+import { Condition } from '../src/condition/Condition.js'
class MockFileChecker implements IFileExistenceChecker {
private files: FileInput[] = [
@@ -90,3 +91,17 @@ test('file matcher', async () => {
])
).toBe(false)
})
+
+test('condition with file matcher', async () => {
+ const checker = new MockFileChecker()
+ const condition = new Condition({
+ files: [
+ {
+ path: '/home/user/hello.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ ],
+ })
+ expect(await condition.check(checker)).toBe(true)
+})
From 77fe2d37b3639019fbcaf9b750652b1b7578494a Mon Sep 17 00:00:00 2001
From: wancat
Date: Fri, 8 Mar 2024 00:38:49 +0800
Subject: [PATCH 15/82] feat: create stage
---
packages/game/src/Stage.ts | 18 +++++++++++++
packages/game/src/condition/CommandMatcher.ts | 4 +--
packages/game/src/condition/Condition.ts | 4 +--
packages/game/src/condition/ErrorMatcher.ts | 4 +--
packages/game/src/condition/Matcher.ts | 4 +--
packages/game/src/condition/NotMatcher.ts | 4 +--
packages/game/src/condition/OrMatcher.ts | 4 +--
packages/game/src/condition/OutputMatcher.ts | 4 +--
packages/game/src/condition/PwdMatcher.ts | 4 +--
packages/game/src/types.ts | 10 ++++++--
packages/game/test/stage.test.ts | 25 +++++++++++++++++++
11 files changed, 67 insertions(+), 18 deletions(-)
create mode 100644 packages/game/src/Stage.ts
create mode 100644 packages/game/test/stage.test.ts
diff --git a/packages/game/src/Stage.ts b/packages/game/src/Stage.ts
new file mode 100644
index 0000000..7517dc9
--- /dev/null
+++ b/packages/game/src/Stage.ts
@@ -0,0 +1,18 @@
+import { IStage, ICommand } from './types'
+import { Condition } from './condition/Condition'
+
+export class Stage {
+ id: string
+ name: string
+ condition: Condition
+
+ constructor({ id, name, condition }: IStage) {
+ this.id = id
+ this.name = name
+ this.condition = new Condition(condition)
+ }
+
+ satisfies(command: ICommand): boolean {
+ return this.condition.match(command)
+ }
+}
diff --git a/packages/game/src/condition/CommandMatcher.ts b/packages/game/src/condition/CommandMatcher.ts
index 1387403..3f71bcd 100644
--- a/packages/game/src/condition/CommandMatcher.ts
+++ b/packages/game/src/condition/CommandMatcher.ts
@@ -1,4 +1,4 @@
-import { Command } from '../types.js'
+import { ICommand } from '../types.js'
import { Matcher } from './Matcher.js'
export class CommandMatcher implements Matcher {
@@ -7,7 +7,7 @@ export class CommandMatcher implements Matcher {
this.matcher = new RegExp(command, flags)
}
- match(command: Command): boolean {
+ match(command: ICommand): boolean {
return !!command.command && this.matcher.test(command.command)
}
}
diff --git a/packages/game/src/condition/Condition.ts b/packages/game/src/condition/Condition.ts
index fc8aea4..82c6c57 100644
--- a/packages/game/src/condition/Condition.ts
+++ b/packages/game/src/condition/Condition.ts
@@ -1,5 +1,5 @@
import {
- Command,
+ ICommand,
ICondition,
IFileExistenceChecker,
FileExistenceInput,
@@ -30,7 +30,7 @@ export class Condition {
this.matchers.push(new ErrorMatcher(error)) // always check unexpected error
}
- match(command: Command): boolean {
+ match(command: ICommand): boolean {
return this.matchers.every((matcher) => {
return matcher.match(command)
})
diff --git a/packages/game/src/condition/ErrorMatcher.ts b/packages/game/src/condition/ErrorMatcher.ts
index b77a2a8..6fd1d15 100644
--- a/packages/game/src/condition/ErrorMatcher.ts
+++ b/packages/game/src/condition/ErrorMatcher.ts
@@ -1,5 +1,5 @@
import { Matcher } from './Matcher.js'
-import { Command } from '../types.js'
+import { ICommand } from '../types.js'
export class ErrorMatcher implements Matcher {
private matcher?: RegExp
@@ -9,7 +9,7 @@ export class ErrorMatcher implements Matcher {
}
}
- match(command: Command): boolean {
+ match(command: ICommand): boolean {
if (!this.matcher) {
return !command.error
}
diff --git a/packages/game/src/condition/Matcher.ts b/packages/game/src/condition/Matcher.ts
index 862942a..0af7c33 100644
--- a/packages/game/src/condition/Matcher.ts
+++ b/packages/game/src/condition/Matcher.ts
@@ -1,5 +1,5 @@
-import { Command } from '../types.js'
+import { ICommand } from '../types.js'
export interface Matcher {
- match(command: Command): boolean
+ match(command: ICommand): boolean
}
diff --git a/packages/game/src/condition/NotMatcher.ts b/packages/game/src/condition/NotMatcher.ts
index f37f746..1e9a846 100644
--- a/packages/game/src/condition/NotMatcher.ts
+++ b/packages/game/src/condition/NotMatcher.ts
@@ -1,10 +1,10 @@
-import { Command } from '../types.js'
+import { ICommand } from '../types.js'
import { Matcher } from './Matcher.js'
export class NotMatcher implements Matcher {
constructor(private condition: Matcher) {}
- match(command: Command): boolean {
+ match(command: ICommand): boolean {
return !this.condition.match(command)
}
}
diff --git a/packages/game/src/condition/OrMatcher.ts b/packages/game/src/condition/OrMatcher.ts
index eb51286..70c2091 100644
--- a/packages/game/src/condition/OrMatcher.ts
+++ b/packages/game/src/condition/OrMatcher.ts
@@ -1,10 +1,10 @@
-import { Command } from '../types.js'
+import { ICommand } from '../types.js'
import { Matcher } from './Matcher.js'
export class OrMatcher implements Matcher {
constructor(private conditions: Matcher[]) {}
- match(command: Command): boolean {
+ match(command: ICommand): boolean {
return this.conditions.some((condition) => condition.match(command))
}
}
diff --git a/packages/game/src/condition/OutputMatcher.ts b/packages/game/src/condition/OutputMatcher.ts
index 643c558..89aa9a2 100644
--- a/packages/game/src/condition/OutputMatcher.ts
+++ b/packages/game/src/condition/OutputMatcher.ts
@@ -1,4 +1,4 @@
-import { Command } from '../types.js'
+import { ICommand } from '../types.js'
import { Matcher } from './Matcher.js'
export class OutputMatcher implements Matcher {
@@ -7,7 +7,7 @@ export class OutputMatcher implements Matcher {
this.matcher = new RegExp(pattern, args)
}
- match(command: Command): boolean {
+ match(command: ICommand): boolean {
return !!command.output && this.matcher.test(command.output.trim())
}
}
diff --git a/packages/game/src/condition/PwdMatcher.ts b/packages/game/src/condition/PwdMatcher.ts
index dac9c78..781a7c5 100644
--- a/packages/game/src/condition/PwdMatcher.ts
+++ b/packages/game/src/condition/PwdMatcher.ts
@@ -1,10 +1,10 @@
-import { Command } from '../types.js'
+import { ICommand } from '../types.js'
import { Matcher } from './Matcher.js'
export class PwdMatcher implements Matcher {
constructor(private pwd: string) {}
- match(command: Command): boolean {
+ match(command: ICommand): boolean {
return command.pwd === this.pwd
}
}
diff --git a/packages/game/src/types.ts b/packages/game/src/types.ts
index 4bcbb1a..52fff79 100644
--- a/packages/game/src/types.ts
+++ b/packages/game/src/types.ts
@@ -1,4 +1,4 @@
-export interface Command {
+export interface ICommand {
command?: string
output?: string
error?: string
@@ -12,7 +12,7 @@ export interface ICondition {
pwd?: string
or?: ICondition[]
not?: ICondition
- files: FileExistenceInput[]
+ files?: FileExistenceInput[]
}
export enum FileType {
@@ -32,3 +32,9 @@ export interface FileExistenceInput extends FileInput {
export interface IFileExistenceChecker {
exists(file: FileInput): Promise
}
+
+export interface IStage {
+ id: string
+ name: string
+ condition: ICondition
+}
diff --git a/packages/game/test/stage.test.ts b/packages/game/test/stage.test.ts
new file mode 100644
index 0000000..8fa1617
--- /dev/null
+++ b/packages/game/test/stage.test.ts
@@ -0,0 +1,25 @@
+import { test, expect } from '@jest/globals'
+import { Stage } from '../src/Stage'
+
+test('check stage condition', () => {
+ const stage = new Stage({
+ id: 'stage1',
+ name: 'List the files using `ls`',
+ condition: {
+ command: 'ls',
+ pwd: '/home/user',
+ },
+ })
+ expect(
+ stage.satisfies({
+ command: 'ls',
+ pwd: '/home/user',
+ })
+ ).toBe(true)
+ expect(
+ stage.satisfies({
+ command: 'ls',
+ pwd: '/home/user/Downloads',
+ })
+ ).toBe(false)
+})
From 5bea2ea78c4aff40067e91b773f6c717a51e4f43 Mon Sep 17 00:00:00 2001
From: wancat
Date: Fri, 8 Mar 2024 00:47:50 +0800
Subject: [PATCH 16/82] feat: add stage condition checks
---
packages/game/src/Stage.ts | 9 ++--
packages/game/test/asyncCondition.test.ts | 2 +-
packages/game/test/stage.test.ts | 62 +++++++++++++++++++----
3 files changed, 60 insertions(+), 13 deletions(-)
diff --git a/packages/game/src/Stage.ts b/packages/game/src/Stage.ts
index 7517dc9..579bb74 100644
--- a/packages/game/src/Stage.ts
+++ b/packages/game/src/Stage.ts
@@ -1,4 +1,4 @@
-import { IStage, ICommand } from './types'
+import { IStage, ICommand, IFileExistenceChecker } from './types'
import { Condition } from './condition/Condition'
export class Stage {
@@ -12,7 +12,10 @@ export class Stage {
this.condition = new Condition(condition)
}
- satisfies(command: ICommand): boolean {
- return this.condition.match(command)
+ async satisfies(
+ command: ICommand,
+ checker: IFileExistenceChecker
+ ): Promise {
+ return this.condition.match(command) && this.condition.check(checker)
}
}
diff --git a/packages/game/test/asyncCondition.test.ts b/packages/game/test/asyncCondition.test.ts
index da4399d..8ad2630 100644
--- a/packages/game/test/asyncCondition.test.ts
+++ b/packages/game/test/asyncCondition.test.ts
@@ -3,7 +3,7 @@ import { IFileExistenceChecker, FileType, FileInput } from '../src/types.js'
import { checkFiles } from '../src/condition/FileMatcher.js'
import { Condition } from '../src/condition/Condition.js'
-class MockFileChecker implements IFileExistenceChecker {
+export class MockFileChecker implements IFileExistenceChecker {
private files: FileInput[] = [
{
path: '/home/user/hello.txt',
diff --git a/packages/game/test/stage.test.ts b/packages/game/test/stage.test.ts
index 8fa1617..5631e21 100644
--- a/packages/game/test/stage.test.ts
+++ b/packages/game/test/stage.test.ts
@@ -1,7 +1,11 @@
import { test, expect } from '@jest/globals'
import { Stage } from '../src/Stage'
+import { FileType } from '../src/types'
+import { MockFileChecker } from './asyncCondition.test'
-test('check stage condition', () => {
+const checker = new MockFileChecker()
+
+test('check stage condition', async () => {
const stage = new Stage({
id: 'stage1',
name: 'List the files using `ls`',
@@ -11,15 +15,55 @@ test('check stage condition', () => {
},
})
expect(
- stage.satisfies({
- command: 'ls',
- pwd: '/home/user',
- })
+ await stage.satisfies(
+ {
+ command: 'ls',
+ pwd: '/home/user',
+ },
+ checker
+ )
).toBe(true)
expect(
- stage.satisfies({
- command: 'ls',
- pwd: '/home/user/Downloads',
- })
+ await stage.satisfies(
+ {
+ command: 'ls',
+ pwd: '/home/user/Downloads',
+ },
+ checker
+ )
).toBe(false)
})
+
+test('check stage with async condition truthy', async () => {
+ const stage = new Stage({
+ id: 'stage1',
+ name: 'Create file',
+ condition: {
+ files: [
+ {
+ path: '/home/user/hello.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ ],
+ },
+ })
+ expect(await stage.satisfies({}, checker)).toBe(true)
+})
+
+test('check stage with async condition falsy', async () => {
+ const stage = new Stage({
+ id: 'stage1',
+ name: 'Create file',
+ condition: {
+ files: [
+ {
+ path: '/home/user/not-exists.txt',
+ type: FileType.FILE,
+ exists: true,
+ },
+ ],
+ },
+ })
+ expect(await stage.satisfies({}, checker)).toBe(false)
+})
From b449ea455a268049b4cc3a56d29814ced5c6fb6d Mon Sep 17 00:00:00 2001
From: wancat
Date: Fri, 8 Mar 2024 01:05:26 +0800
Subject: [PATCH 17/82] feat: add Session and stage active check
---
packages/game/src/Session.ts | 17 +++++++++++++++++
packages/game/src/Stage.ts | 24 ++++++++++++++++++++----
packages/game/src/types.ts | 7 ++++++-
packages/game/test/stage.test.ts | 19 +++++++++++++++++++
4 files changed, 62 insertions(+), 5 deletions(-)
create mode 100644 packages/game/src/Session.ts
diff --git a/packages/game/src/Session.ts b/packages/game/src/Session.ts
new file mode 100644
index 0000000..e8b5417
--- /dev/null
+++ b/packages/game/src/Session.ts
@@ -0,0 +1,17 @@
+import { ISession } from './types'
+
+export class Session implements ISession {
+ private completed: string[] = []
+
+ constructor({ completedStages }: ISession) {
+ this.completed = completedStages
+ }
+
+ get completedStages() {
+ return this.completed
+ }
+
+ complete(stageId: string) {
+ this.completed.push(stageId)
+ }
+}
diff --git a/packages/game/src/Stage.ts b/packages/game/src/Stage.ts
index 579bb74..e440488 100644
--- a/packages/game/src/Stage.ts
+++ b/packages/game/src/Stage.ts
@@ -1,15 +1,17 @@
-import { IStage, ICommand, IFileExistenceChecker } from './types'
+import { IStage, ICommand, IFileExistenceChecker, ISession } from './types'
import { Condition } from './condition/Condition'
export class Stage {
id: string
name: string
- condition: Condition
+ private condition: Condition
+ private requirements: string[]
- constructor({ id, name, condition }: IStage) {
+ constructor({ id, name, condition, requirements }: IStage) {
this.id = id
- this.name = name
+ this.name = name || ''
this.condition = new Condition(condition)
+ this.requirements = requirements || []
}
async satisfies(
@@ -18,4 +20,18 @@ export class Stage {
): Promise {
return this.condition.match(command) && this.condition.check(checker)
}
+
+ private checkRequirements(session: ISession): boolean {
+ return this.requirements.every((req) =>
+ session.completedStages.includes(req)
+ )
+ }
+
+ private finished(session: ISession): boolean {
+ return session.completedStages.includes(this.id)
+ }
+
+ active(session: ISession): boolean {
+ return !this.finished(session) && this.checkRequirements(session)
+ }
}
diff --git a/packages/game/src/types.ts b/packages/game/src/types.ts
index 52fff79..972200f 100644
--- a/packages/game/src/types.ts
+++ b/packages/game/src/types.ts
@@ -35,6 +35,11 @@ export interface IFileExistenceChecker {
export interface IStage {
id: string
- name: string
+ name?: string
+ requirements?: string[]
condition: ICondition
}
+
+export interface ISession {
+ completedStages: string[]
+}
diff --git a/packages/game/test/stage.test.ts b/packages/game/test/stage.test.ts
index 5631e21..de81ade 100644
--- a/packages/game/test/stage.test.ts
+++ b/packages/game/test/stage.test.ts
@@ -2,6 +2,7 @@ import { test, expect } from '@jest/globals'
import { Stage } from '../src/Stage'
import { FileType } from '../src/types'
import { MockFileChecker } from './asyncCondition.test'
+import { Session } from '../src/Session'
const checker = new MockFileChecker()
@@ -67,3 +68,21 @@ test('check stage with async condition falsy', async () => {
})
expect(await stage.satisfies({}, checker)).toBe(false)
})
+
+test('stage active checks', () => {
+ const session = new Session({
+ completedStages: ['stage1'],
+ })
+ const stage3 = new Stage({
+ id: 'stage3',
+ requirements: ['stage1', 'stage2'],
+ condition: {},
+ })
+ expect(stage3.active(session)).toBe(false)
+
+ session.complete('stage2')
+ expect(stage3.active(session)).toBe(true)
+
+ session.complete('stage3')
+ expect(stage3.active(session)).toBe(false)
+})
From e66598f1a76fcf44fe22ed0e4fd3f0ab3b0ddab7 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 28 Aug 2024 14:52:45 +0800
Subject: [PATCH 18/82] chore: update dependencies
---
package.json | 3 +-
yarn.lock | 134 +++++++++++----------------------------------------
2 files changed, 30 insertions(+), 107 deletions(-)
diff --git a/package.json b/package.json
index bbd58c8..1185bbb 100644
--- a/package.json
+++ b/package.json
@@ -56,5 +56,6 @@
"dependencies": {
"latest": "^0.2.0",
"typescript-eslint": "^7.4.0"
- }
+ },
+ "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
diff --git a/yarn.lock b/yarn.lock
index 4279b4b..746b92f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -34,27 +34,6 @@
integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==
"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9", "@babel/core@^7.24.0":
- version "7.24.0"
- resolved "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz"
- integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==
- dependencies:
- "@ampproject/remapping" "^2.2.0"
- "@babel/code-frame" "^7.23.5"
- "@babel/generator" "^7.23.6"
- "@babel/helper-compilation-targets" "^7.23.6"
- "@babel/helper-module-transforms" "^7.23.3"
- "@babel/helpers" "^7.24.0"
- "@babel/parser" "^7.24.0"
- "@babel/template" "^7.24.0"
- "@babel/traverse" "^7.24.0"
- "@babel/types" "^7.24.0"
- convert-source-map "^2.0.0"
- debug "^4.1.0"
- gensync "^1.0.0-beta.2"
- json5 "^2.2.3"
- semver "^6.3.1"
-
-"@babel/core@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b"
integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==
@@ -198,29 +177,6 @@
"@babel/types" "^7.22.5"
"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
- version "7.24.0"
- resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz"
- integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==
-
-"@babel/helper-remap-async-to-generator@^7.22.20":
- version "7.22.20"
- resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz"
- integrity sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==
- dependencies:
- "@babel/helper-annotate-as-pure" "^7.22.5"
- "@babel/helper-environment-visitor" "^7.22.20"
- "@babel/helper-wrap-function" "^7.22.20"
-
-"@babel/helper-replace-supers@^7.22.20":
- version "7.22.20"
- resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz"
- integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==
- dependencies:
- "@babel/helper-environment-visitor" "^7.22.20"
- "@babel/helper-member-expression-to-functions" "^7.22.15"
- "@babel/helper-optimise-call-expression" "^7.22.5"
-
-"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.3":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a"
integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==
@@ -288,15 +244,6 @@
"@babel/template" "^7.22.15"
"@babel/types" "^7.22.19"
-"@babel/helpers@^7.24.0":
- version "7.24.0"
- resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz"
- integrity sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==
- dependencies:
- "@babel/template" "^7.24.0"
- "@babel/traverse" "^7.24.0"
- "@babel/types" "^7.24.0"
-
"@babel/helpers@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b"
@@ -316,40 +263,6 @@
js-tokens "^4.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.0":
- version "7.24.0"
- resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz"
- integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==
-
-"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3":
- version "7.23.3"
- resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz"
- integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.22.5"
-
-"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3":
- version "7.23.3"
- resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz"
- integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.22.5"
- "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
- "@babel/plugin-transform-optional-chaining" "^7.23.3"
-
-"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7":
- version "7.23.7"
- resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz"
- integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==
- dependencies:
- "@babel/helper-environment-visitor" "^7.22.20"
- "@babel/helper-plugin-utils" "^7.22.5"
-
-"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2":
- version "7.21.0-placeholder-for-preset-env.2"
- resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz"
- integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
-
-"@babel/parser@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac"
integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==
@@ -1073,15 +986,6 @@
globals "^11.1.0"
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
- version "7.24.0"
- resolved "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz"
- integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==
- dependencies:
- "@babel/helper-string-parser" "^7.23.4"
- "@babel/helper-validator-identifier" "^7.22.20"
- to-fast-properties "^2.0.0"
-
-"@babel/types@^7.22.19", "@babel/types@^7.24.0", "@babel/types@^7.4.4":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf"
integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==
@@ -3650,13 +3554,6 @@ cookie@0.6.0:
resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz"
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
-core-js-compat@^3.31.0, core-js-compat@^3.34.0:
- version "3.36.0"
- resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz"
- integrity sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==
- dependencies:
- browserslist "^4.22.3"
-
core-js-compat@^3.31.0, core-js-compat@^3.34.0:
version "3.36.0"
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.0.tgz#087679119bc2fdbdefad0d45d8e5d307d45ba190"
@@ -8734,7 +8631,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -8752,6 +8649,15 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz"
@@ -8812,7 +8718,7 @@ stringstream@~0.0.4:
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72"
integrity sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -8826,6 +8732,13 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1, strip-ansi@~3.0.1:
dependencies:
ansi-regex "^2.0.0"
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz"
@@ -9678,7 +9591,7 @@ wordwrap@^1.0.0:
resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz"
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -9696,6 +9609,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz"
From 19c44fbe5259d7fb52ac15b04548921e79d14587 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Thu, 10 Oct 2024 16:22:20 +0800
Subject: [PATCH 19/82] wip: game schema
---
packages/game/package.json | 4 +-
packages/game/src/schema/condition.ts | 0
packages/game/src/schema/index.ts | 54 ++++++++++++++++++++++++
packages/game/src/schema/requirements.ts | 0
packages/game/src/schema/stage.ts | 0
packages/game/test/condition.test.ts | 12 ++++++
yarn.lock | 2 +-
7 files changed, 70 insertions(+), 2 deletions(-)
create mode 100644 packages/game/src/schema/condition.ts
create mode 100644 packages/game/src/schema/index.ts
create mode 100644 packages/game/src/schema/requirements.ts
create mode 100644 packages/game/src/schema/stage.ts
diff --git a/packages/game/package.json b/packages/game/package.json
index 7e6a856..5854459 100644
--- a/packages/game/package.json
+++ b/packages/game/package.json
@@ -6,5 +6,7 @@
"scripts": {
"build": "tsc -b"
},
- "dependencies": {}
+ "dependencies": {
+ "zod": "^3.23.8"
+ }
}
diff --git a/packages/game/src/schema/condition.ts b/packages/game/src/schema/condition.ts
new file mode 100644
index 0000000..e69de29
diff --git a/packages/game/src/schema/index.ts b/packages/game/src/schema/index.ts
new file mode 100644
index 0000000..f21337b
--- /dev/null
+++ b/packages/game/src/schema/index.ts
@@ -0,0 +1,54 @@
+import { z } from 'zod'
+
+export const requirementsSchema = z.object({
+ requirements: z.array(z.string()),
+})
+
+export type IRequirements = z.infer
+
+export const fileInputSchema = z.object({
+ path: z.string(),
+ type: z.enum(['file', 'folder']),
+})
+
+export type IFileInput = z.infer
+
+export const fileExistenceInputSchema = fileInputSchema.extend({
+ exists: z.boolean(),
+})
+
+export type IFileExistenceInput = z.infer
+
+const baseConditionSchema = z.object({
+ command: z.string().optional(),
+ output: z.string().optional(),
+ error: z.string().optional(),
+ pwd: z.string().optional(),
+ files: z.array(fileExistenceInputSchema).optional(),
+})
+
+export type ICondition = z.infer & {
+ or?: ICondition[]
+ not?: ICondition
+}
+
+export const conditionSchema: z.ZodType =
+ baseConditionSchema.extend({
+ or: z.lazy(() => z.array(conditionSchema)).optional(),
+ not: z.lazy(() => conditionSchema).optional(),
+ })
+
+export const responseSchema = z.object({
+ type: z.enum(['narrative', 'dialogue']),
+ content: z.string(),
+})
+
+export const stageSchema = z.object({
+ id: z.string().regex(/^[a-zA-Z0-9_-]+$/),
+ name: z.string().optional(),
+ requirements: z.array(z.string()),
+ condition: conditionSchema,
+ response: responseSchema,
+})
+
+export type IStage = z.infer
diff --git a/packages/game/src/schema/requirements.ts b/packages/game/src/schema/requirements.ts
new file mode 100644
index 0000000..e69de29
diff --git a/packages/game/src/schema/stage.ts b/packages/game/src/schema/stage.ts
new file mode 100644
index 0000000..e69de29
diff --git a/packages/game/test/condition.test.ts b/packages/game/test/condition.test.ts
index 11dd056..ad05f5c 100644
--- a/packages/game/test/condition.test.ts
+++ b/packages/game/test/condition.test.ts
@@ -4,6 +4,7 @@ import { OutputMatcher } from '../src/condition/OutputMatcher'
import { PwdMatcher } from '../src/condition/PwdMatcher'
import { CommandMatcher } from '../src/condition/CommandMatcher'
import { ErrorMatcher } from '../src/condition/ErrorMatcher.js'
+import { conditionSchema } from '../src/schema'
test('command match', () => {
const matcher = new CommandMatcher('^echo start$')
@@ -80,3 +81,14 @@ test('condition with NOT', () => {
expect(condition.match({ command: 'echo start' })).toBe(false)
expect(condition.match({ command: 'echo hello' })).toBe(true)
})
+
+it('should parse condition', () => {
+ const condition = {
+ command: 'echo start',
+ output: 'start',
+ not: {
+ pwd: '/home/user',
+ },
+ }
+ expect(conditionSchema.safeParse(condition).error).toBeUndefined()
+})
diff --git a/yarn.lock b/yarn.lock
index 746b92f..13fbb96 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9747,5 +9747,5 @@ yocto-queue@^0.1.0:
zod@^3.23.8:
version "3.23.8"
- resolved "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
From 6326b84a60dc147f179010f9580840dec74d426a Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 16 Apr 2025 15:27:00 +0800
Subject: [PATCH 20/82] feat: init trpc
---
server/package.json | 4 +++-
server/src/index.ts | 9 +++++++++
server/src/routers/index.ts | 11 +++++++++++
server/src/trpc.ts | 11 +++++++++++
server/tests/trpc.test.ts | 0
yarn.lock | 10 ++++++++++
6 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 server/src/routers/index.ts
create mode 100644 server/src/trpc.ts
create mode 100644 server/tests/trpc.test.ts
diff --git a/server/package.json b/server/package.json
index 432f5dd..00dc766 100644
--- a/server/package.json
+++ b/server/package.json
@@ -17,6 +17,7 @@
"@linux-odyssey/file-graph": "*",
"@linux-odyssey/models": "*",
"@linux-odyssey/utils": "*",
+ "@trpc/server": "^11.1.0",
"bcrypt": "^5.1.1",
"commander": "^11.0.0",
"connect-mongo": "^5.0.0",
@@ -44,7 +45,8 @@
"swagger-ui-express": "^5.0.0",
"validator": "^13.11.0",
"winston": "^3.11.0",
- "yaml": "^2.3.1"
+ "yaml": "^2.3.1",
+ "zod": "^3.24.2"
},
"devDependencies": {
"@swc/core": "^1.4.2",
diff --git a/server/src/index.ts b/server/src/index.ts
index 22916d8..b0d2f01 100644
--- a/server/src/index.ts
+++ b/server/src/index.ts
@@ -4,6 +4,7 @@ import http from 'http'
import YAML from 'yaml'
import swaggerUI from 'swagger-ui-express'
import passport from 'passport'
+import * as trpcExpress from '@trpc/server/adapters/express'
import connectDB from '@linux-odyssey/models'
import './auth/passport.js'
@@ -17,6 +18,7 @@ import sessionMiddleware from './middleware/session.js'
import expiryRemovalScheduler from './containers/expiryChecker.js'
import setupTest from './utils/setupTest.js'
import logger from './utils/logger.js'
+import { appRouter } from './routers/index.js'
async function main() {
if (!config.secret) {
@@ -70,6 +72,13 @@ async function main() {
})
app.use('/api/v1', apiRouter)
+ app.use(
+ '/trpc',
+ trpcExpress.createExpressMiddleware({
+ router: appRouter,
+ // createContext,
+ })
+ )
app.use(errorHandler)
server.listen(config.port, '0.0.0.0', () => {
diff --git a/server/src/routers/index.ts b/server/src/routers/index.ts
new file mode 100644
index 0000000..f83f4d2
--- /dev/null
+++ b/server/src/routers/index.ts
@@ -0,0 +1,11 @@
+import { router, publicProcedure } from '../trpc.js'
+
+export const appRouter = router({
+ userList: publicProcedure.query(async () => {
+ // Retrieve users from a datasource, this is an imaginary database
+ return 'hello'
+ }),
+})
+// Export type router type signature,
+// NOT the router itself.
+export type AppRouter = typeof appRouter
diff --git a/server/src/trpc.ts b/server/src/trpc.ts
new file mode 100644
index 0000000..e946384
--- /dev/null
+++ b/server/src/trpc.ts
@@ -0,0 +1,11 @@
+import { initTRPC } from '@trpc/server'
+/**
+ * Initialization of tRPC backend
+ * Should be done only once per backend!
+ */
+const t = initTRPC.create()
+/**
+ * Export reusable router and procedure helpers
+ * that can be used throughout the router
+ */
+export const { router, procedure: publicProcedure } = t
diff --git a/server/tests/trpc.test.ts b/server/tests/trpc.test.ts
new file mode 100644
index 0000000..e69de29
diff --git a/yarn.lock b/yarn.lock
index 78ca72a..61a3994 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1711,6 +1711,11 @@
lz-string "^1.5.0"
pretty-format "^27.0.2"
+"@trpc/server@^11.1.0":
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/@trpc/server/-/server-11.1.0.tgz#8169fa8b944beddf65a95f376d4afea5732be254"
+ integrity sha512-uAJ7ikejeujVkf53XFJ/0W8nr7bDjul+Szk5Rsepq97Hb/WS1RkRXdyX4KqAyCE9b1vDFCJVJwSxiIZdRtbTZQ==
+
"@tsconfig/node10@^1.0.7":
version "1.0.9"
resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz"
@@ -9780,3 +9785,8 @@ zod@^3.23.8:
version "3.23.8"
resolved "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz"
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==
+
+zod@^3.24.2:
+ version "3.24.2"
+ resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3"
+ integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==
From 529869671c7e3165dcc4140387d2b3f6e486e7ac Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 16 Apr 2025 15:36:12 +0800
Subject: [PATCH 21/82] feat: createContext
---
server/src/index.ts | 3 ++-
server/src/routers/index.ts | 4 ++--
server/src/trpc.ts | 19 ++++++++++++++-----
3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/server/src/index.ts b/server/src/index.ts
index b0d2f01..d287884 100644
--- a/server/src/index.ts
+++ b/server/src/index.ts
@@ -19,6 +19,7 @@ import expiryRemovalScheduler from './containers/expiryChecker.js'
import setupTest from './utils/setupTest.js'
import logger from './utils/logger.js'
import { appRouter } from './routers/index.js'
+import { createContext } from './trpc.js'
async function main() {
if (!config.secret) {
@@ -76,7 +77,7 @@ async function main() {
'/trpc',
trpcExpress.createExpressMiddleware({
router: appRouter,
- // createContext,
+ createContext,
})
)
app.use(errorHandler)
diff --git a/server/src/routers/index.ts b/server/src/routers/index.ts
index f83f4d2..1cd5c2a 100644
--- a/server/src/routers/index.ts
+++ b/server/src/routers/index.ts
@@ -1,9 +1,9 @@
import { router, publicProcedure } from '../trpc.js'
export const appRouter = router({
- userList: publicProcedure.query(async () => {
+ userList: publicProcedure.query(async (opts) => {
// Retrieve users from a datasource, this is an imaginary database
- return 'hello'
+ return opts.ctx
}),
})
// Export type router type signature,
diff --git a/server/src/trpc.ts b/server/src/trpc.ts
index e946384..f2d2ecd 100644
--- a/server/src/trpc.ts
+++ b/server/src/trpc.ts
@@ -1,9 +1,18 @@
import { initTRPC } from '@trpc/server'
-/**
- * Initialization of tRPC backend
- * Should be done only once per backend!
- */
-const t = initTRPC.create()
+import { CreateNextContextOptions } from '@trpc/server/adapters/next'
+
+export const createContext = async (opts: CreateNextContextOptions) => {
+ const { session, user, ip } = opts.req
+ return {
+ session,
+ user,
+ ip,
+ }
+}
+
+export type AppContext = Awaited>
+
+const t = initTRPC.context().create()
/**
* Export reusable router and procedure helpers
* that can be used throughout the router
From 55a41dd3b53fac5f0c2f6453cb3b17d935cfee7d Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 16 Apr 2025 16:02:23 +0800
Subject: [PATCH 22/82] feat: integrate trpc to app
---
app/package.json | 1 +
.../components/header/GameHeaderComponents.vue | 13 +++++++++----
app/src/utils/trpc.ts | 16 ++++++++++++++++
app/vite.config.ts | 5 +++++
server/src/routers/index.ts | 5 +++--
server/src/routers/linkRouter.ts | 11 +++++++++++
yarn.lock | 5 +++++
7 files changed, 50 insertions(+), 6 deletions(-)
create mode 100644 app/src/utils/trpc.ts
create mode 100644 server/src/routers/linkRouter.ts
diff --git a/app/package.json b/app/package.json
index e689a4d..9d70fd4 100644
--- a/app/package.json
+++ b/app/package.json
@@ -20,6 +20,7 @@
"@linux-odyssey/file-graph": "*",
"@linux-odyssey/models": "*",
"@linux-odyssey/utils": "*",
+ "@trpc/client": "^11.1.0",
"@types/dompurify": "^3.0.5",
"axios": "^1.6.0",
"dompurify": "^3.0.6",
diff --git a/app/src/components/header/GameHeaderComponents.vue b/app/src/components/header/GameHeaderComponents.vue
index 3789c10..1987895 100644
--- a/app/src/components/header/GameHeaderComponents.vue
+++ b/app/src/components/header/GameHeaderComponents.vue
@@ -3,7 +3,7 @@ import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useToast } from 'vue-toastification'
import { logout } from '../../utils/auth'
-import { surveyUrl } from '../../config'
+import { trpc } from '../../utils/trpc'
import { openBugReport } from '../../utils/formbricks'
import useSession from '../../store/session'
import useUserProfile from '../../store/userProfile'
@@ -26,6 +26,11 @@ const handleLogout = async () => {
}
}
+const openSurvey = async () => {
+ const surveyUrl = await trpc.links.surveyLink.query()
+ window.open(surveyUrl, '_blank')
+}
+
onMounted(async () => {
try {
await userStore.loadUserProfile()
@@ -61,18 +66,18 @@ onMounted(async () => {
>
{{ userStore.username }}
-
Survey
-
+
({
+ links: [
+ httpBatchLink({
+ url: '/trpc',
+ // You can pass any HTTP headers you wish here
+ // async headers() {
+ // return {
+ // authorization: getAuthCookie(),
+ // }
+ // },
+ }),
+ ],
+})
diff --git a/app/vite.config.ts b/app/vite.config.ts
index 433a916..f1811bb 100644
--- a/app/vite.config.ts
+++ b/app/vite.config.ts
@@ -6,6 +6,11 @@ export default defineConfig({
plugins: [vue()],
server: {
proxy: {
+ '/trpc': {
+ target: process.env.API_TARGET || 'http://localhost:3000',
+ changeOrigin: false,
+ xfwd: true,
+ },
'/api': {
target: process.env.API_TARGET || 'http://localhost:3000',
changeOrigin: false,
diff --git a/server/src/routers/index.ts b/server/src/routers/index.ts
index 1cd5c2a..2d7bd5f 100644
--- a/server/src/routers/index.ts
+++ b/server/src/routers/index.ts
@@ -1,11 +1,12 @@
import { router, publicProcedure } from '../trpc.js'
+import { linkRouter } from './linkRouter.js'
export const appRouter = router({
userList: publicProcedure.query(async (opts) => {
// Retrieve users from a datasource, this is an imaginary database
return opts.ctx
}),
+ links: linkRouter,
})
-// Export type router type signature,
-// NOT the router itself.
+
export type AppRouter = typeof appRouter
diff --git a/server/src/routers/linkRouter.ts b/server/src/routers/linkRouter.ts
new file mode 100644
index 0000000..d3221bb
--- /dev/null
+++ b/server/src/routers/linkRouter.ts
@@ -0,0 +1,11 @@
+import config from '../config.js'
+import { publicProcedure, router } from '../trpc.js'
+
+export const linkRouter = router({
+ surveyLink: publicProcedure.query(() => {
+ return config.surveyUrl
+ }),
+ bugReportLink: publicProcedure.query(() => {
+ return config.bugReportUrl
+ }),
+})
diff --git a/yarn.lock b/yarn.lock
index 61a3994..1ecf491 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1711,6 +1711,11 @@
lz-string "^1.5.0"
pretty-format "^27.0.2"
+"@trpc/client@^11.1.0":
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/@trpc/client/-/client-11.1.0.tgz#102ec1f14aa39c4caf5106c51f38a3d4bee293b0"
+ integrity sha512-Q3pL4p7AddxI/ZJTEFo1utKSdasDFjZPECIPsKDkthEt52k530JkYVltTdLkYFKrNWXKKBo8MN7NwchelczoRw==
+
"@trpc/server@^11.1.0":
version "11.1.0"
resolved "https://registry.yarnpkg.com/@trpc/server/-/server-11.1.0.tgz#8169fa8b944beddf65a95f376d4afea5732be254"
From ac92950177e83ad1064308d045131a1e61689d1f Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 16 Apr 2025 16:24:29 +0800
Subject: [PATCH 23/82] feat: migrate quest api to trpc
---
app/src/components/QuestIntro.vue | 4 +--
app/src/components/QuestMap.vue | 4 +--
app/src/store/session.ts | 9 +++---
app/src/utils/api.ts | 11 -------
packages/constants/index.ts | 2 ++
packages/constants/src/quest.ts | 6 ++++
packages/constants/tsconfig.json | 4 ++-
server/src/api/controllers/questController.ts | 28 -----------------
server/src/api/routes/index.ts | 2 --
server/src/api/routes/questRouter.ts | 10 -------
server/src/api/validators/questValidator.ts | 7 -----
server/src/api/validators/sessionValidator.ts | 7 ++---
server/src/routers/index.ts | 2 ++
server/src/routers/questRouter.ts | 30 +++++++++++++++++++
14 files changed, 55 insertions(+), 71 deletions(-)
create mode 100644 packages/constants/src/quest.ts
delete mode 100644 server/src/api/controllers/questController.ts
delete mode 100644 server/src/api/routes/questRouter.ts
delete mode 100644 server/src/api/validators/questValidator.ts
create mode 100644 server/src/routers/questRouter.ts
diff --git a/app/src/components/QuestIntro.vue b/app/src/components/QuestIntro.vue
index efb5ab7..e9f62e8 100644
--- a/app/src/components/QuestIntro.vue
+++ b/app/src/components/QuestIntro.vue
@@ -2,8 +2,8 @@
import { useRouter } from 'vue-router'
import { useToast } from 'vue-toastification'
import { ref, defineProps, onMounted } from 'vue'
-import { getQuest } from '../utils/api'
import MarkdownText from './MarkdownText.vue'
+import { trpc } from '../utils/trpc'
const props = defineProps({
questTitle: {
@@ -49,7 +49,7 @@ const handleColour = () => {
}
}
onMounted(async () => {
- const quest = await getQuest(questId)
+ const quest = await trpc.quests.getQuestDetail.query(questId)
questInstruction.value = quest.instruction
handleColour()
})
diff --git a/app/src/components/QuestMap.vue b/app/src/components/QuestMap.vue
index 95a003f..4a0846a 100644
--- a/app/src/components/QuestMap.vue
+++ b/app/src/components/QuestMap.vue
@@ -2,7 +2,7 @@
import { ref, onMounted, watch, computed } from 'vue'
import { useToast } from 'vue-toastification'
import { DAG } from '@linux-odyssey/utils'
-import { getQuests } from '../utils/api'
+import { trpc } from '../utils/trpc'
import useUserProfile from '../store/userProfile'
import QuestIntro from './QuestIntro.vue'
@@ -64,7 +64,7 @@ async function computeGraphData() {
if (!store.progress) return
try {
- const quests = await getQuests()
+ const quests = await trpc.quests.getQuests.query()
const dag = new DAG(quests)
const nodesValues = dag.getNodes()
diff --git a/app/src/store/session.ts b/app/src/store/session.ts
index d6ced19..150c064 100644
--- a/app/src/store/session.ts
+++ b/app/src/store/session.ts
@@ -1,10 +1,11 @@
import { defineStore } from 'pinia'
import { FileGraph, FileObject } from '@linux-odyssey/file-graph'
-import { IQuest } from '@linux-odyssey/models'
-import { createSession, getActiveSession, getQuest } from '../utils/api'
+import { QuestDetailResponse } from '@linux-odyssey/constants'
+import { createSession, getActiveSession } from '../utils/api'
import Socket from '../utils/socket'
import SocketTerminal from '../utils/terminal'
import { Session, StageResponse } from '../types'
+import { trpc } from '../utils/trpc'
const socket = new Socket()
const term = new SocketTerminal(40, 80)
@@ -13,7 +14,7 @@ let hasSetup = false
interface Store {
session: Session | null
questId: string
- quest: IQuest | null
+ quest: QuestDetailResponse | null
}
const useSession = defineStore('session', {
@@ -24,7 +25,7 @@ const useSession = defineStore('session', {
}),
actions: {
async setQuest(questId: string) {
- this.quest = await getQuest(questId)
+ this.quest = await trpc.quests.getQuestDetail.query(questId)
this.questId = questId
},
async setSession(session: Session) {
diff --git a/app/src/utils/api.ts b/app/src/utils/api.ts
index 81f2121..f17d3d9 100644
--- a/app/src/utils/api.ts
+++ b/app/src/utils/api.ts
@@ -1,5 +1,4 @@
import axios from 'axios'
-import { IQuest } from '@linux-odyssey/models'
import { GetSessionsRequest } from '@linux-odyssey/constants'
import { Session } from '../types'
import { UserProfile } from '../store/userProfile'
@@ -18,11 +17,6 @@ export async function getUserProfile(): Promise {
return res.data
}
-export async function getQuest(id: string): Promise {
- const res = await api.get(`/quests/${id}`)
- return res.data
-}
-
export async function createSession(questId: string): Promise {
const res = await api.post('/sessions', { questId })
return res.data
@@ -43,8 +37,3 @@ export async function getActiveSession(
})
return res.data
}
-
-export async function getQuests(): Promise {
- const res = await api.get('/quests')
- return res.data
-}
diff --git a/packages/constants/index.ts b/packages/constants/index.ts
index c555e8e..563849a 100644
--- a/packages/constants/index.ts
+++ b/packages/constants/index.ts
@@ -1,5 +1,7 @@
import { z } from 'zod'
+export * from './src/quest.js'
+
export const passwordPolicy = {
minLength: 8,
minNumbers: 1,
diff --git a/packages/constants/src/quest.ts b/packages/constants/src/quest.ts
new file mode 100644
index 0000000..69adbe0
--- /dev/null
+++ b/packages/constants/src/quest.ts
@@ -0,0 +1,6 @@
+export interface QuestDetailResponse {
+ _id: string
+ title: string
+ instruction: string
+ requirements: string[]
+}
diff --git a/packages/constants/tsconfig.json b/packages/constants/tsconfig.json
index 318a4cf..4972b05 100644
--- a/packages/constants/tsconfig.json
+++ b/packages/constants/tsconfig.json
@@ -2,8 +2,10 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"composite": true,
+ "module": "Node16",
+ "moduleResolution": "node16",
"outDir": "./dist"
},
- "include": ["*.js", "*.ts"],
+ "include": ["*.js", "*.ts", "src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
diff --git a/server/src/api/controllers/questController.ts b/server/src/api/controllers/questController.ts
deleted file mode 100644
index e9a7660..0000000
--- a/server/src/api/controllers/questController.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Quest } from '@linux-odyssey/models'
-import { matchedData } from 'express-validator'
-import type { Request, Response } from 'express'
-import { asyncHandler } from '../../middleware/error.js'
-
-export const getQuests = asyncHandler(async (req: Request, res: Response) => {
- const quests = await Quest.find({})
- res.json(
- quests.map(({ title, _id, requirements }) => ({
- _id,
- title,
- requirements,
- }))
- )
-})
-
-export const getQuestDetail = asyncHandler(
- async (req: Request, res: Response) => {
- const { questId } = matchedData(req)
- const quest = await Quest.findById(questId)
- if (!quest) {
- res.status(404).json({ message: 'Quest not found.' })
- return
- }
- const { _id, title, instruction, requirements } = quest
- res.json({ _id, title, instruction, requirements })
- }
-)
diff --git a/server/src/api/routes/index.ts b/server/src/api/routes/index.ts
index 1ced879..fb3b318 100644
--- a/server/src/api/routes/index.ts
+++ b/server/src/api/routes/index.ts
@@ -1,7 +1,6 @@
import { Router } from 'express'
import passport from 'passport'
import sessions from './sessionRouter.js'
-import quests from './questRouter.js'
import commands from './commandRouter.js'
import authRouter from './authRouter.js'
import authRequired from '../../middleware/authRequired.js'
@@ -29,7 +28,6 @@ router.use(
router.use('/auth', authRouter)
router.use('/sessions', authRequired, sessions)
-router.use('/quests', quests)
router.use('/users', userRouter)
router.get('/survey', (req, res) => {
diff --git a/server/src/api/routes/questRouter.ts b/server/src/api/routes/questRouter.ts
deleted file mode 100644
index 4749f54..0000000
--- a/server/src/api/routes/questRouter.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Router } from 'express'
-import * as questController from '../controllers/questController.js'
-import { questIdValidator } from '../validators/questValidator.js'
-
-const router = Router()
-
-router.get('/', questController.getQuests)
-router.get('/:questId', questIdValidator, questController.getQuestDetail)
-
-export default router
diff --git a/server/src/api/validators/questValidator.ts b/server/src/api/validators/questValidator.ts
deleted file mode 100644
index 3a2a18e..0000000
--- a/server/src/api/validators/questValidator.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { check } from 'express-validator'
-import { noError } from '../../middleware/validator.js'
-
-export const checkQuestId = () =>
- check('questId').notEmpty().isString().isLowercase().isLength({ max: 64 })
-
-export const questIdValidator = [checkQuestId(), noError]
diff --git a/server/src/api/validators/sessionValidator.ts b/server/src/api/validators/sessionValidator.ts
index 558b5b6..509defb 100644
--- a/server/src/api/validators/sessionValidator.ts
+++ b/server/src/api/validators/sessionValidator.ts
@@ -1,5 +1,4 @@
import { check } from 'express-validator'
-import { checkQuestId } from './questValidator.js'
import { noError } from '../../middleware/validator.js'
const checkSessionStatus = () =>
@@ -8,7 +7,7 @@ const checkSessionStatus = () =>
export const checkSessionId = () =>
check('sessionId').notEmpty().isString().isMongoId()
-export const sessionListValidator = [checkQuestId(), checkSessionStatus()]
+export const sessionListValidator = [checkSessionStatus()]
export const sessionDetailValidator = [checkSessionId()]
-export const createSessionValidator = [checkQuestId(), noError]
-export const activeSessionValidator = [checkQuestId(), noError]
+export const createSessionValidator = [noError]
+export const activeSessionValidator = [noError]
diff --git a/server/src/routers/index.ts b/server/src/routers/index.ts
index 2d7bd5f..288d2f3 100644
--- a/server/src/routers/index.ts
+++ b/server/src/routers/index.ts
@@ -1,5 +1,6 @@
import { router, publicProcedure } from '../trpc.js'
import { linkRouter } from './linkRouter.js'
+import { questRouter } from './questRouter.js'
export const appRouter = router({
userList: publicProcedure.query(async (opts) => {
@@ -7,6 +8,7 @@ export const appRouter = router({
return opts.ctx
}),
links: linkRouter,
+ quests: questRouter,
})
export type AppRouter = typeof appRouter
diff --git a/server/src/routers/questRouter.ts b/server/src/routers/questRouter.ts
new file mode 100644
index 0000000..0c39a1b
--- /dev/null
+++ b/server/src/routers/questRouter.ts
@@ -0,0 +1,30 @@
+import { TRPCError } from '@trpc/server'
+import { Quest } from '@linux-odyssey/models'
+import { QuestDetailResponse } from '@linux-odyssey/constants'
+import { z } from 'zod'
+import { router, publicProcedure } from '../trpc.js'
+
+export const questRouter = router({
+ getQuests: publicProcedure.query(async () => {
+ const quests = await Quest.find({})
+ return quests.map(({ title, _id, requirements }) => ({
+ _id,
+ title,
+ requirements,
+ }))
+ }),
+ getQuestDetail: publicProcedure
+ .input(z.string())
+ .query(async (opts): Promise => {
+ const id = opts.input
+ const quest = await Quest.findById(id)
+ if (!quest) {
+ throw new TRPCError({
+ code: 'NOT_FOUND',
+ message: 'Quest not found.',
+ })
+ }
+ const { _id, title, instruction, requirements } = quest
+ return { _id, title, instruction, requirements }
+ }),
+})
From 423548804a5a3ea5883b80bd60bebb553da40566 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 16 Apr 2025 16:40:03 +0800
Subject: [PATCH 24/82] feat: migreate get user profile to trpc
---
app/src/store/userProfile.ts | 4 +--
app/src/utils/api.ts | 6 -----
packages/models/src/index.ts | 2 +-
server/src/api/controllers/userController.ts | 20 ---------------
server/src/api/routes/index.ts | 19 --------------
server/src/api/routes/userRouter.ts | 9 -------
server/src/api/validators/questValidator.ts | 7 ++++++
server/src/api/validators/sessionValidator.ts | 7 +++---
server/src/routers/index.ts | 2 ++
server/src/routers/userRouter.ts | 25 +++++++++++++++++++
server/src/trpc.ts | 15 +++++++++--
11 files changed, 54 insertions(+), 62 deletions(-)
delete mode 100644 server/src/api/controllers/userController.ts
delete mode 100644 server/src/api/routes/userRouter.ts
create mode 100644 server/src/api/validators/questValidator.ts
create mode 100644 server/src/routers/userRouter.ts
diff --git a/app/src/store/userProfile.ts b/app/src/store/userProfile.ts
index 2a7feaf..8a6f172 100644
--- a/app/src/store/userProfile.ts
+++ b/app/src/store/userProfile.ts
@@ -1,5 +1,5 @@
import { defineStore } from 'pinia'
-import { getUserProfile } from '../utils/api'
+import { trpc } from '../utils/trpc'
interface IProgress {
quest: string
@@ -23,7 +23,7 @@ const useUserProfile = defineStore('userProfile', {
}),
actions: {
async loadUserProfile() {
- const res = await getUserProfile()
+ const res = await trpc.users.getMyProfile.query()
this.$patch(res)
},
async resetUserProfile() {
diff --git a/app/src/utils/api.ts b/app/src/utils/api.ts
index f17d3d9..5c9015f 100644
--- a/app/src/utils/api.ts
+++ b/app/src/utils/api.ts
@@ -1,7 +1,6 @@
import axios from 'axios'
import { GetSessionsRequest } from '@linux-odyssey/constants'
import { Session } from '../types'
-import { UserProfile } from '../store/userProfile'
const api = axios.create({
baseURL: '/api/v1',
@@ -12,11 +11,6 @@ const api = axios.create({
})
export default api
-export async function getUserProfile(): Promise {
- const res = await api.get('/users/me')
- return res.data
-}
-
export async function createSession(questId: string): Promise {
const res = await api.post('/sessions', { questId })
return res.data
diff --git a/packages/models/src/index.ts b/packages/models/src/index.ts
index 59332a0..014f076 100644
--- a/packages/models/src/index.ts
+++ b/packages/models/src/index.ts
@@ -4,7 +4,7 @@ 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 { UserProfile, IUserProfile, IProgress } from './userProfile.js'
export { IFileCondition, ICondition } from './condition.js'
export { IStage } from './stage.js'
export { IRequirement } from './requirement.js'
diff --git a/server/src/api/controllers/userController.ts b/server/src/api/controllers/userController.ts
deleted file mode 100644
index 220cf2c..0000000
--- a/server/src/api/controllers/userController.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { Express, Request, Response } from 'express'
-import { UserProfile } from '@linux-odyssey/models'
-import { asyncHandler } from '../../middleware/error.js'
-
-export const me = asyncHandler(async (req: Request, res: Response) => {
- const { id, username, email } = req.user as Express.ExistingUser
-
- const userProfile = await UserProfile.findOne({
- user: id,
- })
- if (!userProfile) {
- throw new Error(`UserProfile not found for user ${username} ${id}!`)
- }
- const { progress } = userProfile
- res.json({
- username,
- email,
- progress,
- })
-})
diff --git a/server/src/api/routes/index.ts b/server/src/api/routes/index.ts
index fb3b318..a9aeba6 100644
--- a/server/src/api/routes/index.ts
+++ b/server/src/api/routes/index.ts
@@ -4,7 +4,6 @@ import sessions from './sessionRouter.js'
import commands from './commandRouter.js'
import authRouter from './authRouter.js'
import authRequired from '../../middleware/authRequired.js'
-import userRouter from './userRouter.js'
import config from '../../config.js'
import leaderboardController from '../controllers/leaderboardController.js'
@@ -28,24 +27,6 @@ router.use(
router.use('/auth', authRouter)
router.use('/sessions', authRequired, sessions)
-router.use('/users', userRouter)
-
-router.get('/survey', (req, res) => {
- if (!config.surveyUrl) {
- res.status(404).send('Survey not configured')
- return
- }
- res.redirect(config.surveyUrl)
-})
-
-router.get('/bug-report', (req, res) => {
- if (!config.bugReportUrl) {
- res.status(404).send('Bug report not configured')
- return
- }
- res.redirect(config.bugReportUrl)
-})
-
router.get('/leaderboard', leaderboardController)
export default router
diff --git a/server/src/api/routes/userRouter.ts b/server/src/api/routes/userRouter.ts
deleted file mode 100644
index 235127f..0000000
--- a/server/src/api/routes/userRouter.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import express from 'express'
-import { me } from '../controllers/userController.js'
-import authRequired from '../../middleware/authRequired.js'
-
-const router = express.Router()
-
-router.get('/me', authRequired, me)
-
-export default router
diff --git a/server/src/api/validators/questValidator.ts b/server/src/api/validators/questValidator.ts
new file mode 100644
index 0000000..3a2a18e
--- /dev/null
+++ b/server/src/api/validators/questValidator.ts
@@ -0,0 +1,7 @@
+import { check } from 'express-validator'
+import { noError } from '../../middleware/validator.js'
+
+export const checkQuestId = () =>
+ check('questId').notEmpty().isString().isLowercase().isLength({ max: 64 })
+
+export const questIdValidator = [checkQuestId(), noError]
diff --git a/server/src/api/validators/sessionValidator.ts b/server/src/api/validators/sessionValidator.ts
index 509defb..558b5b6 100644
--- a/server/src/api/validators/sessionValidator.ts
+++ b/server/src/api/validators/sessionValidator.ts
@@ -1,4 +1,5 @@
import { check } from 'express-validator'
+import { checkQuestId } from './questValidator.js'
import { noError } from '../../middleware/validator.js'
const checkSessionStatus = () =>
@@ -7,7 +8,7 @@ const checkSessionStatus = () =>
export const checkSessionId = () =>
check('sessionId').notEmpty().isString().isMongoId()
-export const sessionListValidator = [checkSessionStatus()]
+export const sessionListValidator = [checkQuestId(), checkSessionStatus()]
export const sessionDetailValidator = [checkSessionId()]
-export const createSessionValidator = [noError]
-export const activeSessionValidator = [noError]
+export const createSessionValidator = [checkQuestId(), noError]
+export const activeSessionValidator = [checkQuestId(), noError]
diff --git a/server/src/routers/index.ts b/server/src/routers/index.ts
index 288d2f3..7e18636 100644
--- a/server/src/routers/index.ts
+++ b/server/src/routers/index.ts
@@ -1,6 +1,7 @@
import { router, publicProcedure } from '../trpc.js'
import { linkRouter } from './linkRouter.js'
import { questRouter } from './questRouter.js'
+import { userRouter } from './userRouter.js'
export const appRouter = router({
userList: publicProcedure.query(async (opts) => {
@@ -9,6 +10,7 @@ export const appRouter = router({
}),
links: linkRouter,
quests: questRouter,
+ users: userRouter,
})
export type AppRouter = typeof appRouter
diff --git a/server/src/routers/userRouter.ts b/server/src/routers/userRouter.ts
new file mode 100644
index 0000000..46c0977
--- /dev/null
+++ b/server/src/routers/userRouter.ts
@@ -0,0 +1,25 @@
+import { UserProfile } from '@linux-odyssey/models'
+import { TRPCError } from '@trpc/server'
+import { protectedProcedure, router } from '../trpc.js'
+
+export const userRouter = router({
+ getMyProfile: protectedProcedure.query(async (opts) => {
+ const { id, username, email } = opts.ctx.user
+
+ const userProfile = await UserProfile.findOne({
+ user: id,
+ })
+ if (!userProfile) {
+ throw new TRPCError({
+ code: 'NOT_FOUND',
+ message: `UserProfile not found for user ${username} ${id}!`,
+ })
+ }
+ const { progress } = userProfile
+ return {
+ username,
+ email,
+ progress,
+ }
+ }),
+})
diff --git a/server/src/trpc.ts b/server/src/trpc.ts
index f2d2ecd..8e7c939 100644
--- a/server/src/trpc.ts
+++ b/server/src/trpc.ts
@@ -1,12 +1,13 @@
-import { initTRPC } from '@trpc/server'
+import { initTRPC, TRPCError } from '@trpc/server'
import { CreateNextContextOptions } from '@trpc/server/adapters/next'
export const createContext = async (opts: CreateNextContextOptions) => {
- const { session, user, ip } = opts.req
+ const { session, user, ip, isAuthenticated } = opts.req
return {
session,
user,
ip,
+ isAuthenticated,
}
}
@@ -18,3 +19,13 @@ const t = initTRPC.context().create()
* that can be used throughout the router
*/
export const { router, procedure: publicProcedure } = t
+
+export const protectedProcedure = publicProcedure.use(async (opts) => {
+ if (opts.ctx.isAuthenticated() && !('newUser' in opts.ctx.user)) {
+ return opts.next()
+ }
+ throw new TRPCError({
+ code: 'UNAUTHORIZED',
+ message: 'Login required',
+ })
+})
From 963655c1f7ed3271cfc675117c108ed6cb107fe6 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 16 Apr 2025 16:58:24 +0800
Subject: [PATCH 25/82] wip: get active session
---
app/src/store/session.ts | 2 +-
app/src/utils/api.ts | 8 -----
app/src/views/RegisterPage.vue | 2 +-
packages/constants/{ => src}/index.ts | 3 +-
packages/constants/src/session.ts | 15 +++++++++
packages/constants/tsconfig.json | 3 +-
server/src/routers/sessionRouter.ts | 48 +++++++++++++++++++++++++++
7 files changed, 69 insertions(+), 12 deletions(-)
rename packages/constants/{ => src}/index.ts (89%)
create mode 100644 packages/constants/src/session.ts
create mode 100644 server/src/routers/sessionRouter.ts
diff --git a/app/src/store/session.ts b/app/src/store/session.ts
index 150c064..64d74dc 100644
--- a/app/src/store/session.ts
+++ b/app/src/store/session.ts
@@ -1,6 +1,6 @@
import { defineStore } from 'pinia'
import { FileGraph, FileObject } from '@linux-odyssey/file-graph'
-import { QuestDetailResponse } from '@linux-odyssey/constants'
+import { QuestDetailResponse } from '../../../packages/constants/dist/src'
import { createSession, getActiveSession } from '../utils/api'
import Socket from '../utils/socket'
import SocketTerminal from '../utils/terminal'
diff --git a/app/src/utils/api.ts b/app/src/utils/api.ts
index 5c9015f..19c589e 100644
--- a/app/src/utils/api.ts
+++ b/app/src/utils/api.ts
@@ -1,5 +1,4 @@
import axios from 'axios'
-import { GetSessionsRequest } from '@linux-odyssey/constants'
import { Session } from '../types'
const api = axios.create({
@@ -16,13 +15,6 @@ export async function createSession(questId: string): Promise {
return res.data
}
-export async function getSessions(
- request: GetSessionsRequest
-): Promise {
- const res = await api.get('/sessions', { params: request })
- return res.data
-}
-
export async function getActiveSession(
questId: string
): Promise {
diff --git a/app/src/views/RegisterPage.vue b/app/src/views/RegisterPage.vue
index 6fd0d67..36b73d8 100644
--- a/app/src/views/RegisterPage.vue
+++ b/app/src/views/RegisterPage.vue
@@ -1,7 +1,7 @@
@@ -69,21 +73,19 @@ const right = () => {
diff --git a/app/src/components/game/QuestPart.vue b/app/src/components/game/QuestPart.vue
index f1cb41f..0b04f1b 100644
--- a/app/src/components/game/QuestPart.vue
+++ b/app/src/components/game/QuestPart.vue
@@ -2,11 +2,10 @@
import { computed } from 'vue'
import MarkdownText from '../MarkdownText.vue'
import useSession from '../../store/session'
-import { Task } from '../../types'
const sessionStore = useSession()
const tasks = computed(() => {
- return sessionStore.session?.tasks.map((task: Task) => {
+ return sessionStore.session?.tasks.map((task) => {
const prefix = task.completed ? '✓' : '➤'
const color = task.completed ? 'text-text-primary' : 'text-text'
return {
diff --git a/app/src/store/session.ts b/app/src/store/session.ts
index 64d74dc..1a34bb9 100644
--- a/app/src/store/session.ts
+++ b/app/src/store/session.ts
@@ -1,16 +1,23 @@
import { defineStore } from 'pinia'
import { FileGraph, FileObject } from '@linux-odyssey/file-graph'
-import { QuestDetailResponse } from '../../../packages/constants/dist/src'
+import { IResponse, ITask } from '@linux-odyssey/game'
import { createSession, getActiveSession } from '../utils/api'
import Socket from '../utils/socket'
import SocketTerminal from '../utils/terminal'
-import { Session, StageResponse } from '../types'
+import { Session } from '../types'
import { trpc } from '../utils/trpc'
const socket = new Socket()
const term = new SocketTerminal(40, 80)
let hasSetup = false
+interface QuestDetailResponse {
+ id: string
+ title: string
+ instruction: string
+ requirements: string[]
+}
+
interface Store {
session: Session | null
questId: string
@@ -30,7 +37,7 @@ const useSession = defineStore('session', {
},
async setSession(session: Session) {
this.session = session
- this.session.graph = new FileGraph(session.graph)
+ // this.session.graph = new FileGraph(session.graph)
term.reset()
await socket.connect(session)
term.focus()
@@ -55,22 +62,29 @@ const useSession = defineStore('session', {
this.session.pwd = event.pwd
}
},
- newResponse(response: StageResponse) {
+ newResponse(responses: IResponse[]) {
if (!this.session) return
- this.session.responses.push(response.responses)
- this.session.hints.push(response.hints)
- if (response.tasks) {
- this.session.tasks = response.tasks
- }
- if (
- response.status === 'finished' &&
- this.session.status !== 'finished'
- ) {
- this.finish()
- }
- this.session.status = response.status
+ this.session.responses = responses
+ // this.session.hints.push(response.hints)
+ // if (response.tasks) {
+ // this.session.tasks = response.tasks
+ // }
+ // if (
+ // response.status === 'finished' &&
+ // this.session.status !== 'finished'
+ // ) {
+ // this.finish()
+ // }
+ // this.session.status = response.status
+ },
+ newTask(tasks: ITask[]) {
+ if (!this.session) return
+ this.session.tasks = tasks
+ },
+ finish() {
+ if (!this.session) return
+ this.session.status = 'finished'
},
- finish() {},
reset() {
socket.reset()
term.reset()
@@ -87,8 +101,11 @@ const useSession = defineStore('session', {
socket.on('graph', (event: { discover: FileObject[]; pwd: string }) => {
this.updateGraph(event)
})
- socket.on('response', (response: StageResponse) => {
- this.newResponse(response)
+ socket.on('response', (responses: IResponse[]) => {
+ this.newResponse(responses)
+ })
+ socket.on('task', (tasks: ITask[]) => {
+ this.newTask(tasks)
})
hasSetup = true
},
diff --git a/app/src/types.ts b/app/src/types.ts
index e814aea..b5630c2 100644
--- a/app/src/types.ts
+++ b/app/src/types.ts
@@ -1,6 +1,5 @@
import { FileGraph } from '@linux-odyssey/file-graph'
-// eslint-disable-next-line import/no-relative-packages
-import { IResponse } from '@linux-odyssey/models'
+import { IResponse, ITask } from '@linux-odyssey/game'
export interface Task {
id: number
@@ -21,6 +20,6 @@ export interface Session {
graph: FileGraph
pwd: string
hints: string[][]
- tasks: Task[]
- responses: IResponse[][]
+ tasks: ITask[]
+ responses: IResponse[]
}
diff --git a/app/src/views/GamePage.vue b/app/src/views/GamePage.vue
index ad7cc2b..209130f 100644
--- a/app/src/views/GamePage.vue
+++ b/app/src/views/GamePage.vue
@@ -84,7 +84,7 @@ onMounted(async () => {
diff --git a/app/src/views/RegisterPage.vue b/app/src/views/RegisterPage.vue
index 36b73d8..6fd0d67 100644
--- a/app/src/views/RegisterPage.vue
+++ b/app/src/views/RegisterPage.vue
@@ -1,7 +1,7 @@
@@ -41,7 +45,9 @@ const response = computed(() => {
:icon="['far', 'lightbulb']"
class="text-yellow-200 p-2 content-center"
/>
- 說明
+
+ 說明 {{ current }}/{{ length }}
+
diff --git a/quests/cast/game.yml b/quests/cast/game.yml
index dd88726..897e8a6 100644
--- a/quests/cast/game.yml
+++ b/quests/cast/game.yml
@@ -34,7 +34,7 @@ stages:
你應該可以看到終端機上顯示了你在 `echo` 指令後面的文字。
接下來,請你試著在終端機上顯示 `How are you?`。
hint: |
- 利用 `echo` 指令來在終端機上顯示 `How are you?`
+ 輸入 `echo How are you?`
- id: END
name: 在終端機上顯示 `How are you?`
From 56049a0a29ffa9949aa075df939804ebaeac2bf9 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Wed, 23 Apr 2025 17:58:24 +0800
Subject: [PATCH 52/82] fix: DAG setLayer logic
---
packages/utils/src/dag.ts | 6 +--
packages/utils/tests/dag.test.ts | 68 ++++++++++++++++----------------
2 files changed, 37 insertions(+), 37 deletions(-)
diff --git a/packages/utils/src/dag.ts b/packages/utils/src/dag.ts
index f5fcb07..651ec70 100644
--- a/packages/utils/src/dag.ts
+++ b/packages/utils/src/dag.ts
@@ -18,10 +18,10 @@ export default class DAG {
nodes.map((node) => [node.id, { ...node, layer: 0, index: 0 }])
)
this.edges = new Set<[string, string]>()
- this.nodes.forEach((_, id) => {
+ for (const id of this.nodes.keys()) {
this.setLayer(id)
this.addEdges(id)
- })
+ }
}
getNode(id: string) {
@@ -57,7 +57,7 @@ export default class DAG {
if (!node) {
throw new Error(`Node ${id} not found`)
}
- if (node.layer !== undefined) {
+ if (node.layer !== 0) {
return node.layer
}
const previousLayer = node.requirements.map((rId: string) =>
diff --git a/packages/utils/tests/dag.test.ts b/packages/utils/tests/dag.test.ts
index fbe860d..80b4f05 100644
--- a/packages/utils/tests/dag.test.ts
+++ b/packages/utils/tests/dag.test.ts
@@ -5,82 +5,82 @@ describe('dag layers', () => {
it('two layer', () => {
const data = [
{
- _id: 'helloworld',
+ id: 'helloworld',
requirements: [],
},
{
- _id: 'spell',
+ id: 'spell',
requirements: ['helloworld'],
},
]
const dag = new DAG(data)
- expect(dag.getNode('helloworld').layer).toBe(1)
- expect(dag.getNode('spell').layer).toBe(2)
+ expect(dag.getNode('helloworld')?.layer).toBe(1)
+ expect(dag.getNode('spell')?.layer).toBe(2)
})
it('branch', () => {
const data = [
{
- _id: 'helloworld',
+ id: 'helloworld',
requirements: [],
},
{
- _id: 'spell',
+ id: 'spell',
requirements: ['helloworld'],
},
{
- _id: 'discover',
+ id: 'discover',
requirements: ['helloworld'],
},
]
const dag = new DAG(data)
- expect(dag.getNode('helloworld').layer).toBe(1)
- expect(dag.getNode('spell').layer).toBe(2)
- expect(dag.getNode('discover').layer).toBe(2)
+ expect(dag.getNode('helloworld')?.layer).toBe(1)
+ expect(dag.getNode('spell')?.layer).toBe(2)
+ expect(dag.getNode('discover')?.layer).toBe(2)
})
it('merge', () => {
const data = [
{
- _id: 'A',
+ id: 'A',
requirements: [],
},
{
- _id: 'B',
+ id: 'B',
requirements: [],
},
{
- _id: 'C',
+ id: 'C',
requirements: ['A', 'B'],
},
]
const dag = new DAG(data)
- expect(dag.getNode('A').layer).toBe(1)
- expect(dag.getNode('B').layer).toBe(1)
- expect(dag.getNode('C').layer).toBe(2)
+ expect(dag.getNode('A')?.layer).toBe(1)
+ expect(dag.getNode('B')?.layer).toBe(1)
+ expect(dag.getNode('C')?.layer).toBe(2)
})
it('skip', () => {
const data = [
{
- _id: 'A',
+ id: 'A',
requirements: [],
},
{
- _id: 'B',
+ id: 'B',
requirements: [],
},
{
- _id: 'C',
+ id: 'C',
requirements: ['A'],
},
{
- _id: 'D',
+ id: 'D',
requirements: ['B', 'C'],
},
]
const dag = new DAG(data)
- expect(dag.getNode('A').layer).toBe(1)
- expect(dag.getNode('B').layer).toBe(1)
- expect(dag.getNode('C').layer).toBe(2)
- expect(dag.getNode('D').layer).toBe(3)
+ expect(dag.getNode('A')?.layer).toBe(1)
+ expect(dag.getNode('B')?.layer).toBe(1)
+ expect(dag.getNode('C')?.layer).toBe(2)
+ expect(dag.getNode('D')?.layer).toBe(3)
})
})
@@ -88,11 +88,11 @@ describe('dag edges', () => {
it('one edge', () => {
const data = [
{
- _id: 'helloworld',
+ id: 'helloworld',
requirements: [],
},
{
- _id: 'spell',
+ id: 'spell',
requirements: ['helloworld'],
},
]
@@ -104,15 +104,15 @@ describe('dag edges', () => {
it('branch edges', () => {
const data = [
{
- _id: 'helloworld',
+ id: 'helloworld',
requirements: [],
},
{
- _id: 'spell',
+ id: 'spell',
requirements: ['helloworld'],
},
{
- _id: 'discover',
+ id: 'discover',
requirements: ['helloworld'],
},
]
@@ -131,11 +131,11 @@ describe('dag layers', () => {
it('two layer', () => {
const data = [
{
- _id: 'helloworld',
+ id: 'helloworld',
requirements: [],
},
{
- _id: 'spell',
+ id: 'spell',
requirements: ['helloworld'],
},
]
@@ -147,15 +147,15 @@ describe('dag layers', () => {
it('branch layers', () => {
const data = [
{
- _id: 'helloworld',
+ id: 'helloworld',
requirements: [],
},
{
- _id: 'spell',
+ id: 'spell',
requirements: ['helloworld'],
},
{
- _id: 'discover',
+ id: 'discover',
requirements: ['helloworld'],
},
]
From 0685d712990b732a33069996257d05deab5293c7 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Thu, 24 Apr 2025 18:08:09 +0800
Subject: [PATCH 53/82] refactor: remove print.js and simplify response
handling in cli.js
---
packages/container/cli.js | 26 +-------
packages/container/print.js | 115 ------------------------------------
2 files changed, 1 insertion(+), 140 deletions(-)
delete mode 100644 packages/container/print.js
diff --git a/packages/container/cli.js b/packages/container/cli.js
index e8397b5..3f303af 100644
--- a/packages/container/cli.js
+++ b/packages/container/cli.js
@@ -3,7 +3,6 @@ const fs = require('fs').promises
const { exit } = require('process')
const minimist = require('minimist')
const axios = require('axios')
-const { colorize, printResponses, printHints } = require('./print.js')
const discoverFiles = require('./discover.js')
const {
@@ -46,19 +45,6 @@ async function handleCommand(command) {
}, {})
}
-async function handleResponse({ responses, hints, end }) {
- if (responses) {
- await printResponses(responses, 90)
- }
- if (hints) {
- await printHints(hints, 90)
- }
- if (end) {
- console.log(colorize('Quest completed!', 'blue'))
- }
- await api.post('/commands/completed')
-}
-
async function main() {
if (!CMD_NAME) exit(0)
@@ -74,17 +60,7 @@ async function main() {
pwd: PWD,
params,
}
- try {
- const res = await api.post('/commands', payload)
- if (!res.data || !res.data.responses) return
- await handleResponse(res.data)
- } catch (err) {
- if (err.response) {
- console.error(err.response.data)
- return
- }
- console.error(err.message)
- }
+ await api.post('/commands', payload)
}
main()
diff --git a/packages/container/print.js b/packages/container/print.js
deleted file mode 100644
index 8f3eee3..0000000
--- a/packages/container/print.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* eslint-disable no-restricted-syntax */
-/* eslint-disable no-await-in-loop */
-const readline = require('readline')
-
-const RETURN_SYMBOL = '\u21B5'
-
-// ANSI color map
-const ANSI_COLORS = {
- default: 0,
- black: 30,
- red: 31,
- green: 32,
- yellow: 33,
- blue: 34,
- magenta: 35,
- cyan: 36,
- white: 37,
-}
-
-function colorCode(color) {
- return `\x1b[${ANSI_COLORS[color]}m`
-}
-
-function colorize(content, color) {
- if (!color) return content
- return `${colorCode(color)}${content}${colorCode('default')}`
-}
-
-process.stdin.setRawMode(true)
-
-const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- terminal: false,
-})
-
-function waitForEnter() {
- return new Promise((resolve) => {
- rl.once('line', resolve)
- })
-}
-
-function formatLine(content, color) {
- let result = colorCode(color)
- let codeBlock = false
- for (const c of content) {
- switch (c) {
- case '`':
- result += colorCode(codeBlock ? color : 'green')
- codeBlock = !codeBlock
- break
-
- default:
- result += c
- }
- }
- return result + colorCode('default') + RETURN_SYMBOL
-}
-
-function printLine(content, delay, color) {
- const printContent = formatLine(content, color)
- return new Promise((resolve) => {
- let i = 0
- const timer = setInterval(() => {
- process.stdout.write(printContent[i])
- i += 1
- if (i >= printContent.length) {
- clearInterval(timer)
- process.stdout.write('\n')
- resolve()
- }
- }, delay)
-
- waitForEnter().then(() => {
- clearInterval(timer)
- if (i >= printContent.length) return
- process.stdout.write(printContent.slice(i))
- process.stdout.write('\n')
- resolve()
- })
- })
-}
-
-async function printResponses(responses, delay = 100) {
- console.log()
- console.log(colorize('==============================', 'green'))
- for (const response of responses) {
- const { type, content, speaker, color } = response
- if (type === 'narrative') {
- for (const line of content) {
- await printLine(line, delay, color || 'cyan')
- }
- }
- if (type === 'dialogue') {
- console.log(colorize(`${speaker}:`, 'green'))
- for (const line of content) {
- await printLine(` ${line}`, delay, color || 'cyan')
- }
- }
- console.log(colorize('------------------------------', 'green'))
- console.log()
- }
-}
-
-async function printHints(hints, delay = 100) {
- for (const hint of hints) {
- await printLine(hint, delay, 'yellow')
- }
-}
-
-module.exports = {
- printResponses,
- printHints,
- colorize,
-}
From 7e50c8e06c7bf45470d652014b760508472171ad Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Thu, 24 Apr 2025 18:10:47 +0800
Subject: [PATCH 54/82] refactor: remove condition tests and update file node
interfaces in game session
TODO: replace "folder" with "directory"
---
packages/constants/tests/condition.test.ts | 13 ---------
packages/file-graph/src/index.ts | 4 +--
packages/game/src/Session.ts | 12 ++++----
packages/game/src/schema/command.ts | 23 +++++++++++++++
packages/game/src/schema/index.ts | 12 ++------
.../src/api/controllers/commandController.ts | 28 ++++++++-----------
6 files changed, 46 insertions(+), 46 deletions(-)
delete mode 100644 packages/constants/tests/condition.test.ts
create mode 100644 packages/game/src/schema/command.ts
diff --git a/packages/constants/tests/condition.test.ts b/packages/constants/tests/condition.test.ts
deleted file mode 100644
index 60b388a..0000000
--- a/packages/constants/tests/condition.test.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { describe, it, expect } from '@jest/globals'
-import { conditionSchema } from '../src/index.js'
-
-describe('parsing condition', () => {
- it('should parse condition', () => {
- const condition = {
- command: ['^echo start$'],
- output: ['^start$'],
- }
- const result = conditionSchema.safeParse(condition)
- expect(result.error).toBeUndefined()
- })
-})
diff --git a/packages/file-graph/src/index.ts b/packages/file-graph/src/index.ts
index 40b8ea8..d3f4a64 100644
--- a/packages/file-graph/src/index.ts
+++ b/packages/file-graph/src/index.ts
@@ -2,9 +2,9 @@ export { default as File, FileObject } from './file.js'
export { default as FileNode } from './fileNode.js'
export { default as FileGraph, Event } from './fileGraph.js'
-export interface INode {
+export interface IFileNode {
path: string
type: string
discovered: boolean
- children?: INode[]
+ children?: IFileNode[]
}
diff --git a/packages/game/src/Session.ts b/packages/game/src/Session.ts
index 4b5c088..011e80e 100644
--- a/packages/game/src/Session.ts
+++ b/packages/game/src/Session.ts
@@ -1,4 +1,4 @@
-import { FileGraph, INode } from '@linux-odyssey/file-graph'
+import { FileGraph, FileNode, IFileNode } from '@linux-odyssey/file-graph'
import { Quest } from './Quest'
import {
IQuest,
@@ -15,13 +15,15 @@ export class GameSession {
private graph: FileGraph
constructor(
- { completedEvents, graph }: ISession,
+ { completedEvents, graph }: Partial,
quest: IQuest,
checker: IFileExistenceChecker
) {
- this.completed = completedEvents
+ this.completed = completedEvents || []
this.quest = new Quest(quest, checker)
- this.graph = new FileGraph(graph)
+ this.graph = new FileGraph(
+ graph ?? new FileNode({ path: '/', type: 'root', discovered: false })
+ )
}
get completedEvents() {
@@ -56,7 +58,7 @@ export class GameSession {
return this.quest.getTasks(this.completed)
}
- getGraph(): INode {
+ getGraph(): IFileNode {
return this.graph
}
}
diff --git a/packages/game/src/schema/command.ts b/packages/game/src/schema/command.ts
new file mode 100644
index 0000000..02231d2
--- /dev/null
+++ b/packages/game/src/schema/command.ts
@@ -0,0 +1,23 @@
+import { z } from 'zod'
+
+const fileSchema = z.object({
+ path: z.string(),
+ type: z.enum(['file', 'directory']),
+ discovered: z.boolean(),
+})
+
+export const commandParamsSchema = z.object({
+ discover: fileSchema.array().optional(),
+})
+
+export type ICommandParams = z.infer
+
+export const commandSchema = z.object({
+ command: z.string().optional(),
+ output: z.string().optional(),
+ error: z.string().optional(),
+ pwd: z.string().optional(),
+ params: commandParamsSchema.optional(),
+})
+
+export type ICommand = z.infer
diff --git a/packages/game/src/schema/index.ts b/packages/game/src/schema/index.ts
index 783c5c9..46a5859 100644
--- a/packages/game/src/schema/index.ts
+++ b/packages/game/src/schema/index.ts
@@ -1,4 +1,4 @@
-import { INode } from '@linux-odyssey/file-graph'
+import { IFileNode } from '@linux-odyssey/file-graph'
export * from './condition.js'
export * from './stage.js'
@@ -6,17 +6,11 @@ export * from './requirements.js'
export * from './response.js'
export * from './quest.js'
export * from './exception.js'
-
-export interface ICommand {
- command?: string
- output?: string
- error?: string
- pwd?: string
-}
+export * from './command.js'
export interface ISession {
completedEvents: string[]
- graph: INode
+ graph: IFileNode
}
export interface ITask {
diff --git a/server/src/api/controllers/commandController.ts b/server/src/api/controllers/commandController.ts
index 68cd71e..2784af4 100644
--- a/server/src/api/controllers/commandController.ts
+++ b/server/src/api/controllers/commandController.ts
@@ -1,6 +1,5 @@
-import { GameSession } from '@linux-odyssey/game'
+import { GameSession, commandSchema } from '@linux-odyssey/game'
import { Command, Session } from '@linux-odyssey/models'
-import { matchedData } from 'express-validator'
import type { Request, Response } from 'express'
import { pushToSession } from '../socket.js'
import { finishSession } from '../../models/sessionManager.js'
@@ -9,7 +8,7 @@ import { questManager } from '../../models/quest.js'
import { CLIFileExistenceChecker } from '../../containers/cli.js'
export const newCommand = asyncHandler(async (req: Request, res: Response) => {
- const { command, pwd, output, error, params } = matchedData(req)
+ const command = commandSchema.parse(req.body)
console.log('command', command)
@@ -31,16 +30,6 @@ export const newCommand = asyncHandler(async (req: Request, res: Response) => {
session.lastActivityAt = new Date()
- const c = new Command({
- session,
- command,
- pwd,
- output,
- error,
- })
-
- await c.save()
-
const quest = await questManager.get(session.quest)
if (!quest) {
res.status(404).json({ message: 'quest not found' })
@@ -53,12 +42,17 @@ export const newCommand = asyncHandler(async (req: Request, res: Response) => {
new CLIFileExistenceChecker()
)
- const event = await gameSession.runCommand(c)
+ const event = await gameSession.runCommand(command)
console.log('event', event)
- if (event) {
- c.stage = event
- await c.save()
+ const c = new Command({
+ ...command,
+ session: sessionId,
+ stage: event,
+ })
+
+ await c.save()
+ if (event) {
session.completedEvents = gameSession.completedEvents
if (gameSession.isFinished()) {
From cdd22634e0a8d1c5cb1d705f8d1131527e6aa4b7 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Thu, 24 Apr 2025 21:24:55 +0800
Subject: [PATCH 55/82] refactor: replace "folder" with "directory" across file
handling components and tests
---
app/src/components/FileNode.vue | 4 +-
packages/container/discover.js | 2 +-
packages/file-graph/src/file.ts | 6 +-
packages/file-graph/src/fileGraph.ts | 2 +-
packages/file-graph/src/fileNode.ts | 2 +-
packages/file-graph/tests/file.test.ts | 2 +-
packages/file-graph/tests/fileGraph.test.ts | 33 +++++-----
packages/file-graph/tests/fileNode.test.ts | 60 ++++++++---------
packages/game/quest.json | 48 +++-----------
packages/game/src/schema/condition.ts | 2 +-
packages/game/test/asyncCondition.test.ts | 6 +-
packages/models/src/session.ts | 2 +-
packages/utils/src/commands.ts | 2 +-
packages/utils/tests/commands.test.ts | 2 +-
quests/cast/game.yml | 4 +-
quests/get-started/answer.sh | 4 ++
quests/get-started/game.yml | 71 +++++++++++++++++++++
server/src/containers/docker.ts | 2 +-
18 files changed, 150 insertions(+), 104 deletions(-)
create mode 100644 quests/get-started/answer.sh
create mode 100644 quests/get-started/game.yml
diff --git a/app/src/components/FileNode.vue b/app/src/components/FileNode.vue
index 45f556f..3744fdf 100644
--- a/app/src/components/FileNode.vue
+++ b/app/src/components/FileNode.vue
@@ -22,8 +22,8 @@ function nodeClass() {
{
diff --git a/packages/file-graph/src/fileNode.ts b/packages/file-graph/src/fileNode.ts
index 7c64fe1..6b45456 100644
--- a/packages/file-graph/src/fileNode.ts
+++ b/packages/file-graph/src/fileNode.ts
@@ -45,7 +45,7 @@ export default class FileNode extends File {
} else if (makeParents) {
const parent = new FileNode({
path: parentPath,
- type: 'folder',
+ type: 'directory',
discovered: false,
children: [file],
})
diff --git a/packages/file-graph/tests/file.test.ts b/packages/file-graph/tests/file.test.ts
index 57eba95..e33907f 100644
--- a/packages/file-graph/tests/file.test.ts
+++ b/packages/file-graph/tests/file.test.ts
@@ -4,7 +4,7 @@ import File from '../src/file.js'
describe('File', () => {
let file: File
beforeEach(() => {
- file = new File({ path: '/home/user', type: 'folder', discovered: true })
+ file = new File({ path: '/home/user', type: 'directory', discovered: true })
})
const filesToCompare = [
diff --git a/packages/file-graph/tests/fileGraph.test.ts b/packages/file-graph/tests/fileGraph.test.ts
index c9ff417..195f631 100644
--- a/packages/file-graph/tests/fileGraph.test.ts
+++ b/packages/file-graph/tests/fileGraph.test.ts
@@ -1,6 +1,7 @@
import { describe, test, expect } from '@jest/globals'
import FileGraph from '../src/fileGraph.js'
import FileNode from '../src/fileNode.js'
+import { FileObject } from '../src/file.js'
describe('FileGraph', () => {
let root: FileNode
@@ -8,7 +9,7 @@ describe('FileGraph', () => {
beforeEach(() => {
root = new FileNode({
path: '/',
- type: 'folder',
+ type: 'directory',
discovered: true,
})
})
@@ -16,7 +17,7 @@ describe('FileGraph', () => {
test('add files to graph', () => {
const fileGraph = new FileGraph(root)
- const filesToAdd = [
+ const filesToAdd: FileObject[] = [
{
path: '/home/user/file1.txt',
type: 'file',
@@ -24,7 +25,7 @@ describe('FileGraph', () => {
},
{
path: '/home/user/folder1',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
]
@@ -41,12 +42,12 @@ describe('FileGraph', () => {
const filesToAdd = [
{
path: '/home/user/folder1',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
path: '/home/user/folder2',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
@@ -61,22 +62,22 @@ describe('FileGraph', () => {
},
]
- fileGraph.add(filesToAdd)
+ fileGraph.add(filesToAdd as FileObject[])
const filesToRemove = [
{
path: '/home/user/folder1/file1.txt',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
path: '/home/user/folder2',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
]
- fileGraph.remove(filesToRemove)
+ fileGraph.remove(filesToRemove as FileObject[])
expect(fileGraph.children[0].children[0].children.length).toBe(1)
expect(fileGraph.children[0].children[0].children[0].name).toBe('folder1')
@@ -90,7 +91,7 @@ describe('FileGraph', () => {
const discoverFiles = [
{
path: '/home/user/folder1',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
@@ -110,7 +111,7 @@ describe('FileGraph', () => {
},
]
- fileGraph.discover(discoverFiles)
+ fileGraph.discover(discoverFiles as FileObject[])
expect(fileGraph.children[0].children[0].children[0].children.length).toBe(
3
)
@@ -122,12 +123,12 @@ describe('FileGraph', () => {
const filesToAdd = [
{
path: '/home/user/folder1',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
path: '/home/user/folder2',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
@@ -142,12 +143,12 @@ describe('FileGraph', () => {
},
]
- fileGraph.add(filesToAdd)
+ fileGraph.add(filesToAdd as FileObject[])
const newFiles = [
{
path: '/home/user/folder1',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
@@ -167,7 +168,7 @@ describe('FileGraph', () => {
},
]
- fileGraph.discover(newFiles)
+ fileGraph.discover(newFiles as FileObject[])
expect(fileGraph.children[0].children[0].children.length).toBe(2)
expect(fileGraph.children[0].children[0].children[0].children.length).toBe(
diff --git a/packages/file-graph/tests/fileNode.test.ts b/packages/file-graph/tests/fileNode.test.ts
index 14c6818..6f4afd9 100644
--- a/packages/file-graph/tests/fileNode.test.ts
+++ b/packages/file-graph/tests/fileNode.test.ts
@@ -43,7 +43,7 @@ describe('FileNode', () => {
rootNode = new FileNode({
path: '/home/rudeus',
name: 'rudeus',
- type: 'folder',
+ type: 'directory',
discovered: true,
})
})
@@ -51,7 +51,7 @@ describe('FileNode', () => {
test('should throw error when adding duplicate item', () => {
const child = {
path: '/home/rudeus/test',
- type: 'folder',
+ type: 'directory',
discovered: true,
}
@@ -70,7 +70,7 @@ describe('FileNode', () => {
const child = {
path: '/home/rudeus/alphabet/test',
name: 'test',
- type: 'folder',
+ type: 'directory',
discovered: true,
}
@@ -91,7 +91,7 @@ describe('FileNode', () => {
{
path: '/home/rudeus/test',
name: 'test',
- type: 'folder',
+ type: 'directory',
discovered: true,
},
{
@@ -131,21 +131,21 @@ describe('FileNode', () => {
test('merge-subtree', () => {
const root = {
path: '/',
- type: 'folder',
+ type: 'directory',
discovered: true,
}
const files1 = [
root,
{ path: '/a', type: 'file', discovered: true },
- { path: '/b', type: 'folder', discovered: true },
- { path: '/b/c', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
+ { path: '/b/c', type: 'directory', discovered: true },
{ path: '/b/d', type: 'file', discovered: true },
{ path: '/b/c/f', type: 'file', discovered: true },
]
const files2 = [
- { path: '/b', type: 'folder', discovered: true },
- { path: '/b/c', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
+ { path: '/b/c', type: 'directory', discovered: true },
{ path: '/b/e', type: 'file', discovered: true },
{ path: '/b/c/g', type: 'file', discovered: true },
]
@@ -153,8 +153,8 @@ describe('FileNode', () => {
const expected = [
root,
{ path: '/a', type: 'file', discovered: true },
- { path: '/b', type: 'folder', discovered: true },
- { path: '/b/c', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
+ { path: '/b/c', type: 'directory', discovered: true },
{ path: '/b/e', type: 'file', discovered: true },
{ path: '/b/c/g', type: 'file', discovered: true },
]
@@ -168,29 +168,29 @@ describe('FileNode', () => {
// The original tree should keep the children that are not in the node to merge
const root = {
path: '/',
- type: 'folder',
+ type: 'directory',
discovered: true,
}
const files1 = [
root,
{ path: '/a', type: 'file', discovered: true },
- { path: '/b', type: 'folder', discovered: true },
- { path: '/b/c', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
+ { path: '/b/c', type: 'directory', discovered: true },
{ path: '/b/d', type: 'file', discovered: true },
{ path: '/b/c/f', type: 'file', discovered: true },
]
const files2 = [
- { path: '/b', type: 'folder', discovered: true },
- { path: '/b/c', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
+ { path: '/b/c', type: 'directory', discovered: true },
{ path: '/b/e', type: 'file', discovered: true },
]
const expected = [
root,
{ path: '/a', type: 'file', discovered: true },
- { path: '/b', type: 'folder', discovered: true },
- { path: '/b/c', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
+ { path: '/b/c', type: 'directory', discovered: true },
{ path: '/b/e', type: 'file', discovered: true },
{ path: '/b/c/f', type: 'file', discovered: true },
]
@@ -201,19 +201,19 @@ describe('FileNode', () => {
test('merge-hidden', () => {
const root = {
path: '/',
- type: 'folder',
+ type: 'directory',
discovered: true,
}
const files1 = [
root,
{ path: '/a', type: 'file', discovered: true },
{ path: '/.b', type: 'file', discovered: false },
- { path: '/c', type: 'folder', discovered: true },
+ { path: '/c', type: 'directory', discovered: true },
{ path: '/c/.d', type: 'file', discovered: false },
]
const files2 = [
- { path: '/c', type: 'folder', discovered: true },
+ { path: '/c', type: 'directory', discovered: true },
{ path: '/c/.d', type: 'file', discovered: true },
]
@@ -221,7 +221,7 @@ describe('FileNode', () => {
root,
{ path: '/a', type: 'file', discovered: true },
{ path: '/.b', type: 'file', discovered: false },
- { path: '/c', type: 'folder', discovered: true },
+ { path: '/c', type: 'directory', discovered: true },
{ path: '/c/.d', type: 'file', discovered: true },
]
@@ -231,24 +231,24 @@ describe('FileNode', () => {
test('remove-child', () => {
const root = {
path: '/',
- type: 'folder',
+ type: 'directory',
discovered: true,
}
const files = [
root,
{ path: '/a', type: 'file', discovered: true },
- { path: '/b', type: 'folder', discovered: true },
- { path: '/b/c', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
+ { path: '/b/c', type: 'directory', discovered: true },
{ path: '/b/d', type: 'file', discovered: true },
{ path: '/b/c/f', type: 'file', discovered: true },
]
- const fileToRemove = { path: '/b/c', type: 'folder', discovered: true }
+ const fileToRemove = { path: '/b/c', type: 'directory', discovered: true }
const expected = [
root,
{ path: '/a', type: 'file', discovered: true },
- { path: '/b', type: 'folder', discovered: true },
+ { path: '/b', type: 'directory', discovered: true },
{ path: '/b/d', type: 'file', discovered: true },
]
@@ -259,7 +259,7 @@ describe('FileNode', () => {
test('load nested fileNode', () => {
const data = {
path: '/',
- type: 'folder',
+ type: 'directory',
discovered: true,
children: [
{
@@ -269,12 +269,12 @@ test('load nested fileNode', () => {
},
{
path: '/b',
- type: 'folder',
+ type: 'directory',
discovered: true,
children: [
{
path: '/b/c',
- type: 'folder',
+ type: 'directory',
discovered: true,
children: [
{
diff --git a/packages/game/quest.json b/packages/game/quest.json
index ce8d226..4b50b7c 100644
--- a/packages/game/quest.json
+++ b/packages/game/quest.json
@@ -61,20 +61,13 @@
},
"type": {
"type": "string",
- "enum": [
- "file",
- "folder"
- ]
+ "enum": ["file", "directory"]
},
"exists": {
"type": "boolean"
}
},
- "required": [
- "path",
- "type",
- "exists"
- ],
+ "required": ["path", "type", "exists"],
"additionalProperties": false
}
},
@@ -95,10 +88,7 @@
"properties": {
"type": {
"type": "string",
- "enum": [
- "narrative",
- "dialogue"
- ],
+ "enum": ["narrative", "dialogue"],
"default": "narrative"
},
"content": {
@@ -108,9 +98,7 @@
"type": "string"
}
},
- "required": [
- "content"
- ],
+ "required": ["content"],
"additionalProperties": false
},
"exceptions": {
@@ -132,20 +120,12 @@
"default": false
}
},
- "required": [
- "id",
- "condition",
- "response"
- ],
+ "required": ["id", "condition", "response"],
"additionalProperties": false
}
}
},
- "required": [
- "id",
- "condition",
- "response"
- ],
+ "required": ["id", "condition", "response"],
"additionalProperties": false
}
},
@@ -168,22 +148,12 @@
"default": []
}
},
- "required": [
- "id",
- "condition",
- "response"
- ],
+ "required": ["id", "condition", "response"],
"additionalProperties": false
}
}
},
- "required": [
- "id",
- "title",
- "image",
- "instruction",
- "stages"
- ],
+ "required": ["id", "title", "image", "instruction", "stages"],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
-}
\ No newline at end of file
+}
diff --git a/packages/game/src/schema/condition.ts b/packages/game/src/schema/condition.ts
index 090eb2a..f5bb96e 100644
--- a/packages/game/src/schema/condition.ts
+++ b/packages/game/src/schema/condition.ts
@@ -2,7 +2,7 @@ import { z } from 'zod'
export const fileInputSchema = z.object({
path: z.string(),
- type: z.enum(['file', 'folder']),
+ type: z.enum(['file', 'directory']),
})
export type IFileInput = z.infer
diff --git a/packages/game/test/asyncCondition.test.ts b/packages/game/test/asyncCondition.test.ts
index 642b2de..e7451a5 100644
--- a/packages/game/test/asyncCondition.test.ts
+++ b/packages/game/test/asyncCondition.test.ts
@@ -15,7 +15,7 @@ export class MockFileChecker implements IFileExistenceChecker {
},
{
path: '/home/user/Downloads',
- type: 'folder',
+ type: 'directory',
},
]
@@ -57,7 +57,7 @@ test('file matcher', async () => {
await checkFiles(checker, [
{
path: '/home/user/Downloads',
- type: 'folder',
+ type: 'directory',
exists: true,
},
])
@@ -71,7 +71,7 @@ test('file matcher', async () => {
},
{
path: '/home/user/Downloads',
- type: 'folder',
+ type: 'directory',
exists: true,
},
])
diff --git a/packages/models/src/session.ts b/packages/models/src/session.ts
index 1ee09e3..1190f99 100644
--- a/packages/models/src/session.ts
+++ b/packages/models/src/session.ts
@@ -66,7 +66,7 @@ export const Session = model(
type: nodeSchema,
default: {
path: '/',
- type: 'folder',
+ type: 'directory',
},
},
},
diff --git a/packages/utils/src/commands.ts b/packages/utils/src/commands.ts
index d309b60..1f1a8eb 100644
--- a/packages/utils/src/commands.ts
+++ b/packages/utils/src/commands.ts
@@ -5,7 +5,7 @@ export interface File {
const fileTypes = new Map([
['file', '-f'],
- ['folder', '-d'],
+ ['directory', '-d'],
['link', '-L'],
['socket', '-S'],
])
diff --git a/packages/utils/tests/commands.test.ts b/packages/utils/tests/commands.test.ts
index 77d02d1..c926b98 100644
--- a/packages/utils/tests/commands.test.ts
+++ b/packages/utils/tests/commands.test.ts
@@ -12,7 +12,7 @@ describe('buildFileCheckCmd function', () => {
output: ['test', '-f', '/etc/passwd'],
},
{
- input: { path: '/etc', type: 'folder' },
+ input: { path: '/etc', type: 'directory' },
output: ['test', '-d', '/etc'],
},
{
diff --git a/quests/cast/game.yml b/quests/cast/game.yml
index 897e8a6..bb74680 100644
--- a/quests/cast/game.yml
+++ b/quests/cast/game.yml
@@ -5,8 +5,8 @@ instruction: |
在這個關卡中,你將會學到:
1. 如何使用 `echo` 在終端機上顯示文字。
-# requirements:
-# - get-started
+requirements:
+ - get-started
stages:
- id: start
diff --git a/quests/get-started/answer.sh b/quests/get-started/answer.sh
new file mode 100644
index 0000000..cbe1543
--- /dev/null
+++ b/quests/get-started/answer.sh
@@ -0,0 +1,4 @@
+echo start
+echo hello
+echo next
+echo finish
\ No newline at end of file
diff --git a/quests/get-started/game.yml b/quests/get-started/game.yml
new file mode 100644
index 0000000..617e9a0
--- /dev/null
+++ b/quests/get-started/game.yml
@@ -0,0 +1,71 @@
+id: get-started
+image: base
+title: 終端機的基本知識
+instruction: |
+ 歡迎來到 Linux Odyssey!
+ 在這個關卡中,你將會學到:
+ 1. 如何使用這個網站
+ 2. 如何使用終端機
+
+stages:
+ - id: start
+ name: 按下 `開始` 按鈕開始
+ condition:
+ command: ^echo start$
+ response:
+ content: |
+ 在畫面的中下方的區塊是終端機,你可以在終端機裡輸入指令來操作電腦。
+ 在終端機中,你所看到的 `commander:~ $` 叫做命令提示字串。
+ 命令提示字串最後的錢字號 `$` 叫命令提示符,你必須將指令輸入在它的後方。
+ 當你輸入完指令並按下 Enter 之後,終端機會執行你輸入的指令,並且會從終端機的下一行開始輸出指令的執行結果。
+ 直到你看到新的 `commander:~ $` 出現時,代表你可以輸入下一個指令了。
+ 現在請你輸入 `echo hello` 來看看會發生什麼事。
+ hint: |
+ 在 `commander:~ $` 後面輸入 `echo hello` 並按下 Enter
+
+ - id: echo-hello
+ name: 在終端機輸入 `echo hello`
+ requirements:
+ - start
+ condition:
+ command: ^echo hello$
+ response:
+ content: |
+ 你應該可以看到終端機上顯示了以下內容:
+ ```
+ commander:~ $ echo hello
+ hello
+ ```
+ 第一行的 `commander:~ $` 是命令提示字串,接在後方的 `echo hello` 是你輸入的指令。
+ 第二行的 `hello` 則是終端機的輸出結果。
+ 你現在知道了如何在終端機上輸入指令,以及查看終端機輸出的位置。
+ 現在請輸入 `echo next` 來繼續下一個步驟。
+ hint: |
+ 輸入 `echo next` 繼續下一個步驟
+
+ - id: echo-next
+ name: 在終端機輸入 `echo next`
+ requirements:
+ - echo-hello
+ condition:
+ command: ^echo next$
+ response:
+ content: |
+ `Ctrl + C` 在終端機中是一個很重要的快捷鍵,它可以用來中斷正在執行的指令,並產生一個新的命令提示字串,讓你可以繼續輸入指令。
+ 如果指令執行很久沒有反應,或你因為其他原因想要中斷指令,你可以按下 `Ctrl + C` 來中斷指令。
+ 又或者你輸入了錯誤的指令,卻懶得慢慢刪除,你也可以按下 `Ctrl + C` 來產生新的命令提示字串重新輸入指令。
+ 如果你已經理解了剛才的說明,請輸入 `echo finish` 來結束這一關。
+ hint: |
+ 按下 `Ctrl + C` 能夠中斷正在執行的指令
+ 按下 `Ctrl + C` 能夠產生新的命令提示字串
+ 輸入 `echo finish` 來結束這一關
+
+ - id: END
+ name: 結束關卡
+ requirements:
+ - echo-next
+ condition:
+ command: ^echo finish$
+ response:
+ content: |
+ 恭喜你,你已經完成了這個關卡!
diff --git a/server/src/containers/docker.ts b/server/src/containers/docker.ts
index 0d488eb..00cff59 100644
--- a/server/src/containers/docker.ts
+++ b/server/src/containers/docker.ts
@@ -40,7 +40,7 @@ export async function createContainer(
)
}
if (!config.isProduction && config.docker.mountQuest && imageId !== 'base') {
- logger.info('Mounting quest folder', questId)
+ logger.info('Mounting quest directory', questId)
binds = [
`${config.docker.hostProjectRoot}/quests/${questId}/home:/home/commander`,
`${config.docker.hostProjectRoot}/packages/container:/usr/local/lib/container`,
From 2d95ca382ffc1a1584352276f57a9a6da21677ae Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Thu, 24 Apr 2025 22:05:10 +0800
Subject: [PATCH 56/82] wip: integrate filegraph into session
---
app/src/store/session.ts | 30 ++++++-------
app/src/types.ts | 2 +-
packages/file-graph/package.json | 4 +-
packages/file-graph/src/fileGraph.ts | 4 +-
packages/file-graph/src/fileNode.ts | 11 ++++-
packages/file-graph/src/index.ts | 11 +----
packages/file-graph/tsconfig.json | 5 ++-
packages/game/src/Session.ts | 6 ++-
packages/game/test/session.test.ts | 43 +++++++++++++++++++
packages/models/src/session.ts | 7 ++-
.../src/api/controllers/commandController.ts | 2 +
server/src/routers/sessionRouter.ts | 9 ++--
tsconfig.json | 13 +++++-
13 files changed, 105 insertions(+), 42 deletions(-)
diff --git a/app/src/store/session.ts b/app/src/store/session.ts
index 6b28363..8853faa 100644
--- a/app/src/store/session.ts
+++ b/app/src/store/session.ts
@@ -1,6 +1,7 @@
import { defineStore } from 'pinia'
-import { FileGraph, FileObject } from '@linux-odyssey/file-graph'
+import { FileGraph, FileGraphUpdateEvent } from '@linux-odyssey/file-graph'
import { IResponse, ITask } from '@linux-odyssey/game'
+import type { SessionDetail } from 'server/src/routers/sessionRouter'
import Socket from '../utils/socket'
import SocketTerminal from '../utils/terminal'
import { Session } from '../types'
@@ -21,6 +22,7 @@ interface SessionUpdate {
status: string
responses: IResponse[]
tasks: ITask[]
+ graphUpdate: FileGraphUpdateEvent
}
interface Store {
@@ -40,12 +42,14 @@ const useSession = defineStore('session', {
this.quest = await trpc.quests.getQuestDetail.query(questId)
this.questId = questId
},
- async setSession(session: Session) {
+ async setSession(session: SessionDetail) {
console.log('set session', session)
- this.session = session
- // this.session.graph = new FileGraph(session.graph)
+ this.session = {
+ ...session,
+ graph: new FileGraph(session.graph),
+ }
term.reset()
- await socket.connect(session)
+ await socket.connect(this.session)
term.focus()
},
async createSession() {
@@ -63,24 +67,14 @@ const useSession = defineStore('session', {
this.setSession(session)
}
},
- // updateGraph(event: { discover?: FileObject[]; pwd?: string }) {
- // if (!this.session) return
- // if (event.discover) {
- // this.session.graph.discover(event.discover)
- // }
- // if (event.pwd) {
- // this.session.pwd = event.pwd
- // }
- // },
newUpdate(update: SessionUpdate) {
if (!this.session) return
this.session.responses = update.responses
this.session.tasks = update.tasks
this.session.status = update.status
- // this.session.hints.push(response.hints)
- // if (response.tasks) {
- // this.session.tasks = response.tasks
- // }
+ if (update.graphUpdate) {
+ this.session.graph.handleEvent(update.graphUpdate)
+ }
// if (
// response.status === 'finished' &&
// this.session.status !== 'finished'
diff --git a/app/src/types.ts b/app/src/types.ts
index e59e4c7..6e0da1c 100644
--- a/app/src/types.ts
+++ b/app/src/types.ts
@@ -17,7 +17,7 @@ export interface StageResponse {
export interface Session {
_id: string
status: string
- // graph: FileGraph
+ graph: FileGraph
// pwd: string
// hints: string[][]
tasks: ITask[]
diff --git a/packages/file-graph/package.json b/packages/file-graph/package.json
index 79cc492..1c615a7 100644
--- a/packages/file-graph/package.json
+++ b/packages/file-graph/package.json
@@ -1,17 +1,19 @@
{
"name": "@linux-odyssey/file-graph",
"version": "1.0.0",
+ "type": "module",
"main": "./dist/cjs/index.js",
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"require": "./dist/cjs/index.js",
+ "import": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts"
}
},
"license": "MIT",
"scripts": {
- "build": "tsc -p tsconfig.cjs.json",
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.cjs.json",
"dev": "tsc -w",
"test": "yarn build && jest"
}
diff --git a/packages/file-graph/src/fileGraph.ts b/packages/file-graph/src/fileGraph.ts
index b974967..4f77de2 100644
--- a/packages/file-graph/src/fileGraph.ts
+++ b/packages/file-graph/src/fileGraph.ts
@@ -1,7 +1,7 @@
import { FileObject } from './file.js'
import FileNode from './fileNode.js'
-export interface Event {
+export interface FileGraphUpdateEvent {
add?: FileObject[]
remove?: FileObject[]
discover?: FileObject[]
@@ -42,7 +42,7 @@ export default class FileGraph extends FileNode {
this.merge(newNode)
}
- handleEvent(event: Event) {
+ handleEvent(event: FileGraphUpdateEvent) {
// eslint-disable-next-line default-case
switch (true) {
case !!event.add:
diff --git a/packages/file-graph/src/fileNode.ts b/packages/file-graph/src/fileNode.ts
index 6b45456..c149220 100644
--- a/packages/file-graph/src/fileNode.ts
+++ b/packages/file-graph/src/fileNode.ts
@@ -6,10 +6,17 @@ import {
} from './errors.js'
import { dirname } from './utils.js'
-export default class FileNode extends File {
+export interface IFileNode {
+ path: string
+ type: 'file' | 'directory'
+ discovered: boolean
+ children?: IFileNode[]
+}
+
+export default class FileNode extends File implements IFileNode {
children: FileNode[]
- constructor(file: FileObject | FileNode) {
+ constructor(file: FileObject | IFileNode) {
super(file)
this.children = []
if ((file).children)
diff --git a/packages/file-graph/src/index.ts b/packages/file-graph/src/index.ts
index d3f4a64..6f0cb49 100644
--- a/packages/file-graph/src/index.ts
+++ b/packages/file-graph/src/index.ts
@@ -1,10 +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'
-
-export interface IFileNode {
- path: string
- type: string
- discovered: boolean
- children?: IFileNode[]
-}
+export { default as FileNode, IFileNode } from './fileNode.js'
+export { default as FileGraph, FileGraphUpdateEvent } from './fileGraph.js'
diff --git a/packages/file-graph/tsconfig.json b/packages/file-graph/tsconfig.json
index 83e051b..8eb4125 100644
--- a/packages/file-graph/tsconfig.json
+++ b/packages/file-graph/tsconfig.json
@@ -4,8 +4,11 @@
"rootDir": "src",
"composite": true,
"module": "NodeNext",
+ "moduleResolution": "NodeNext",
"outDir": "./dist/esm",
- "declarationDir": "./dist/types"
+ "declarationDir": "./dist/types",
+ "target": "ES2020",
+ "useDefineForClassFields": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
diff --git a/packages/game/src/Session.ts b/packages/game/src/Session.ts
index 011e80e..d44fc98 100644
--- a/packages/game/src/Session.ts
+++ b/packages/game/src/Session.ts
@@ -7,6 +7,7 @@ import {
IFileExistenceChecker,
IResponse,
ITask,
+ ICommandParams,
} from './schema'
export class GameSession {
@@ -22,7 +23,7 @@ export class GameSession {
this.completed = completedEvents || []
this.quest = new Quest(quest, checker)
this.graph = new FileGraph(
- graph ?? new FileNode({ path: '/', type: 'root', discovered: false })
+ graph ?? { path: '/', type: 'directory', discovered: false }
)
}
@@ -39,6 +40,9 @@ export class GameSession {
}
async runCommand(command: ICommand) {
+ if (command.params) {
+ this.graph.handleEvent(command.params)
+ }
const stageId = await this.quest.findSatisfiedEvent(command, this.completed)
if (stageId) {
this.complete(stageId)
diff --git a/packages/game/test/session.test.ts b/packages/game/test/session.test.ts
index b1d633f..2fcb805 100644
--- a/packages/game/test/session.test.ts
+++ b/packages/game/test/session.test.ts
@@ -168,4 +168,47 @@ describe('Session', () => {
{ id: 'stage4', name: 'Stage 4', completed: false },
])
})
+
+ it('should update graph', () => {
+ const session = new GameSession({}, quest, new MockFileChecker())
+
+ expect(session.getGraph()).toMatchObject({
+ path: '/',
+ type: 'directory',
+ discovered: false,
+ })
+
+ session.runCommand({
+ command: 'ls',
+ params: {
+ discover: [
+ {
+ path: '/home/user',
+ type: 'directory',
+ discovered: true,
+ },
+ ],
+ },
+ })
+
+ expect(session.getGraph()).toMatchObject({
+ path: '/',
+ type: 'directory',
+ discovered: false,
+ children: [
+ {
+ path: '/home',
+ type: 'directory',
+ discovered: false,
+ children: [
+ {
+ path: '/home/user',
+ type: 'directory',
+ discovered: true,
+ },
+ ],
+ },
+ ],
+ })
+ })
})
diff --git a/packages/models/src/session.ts b/packages/models/src/session.ts
index 1190f99..cae81e8 100644
--- a/packages/models/src/session.ts
+++ b/packages/models/src/session.ts
@@ -2,14 +2,17 @@ import { model, Schema, Types } from 'mongoose'
export interface INode {
path: string
- type: string
+ type: 'file' | 'directory'
discovered: boolean
children?: INode[]
}
const nodeSchema = new Schema({
path: String,
- type: String,
+ type: {
+ type: String,
+ enum: ['file', 'directory'],
+ },
discovered: {
type: Boolean,
default: false,
diff --git a/server/src/api/controllers/commandController.ts b/server/src/api/controllers/commandController.ts
index 2784af4..daa985a 100644
--- a/server/src/api/controllers/commandController.ts
+++ b/server/src/api/controllers/commandController.ts
@@ -54,6 +54,7 @@ export const newCommand = asyncHandler(async (req: Request, res: Response) => {
await c.save()
if (event) {
session.completedEvents = gameSession.completedEvents
+ session.graph = gameSession.getGraph()
if (gameSession.isFinished()) {
await finishSession(session)
@@ -64,6 +65,7 @@ export const newCommand = asyncHandler(async (req: Request, res: Response) => {
responses: gameSession.getResponses(),
tasks: gameSession.getTasks(),
status: session.status,
+ graphUpdate: command.params,
})
}
diff --git a/server/src/routers/sessionRouter.ts b/server/src/routers/sessionRouter.ts
index 0c7ba7d..cf82e83 100644
--- a/server/src/routers/sessionRouter.ts
+++ b/server/src/routers/sessionRouter.ts
@@ -7,6 +7,8 @@ import config from '../config.js'
import { protectedProcedure, router } from '../trpc.js'
import { questManager } from '../models/quest.js'
+export type SessionDetail = Awaited>
+
function sessionDetail(session: ISession) {
const quest = questManager.get(session.quest)
if (!quest) {
@@ -22,14 +24,15 @@ function sessionDetail(session: ISession) {
)
return {
_id: session._id.toString(),
- user: session.user,
+ user: session.user.toString(),
quest: session.quest,
status: session.status,
- createdAt: session.createdAt,
- lastActivityAt: session.lastActivityAt,
+ createdAt: session.createdAt.toISOString(),
+ lastActivityAt: session.lastActivityAt.toISOString(),
completedEvents: session.completedEvents,
responses: gameSession.getResponses(),
tasks: gameSession.getTasks(),
+ graph: gameSession.getGraph(),
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 862aad0..e4f25ca 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"target": "ESNext", // 要編譯成的 JS 目標版本
- "module": "NodeNext", // 要編譯成的 module
+ "module": "ESNext", // 要編譯成的 module
"moduleResolution": "NodeNext", // module 解析方式, default "classic"
"esModuleInterop": true, // module 兼容, 會影響 build 方式
"forceConsistentCasingInFileNames": true,
@@ -9,6 +9,15 @@
"skipLibCheck": true,
"sourceMap": true,
"declaration": true,
- "declarationMap": true
+ "declarationMap": true,
+ "baseUrl": ".",
+ "paths": {
+ "@/*": ["*"],
+ "@app/*": ["app/*"],
+ "@server/*": ["server/*"],
+ "@models/*": ["packages/models/src/*"],
+ "@game/*": ["packages/game/src/*"],
+ "@file-graph/*": ["packages/file-graph/src/*"]
+ }
}
}
From 87b8ca5d045beab346c3c105f11db4658e2e5463 Mon Sep 17 00:00:00 2001
From: Justin Lin
Date: Thu, 24 Apr 2025 23:20:40 +0800
Subject: [PATCH 57/82] wip: replace packages with pure files
---
.eslintrc.js | 33 +-
app/package.json | 14 +-
app/src/components/QuestMap.vue | 2 +-
app/src/store/session.ts | 11 +-
app/src/types.ts | 4 +-
app/src/utils/trpc.ts | 2 +-
app/src/views/ChooseUsernamePage.vue | 2 +-
app/src/views/RegisterPage.vue | 4 +-
app/tsconfig.app.json | 14 +
app/tsconfig.json | 26 +-
app/tsconfig.node.json | 24 +
app/vite.config.ts | 10 +
packages/analytics/package.json | 1 -
packages/analytics/src/index.ts | 2 +-
packages/analytics/src/models/commands.ts | 2 +-
packages/analytics/src/models/quests.ts | 2 +-
packages/analytics/src/models/sessions.ts | 2 +-
packages/analytics/src/models/users.ts | 2 +-
packages/constants/{src => }/index.ts | 0
packages/constants/package.json | 17 -
packages/constants/{src => }/session.ts | 0
packages/constants/tsconfig.json | 12 -
packages/constants/{src => }/utils.ts | 0
packages/file-graph/{src => }/errors.ts | 0
packages/file-graph/{src => }/file.ts | 0
packages/file-graph/{src => }/fileGraph.ts | 0
packages/file-graph/{src => }/fileNode.ts | 0
packages/file-graph/index.ts | 3 +
packages/file-graph/package.json | 20 -
packages/file-graph/src/index.ts | 3 -
packages/file-graph/tsconfig.cjs.json | 9 -
packages/file-graph/tsconfig.json | 15 -
packages/file-graph/{src => }/utils.ts | 0
packages/game/{src => }/Event.ts | 0
packages/game/{src => }/Exception.ts | 0
packages/game/{src => }/Quest.ts | 0
packages/game/{src => }/Session.ts | 3 +-
packages/game/{src => }/Stage.ts | 0
packages/game/{src => }/cli.ts | 0
.../{src => }/condition/CommandMatcher.ts | 0
.../game/{src => }/condition/Condition.ts | 0
.../game/{src => }/condition/ErrorMatcher.ts | 0
.../game/{src => }/condition/FileMatcher.ts | 0
packages/game/{src => }/condition/Matcher.ts | 0
.../game/{src => }/condition/NotMatcher.ts | 0
.../game/{src => }/condition/OrMatcher.ts | 0
.../game/{src => }/condition/OutputMatcher.ts | 0
.../game/{src => }/condition/PwdMatcher.ts | 0
packages/game/{src => }/index.ts | 0
packages/game/package.json | 21 -
packages/game/{src => }/schema/command.ts | 0
packages/game/{src => }/schema/condition.ts | 0
packages/game/{src => }/schema/exception.ts | 0
packages/game/{src => }/schema/index.ts | 2 +-
packages/game/{src => }/schema/quest.ts | 0
.../game/{src => }/schema/requirements.ts | 0
packages/game/{src => }/schema/response.ts | 0
packages/game/{src => }/schema/stage.ts | 0
packages/game/tsconfig.json | 11 -
packages/models/{src => }/command.ts | 0
packages/models/{src => }/index.ts | 0
packages/models/package.json | 17 -
packages/models/{src => }/session.ts | 0
packages/models/tsconfig.json | 10 -
packages/models/{src => }/user.ts | 0
packages/models/{src => }/userProfile.ts | 0
packages/utils/{src => }/auth.ts | 0
packages/utils/{src => }/commands.ts | 0
packages/utils/{src => }/dag.ts | 0
packages/utils/{src => }/index.ts | 0
packages/utils/package.json | 13 -
packages/utils/tsconfig.json | 11 -
server/migrations/0001-add-isGuest.ts | 2 +-
server/nodemon.json | 5 -
server/package.json | 22 +-
.../src/api/controllers/commandController.ts | 14 +-
.../api/controllers/leaderboardController.ts | 2 +-
server/src/api/socket.ts | 2 +-
server/src/api/validators/authValidator.ts | 6 +-
server/src/auth/oauthVerify.ts | 2 +-
server/src/auth/passport.ts | 2 +-
server/src/auth/passwordStrategy.ts | 2 +-
server/src/cli/clean.ts | 8 +-
server/src/config.ts | 10 +-
server/src/containers/cli.ts | 4 +-
server/src/containers/expiryChecker.ts | 4 +-
server/src/index.ts | 2 +-
server/src/models/quest.ts | 6 +-
server/src/models/sessionManager.ts | 6 +-
server/src/models/userManager.ts | 2 +-
server/src/routers/sessionRouter.ts | 4 +-
server/src/routers/userRouter.ts | 2 +-
server/src/utils/setupTest.ts | 2 +-
server/tsconfig.json | 9 +-
tsconfig.json | 16 +-
vite-project/.gitignore | 24 +
vite-project/.vscode/extensions.json | 3 +
vite-project/README.md | 5 +
vite-project/index.html | 13 +
vite-project/package.json | 21 +
vite-project/public/vite.svg | 1 +
vite-project/src/App.vue | 30 +
vite-project/src/assets/vue.svg | 1 +
vite-project/src/components/HelloWorld.vue | 41 ++
vite-project/src/main.ts | 5 +
vite-project/src/style.css | 79 +++
vite-project/src/vite-env.d.ts | 1 +
vite-project/tsconfig.app.json | 14 +
vite-project/tsconfig.json | 7 +
vite-project/tsconfig.node.json | 24 +
vite-project/vite.config.ts | 7 +
yarn.lock | 528 ++++++++++--------
112 files changed, 740 insertions(+), 522 deletions(-)
create mode 100644 app/tsconfig.app.json
create mode 100644 app/tsconfig.node.json
rename packages/constants/{src => }/index.ts (100%)
delete mode 100644 packages/constants/package.json
rename packages/constants/{src => }/session.ts (100%)
delete mode 100644 packages/constants/tsconfig.json
rename packages/constants/{src => }/utils.ts (100%)
rename packages/file-graph/{src => }/errors.ts (100%)
rename packages/file-graph/{src => }/file.ts (100%)
rename packages/file-graph/{src => }/fileGraph.ts (100%)
rename packages/file-graph/{src => }/fileNode.ts (100%)
create mode 100644 packages/file-graph/index.ts
delete mode 100644 packages/file-graph/package.json
delete mode 100644 packages/file-graph/src/index.ts
delete mode 100644 packages/file-graph/tsconfig.cjs.json
delete mode 100644 packages/file-graph/tsconfig.json
rename packages/file-graph/{src => }/utils.ts (100%)
rename packages/game/{src => }/Event.ts (100%)
rename packages/game/{src => }/Exception.ts (100%)
rename packages/game/{src => }/Quest.ts (100%)
rename packages/game/{src => }/Session.ts (93%)
rename packages/game/{src => }/Stage.ts (100%)
rename packages/game/{src => }/cli.ts (100%)
rename packages/game/{src => }/condition/CommandMatcher.ts (100%)
rename packages/game/{src => }/condition/Condition.ts (100%)
rename packages/game/{src => }/condition/ErrorMatcher.ts (100%)
rename packages/game/{src => }/condition/FileMatcher.ts (100%)
rename packages/game/{src => }/condition/Matcher.ts (100%)
rename packages/game/{src => }/condition/NotMatcher.ts (100%)
rename packages/game/{src => }/condition/OrMatcher.ts (100%)
rename packages/game/{src => }/condition/OutputMatcher.ts (100%)
rename packages/game/{src => }/condition/PwdMatcher.ts (100%)
rename packages/game/{src => }/index.ts (100%)
delete mode 100644 packages/game/package.json
rename packages/game/{src => }/schema/command.ts (100%)
rename packages/game/{src => }/schema/condition.ts (100%)
rename packages/game/{src => }/schema/exception.ts (100%)
rename packages/game/{src => }/schema/index.ts (87%)
rename packages/game/{src => }/schema/quest.ts (100%)
rename packages/game/{src => }/schema/requirements.ts (100%)
rename packages/game/{src => }/schema/response.ts (100%)
rename packages/game/{src => }/schema/stage.ts (100%)
delete mode 100644 packages/game/tsconfig.json
rename packages/models/{src => }/command.ts (100%)
rename packages/models/{src => }/index.ts (100%)
delete mode 100644 packages/models/package.json
rename packages/models/{src => }/session.ts (100%)
delete mode 100644 packages/models/tsconfig.json
rename packages/models/{src => }/user.ts (100%)
rename packages/models/{src => }/userProfile.ts (100%)
rename packages/utils/{src => }/auth.ts (100%)
rename packages/utils/{src => }/commands.ts (100%)
rename packages/utils/{src => }/dag.ts (100%)
rename packages/utils/{src => }/index.ts (100%)
delete mode 100644 packages/utils/package.json
delete mode 100644 packages/utils/tsconfig.json
delete mode 100644 server/nodemon.json
create mode 100644 vite-project/.gitignore
create mode 100644 vite-project/.vscode/extensions.json
create mode 100644 vite-project/README.md
create mode 100644 vite-project/index.html
create mode 100644 vite-project/package.json
create mode 100644 vite-project/public/vite.svg
create mode 100644 vite-project/src/App.vue
create mode 100644 vite-project/src/assets/vue.svg
create mode 100644 vite-project/src/components/HelloWorld.vue
create mode 100644 vite-project/src/main.ts
create mode 100644 vite-project/src/style.css
create mode 100644 vite-project/src/vite-env.d.ts
create mode 100644 vite-project/tsconfig.app.json
create mode 100644 vite-project/tsconfig.json
create mode 100644 vite-project/tsconfig.node.json
create mode 100644 vite-project/vite.config.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index ebe45d0..b383fdd 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -20,9 +20,12 @@ module.exports = {
settings: {
'import/resolver': {
node: {
- extensions: ['.js', '.jsx', '.ts', '.tsx'],
+ extensions: ['.js', '.ts'],
+ moduleDirectory: ['node_modules', 'packages', 'server/src'],
+ },
+ typescript: {
+ alwaysTryTypes: true,
},
- typescript: {},
},
vue: {
version: '3.0', // Explicitly specify Vue 3
@@ -63,10 +66,10 @@ module.exports = {
// Allow missing file extensions
'import/extensions': [
- 'warn',
+ 'off',
'ignorePackages',
{
- js: 'off',
+ js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
@@ -79,12 +82,30 @@ module.exports = {
'@typescript-eslint/no-empty-function': 'error',
'no-shadow': 'off',
'@typescript-eslint/no-shadow': 'error',
+ 'no-restricted-imports': [
+ 'error',
+ {
+ patterns: [
+ {
+ group: ['../*'],
+ message: 'Relative imports are not allowed.',
+ allowSameFolder: true,
+ },
+ ],
+ },
+ ],
},
overrides: [
{
- files: ['**/tests/**/*.js', '**/tests/**/*.ts', '**/*.test.ts'], // Adjust the pattern to match your test files
+ files: ['**/tests/**/*.js', '**/tests/**/*.ts', '**/*.test.ts'],
+ rules: {
+ 'import/extensions': 'off',
+ 'import/no-extraneous-dependencies': 'off',
+ },
+ },
+ {
+ files: ['server/**/*.ts'],
rules: {
- 'import/extensions': 'off', // Turn off the rule for test files
'import/no-extraneous-dependencies': 'off',
},
},
diff --git a/app/package.json b/app/package.json
index 78d5bd4..d0784f0 100644
--- a/app/package.json
+++ b/app/package.json
@@ -16,11 +16,6 @@
"@fortawesome/free-regular-svg-icons": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/vue-fontawesome": "^3.0.3",
- "@linux-odyssey/constants": "*",
- "@linux-odyssey/file-graph": "*",
- "@linux-odyssey/game": "*",
- "@linux-odyssey/models": "*",
- "@linux-odyssey/utils": "*",
"@trpc/client": "^11.1.0",
"@types/dompurify": "^3.0.5",
"axios": "^1.6.0",
@@ -39,13 +34,14 @@
},
"devDependencies": {
"@types/validator": "^13.11.9",
- "@vitejs/plugin-vue": "^4.5.2",
"@vue/compiler-sfc": "^3.3.13",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.31",
"tailwindcss": "^3.3.3",
- "typescript": "^5.3.3",
- "vite": "^4.5.3",
- "vue-tsc": "^2.0.10"
+ "@vitejs/plugin-vue": "^5.2.2",
+ "@vue/tsconfig": "^0.7.0",
+ "typescript": "~5.7.2",
+ "vite": "^6.3.1",
+ "vue-tsc": "^2.2.8"
}
}
diff --git a/app/src/components/QuestMap.vue b/app/src/components/QuestMap.vue
index e701b08..5297f1e 100644
--- a/app/src/components/QuestMap.vue
+++ b/app/src/components/QuestMap.vue
@@ -1,7 +1,7 @@
+