diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 6878beb..0000000 --- a/.babelrc +++ /dev/null @@ -1,14 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "targets": { - "chrome": 52 - }, - "debug": false, - "useBuiltIns": "usage" - } - ] - ] -} diff --git a/.eslintrc.js b/.eslintrc.js index 1a35f0a..3631f7f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,28 +1,11 @@ module.exports = { - extends: ['airbnb-base', './scripts/eslint/index.js'], - plugins: ['import'], - parser: 'babel-eslint', + extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', './scripts/eslint/index.js'], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + root: true, env: { browser: true, - commonjs: true, es6: true, node: true, }, - parserOptions: { - ecmaVersion: 2017, - ecmaFeatures: { - experimentalObjectRestSpread: true, - }, - sourceType: 'module', - }, - settings: { - 'import/resolver': { - webpack: { - config: 'webpack.config.js', - }, - }, - }, - rules: { - strict: 'error', - }, }; diff --git a/README.md b/README.md index 2da346c..9406299 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ const isGameEntity = function isGameEntityFunc(state) { } return { - id: getUUID(), + id: uuidv4(), printInfo, }; }; diff --git a/config/index.ejs b/config/index.ejs deleted file mode 100644 index b970eac..0000000 --- a/config/index.ejs +++ /dev/null @@ -1,127 +0,0 @@ -<% var item, key %><% -htmlWebpackPlugin.options.appMountIds = htmlWebpackPlugin.options.appMountIds || [] %><% -htmlWebpackPlugin.options.lang = htmlWebpackPlugin.options.lang || "en" %><% -htmlWebpackPlugin.options.links = htmlWebpackPlugin.options.links || [] %><% -htmlWebpackPlugin.options.meta = htmlWebpackPlugin.options.meta || [] %><% -htmlWebpackPlugin.options.scripts = htmlWebpackPlugin.options.scripts || [] -%> - manifest="<%= htmlWebpackPlugin.files.manifest %>"<% } %>> - - - <% - - if (htmlWebpackPlugin.options.baseHref) { %> - <% - } %><% - - if (Array.isArray(htmlWebpackPlugin.options.meta)) { %><% - for (item of htmlWebpackPlugin.options.meta) { %> - <%= key %>="<%= item[key] %>"<% } %>><% - } %><% - } %><% - - %> - <%= htmlWebpackPlugin.options.title %><% - - if (htmlWebpackPlugin.files.favicon) { %> - <% - } %><% - - if (htmlWebpackPlugin.options.mobile) { %> - <% - } %><% - - for (item of htmlWebpackPlugin.options.links) { %><% - if (typeof item === 'string' || item instanceof String) { item = { href: item, rel: 'stylesheet' } } %> - <%= key %>="<%= item[key] %>"<% } %> /><% - } %><% - - for (key in htmlWebpackPlugin.files.css) { %><% - if (htmlWebpackPlugin.files.cssIntegrity) { %> - <% - } else { %> - <% - } %><% - } %><% - if (htmlWebpackPlugin.options.headHtmlSnippet) { %> - <%= htmlWebpackPlugin.options.headHtmlSnippet %><% - } %> - - <% - if (htmlWebpackPlugin.options.unsupportedBrowser) { %> - -
- Sorry, your browser is not supported. Please upgrade to the latest version or switch your browser to use this - site. See outdatedbrowser.com for options. -
<% - } %><% - - if (htmlWebpackPlugin.options.bodyHtmlSnippet) { %> - <%= htmlWebpackPlugin.options.bodyHtmlSnippet %><% - } %><% - - if (htmlWebpackPlugin.options.appMountId) { %> -
<% - if (htmlWebpackPlugin.options.appMountHtmlSnippet) { %> - <%= htmlWebpackPlugin.options.appMountHtmlSnippet %><% - } %> -
<% - } %><% - - for (item of htmlWebpackPlugin.options.appMountIds) { %> -
<% - } %><% - - if (htmlWebpackPlugin.options.window) { %> - <% - } %><% - - if (htmlWebpackPlugin.options.inlineManifestWebpackName) { %> - <%= htmlWebpackPlugin.files[htmlWebpackPlugin.options.inlineManifestWebpackName] %><% - } %><% - - for (item of htmlWebpackPlugin.options.scripts) { %><% - if (typeof item === 'string' || item instanceof String) { item = { src: item, type: 'text/javascript' } } %> - <%= key %>="<%= item[key] %>"<% } %>><% - } %><% - - for (key in htmlWebpackPlugin.files.chunks) { %><% - if (htmlWebpackPlugin.files.jsIntegrity) { %> - <% - } else { %> - <% - } %><% - } %><% - - if (htmlWebpackPlugin.options.devServer) { %> - <% - } %><% - - if (htmlWebpackPlugin.options.googleAnalytics) { %> - - <% - } %> - - diff --git a/config/webpack.config.base.js b/config/webpack.config.base.js deleted file mode 100644 index efeeadd..0000000 --- a/config/webpack.config.base.js +++ /dev/null @@ -1,115 +0,0 @@ -const webpack = require('webpack'); -const path = require('path'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); - -const pkg = require('../package.json'); - -const PATHS = { - src: path.join(__dirname, '../src'), - dist: path.join(__dirname, '../dist'), -}; - -module.exports = { - context: __dirname, - entry: { - app: [PATHS.src], - vendors: Object.keys(pkg.dependencies), - }, - output: { - filename: '[name].js', - path: PATHS.dist, - publicPath: '/', - }, - resolve: { - extensions: ['.js', '.jsx', '.jsm'], - alias: { - configs: path.resolve(__dirname, '../src/configs'), - core: path.resolve(__dirname, '../src/core'), - styles: path.resolve(__dirname, '../styles'), - assets: path.resolve(__dirname, '../assets'), - scenes: path.resolve(__dirname, '../src/scenes'), - entities: path.resolve(__dirname, '../src/entities'), - components: path.resolve(__dirname, '../src/components'), - utils: path.resolve(__dirname, '../src/utils'), - root: path.resolve(__dirname, '../src'), - }, - }, - module: { - rules: [ - { - test: [/\.vert$/, /\.frag$/], - use: 'raw-loader', - }, - { - test: /\.js$/, - exclude: /node_modules/, - use: 'babel-loader', - }, - { - test: /\.scss$/, - use: [ - { - loader: 'style-loader', - }, - { - loader: 'css-loader', - options: { - modules: true, - camelCase: 'dashes', - localIdentName: '[path][name]__[local]', - }, - }, - { - loader: 'resolve-url-loader', - }, - { - loader: 'sass-loader', - }, - ], - }, - { - test: /\.(jpg|png|woff)$/, - use: 'file-loader', - }, - ], - }, - plugins: [ - new webpack.DefinePlugin({ - CANVAS_RENDERER: JSON.stringify(true), - WEBGL_RENDERER: JSON.stringify(true), - PRODUCTION: JSON.stringify(false), - }), - new HtmlWebpackPlugin({ - template: './index.ejs', - title: 'Boilerplate -- Change me', - meta: [{ name: 'robots', content: 'noindex,nofollow' }], - appMountIds: ['game'], - inject: false, - minify: { - collapseWhitespace: true, - conservativeCollapse: true, - preserveLineBreaks: true, - useShortDoctype: true, - html5: true, - }, - mobile: true, - }), - new webpack.HotModuleReplacementPlugin(), - new webpack.NamedModulesPlugin(), - new CopyWebpackPlugin({ - patterns: [ - { - from: path.join(__dirname, '../assets/images/'), - to: path.join(PATHS.dist, 'assets/images/'), - flatten: false, - }, - { - from: path.join(__dirname, '../assets/audio/'), - to: path.join(PATHS.dist, 'assets/audio/'), - flatten: false, - }, - ], - }), - ], -}; diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js deleted file mode 100644 index 9000db1..0000000 --- a/config/webpack.config.dev.js +++ /dev/null @@ -1,31 +0,0 @@ -const baseConfig = require('./webpack.config.base'); -const path = require('path'); -const { merge } = require('webpack-merge'); - -const PATHS = { - src: path.join(__dirname, '../src'), - dist: path.join(__dirname, '../dist'), -}; - -const PORT = 3000; - -module.exports = merge(baseConfig, { - mode: 'development', - devtool: 'eval-source-map', - devServer: { - contentBase: PATHS.dist, - compress: true, - headers: { - 'X-Content-Type-Options': 'nosniff', - 'X-Frame-Options': 'DENY', - }, - open: true, - overlay: { - warnings: true, - errors: true, - }, - port: PORT, - publicPath: `http://localhost:${PORT}/`, - hot: true, - }, -}); diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js deleted file mode 100644 index bba5a96..0000000 --- a/config/webpack.config.prod.js +++ /dev/null @@ -1,14 +0,0 @@ -const baseConfig = require('./webpack.config.base'); -const { merge } = require('webpack-merge'); - -module.exports = merge(baseConfig, { - mode: 'production', - node: { - fs: 'empty', - net: 'empty', - tls: 'empty', - }, - optimization: { - minimize: true, - }, -}); diff --git a/index.html b/index.html new file mode 100644 index 0000000..0d9375a --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + + + +
+ + + \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json deleted file mode 100644 index e865c02..0000000 --- a/jsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", // This must be specified if "paths" is. - "paths": { - "configs/*": ["src/configs/*"], - "core/*": ["src/core/*"], - "styles/*": ["styles/*"], - "assets/*": ["assets/*"], - "scenes/*": ["src/scenes/*"], - "entities/*": ["src/entities/*"], - "components/*": ["src/components/*"], - "utils/*": ["src/utils/*"], - "root/*": ["src/"], - } - } -} diff --git a/package.json b/package.json index 8b329b1..93ee05a 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { "name": "phaser-3-boilerplate", - "version": "1.2.0", + "version": "2.0.0", "description": "Phaser 3 Boilerplate project for rapid development.", "author": "Christian Holt (Sidaroth@protonmail.com)", - "main": "src/index.js", + "main": "src/index.ts", "scripts": { - "default:start": "npm run clean && webpack --mode development", - "start": "webpack-dev-server --config config/webpack.config.dev.js", - "build": "npm run clean && webpack --mode production --config config/webpack.config.prod.js", - "clean": "rimraf dist" + "start": "pnpm run dev", + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "lint": "eslint src --ext .ts && tsc", + "lint:fix": "eslint src --ext .ts --fix" }, "license": "MIT", "licenseUrl": "http://www.opensource.org/licenses/mit-license.php", @@ -18,42 +20,34 @@ "url": "git+https://github.com/sidaroth/Phaser3.Boilerplate.git" }, "devDependencies": { - "@babel/core": "^7.11.1", - "@babel/plugin-proposal-object-rest-spread": "^7.11.0", - "@babel/preset-env": "^7.11.0", - "babel-eslint": "^8.2.6", - "babel-loader": "^8.1.0", - "copy-webpack-plugin": "^6.0.3", - "core-js": "^2.6.11", - "css-loader": "^1.0.1", - "eslint": "^4.19.1", - "eslint-config-airbnb-base": "^12.1.0", - "eslint-config-standard": "^10.2.1", - "eslint-import-resolver-webpack": "^0.10.1", - "eslint-plugin-import": "^2.22.0", - "eslint-plugin-node": "^4.2.2", - "eslint-plugin-promise": "^3.8.0", - "eslint-plugin-standard": "^3.1.0", - "expose-loader": "^0.7.5", - "file-loader": "^1.1.11", - "html-webpack-plugin": "^3.1.0", - "html-webpack-template": "^6.1.0", - "mini-css-extract-plugin": "^0.4.5", - "node-sass": "^4.14.1", - "raw-loader": "^0.5.1", - "resolve-url-loader": "^2.3.2", - "rimraf": "^2.7.1", - "sass-loader": "^7.3.1", - "style-loader": "^0.21.0", - "webpack": "^4.44.1", - "webpack-cli": "^3.3.12", - "webpack-dev-server": "^3.11.0" + "@types/dat.gui": "^0.7.10", + "@types/stats": "^0.16.30", + "@types/uuid": "^9.0.4", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", + "esbuild": "^0.19.4", + "eslint": "^8.50.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-airbnb-typescript": "^17.1.0", + "eslint-import-resolver-alias": "^1.1.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-standard": "^5.0.0", + "rollup-plugin-strip-code": "^0.2.7", + "tslib": "^2.6.2", + "typescript": "^5.2.2", + "vite": "^4.4.11", + "vite-plugin-dts": "^3.6.0", + "vite-plugin-eslint": "^1.8.1" }, "dependencies": { - "dat.gui": "^0.7.7", - "immutable": "^3.8.2", - "phaser": "^3.24.1", - "stats-js": "^1.0.1", - "webpack-merge": "^5.1.2" + "@types/node": "^20.8.2", + "dat.gui": "^0.7.9", + "immutable": "^4.3.4", + "phaser": "^3.60.0", + "sass": "^1.68.0", + "stats.js": "^0.17.0", + "uuid": "^9.0.1" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..1616688 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2843 @@ +lockfileVersion: 5.4 + +specifiers: + '@types/dat.gui': ^0.7.10 + '@types/node': ^20.8.2 + '@types/stats': ^0.16.30 + '@types/uuid': ^9.0.4 + '@typescript-eslint/eslint-plugin': ^6.7.4 + '@typescript-eslint/parser': ^6.7.4 + dat.gui: ^0.7.9 + esbuild: ^0.19.4 + eslint: ^8.50.0 + eslint-config-airbnb-base: ^15.0.0 + eslint-config-airbnb-typescript: ^17.1.0 + eslint-import-resolver-alias: ^1.1.2 + eslint-plugin-import: ^2.28.1 + eslint-plugin-node: ^11.1.0 + eslint-plugin-promise: ^6.1.1 + eslint-plugin-standard: ^5.0.0 + immutable: ^4.3.4 + phaser: ^3.60.0 + rollup-plugin-strip-code: ^0.2.7 + sass: ^1.68.0 + stats.js: ^0.17.0 + tslib: ^2.6.2 + typescript: ^5.2.2 + uuid: ^9.0.1 + vite: ^4.4.10 + vite-plugin-dts: ^3.6.0 + vite-plugin-eslint: ^1.8.1 + +dependencies: + '@types/node': 20.8.2 + dat.gui: 0.7.9 + immutable: 4.3.4 + phaser: 3.60.0 + sass: 1.68.0 + stats.js: 0.17.0 + uuid: 9.0.1 + +devDependencies: + '@types/dat.gui': 0.7.10 + '@types/stats': 0.16.30 + '@types/uuid': 9.0.4 + '@typescript-eslint/eslint-plugin': 6.7.4_sjhwt3bl5psuxqi3hx6z7r6ola + '@typescript-eslint/parser': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + esbuild: 0.19.4 + eslint: 8.50.0 + eslint-config-airbnb-base: 15.0.0_mc36sq7crv2v5vtlozlclqwu5e + eslint-config-airbnb-typescript: 17.1.0_fwsuazv5pgoz2k7mdjirunpzam + eslint-import-resolver-alias: 1.1.2_b6377bcr3argvnmxmq6ha6uyl4 + eslint-plugin-import: 2.28.1_4nytrgfpfmroylhx7ogxfohaye + eslint-plugin-node: 11.1.0_eslint@8.50.0 + eslint-plugin-promise: 6.1.1_eslint@8.50.0 + eslint-plugin-standard: 5.0.0_eslint@8.50.0 + rollup-plugin-strip-code: 0.2.7 + tslib: 2.6.2 + typescript: 5.2.2 + vite: 4.4.10_xw5nuywhrj3t7rakopdrzdmjn4 + vite-plugin-dts: 3.6.0_c3vqjxdev4cverowl5dawv6nn4 + vite-plugin-eslint: 1.8.1_eslint@8.50.0+vite@4.4.10 + +packages: + + /@aashutoshrathi/word-wrap/1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@babel/helper-string-parser/7.22.5: + resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier/7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/parser/7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.0 + dev: true + + /@babel/types/7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@esbuild/android-arm/0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm/0.19.4: + resolution: {integrity: sha512-uBIbiYMeSsy2U0XQoOGVVcpIktjLMEKa7ryz2RLr7L/vTnANNEsPVAh4xOv7ondGz6ac1zVb0F8Jx20rQikffQ==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.19.4: + resolution: {integrity: sha512-mRsi2vJsk4Bx/AFsNBqOH2fqedxn5L/moT58xgg51DjX1la64Z3Npicut2VbhvDFO26qjWtPMsVxCd80YTFVeg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.19.4: + resolution: {integrity: sha512-4iPufZ1TMOD3oBlGFqHXBpa3KFT46aLl6Vy7gwed0ZSYgHaZ/mihbYb4t7Z9etjkC9Al3ZYIoOaHrU60gcMy7g==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.19.4: + resolution: {integrity: sha512-Lviw8EzxsVQKpbS+rSt6/6zjn9ashUZ7Tbuvc2YENgRl0yZTktGlachZ9KMJUsVjZEGFVu336kl5lBgDN6PmpA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.19.4: + resolution: {integrity: sha512-YHbSFlLgDwglFn0lAO3Zsdrife9jcQXQhgRp77YiTDja23FrC2uwnhXMNkAucthsf+Psr7sTwYEryxz6FPAVqw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.19.4: + resolution: {integrity: sha512-vz59ijyrTG22Hshaj620e5yhs2dU1WJy723ofc+KUgxVCM6zxQESmWdMuVmUzxtGqtj5heHyB44PjV/HKsEmuQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.19.4: + resolution: {integrity: sha512-3sRbQ6W5kAiVQRBWREGJNd1YE7OgzS0AmOGjDmX/qZZecq8NFlQsQH0IfXjjmD0XtUYqr64e0EKNFjMUlPL3Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.19.4: + resolution: {integrity: sha512-z/4ArqOo9EImzTi4b6Vq+pthLnepFzJ92BnofU1jgNlcVb+UqynVFdoXMCFreTK7FdhqAzH0vmdwW5373Hm9pg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.19.4: + resolution: {integrity: sha512-ZWmWORaPbsPwmyu7eIEATFlaqm0QGt+joRE9sKcnVUG3oBbr/KYdNE2TnkzdQwX6EDRdg/x8Q4EZQTXoClUqqA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.19.4: + resolution: {integrity: sha512-EGc4vYM7i1GRUIMqRZNCTzJh25MHePYsnQfKDexD8uPTCm9mK56NIL04LUfX2aaJ+C9vyEp2fJ7jbqFEYgO9lQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.19.4: + resolution: {integrity: sha512-WVhIKO26kmm8lPmNrUikxSpXcgd6HDog0cx12BUfA2PkmURHSgx9G6vA19lrlQOMw+UjMZ+l3PpbtzffCxFDRg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.19.4: + resolution: {integrity: sha512-keYY+Hlj5w86hNp5JJPuZNbvW4jql7c1eXdBUHIJGTeN/+0QFutU3GrS+c27L+NTmzi73yhtojHk+lr2+502Mw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.19.4: + resolution: {integrity: sha512-tQ92n0WMXyEsCH4m32S21fND8VxNiVazUbU4IUGVXQpWiaAxOBvtOtbEt3cXIV3GEBydYsY8pyeRMJx9kn3rvw==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.19.4: + resolution: {integrity: sha512-tRRBey6fG9tqGH6V75xH3lFPpj9E8BH+N+zjSUCnFOX93kEzqS0WdyJHkta/mmJHn7MBaa++9P4ARiU4ykjhig==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.19.4: + resolution: {integrity: sha512-152aLpQqKZYhThiJ+uAM4PcuLCAOxDsCekIbnGzPKVBRUDlgaaAfaUl5NYkB1hgY6WN4sPkejxKlANgVcGl9Qg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.19.4: + resolution: {integrity: sha512-Mi4aNA3rz1BNFtB7aGadMD0MavmzuuXNTaYL6/uiYIs08U7YMPETpgNn5oue3ICr+inKwItOwSsJDYkrE9ekVg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.19.4: + resolution: {integrity: sha512-9+Wxx1i5N/CYo505CTT7T+ix4lVzEdz0uCoYGxM5JDVlP2YdDC1Bdz+Khv6IbqmisT0Si928eAxbmGkcbiuM/A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.19.4: + resolution: {integrity: sha512-MFsHleM5/rWRW9EivFssop+OulYVUoVcqkyOkjiynKBCGBj9Lihl7kh9IzrreDyXa4sNkquei5/DTP4uCk25xw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.19.4: + resolution: {integrity: sha512-6Xq8SpK46yLvrGxjp6HftkDwPP49puU4OF0hEL4dTxqCbfx09LyrbUj/D7tmIRMj5D5FCUPksBbxyQhp8tmHzw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.19.4: + resolution: {integrity: sha512-PkIl7Jq4mP6ke7QKwyg4fD4Xvn8PXisagV/+HntWoDEdmerB2LTukRZg728Yd1Fj+LuEX75t/hKXE2Ppk8Hh1w==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.19.4: + resolution: {integrity: sha512-ga676Hnvw7/ycdKB53qPusvsKdwrWzEyJ+AtItHGoARszIqvjffTwaaW3b2L6l90i7MO9i+dlAW415INuRhSGg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.19.4: + resolution: {integrity: sha512-HP0GDNla1T3ZL8Ko/SHAS2GgtjOg+VmWnnYLhuTksr++EnduYB0f3Y2LzHsUwb2iQ13JGoY6G3R8h6Du/WG6uA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils/4.4.0_eslint@8.50.0: + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.50.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp/4.9.0: + resolution: {integrity: sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc/2.1.2: + resolution: {integrity: sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.22.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js/8.50.0: + resolution: {integrity: sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array/0.11.11: + resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer/1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema/1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@microsoft/api-extractor-model/7.28.2_@types+node@20.8.2: + resolution: {integrity: sha512-vkojrM2fo3q4n4oPh4uUZdjJ2DxQ2+RnDQL/xhTWSRUNPF6P4QyrvY357HBxbnltKcYu+nNNolVqc6TIGQ73Ig==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.61.0_@types+node@20.8.2 + transitivePeerDependencies: + - '@types/node' + dev: true + + /@microsoft/api-extractor/7.37.3_@types+node@20.8.2: + resolution: {integrity: sha512-daC5IKZw/Qg8DYucnQVvagihKsTr5L7Bgf5VJYe/FwQhQuR9VRqKZfr2JkqoszsVqOf8C0KtFNTaqyB7chD/HQ==} + hasBin: true + dependencies: + '@microsoft/api-extractor-model': 7.28.2_@types+node@20.8.2 + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.61.0_@types+node@20.8.2 + '@rushstack/rig-package': 0.5.1 + '@rushstack/ts-command-line': 4.16.1 + colors: 1.2.5 + lodash: 4.17.21 + resolve: 1.22.6 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.0.4 + transitivePeerDependencies: + - '@types/node' + dev: true + + /@microsoft/tsdoc-config/0.16.2: + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + dev: true + + /@microsoft/tsdoc/0.14.2: + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + dev: true + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@rollup/pluginutils/4.2.1: + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@rollup/pluginutils/5.0.4: + resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.2 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@rushstack/node-core-library/3.61.0_@types+node@20.8.2: + resolution: {integrity: sha512-tdOjdErme+/YOu4gPed3sFS72GhtWCgNV9oDsHDnoLY5oDfwjKUc9Z+JOZZ37uAxcm/OCahDHfuu2ugqrfWAVQ==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 20.8.2 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.6 + semver: 7.5.4 + z-schema: 5.0.5 + dev: true + + /@rushstack/rig-package/0.5.1: + resolution: {integrity: sha512-pXRYSe29TjRw7rqxD4WS3HN/sRSbfr+tJs4a9uuaSIBAITbUggygdhuG0VrO0EO+QqH91GhYMN4S6KRtOEmGVA==} + dependencies: + resolve: 1.22.6 + strip-json-comments: 3.1.1 + dev: true + + /@rushstack/ts-command-line/4.16.1: + resolution: {integrity: sha512-+OCsD553GYVLEmz12yiFjMOzuPeCiZ3f8wTiFHL30ZVXexTyPmgjwXEhg2K2P0a2lVf+8YBy7WtPoflB2Fp8/A==} + dependencies: + '@types/argparse': 1.0.38 + argparse: 1.0.10 + colors: 1.2.5 + string-argv: 0.3.2 + dev: true + + /@types/argparse/1.0.38: + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + dev: true + + /@types/dat.gui/0.7.10: + resolution: {integrity: sha512-sLifoNrvs4lgJkAUZcTB28dbWy0AM05Yc0BzTqHheK0tRYRVsJHoFLocB5heDbb5amaFLEXna41GOM6IG06oqA==} + dev: true + + /@types/eslint/8.44.3: + resolution: {integrity: sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==} + dependencies: + '@types/estree': 1.0.2 + '@types/json-schema': 7.0.13 + dev: true + + /@types/estree/1.0.2: + resolution: {integrity: sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==} + dev: true + + /@types/json-schema/7.0.13: + resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==} + dev: true + + /@types/json5/0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/node/20.8.2: + resolution: {integrity: sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==} + + /@types/semver/7.5.3: + resolution: {integrity: sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==} + dev: true + + /@types/stats/0.16.30: + resolution: {integrity: sha512-ihuaNKhVjTQ8UNLJu7Kx96ywf0bSBday/K//HHvO9LKha07Ezxdm6HkazOKUIdayp0EmGEIPBQSL7eLxm8rX0w==} + dev: true + + /@types/uuid/9.0.4: + resolution: {integrity: sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==} + dev: true + + /@typescript-eslint/eslint-plugin/6.7.4_sjhwt3bl5psuxqi3hx6z7r6ola: + resolution: {integrity: sha512-DAbgDXwtX+pDkAHwiGhqP3zWUGpW49B7eqmgpPtg+BKJXwdct79ut9+ifqOFPJGClGKSHXn2PTBatCnldJRUoA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.9.0 + '@typescript-eslint/parser': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/scope-manager': 6.7.4 + '@typescript-eslint/type-utils': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/utils': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + '@typescript-eslint/visitor-keys': 6.7.4 + debug: 4.3.4 + eslint: 8.50.0 + graphemer: 1.4.0 + ignore: 5.2.4 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3_typescript@5.2.2 + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser/6.7.4_jk7qbkaijtltyu4ajmze3dfiwa: + resolution: {integrity: sha512-I5zVZFY+cw4IMZUeNCU7Sh2PO5O57F7Lr0uyhgCJmhN/BuTlnc55KxPonR4+EM3GBdfiCyGZye6DgMjtubQkmA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.7.4 + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/typescript-estree': 6.7.4_typescript@5.2.2 + '@typescript-eslint/visitor-keys': 6.7.4 + debug: 4.3.4 + eslint: 8.50.0 + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager/6.7.4: + resolution: {integrity: sha512-SdGqSLUPTXAXi7c3Ob7peAGVnmMoGzZ361VswK2Mqf8UOYcODiYvs8rs5ILqEdfvX1lE7wEZbLyELCW+Yrql1A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/visitor-keys': 6.7.4 + dev: true + + /@typescript-eslint/type-utils/6.7.4_jk7qbkaijtltyu4ajmze3dfiwa: + resolution: {integrity: sha512-n+g3zi1QzpcAdHFP9KQF+rEFxMb2KxtnJGID3teA/nxKHOVi3ylKovaqEzGBbVY2pBttU6z85gp0D00ufLzViQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.7.4_typescript@5.2.2 + '@typescript-eslint/utils': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + debug: 4.3.4 + eslint: 8.50.0 + ts-api-utils: 1.0.3_typescript@5.2.2 + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types/6.7.4: + resolution: {integrity: sha512-o9XWK2FLW6eSS/0r/tgjAGsYasLAnOWg7hvZ/dGYSSNjCh+49k5ocPN8OmG5aZcSJ8pclSOyVKP2x03Sj+RrCA==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree/6.7.4_typescript@5.2.2: + resolution: {integrity: sha512-ty8b5qHKatlNYd9vmpHooQz3Vki3gG+3PchmtsA4TgrZBKWHNjWfkQid7K7xQogBqqc7/BhGazxMD5vr6Ha+iQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/visitor-keys': 6.7.4 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3_typescript@5.2.2 + typescript: 5.2.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils/6.7.4_jk7qbkaijtltyu4ajmze3dfiwa: + resolution: {integrity: sha512-PRQAs+HUn85Qdk+khAxsVV+oULy3VkbH3hQ8hxLRJXWBEd7iI+GbQxH5SEUSH7kbEoTp6oT1bOwyga24ELALTA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0_eslint@8.50.0 + '@types/json-schema': 7.0.13 + '@types/semver': 7.5.3 + '@typescript-eslint/scope-manager': 6.7.4 + '@typescript-eslint/types': 6.7.4 + '@typescript-eslint/typescript-estree': 6.7.4_typescript@5.2.2 + eslint: 8.50.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys/6.7.4: + resolution: {integrity: sha512-pOW37DUhlTZbvph50x5zZCkFn3xzwkGtNoJHzIM3svpiSkJzwOYr/kVBaXmf+RAQiUDs1AHEZVNPg6UJCJpwRA==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.7.4 + eslint-visitor-keys: 3.4.3 + dev: true + + /@volar/language-core/1.10.1: + resolution: {integrity: sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==} + dependencies: + '@volar/source-map': 1.10.1 + dev: true + + /@volar/source-map/1.10.1: + resolution: {integrity: sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==} + dependencies: + muggle-string: 0.3.1 + dev: true + + /@volar/typescript/1.10.1: + resolution: {integrity: sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==} + dependencies: + '@volar/language-core': 1.10.1 + dev: true + + /@vue/compiler-core/3.3.4: + resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + dependencies: + '@babel/parser': 7.23.0 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-dom/3.3.4: + resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + dependencies: + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + dev: true + + /@vue/language-core/1.8.15_typescript@5.2.2: + resolution: {integrity: sha512-zche5Aw8kkvp3YaghuLiOZyVIpoWHjSQ0EfjxGSsqHOPMamdCoa9x3HtbenpR38UMUoKJ88wiWuiOrV3B/Yq+A==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@volar/language-core': 1.10.1 + '@volar/source-map': 1.10.1 + '@vue/compiler-dom': 3.3.4 + '@vue/reactivity': 3.3.4 + '@vue/shared': 3.3.4 + minimatch: 9.0.3 + muggle-string: 0.3.1 + typescript: 5.2.2 + vue-template-compiler: 2.7.14 + dev: true + + /@vue/reactivity/3.3.4: + resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} + dependencies: + '@vue/shared': 3.3.4 + dev: true + + /@vue/shared/3.3.4: + resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + dev: true + + /@vue/typescript/1.8.15_typescript@5.2.2: + resolution: {integrity: sha512-qWyanQKXOsK84S8rP7QBrqsvUdQ0nZABZmTjXMpb3ox4Bp5IbkscREA3OPUrkgl64mAxwwCzIWcOc3BPTCPjQw==} + dependencies: + '@volar/typescript': 1.10.1 + '@vue/language-core': 1.8.15_typescript@5.2.2 + transitivePeerDependencies: + - typescript + dev: true + + /acorn-jsx/5.3.2_acorn@8.10.0: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.10.0 + dev: true + + /acorn/8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv/6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex/5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles/4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /anymatch/3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + /argparse/1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse/2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-buffer-byte-length/1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + + /array-includes/3.1.7: + resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + get-intrinsic: 1.2.1 + is-string: 1.0.7 + dev: true + + /array-union/2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.findlastindex/1.2.3: + resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + es-shim-unscopables: 1.0.0 + get-intrinsic: 1.2.1 + dev: true + + /array.prototype.flat/1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + es-shim-unscopables: 1.0.0 + dev: true + + /array.prototype.flatmap/1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + es-shim-unscopables: 1.0.0 + dev: true + + /arraybuffer.prototype.slice/1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + get-intrinsic: 1.2.1 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /available-typed-arrays/1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /binary-extensions/2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion/2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + + /call-bind/1.0.2: + resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + dependencies: + function-bind: 1.1.1 + get-intrinsic: 1.2.1 + dev: true + + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /chalk/4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chokidar/3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + /color-convert/2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name/1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /colors/1.2.5: + resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==} + engines: {node: '>=0.1.90'} + dev: true + + /commander/9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + requiresBuild: true + dev: true + optional: true + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /confusing-browser-globals/1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + dev: true + + /cross-spawn/7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /dat.gui/0.7.9: + resolution: {integrity: sha512-sCNc1OHobc+Erc1HqiswYgHdVNpSJUlk/Hz8vzOCsER7rl+oF/4+v8GXFUyCgtXpoCX6+bnmg07DedLvBLwYKQ==} + dev: false + + /de-indent/1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + dev: true + + /debug/3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deep-is/0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /define-data-property/1.1.0: + resolution: {integrity: sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + gopd: 1.0.1 + has-property-descriptors: 1.0.0 + dev: true + + /define-properties/1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.0 + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true + + /dir-glob/3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine/2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine/3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /es-abstract/1.22.2: + resolution: {integrity: sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.1 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 + safe-regex-test: 1.0.0 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.11 + dev: true + + /es-set-tostringtag/2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-shim-unscopables/1.0.0: + resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + dependencies: + has: 1.0.3 + dev: true + + /es-to-primitive/1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /esbuild/0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: true + + /esbuild/0.19.4: + resolution: {integrity: sha512-x7jL0tbRRpv4QUyuDMjONtWFciygUxWaUM1kMX2zWxI0X2YWOt7MSA0g4UdeSiHM8fcYVzpQhKYOycZwxTdZkA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.19.4 + '@esbuild/android-arm64': 0.19.4 + '@esbuild/android-x64': 0.19.4 + '@esbuild/darwin-arm64': 0.19.4 + '@esbuild/darwin-x64': 0.19.4 + '@esbuild/freebsd-arm64': 0.19.4 + '@esbuild/freebsd-x64': 0.19.4 + '@esbuild/linux-arm': 0.19.4 + '@esbuild/linux-arm64': 0.19.4 + '@esbuild/linux-ia32': 0.19.4 + '@esbuild/linux-loong64': 0.19.4 + '@esbuild/linux-mips64el': 0.19.4 + '@esbuild/linux-ppc64': 0.19.4 + '@esbuild/linux-riscv64': 0.19.4 + '@esbuild/linux-s390x': 0.19.4 + '@esbuild/linux-x64': 0.19.4 + '@esbuild/netbsd-x64': 0.19.4 + '@esbuild/openbsd-x64': 0.19.4 + '@esbuild/sunos-x64': 0.19.4 + '@esbuild/win32-arm64': 0.19.4 + '@esbuild/win32-ia32': 0.19.4 + '@esbuild/win32-x64': 0.19.4 + dev: true + + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-airbnb-base/15.0.0_mc36sq7crv2v5vtlozlclqwu5e: + resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.2 + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.50.0 + eslint-plugin-import: 2.28.1_4nytrgfpfmroylhx7ogxfohaye + object.assign: 4.1.4 + object.entries: 1.1.7 + semver: 6.3.1 + dev: true + + /eslint-config-airbnb-typescript/17.1.0_fwsuazv5pgoz2k7mdjirunpzam: + resolution: {integrity: sha512-GPxI5URre6dDpJ0CtcthSZVBAfI+Uw7un5OYNVxP2EYi3H81Jw701yFP7AU+/vCE7xBtFmjge7kfhhk4+RAiig==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^5.13.0 || ^6.0.0 + '@typescript-eslint/parser': ^5.0.0 || ^6.0.0 + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.3 + dependencies: + '@typescript-eslint/eslint-plugin': 6.7.4_sjhwt3bl5psuxqi3hx6z7r6ola + '@typescript-eslint/parser': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + eslint: 8.50.0 + eslint-config-airbnb-base: 15.0.0_mc36sq7crv2v5vtlozlclqwu5e + eslint-plugin-import: 2.28.1_4nytrgfpfmroylhx7ogxfohaye + dev: true + + /eslint-import-resolver-alias/1.1.2_b6377bcr3argvnmxmq6ha6uyl4: + resolution: {integrity: sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w==} + engines: {node: '>= 4'} + peerDependencies: + eslint-plugin-import: '>=1.4.0' + dependencies: + eslint-plugin-import: 2.28.1_4nytrgfpfmroylhx7ogxfohaye + dev: true + + /eslint-import-resolver-node/0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.0 + resolve: 1.22.6 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils/2.8.0_2koj2nlfkn7hmvx3bc24wyffmi: + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + debug: 3.2.7 + eslint: 8.50.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es/3.0.1_eslint@8.50.0: + resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=4.19.1' + dependencies: + eslint: 8.50.0 + eslint-utils: 2.1.0 + regexpp: 3.2.0 + dev: true + + /eslint-plugin-import/2.28.1_4nytrgfpfmroylhx7ogxfohaye: + resolution: {integrity: sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 6.7.4_jk7qbkaijtltyu4ajmze3dfiwa + array-includes: 3.1.7 + array.prototype.findlastindex: 1.2.3 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.50.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0_2koj2nlfkn7hmvx3bc24wyffmi + has: 1.0.3 + is-core-module: 2.13.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.7 + object.groupby: 1.0.1 + object.values: 1.1.7 + semver: 6.3.1 + tsconfig-paths: 3.14.2 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-node/11.1.0_eslint@8.50.0: + resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} + engines: {node: '>=8.10.0'} + peerDependencies: + eslint: '>=5.16.0' + dependencies: + eslint: 8.50.0 + eslint-plugin-es: 3.0.1_eslint@8.50.0 + eslint-utils: 2.1.0 + ignore: 5.2.4 + minimatch: 3.1.2 + resolve: 1.22.6 + semver: 6.3.1 + dev: true + + /eslint-plugin-promise/6.1.1_eslint@8.50.0: + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.50.0 + dev: true + + /eslint-plugin-standard/5.0.0_eslint@8.50.0: + resolution: {integrity: sha512-eSIXPc9wBM4BrniMzJRBm2uoVuXz2EPa+NXPk2+itrVt+r5SbKFERx/IgrK/HmfjddyKVz2f+j+7gBRvu19xLg==} + deprecated: 'standard 16.0.0 and eslint-config-standard 16.0.0 no longer require the eslint-plugin-standard package. You can remove it from your dependencies with ''npm rm eslint-plugin-standard''. More info here: https://github.com/standard/standard/issues/1316' + peerDependencies: + eslint: '>=5.0.0' + dependencies: + eslint: 8.50.0 + dev: true + + /eslint-scope/7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-utils/2.1.0: + resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} + engines: {node: '>=6'} + dependencies: + eslint-visitor-keys: 1.3.0 + dev: true + + /eslint-visitor-keys/1.3.0: + resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} + engines: {node: '>=4'} + dev: true + + /eslint-visitor-keys/3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint/8.50.0: + resolution: {integrity: sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0_eslint@8.50.0 + '@eslint-community/regexpp': 4.9.0 + '@eslint/eslintrc': 2.1.2 + '@eslint/js': 8.50.0 + '@humanwhocodes/config-array': 0.11.11 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.22.0 + graphemer: 1.4.0 + ignore: 5.2.4 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree/9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.10.0 + acorn-jsx: 5.3.2_acorn@8.10.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery/1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse/4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker/0.6.1: + resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} + dev: true + + /estree-walker/2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /eventemitter3/5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /fast-deep-equal/3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob/3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify/2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein/2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq/1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache/6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.1.0 + dev: true + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + + /find-up/5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache/3.1.0: + resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==} + engines: {node: '>=12.0.0'} + dependencies: + flatted: 3.2.9 + keyv: 4.5.3 + rimraf: 3.0.2 + dev: true + + /flatted/3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /for-each/0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /fs-extra/7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + optional: true + + /function-bind/1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /function.prototype.name/1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names/1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /get-intrinsic/1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 + dev: true + + /get-symbol-description/1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + + /glob-parent/6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals/13.22.0: + resolution: {integrity: sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis/1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby/11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.1 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd/1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /graceful-fs/4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer/1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-bigints/1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag/4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors/1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.1 + dev: true + + /has-proto/1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag/1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /has/1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /he/1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /ignore/5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /immutable/4.3.4: + resolution: {integrity: sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==} + + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-lazy/4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: true + + /imurmurhash/0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /internal-slot/1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /is-array-buffer/3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /is-bigint/1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path/2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + + /is-boolean-object/1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-callable/1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module/2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + dependencies: + has: 1.0.3 + dev: true + + /is-date-object/1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + + /is-negative-zero/2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object/1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + /is-path-inside/3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer/1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol/1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array/1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.11 + dev: true + + /is-weakref/1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /isarray/2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe/2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /jju/1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: true + + /js-yaml/4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-buffer/3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-schema-traverse/0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify/1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5/1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /jsonfile/4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /keyv/4.5.3: + resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kolorist/1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: true + + /levn/0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /locate-path/6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.get/4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: true + + /lodash.isequal/4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: true + + /lodash.merge/4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash/4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /magic-string/0.25.3: + resolution: {integrity: sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==} + dependencies: + sourcemap-codec: 1.4.8 + dev: true + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch/9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist/1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /muggle-string/0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + dev: true + + /nanoid/3.3.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /natural-compare/1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /normalize-path/3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + /object-inspect/1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /object-keys/1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign/4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.entries/1.1.7: + resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + dev: true + + /object.fromentries/2.0.7: + resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + dev: true + + /object.groupby/1.0.1: + resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + get-intrinsic: 1.2.1 + dev: true + + /object.values/1.1.7: + resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator/0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit/3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate/5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key/3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type/4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /phaser/3.60.0: + resolution: {integrity: sha512-IKUy35EnoEVcl2EmJ8WOyK4X8OoxHYdlhZLgRGpNrvD1fEagYffhVmwHcapE/tGiLgyrnezmXIo5RrH2NcrTHw==} + dependencies: + eventemitter3: 5.0.1 + dev: false + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + /postcss/8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.6 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /prelude-ls/1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /punycode/2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /readdirp/3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + + /regexp.prototype.flags/1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: true + + /regexpp/3.2.0: + resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} + engines: {node: '>=8'} + dev: true + + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve/1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + dev: true + + /resolve/1.22.6: + resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==} + hasBin: true + dependencies: + is-core-module: 2.13.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup-plugin-strip-code/0.2.7: + resolution: {integrity: sha512-+5t9u/VrHPSfiRWWKMVin+KOtFwFak337FAZxeTjxYDjB3DDoHBQRkXHQvBn713eAfW81t41mGuysqsMXiuTjw==} + dependencies: + magic-string: 0.25.3 + rollup-pluginutils: 2.8.1 + dev: true + + /rollup-pluginutils/2.8.1: + resolution: {integrity: sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==} + dependencies: + estree-walker: 0.6.1 + dev: true + + /rollup/2.79.1: + resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /rollup/3.29.4: + resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-array-concat/1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-regex-test/1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-regex: 1.1.4 + dev: true + + /sass/1.68.0: + resolution: {integrity: sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + chokidar: 3.5.3 + immutable: 4.3.4 + source-map-js: 1.0.2 + + /semver/6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver/7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /set-function-name/2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.0 + dev: true + + /shebang-command/2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex/3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel/1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + object-inspect: 1.12.3 + dev: true + + /slash/3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /source-map-js/1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + + /source-map/0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /sourcemap-codec/1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + dev: true + + /sprintf-js/1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stats.js/0.17.0: + resolution: {integrity: sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==} + dev: false + + /string-argv/0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: true + + /string.prototype.trim/1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + dev: true + + /string.prototype.trimend/1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + dev: true + + /string.prototype.trimstart/1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + dev: true + + /strip-ansi/6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom/3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-json-comments/3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color/7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /text-table/0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /to-fast-properties/2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + + /ts-api-utils/1.0.3_typescript@5.2.2: + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.2.2 + dev: true + + /tsconfig-paths/3.14.2: + resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib/2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + + /type-check/0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest/0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typed-array-buffer/1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length/1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset/1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length/1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typescript/5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} + engines: {node: '>=12.20'} + hasBin: true + dev: true + + /typescript/5.2.2: + resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /unbox-primitive/1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /universalify/0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /uri-js/4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /uuid/9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + + /validator/13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + dev: true + + /vite-plugin-dts/3.6.0_c3vqjxdev4cverowl5dawv6nn4: + resolution: {integrity: sha512-doxhDRFJCZD2sGjIp4V800nm8Y19GvmwckjG5vYPuiqJ7OBjc9NlW1Vp9Gkyh2aXlUs1jTDRH/lxWfcsPLOQHg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + '@microsoft/api-extractor': 7.37.3_@types+node@20.8.2 + '@rollup/pluginutils': 5.0.4 + '@vue/language-core': 1.8.15_typescript@5.2.2 + debug: 4.3.4 + kolorist: 1.8.0 + typescript: 5.2.2 + vite: 4.4.10_xw5nuywhrj3t7rakopdrzdmjn4 + vue-tsc: 1.8.15_typescript@5.2.2 + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + dev: true + + /vite-plugin-eslint/1.8.1_eslint@8.50.0+vite@4.4.10: + resolution: {integrity: sha512-PqdMf3Y2fLO9FsNPmMX+//2BF5SF8nEWspZdgl4kSt7UvHDRHVVfHvxsD7ULYzZrJDGRxR81Nq7TOFgwMnUang==} + peerDependencies: + eslint: '>=7' + vite: '>=2' + dependencies: + '@rollup/pluginutils': 4.2.1 + '@types/eslint': 8.44.3 + eslint: 8.50.0 + rollup: 2.79.1 + vite: 4.4.10_xw5nuywhrj3t7rakopdrzdmjn4 + dev: true + + /vite/4.4.10_xw5nuywhrj3t7rakopdrzdmjn4: + resolution: {integrity: sha512-TzIjiqx9BEXF8yzYdF2NTf1kFFbjMjUSV0LFZ3HyHoI3SGSPLnnFUKiIQtL3gl2AjHvMrprOvQ3amzaHgQlAxw==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.8.2 + esbuild: 0.18.20 + postcss: 8.4.31 + rollup: 3.29.4 + sass: 1.68.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vue-template-compiler/2.7.14: + resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + dev: true + + /vue-tsc/1.8.15_typescript@5.2.2: + resolution: {integrity: sha512-4DoB3LUj7IToLmggoCxRiFG+QU5lem0nv03m1ocqugXA9rSVoTOEoYYaP8vu8b99Eh+/cCVdYOeIAQ+RsgUYUw==} + hasBin: true + peerDependencies: + typescript: '*' + dependencies: + '@vue/language-core': 1.8.15_typescript@5.2.2 + '@vue/typescript': 1.8.15_typescript@5.2.2 + semver: 7.5.4 + typescript: 5.2.2 + dev: true + + /which-boxed-primitive/1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array/1.1.11: + resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which/2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yocto-queue/0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /z-schema/5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.11.0 + optionalDependencies: + commander: 9.5.0 + dev: true diff --git a/scripts/eslint/index.js b/scripts/eslint/index.js index b6220b7..d9cbc8e 100644 --- a/scripts/eslint/index.js +++ b/scripts/eslint/index.js @@ -1,92 +1,6 @@ module.exports = { rules: { - 'prefer-destructuring': [ - 'warn', - { - VariableDeclarator: { - array: false, - object: true, - }, - AssignmentExpression: { - array: true, - object: true, - }, - }, - { - enforceForRenamedProperties: false, - }, - ], - 'no-restricted-syntax': [ - 'warn', - { - selector: 'ForInStatement', - message: - 'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.', - }, - { - selector: 'ForOfStatement', - message: - 'iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.', - }, - { - selector: 'LabeledStatement', - message: 'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.', - }, - { - selector: 'WithStatement', - message: '`with` is disallowed in strict mode because it makes code impossible to predict and optimize.', - }, - ], - indent: [ - 'error', - 4, - { - SwitchCase: 1, - VariableDeclarator: 1, - outerIIFEBody: 1, - // MemberExpression: null, - FunctionDeclaration: { - parameters: 1, - body: 1, - }, - FunctionExpression: { - parameters: 1, - body: 1, - }, - CallExpression: { - arguments: 1, - }, - ArrayExpression: 1, - ObjectExpression: 1, - ImportDeclaration: 1, - flatTernaryExpressions: false, - ignoredNodes: ['JSXElement', 'JSXElement *'], - }, - ], - 'class-methods-use-this': 'warn', - 'no-undef': 'warn', - 'no-unreachable': 'warn', - 'no-unused-vars': 'warn', - 'no-underscore-dangle': 'off', - 'linebreak-style': ['error', 'windows'], - 'no-mixed-operators': [ - 'off', - { - allowSamePrecedence: true, - }, - ], - 'sort-imports': 'off', - 'import/first': 'off', - // https://blog.javascripting.com/2015/09/07/fine-tuning-airbnbs-eslint-config/ - 'max-len': [1, 200, 2, { ignoreComments: true }], - 'no-cond-assign': [2, 'except-parens'], - radix: 0, - 'no-unused-vars': [1, { vars: 'local', args: 'none' }], - 'default-case': 0, - 'no-else-return': 0, - 'no-param-reassign': ['warn', { props: false }], - 'no-continue': 'warn', - 'no-lonely-if': 'warn', - 'no-console': 'off', + "@typescript-eslint/no-explicit-any": "off", + // "@typescript-eslint/no-implicit-any": "error", }, }; diff --git a/src/components/entities/hasTrigger.js b/src/components/entities/hasTrigger.js deleted file mode 100644 index 19a19c5..0000000 --- a/src/components/entities/hasTrigger.js +++ /dev/null @@ -1,87 +0,0 @@ -import Phaser from 'phaser'; - -const hasTrigger = function hasTriggerFunc(state) { - let parentScene; - - let triggerZone; - let overlapsWith = []; - let overlappedEntities = []; - let x = 0; - let y = 0; - let w = 10; - let h = 10; - - function createTriggerZone() { - triggerZone = new Phaser.GameObjects.Zone(parentScene, x, y, w, h); - parentScene.physics.add.existing(triggerZone, true); - } - - function init(newParentScene) { - parentScene = newParentScene; - createTriggerZone(); - } - - function setSize(newW, newH) { - w = newW; - h = newH; - triggerZone.setSize(w, h); - } - - function setPosition(newX, newY) { - x = newX; - y = newY; - triggerZone.setPosition(x, y); - } - - function setOverlaps(bodies) { - overlapsWith = bodies; - } - - function addOverlapBody(body) { - overlapsWith.push(body); - } - - function isOverlappedByAny() { - return overlappedEntities.length > 0; - } - - /** - * It should be possible to optimize state to avoid a double loop (or is it?). - */ - function update() { - const previous = overlappedEntities; - overlappedEntities = []; - parentScene.physics.overlap(triggerZone, overlapsWith, (zone, entity) => { - overlappedEntities.push(entity); - }); - - overlappedEntities.forEach((entity) => { - if (previous.indexOf(entity) === -1) { - state.onEntityEnteredRange(entity); - } - }); - - // If an entity was overlapped previously, but no longer, we emit an exit event. - previous.forEach((entity) => { - if (overlappedEntities.indexOf(entity) === -1) { - state.onEntityLeftRange(entity); - } - }); - } - - return { - // props - // methods - init, - setSize, - setPosition, - setOverlaps, - addOverlapBody, - isOverlappedByAny, - update, - onEntityLeftRange: e => e, - onEntityEnteredRange: e => e, - }; -}; - -export default hasTrigger; diff --git a/src/components/entities/hasTrigger.ts b/src/components/entities/hasTrigger.ts new file mode 100644 index 0000000..aa5349a --- /dev/null +++ b/src/components/entities/hasTrigger.ts @@ -0,0 +1,112 @@ +import { Position } from 'components/hasPosition'; +import { Size } from 'components/hasSize'; +import { ExtendedPhaserScene } from 'components/isScene'; +import Phaser from 'phaser'; + +export interface TriggerComponent { + init(parentScene: ExtendedPhaserScene): void; + onEntityLeftRange(entity: Phaser.Tilemaps.Tile | Phaser.Types.Physics.Arcade.GameObjectWithBody): void; + onEntityEnteredRange(entity: Phaser.Tilemaps.Tile | Phaser.Types.Physics.Arcade.GameObjectWithBody): void; + setSize(size: Size): Size; + setPosition(pos: Position): Position; + setOverlaps(bodies: Array): void; + addOverlapBody(body: Phaser.GameObjects.Zone): void; + isOverlappedByAny(): boolean; + update(): void; +} + +const hasTrigger = function hasTriggerFunc(state: TriggerComponent): TriggerComponent { + let parentScene: ExtendedPhaserScene | undefined; + + let triggerZone: Phaser.GameObjects.Zone | undefined; + let overlapsWith: Array = []; + let overlappedEntities: Array = []; + let x = 0; + let y = 0; + let w = 10; + let h = 10; + + function createTriggerZone() { + if (parentScene) { + triggerZone = new Phaser.GameObjects.Zone(parentScene, x, y, w, h); + parentScene.physics.add.existing(triggerZone, true); + } + } + + function init(newParentScene: ExtendedPhaserScene) { + parentScene = newParentScene; + createTriggerZone(); + } + + function setSize(size: Size): Size { + w = size.height; + h = size.width; + if (triggerZone) { + triggerZone.setSize(w, h); + } + return size; + } + + function setPosition(pos: Position): Position { + x = pos.x; + y = pos.y; + if (triggerZone) { + triggerZone.setPosition(x, y); + } + return pos; + } + + function setOverlaps(bodies: Array) { + overlapsWith = bodies; + } + + function addOverlapBody(body: Phaser.GameObjects.Zone) { + overlapsWith.push(body); + } + + function isOverlappedByAny() { + return overlappedEntities.length > 0; + } + + /** + * It should be possible to optimize state to avoid a double loop (or is it?). + */ + function update() { + const previous = overlappedEntities; + overlappedEntities = []; + if (parentScene && triggerZone) { + parentScene.physics.overlap(triggerZone, overlapsWith, (zone, entity) => { + overlappedEntities.push(entity); + }); + } + + overlappedEntities.forEach((entity) => { + if (previous.indexOf(entity) === -1) { + state.onEntityEnteredRange(entity); + } + }); + + // If an entity was overlapped previously, but no longer, we emit an exit event. + previous.forEach((entity) => { + if (overlappedEntities.indexOf(entity) === -1) { + state.onEntityLeftRange(entity); + } + }); + } + + return { + // props + // methods + init, + setSize, + setPosition, + setOverlaps, + addOverlapBody, + isOverlappedByAny, + update, + onEntityLeftRange: e => e, + onEntityEnteredRange: e => e, + }; +}; + +export default hasTrigger; diff --git a/src/components/entities/isGameEntity.js b/src/components/entities/isGameEntity.js deleted file mode 100644 index 75a8505..0000000 --- a/src/components/entities/isGameEntity.js +++ /dev/null @@ -1,19 +0,0 @@ -import getUUID from 'utils/getUUID'; - -const isGameEntity = function isGameEntityFunc(state) { - function printInfo() { - console.log(`id: %c${state.id}`, 'color: yellow'); - } - - function update() {} - - return { - // props - id: getUUID(), - // methods - printInfo, - update, - }; -}; - -export default isGameEntity; diff --git a/src/components/entities/isGameEntity.ts b/src/components/entities/isGameEntity.ts new file mode 100644 index 0000000..12aed45 --- /dev/null +++ b/src/components/entities/isGameEntity.ts @@ -0,0 +1,26 @@ +import { v4 as uuidv4 } from 'uuid'; + +export interface GameEntityState { + id: string; + + printInfo(): void; + update(): void; +} + +const isGameEntity = function isGameEntityFunc(state: GameEntityState): GameEntityState { + function printInfo() { + console.log(`id: %c${state.id}`, 'color: yellow'); + } + + function update() { } + + return { + // props + id: uuidv4(), + // methods + printInfo, + update, + }; +}; + +export default isGameEntity; diff --git a/src/components/events/canEmit.js b/src/components/events/canEmit.js deleted file mode 100644 index 618f0df..0000000 --- a/src/components/events/canEmit.js +++ /dev/null @@ -1,66 +0,0 @@ -import store from 'root/store'; -import Phaser from 'phaser'; -import createListener from 'core/createListener'; - -const canEmit = function canEmitFunc(state) { - const localEmitter = new Phaser.Events.EventEmitter(); - const listeners = []; - - function emitGlobal(event, data) { - store.messageBus.emit(event, data); - } - - function emit(event, data) { - localEmitter.emit(event, data); - } - - function on(event, fn, context) { - localEmitter.on(event, fn, context); - const listener = createListener(event, fn, false, state); - listeners.push(listener); - return listener; - } - - function once(event, fn, context) { - localEmitter.once(event, fn, context); - const listener = createListener(event, fn, true, state); - listeners.push(listener); - return listener; - } - - function off(listener) { - if (listeners.indexOf(listener) >= 0) { - localEmitter.off(listener.event, listener.fn, listener.once); - listeners.splice(listeners.indexOf(listener), 1); - } - } - - function removeAllListeners() { - if (localEmitter) { - listeners.forEach((l) => { - l.drop(); - }); - } - } - - function destroy() { - if (localEmitter) { - state.removeAllListeners(); - localEmitter.destroy(); - } - } - - return { - // props - // methods - emitGlobal, - emit, - on, - once, - off, - removeAllListeners, - destroy, - }; -}; - -export default canEmit; diff --git a/src/components/events/canEmit.ts b/src/components/events/canEmit.ts new file mode 100644 index 0000000..9abcfa8 --- /dev/null +++ b/src/components/events/canEmit.ts @@ -0,0 +1,77 @@ +import store from 'root/store'; +import Phaser from 'phaser'; +import createListener, { Listener } from 'core/createListener'; +import { EventData } from 'configs/eventConfig'; + +export interface EmitComponent { + emitGlobal: (event: T, data: EventData[T]) => void; + emit: (event: T, data: EventData[T]) => void; + on: (event: T, fn: (e: EventData[T]) => void, context: EmitComponent) => Listener; + once: (event: T, fn: (e: EventData[T]) => void, context: EmitComponent) => Listener; + off: (listener: Listener) => void; + removeAllListeners: () => void; + destroy: () => void; +} + +function canEmit(state: EmitComponent) { + const localEmitter = new Phaser.Events.EventEmitter(); + const listeners: Array> = []; + + function emitGlobal(event: T, data: EventData[T]) { + store.messageBus?.emit(event, data); + } + + function emit(event: T, data: EventData[T]) { + localEmitter.emit(event, data); + } + + function on(event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener { + localEmitter.on(event, fn, context); + const listener = createListener(event, fn, false, state); + listeners.push(listener); + return listener; + } + + function once(event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener { + localEmitter.once(event, fn, context); + const listener = createListener(event, fn, true, state); + listeners.push(listener); + return listener; + } + + function off(listener: Listener) { + if (listeners.indexOf(listener) >= 0) { + localEmitter.off(listener.event, listener.fn, listener.once); + listeners.splice(listeners.indexOf(listener), 1); + } + } + + function removeAllListeners() { + if (localEmitter) { + listeners.forEach((l) => { + l.drop(); + }); + } + } + + function destroy() { + if (localEmitter) { + state.removeAllListeners(); + localEmitter.destroy(); + } + } + const returnState: EmitComponent = { + // props + // methods + emitGlobal, + emit, + on, + once, + off, + removeAllListeners, + destroy, + }; + return returnState; +} + +export default canEmit; diff --git a/src/components/events/canListen.js b/src/components/events/canListen.js deleted file mode 100644 index 30b3683..0000000 --- a/src/components/events/canListen.js +++ /dev/null @@ -1,53 +0,0 @@ -import store from 'root/store'; - -const canListen = function canListenFunc(state) { - const listeners = []; - - function listenOn(emitState, event, fn, context) { - const listener = emitState.on(event, fn, context); - listeners.push(listener); - return listener; - } - - function listenOnce(emitState, event, fn, context) { - const listener = emitState.once(event, fn, context); - listeners.push(listener); - return listener; - } - - function listenGlobal(event, fn, context) { - const listener = store.messageBus.on(event, fn, context); - listeners.push(listener); - return listener; - } - - function listenOnceGlobal(event, fn, context) { - const listener = store.messageBus.once(event, fn, context); - listeners.push(listener); - return listener; - } - - function dropListener(listener) { - listeners.splice(listeners.findIndex(l => l === listener), 1); - listener.drop(); - } - - function destroy() { - listeners.forEach((l) => { - l.drop(); - }); - } - - return { - // props - // methods - dropListener, - listenOn, - listenOnce, - listenGlobal, - listenOnceGlobal, - destroy, - }; -}; - -export default canListen; diff --git a/src/components/events/canListen.ts b/src/components/events/canListen.ts new file mode 100644 index 0000000..8ffc050 --- /dev/null +++ b/src/components/events/canListen.ts @@ -0,0 +1,72 @@ +import store from 'root/store'; +import { EmitComponent } from './canEmit'; +import { EventData } from 'configs/eventConfig'; +import { Listener } from 'core/createListener'; +import { LifeCycle } from 'components/isScene'; + +export interface ListenComponent extends LifeCycle { + dropListener(listener: Listener): void; + listenOn(emitState: EmitComponent, event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener | undefined; + listenOnce(emitState: EmitComponent, event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener | undefined; + listenGlobal(event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener | undefined; + listenOnceGlobal(event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener | undefined; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const canListen = function canListenFunc(state: ListenComponent): ListenComponent { + const listeners: Array> = []; + + function listenOn(emitState: EmitComponent, event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener { + const listener = emitState.on(event, fn, context); + listeners.push(listener); + return listener; + } + + function listenOnce(emitState: EmitComponent, event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener { + const listener = emitState.once(event, fn, context); + listeners.push(listener); + return listener; + } + + function listenGlobal(event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener | undefined{ + const listener = store.messageBus?.on(event, fn, context); + if(listener) { + listeners.push(listener); + } + return listener; + } + + function listenOnceGlobal(event: T, fn: (e: EventData[T]) => void, context: EmitComponent): Listener | undefined { + const listener = store.messageBus?.once(event, fn, context); + if(listener) { + listeners.push(listener); + } + return listener; + } + + function dropListener(listener: Listener) { + listeners.splice(listeners.findIndex(l => l === listener), 1); + listener.drop(); + } + + function destroy() { + listeners.forEach((l) => { + l.drop(); + }); + } + + const returnState: ListenComponent = { + // props + // methods + dropListener, + listenOn, + listenOnce, + listenGlobal, + listenOnceGlobal, + destroy, + }; + + return returnState; +}; + +export default canListen; diff --git a/src/components/hasAudio.js b/src/components/hasAudio.js deleted file mode 100644 index c03ffcb..0000000 --- a/src/components/hasAudio.js +++ /dev/null @@ -1,34 +0,0 @@ -import store from 'root/store'; - -const hasAudio = function hasAudioFunc(state) { - let audioMan = store.audioManager; - - function getAudioManager() { - return audioMan; - } - - function setAudioManager(manager) { - audioMan = manager; - } - - function playSfx(key) { - if (!audioMan) return; - - audioMan.playSfx(key); - } - - function playMusic(key) { - if (!audioMan) return; - - audioMan.playMusic(key); - } - - return { - getAudioManager, - setAudioManager, - playSfx, - playMusic, - }; -}; - -export default hasAudio; diff --git a/src/components/hasAudio.ts b/src/components/hasAudio.ts new file mode 100644 index 0000000..2142352 --- /dev/null +++ b/src/components/hasAudio.ts @@ -0,0 +1,43 @@ +import { AudioManager } from 'core/createAudioManager'; +import store from 'root/store'; + +export interface Audio { + getAudioManager(): AudioManager | undefined; + setAudioManager(manager: AudioManager): void; + playSfx(key: string): void; + playMusic(key: string): void; +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function hasAudio(state: Audio): Audio { + let audioMan: AudioManager | undefined = store.audioManager; + + function getAudioManager(): AudioManager | undefined { + return audioMan; + } + + function setAudioManager(manager: AudioManager) { + audioMan = manager; + } + + function playSfx(key: string) { + if (!audioMan) return; + + audioMan.playSfx(key); + } + + function playMusic(key: string) { + if (!audioMan) return; + + audioMan.playMusic(key); + } + + return { + getAudioManager, + setAudioManager, + playSfx, + playMusic, + }; +} + +export default hasAudio; diff --git a/src/components/hasCamera.js b/src/components/hasCamera.js deleted file mode 100644 index 9e6338d..0000000 --- a/src/components/hasCamera.js +++ /dev/null @@ -1,45 +0,0 @@ - -/** - * Camera abstraction. - */ -const hasCamera = function hasCameraFunc(state) { - let camera; - - function create() { - camera = state.scene.cameras.main; - } - - function setMainCamera(cam) { - camera = cam; - } - - function getCamera() { - return camera; - } - - function setViewport(x, y, w, h) { - if (!camera) return; - camera.setViewport(x, y, w, h); - } - - function setZoom(zoom) { - if (!camera) return; - camera.setZoom(zoom); - } - - function setSize(x, y) { - if (!camera) return; - camera.setSize(x, y); - } - - return { - create, - getCamera, - setMainCamera, - setViewport, - setZoom, - setSize, - }; -}; - -export default hasCamera; diff --git a/src/components/hasCamera.ts b/src/components/hasCamera.ts new file mode 100644 index 0000000..f3e4fbb --- /dev/null +++ b/src/components/hasCamera.ts @@ -0,0 +1,54 @@ +import { ExtendedPhaserScene, LifeCycle } from "./isScene"; + +export interface Camera extends LifeCycle { + getCamera: () => Phaser.Cameras.Scene2D.Camera; + setMainCamera: (cam: Phaser.Cameras.Scene2D.Camera) => void; + setViewport: (x: number, y: number, w: number, h: number) => void; + setZoom: (zoom: number) => void; + setSize: (x: number, y: number) => void; + scene: ExtendedPhaserScene; +} +/** + * Camera abstraction. + */ +const hasCamera = function hasCameraFunc(state: Camera) { + let camera: Phaser.Cameras.Scene2D.Camera | undefined; + + function create() { + camera = state.scene.cameras.main; + } + + function setMainCamera(cam: Phaser.Cameras.Scene2D.Camera) { + camera = cam; + } + + function getCamera() { + return camera; + } + + function setViewport(x: number, y: number, w: number, h: number) { + if (!camera) return; + camera.setViewport(x, y, w, h); + } + + function setZoom(zoom: number) { + if (!camera) return; + camera.setZoom(zoom); + } + + function setSize(x: number, y: number) { + if (!camera) return; + camera.setSize(x, y); + } + + return { + create, + getCamera, + setMainCamera, + setViewport, + setZoom, + setSize, + }; +}; + +export default hasCamera; diff --git a/src/components/hasInput.js b/src/components/hasInput.js deleted file mode 100644 index de4653b..0000000 --- a/src/components/hasInput.js +++ /dev/null @@ -1,13 +0,0 @@ -import gameConfig from 'configs/gameConfig'; - -const hasInput = function hasInputFunc(state) { - function getKeyboard() { - return state.scene.manager.getScene(gameConfig.SCENES.GAME).getKeyboard(); - } - - return { - getKeyboard, - }; -}; - -export default hasInput; diff --git a/src/components/hasInput.ts b/src/components/hasInput.ts new file mode 100644 index 0000000..b15e100 --- /dev/null +++ b/src/components/hasInput.ts @@ -0,0 +1,17 @@ +import { SCENES } from 'configs/gameConfig'; +import { SceneComponent } from './isScene'; + +export interface Input extends SceneComponent { +} + +function hasInput(state: Input) { + function getKeyboard() { + return state.scene.scene.manager.getScene(SCENES.GAME).input.keyboard; + } + + return { + getKeyboard, + }; +} + +export default hasInput; diff --git a/src/components/hasPosition.js b/src/components/hasPosition.js deleted file mode 100644 index 7724e1b..0000000 --- a/src/components/hasPosition.js +++ /dev/null @@ -1,45 +0,0 @@ -const hasPosition = function hasPositionFunc(state) { - let x = 0; - let y = 0; - - function setPosition({ x: xp, y: yp }) { - x = xp; - y = yp; - return { x, y }; - } - - function setX(xp) { - state.setPosition({ x: xp, y }); - return xp; - } - - function setY(yp) { - state.setPosition({ x, y: yp }); - return yp; - } - - function getPosition() { - return { x, y }; - } - - function getX() { - return x; - } - - function getY() { - return y; - } - - return { - // props - // methods - setPosition, - setX, - setY, - getPosition, - getX, - getY, - }; -}; - -export default hasPosition; diff --git a/src/components/hasPosition.ts b/src/components/hasPosition.ts new file mode 100644 index 0000000..87df9f9 --- /dev/null +++ b/src/components/hasPosition.ts @@ -0,0 +1,65 @@ +export interface Position { + x: number; + y: number; +} + +export interface PositionComponent { + setPosition: (position: Position) => Position; + setX: (xp: number) => number; + setY: (yp: number) => number; + getPosition: () => Position; + getX: () => number; + getY: () => number; +} + +function hasPosition(state: PositionComponent): PositionComponent { + let x = 0; + let y = 0; + + function setPosition({ x: xp, y: yp }: Position): Position { + x = xp; + y = yp; + return { x, y }; + } + + function setX(xp: number): number { + state.setPosition({ + x: xp, + y + }); + return xp; + } + + function setY(yp: number): number { + state.setPosition({ + x, + y: yp + }); + return yp; + } + + function getPosition(): Position { + return { x, y }; + } + + function getX(): number { + return x; + } + + function getY(): number { + return y; + } + + return { + // props + // methods + setPosition, + setX, + setY, + getPosition, + getX, + getY, + }; +} + +export default hasPosition; diff --git a/src/components/hasSize.js b/src/components/hasSize.js deleted file mode 100644 index d69aa7a..0000000 --- a/src/components/hasSize.js +++ /dev/null @@ -1,46 +0,0 @@ -const hasSize = function hasSizeFunc(state) { - let width = 0; - let height = 0; - - function setSize({ w: wp, h: hp }) { - width = wp; - height = hp; - - return { width, height }; - } - - function setWidth(wp) { - state.setSize({ w: wp, h: height }); - return wp; - } - - function setHeight(hp) { - state.setSize({ w: width, h: hp }); - return hp; - } - - function getSize() { - return { w: width, h: height }; - } - - function getWidth() { - return width; - } - - function getHeight() { - return height; - } - - return { - // props - // methods - setSize, - setWidth, - setHeight, - getSize, - getWidth, - getHeight, - }; -}; - -export default hasSize; diff --git a/src/components/hasSize.ts b/src/components/hasSize.ts new file mode 100644 index 0000000..3b4bc79 --- /dev/null +++ b/src/components/hasSize.ts @@ -0,0 +1,66 @@ +export interface Size { + width: number; + height: number; +} + +export interface SizeComponent { + setSize: (size: Size) => Size; + setWidth: (wp: number) => number; + setHeight: (hp: number) => number; + getSize: () => Size; + getWidth: () => number; + getHeight: () => number; +} + +function hasSize(state: SizeComponent): SizeComponent { + let width = 0; + let height = 0; + + function setSize({ width: wp, height: hp }: Size): Size { + width = wp; + height = hp; + + return { width, height }; + } + + function setWidth(wp: number): number { + state.setSize({ + width: wp, + height + }); + return wp; + } + + function setHeight(hp: number): number { + state.setSize({ + width, + height: hp + }); + return hp; + } + + function getSize(): Size { + return { width, height }; + } + + function getWidth(): number { + return width; + } + + function getHeight(): number { + return height; + } + + return { + // props + // methods + setSize, + setWidth, + setHeight, + getSize, + getWidth, + getHeight, + }; +} + +export default hasSize; diff --git a/src/components/isScene.js b/src/components/isScene.js deleted file mode 100644 index 846b5a6..0000000 --- a/src/components/isScene.js +++ /dev/null @@ -1,66 +0,0 @@ -import Phaser from 'phaser'; - -/** - * Phaser.Scene abstraction. - * Init -> Preload -> Create -> Update -> Destroy - */ -const isScene = function isSceneFunc(state, sceneKey) { - if (!sceneKey) { - throw new Error('Missing sceneKey'); - } - - const scene = new Phaser.Scene(sceneKey); - - // ------ Hook into phasers scene lifecycle ------- - scene.init = () => { - // The ScenePlugin/Manager is not ready until init has run internally. - state.sceneManager = scene.scene; - if (state.init) state.init(); - }; - - scene.preload = () => { - if (state.preload) state.preload(); - }; - - scene.create = () => { - if (state.create) state.create(); - }; - - scene.update = () => { - if (state.update) state.update(); - }; - - - scene.destroy = () => { - if (state.destroy) state.destroy(); - }; - // -------------------------------------- - - function addScene(key, sceneRef, autoStart) { - return state.sceneManager.add(key, sceneRef, autoStart); - } - - function removeScene(sceneRef) { - state.sceneManager.remove(sceneRef); - } - - function addImage(x, y, key, frame = undefined) { - return scene.add.image(x, y, key, frame); - } - - function removeChild(key) { - const child = scene[key]; - if (child) child.destroy(); - } - - return { - sceneManager: undefined, - scene, - addScene, - removeScene, - addImage, - removeChild, - }; -}; - -export default isScene; diff --git a/src/components/isScene.ts b/src/components/isScene.ts new file mode 100644 index 0000000..d681460 --- /dev/null +++ b/src/components/isScene.ts @@ -0,0 +1,89 @@ +import { SCENES } from 'configs/gameConfig'; +import Phaser from 'phaser'; + +export interface LifeCycle { + init?: () => void + preload?: () => void + create?: () => void + update?: () => void + destroy?: () => void +} + +export type ExtendedPhaserScene = Phaser.Scene & LifeCycle + +export interface SceneComponent extends LifeCycle { + sceneManager?: Phaser.Scenes.ScenePlugin; + scene: ExtendedPhaserScene; + addScene: (key: SCENES, sceneRef: ExtendedPhaserScene, autoStart: boolean) => Phaser.Scene | undefined | null; + removeScene: (sceneRef: ExtendedPhaserScene) => void; + addImage: (x: number, y: number, key: string, frame?: string) => Phaser.GameObjects.Image; + removeChild: (key: string) => void; +} + +/** + * Phaser.Scene abstraction. + * Init -> Preload -> Create -> Update -> Destroy + */ +function isScene(state: SceneComponent, sceneKey: SCENES): SceneComponent { + if (!sceneKey) { + throw new Error('Missing sceneKey'); + } + + + + const scene: ExtendedPhaserScene = new Phaser.Scene(sceneKey) as ExtendedPhaserScene; + + // ------ Hook into phasers scene lifecycle ------- + scene.init = () => { + // The ScenePlugin/Manager is not ready until init has run internally. + state.sceneManager = scene.scene; + if (state.init) state.init(); + }; + + scene.preload = () => { + if (state.preload) state.preload(); + }; + + scene.create = () => { + if (state.create) state.create(); + }; + + scene.update = () => { + if (state.update) state.update(); + }; + + + scene.destroy = () => { + if (state.destroy) state.destroy(); + }; + // -------------------------------------- + + function addScene(key: SCENES, sceneRef: ExtendedPhaserScene, autoStart: boolean): Phaser.Scene | null | undefined { + return state.sceneManager?.add(key, sceneRef, autoStart); + } + + function removeScene(sceneRef: ExtendedPhaserScene) { + state.sceneManager?.remove(sceneRef); + } + + function addImage(x: number, y: number, key: string, frame?: string) { + return scene.add.image(x, y, key, frame); + } + + function removeChild(key: string) { + const child = scene.children.getByName(key); + child?.removedFromScene() + if (child) child.destroy(); + } + + return { + sceneManager: undefined, + scene, + addScene, + removeScene, + addImage, + removeChild, + }; +} + +export default isScene; diff --git a/src/configs/audioConfig.js b/src/configs/audioConfig.js deleted file mode 100644 index 2a10028..0000000 --- a/src/configs/audioConfig.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - MUSIC: { - BG_SCORE: { - KEY: 'bg_score', - PATH: 'assets/audio/Philipp_Weigl_-_06_-_Full_of_Stars.mp3', - }, - }, - SFX: { - COIN: { - KEY: 'coin_sfx', - PATH: 'assets/audio/coin.wav', - }, - }, -}; diff --git a/src/configs/audioConfig.ts b/src/configs/audioConfig.ts new file mode 100644 index 0000000..88c8fc1 --- /dev/null +++ b/src/configs/audioConfig.ts @@ -0,0 +1,27 @@ +export interface MusicInfo { + KEY: string; + PATH: string; +} + +export type Music = { [key: string]: MusicInfo } + +export const MUSIC: Music = { + BG_SCORE: { + KEY: 'bg_score', + PATH: 'assets/audio/Philipp_Weigl_-_06_-_Full_of_Stars.mp3', + }, +} + +export interface SfxInfo { + KEY: string; + PATH: string; +} + +export type Sfx = { [key: string]: SfxInfo } + +export const SFX: Sfx = { + COIN: { + KEY: 'coin_sfx', + PATH: 'assets/audio/coin.wav', + }, +} diff --git a/src/configs/devConfig.js b/src/configs/devConfig.js deleted file mode 100644 index 2a489d4..0000000 --- a/src/configs/devConfig.js +++ /dev/null @@ -1,9 +0,0 @@ -export default { - COMPOSITION_INFO: { - ENABLE: false, - ENABLE_FILTER: false, - FILTER: [], - ENABLE_FACTORY_FILTER: false, - FACTORY_FILTER: ['Note'], - }, -}; diff --git a/src/configs/devConfig.ts b/src/configs/devConfig.ts new file mode 100644 index 0000000..1f82723 --- /dev/null +++ b/src/configs/devConfig.ts @@ -0,0 +1,7 @@ +export const COMPOSITION_INFO = { + ENABLE: false, + ENABLE_FILTER: false, + FILTER: [], + ENABLE_FACTORY_FILTER: false, + FACTORY_FILTER: ['Note'], +}; diff --git a/src/configs/eventConfig.js b/src/configs/eventConfig.js deleted file mode 100644 index e818780..0000000 --- a/src/configs/eventConfig.js +++ /dev/null @@ -1,7 +0,0 @@ -export default { - EVENTS: { - GAME: { - STARTED: 'game started', - }, - }, -}; diff --git a/src/configs/eventConfig.ts b/src/configs/eventConfig.ts new file mode 100644 index 0000000..0152aaf --- /dev/null +++ b/src/configs/eventConfig.ts @@ -0,0 +1,47 @@ +export const EVENTS = { + GAME: { + STARTED: 'game_started', + }, + OTHER: { + TEST: 'other_event' + }, + KEYBOARD: { + KEYDOWN: 'keydown', + KEYUP: 'keyup', + }, + BUTTON: { + CLICK: 'button_click' + } +} as const; + +export interface GameStartedEvent { + welcomeMessage: string; +} + +export interface OtherEvent { + test: string; +} + +export interface KeyboardKeyUpEvent { + key: string; + repeat: boolean; + keyCode: number; +} + +export interface KeyboardKeyDownEvent { + key: string; + repeat: boolean; + keyCode: number; +} + +export interface ButtonClickEvent { + buttonName: string; +} + +export interface EventData { + [EVENTS.GAME.STARTED]: GameStartedEvent; + [EVENTS.OTHER.TEST]: OtherEvent; + [EVENTS.KEYBOARD.KEYDOWN]: KeyboardKeyDownEvent; + [EVENTS.KEYBOARD.KEYUP]: KeyboardKeyUpEvent; + [EVENTS.BUTTON.CLICK]: ButtonClickEvent; +} diff --git a/src/configs/gameConfig.js b/src/configs/gameConfig.js deleted file mode 100644 index b8cfe45..0000000 --- a/src/configs/gameConfig.js +++ /dev/null @@ -1,84 +0,0 @@ -export default { - GAME: { - VIEWHEIGHT: 1080, - VIEWWIDTH: 1920, - TITLE: 'Replace Me', - }, - SCENES: { - BOOT: 'game_boot', - LOAD: 'game_load', - GAME: 'game_game', - UI: 'UI', - }, - DEFAULT_TEXT_STYLE: { - font: 'Roboto', - fontSize: 20, - fill: '#ffffff', - smoothed: false, - }, - UI_DEFAULT: { - tint: 0xaaaaaa, - }, - AUDIO: { - musicKeys: ['bgScore'], - sfxKeys: ['coinSfx'], - }, - KEYS: { - LEFT_ARROW: { - CODE: 37, - KEY: '', - }, - UP_ARROW: { - CODE: 38, - KEY: '', - }, - RIGHT_ARROW: { - CODE: 39, - KEY: '', - }, - DOWN_ARROW: { - CODE: 40, - KEY: '', - }, - Z: { - CODE: 90, - KEY: 'Z', - }, - X: { - CODE: 88, - KEY: 'X', - }, - COMMA: { - CODE: 188, - KEY: ',', - }, - DOT: { - CODE: 190, - KEY: '.', - }, - A: { - CODE: 65, - KEY: 'A', - }, - S: { - CODE: 83, - KEY: 'S', - }, - K: { - CODE: 75, - KEY: 'K', - }, - L: { - CODE: 76, - KEY: 'L', - }, - ENTER: { - CODE: 13, - KEY: '', - }, - ESCAPE: { - CODE: 27, - KEY: '', - }, - }, -}; diff --git a/src/configs/gameConfig.ts b/src/configs/gameConfig.ts new file mode 100644 index 0000000..1e6b033 --- /dev/null +++ b/src/configs/gameConfig.ts @@ -0,0 +1,93 @@ +export enum GAME { + VIEWHEIGHT = 1080, + VIEWWIDTH = 1920, + TITLE = 'Replace Me', +} +export enum SCENES { + BOOT = 'game_boot', + LOAD = 'game_load', + GAME = 'game_game', + UI = 'UI', +} +export const DEFAULT_TEXT_STYLE = { + font: 'Roboto', + fontSize: 20, + fill: '#ffffff', + smoothed: false, +} +export const UI_DEFAULT = { + tint: 0xaaaaaa, +} +export const AUDIO = { + musicKeys: ['bgScore'], + sfxKeys: ['coinSfx'], +} + +export interface KeyInfo { + CODE: number; + KEY: string; +} + +export type KeyboardKeys = { [KEY in KeyboardKey]: KeyInfo } + +type KeyboardKey = "LEFT_ARROW" | "UP_ARROW" | "RIGHT_ARROW" | "DOWN_ARROW" | "Z" | "X" | "COMMA" | "DOT" | "A" | "S" | "K" | "L" | "ENTER" | "ESCAPE" + +export const KEYS: KeyboardKeys = { + LEFT_ARROW: { + CODE: 37, + KEY: '', + }, + UP_ARROW: { + CODE: 38, + KEY: '', + }, + RIGHT_ARROW: { + CODE: 39, + KEY: '', + }, + DOWN_ARROW: { + CODE: 40, + KEY: '', + }, + Z: { + CODE: 90, + KEY: 'Z', + }, + X: { + CODE: 88, + KEY: 'X', + }, + COMMA: { + CODE: 188, + KEY: ',', + }, + DOT: { + CODE: 190, + KEY: '.', + }, + A: { + CODE: 65, + KEY: 'A', + }, + S: { + CODE: 83, + KEY: 'S', + }, + K: { + CODE: 75, + KEY: 'K', + }, + L: { + CODE: 76, + KEY: 'L', + }, + ENTER: { + CODE: 13, + KEY: '', + }, + ESCAPE: { + CODE: 27, + KEY: '', + }, +} + diff --git a/src/configs/spriteConfig.js b/src/configs/spriteConfig.js deleted file mode 100644 index ad3e514..0000000 --- a/src/configs/spriteConfig.js +++ /dev/null @@ -1,14 +0,0 @@ -export default { - BACKGROUND: { - KEY: 'background', - PATH: 'assets/images/background.png', - }, - SPEAKER: { - KEY: 'speaker', - PATH: 'assets/images/speaker.png', - }, - SPEAKER_OFF: { - KEY: 'speaker_off', - PATH: 'assets/images/speaker-off.png', - }, -}; diff --git a/src/configs/spriteConfig.ts b/src/configs/spriteConfig.ts new file mode 100644 index 0000000..75841c3 --- /dev/null +++ b/src/configs/spriteConfig.ts @@ -0,0 +1,17 @@ +export interface SpriteConfig { + KEY: string; + PATH: string; +} + +export const BACKGROUND: SpriteConfig = { + KEY: 'background', + PATH: 'assets/images/background.png', +} +export const SPEAKER: SpriteConfig = { + KEY: 'speaker', + PATH: 'assets/images/speaker.png', +} +export const SPEAKER_OFF: SpriteConfig = { + KEY: 'speaker_off', + PATH: 'assets/images/speaker-off.png', +} diff --git a/src/core/createAudioManager.js b/src/core/createAudioManager.js deleted file mode 100644 index 48695e5..0000000 --- a/src/core/createAudioManager.js +++ /dev/null @@ -1,165 +0,0 @@ -import gameConfig from 'configs/gameConfig'; -import spriteConfig from 'configs/spriteConfig'; -import audioConfig from 'configs/audioConfig'; -import createState from 'utils/createState'; - -const createAudioManager = function createAudioManagerFunc(parentScene) { - if (!parentScene) throw new Error('A parent scene must be specified.'); - - const state = {}; - - let scene = parentScene; - let muteIcon; - let currentSong; - - const muteIdentifier = `${gameConfig.GAME.TITLE.replace(/ /g, '_')}_isMuted`; // replace all spaces with _ for safety - const soundEffects = new Map(); - const music = new Map(); - const currentVolume = 0.7; - const defaultSongKey = audioConfig.MUSIC.BG_SCORE.KEY; - - function _updateMute() { - if (state.isAudioMuted()) { - muteIcon.setTexture(spriteConfig.SPEAKER_OFF.KEY); - scene.sound.mute = true; - } else { - muteIcon.setTexture(spriteConfig.SPEAKER.KEY); - scene.sound.mute = false; - } - } - - function _setupMute() { - muteIcon = scene.add.image(1850, 1040, spriteConfig.SPEAKER.KEY); - muteIcon.setScrollFactor(0); - muteIcon.tint = gameConfig.UI_DEFAULT.tint; - muteIcon.depth = 3; - muteIcon.setInteractive(); - muteIcon.on('pointerup', state.toggleMute, state); - - _updateMute(); - } - - function __constructor() { - _setupMute(); - - Object.keys(audioConfig.MUSIC).forEach((objKey) => { - const MUSIC = audioConfig.MUSIC[objKey]; - music.set(MUSIC.KEY, scene.sound.add(MUSIC.KEY)); - }); - - Object.keys(audioConfig.SFX).forEach((objKey) => { - const SFX = audioConfig.SFX[objKey]; - soundEffects.set(SFX.KEY, scene.sound.add(SFX.KEY)); - }); - - state.setPauseOnBlur(true); - - return state; - } - - function setScene(newScene) { - // TODO move from old to new, if scene is already defined - scene = newScene; - return state; - } - - function setPauseOnBlur(pauseOnBlur) { - if (scene) { - scene.sound.pauseOnBlur = pauseOnBlur; // Keep audio playing even when losing focus. - } - return state; - } - - function playSfx(key) { - if (soundEffects.has(key)) { - console.log('playing', key); - soundEffects.get(key).play(); - } - } - - function pauseMusic() { - if (currentSong) { - currentSong.pause(); - } - state.isMusicPlaying = false; - } - - function playMusic(key = defaultSongKey) { - if (!state.isMusicPlaying && music.has(key)) { - currentSong = music.get(key); - currentSong.volume = currentVolume; - currentSong.play(); - state.isMusicPlaying = true; - } - } - - function stopMusic() { - if (currentSong) { - currentSong.stop(); - currentSong = null; - } - state.isMusicPlaying = false; - } - - function getCurrentVolume() { - return currentVolume; - } - - function getCurrentSong() { - return currentSong; - } - - function getAudioContext(key = defaultSongKey) { - return music.get(key).source.context; - } - - function getAudioSource(key = defaultSongKey) { - return music.get(key).source; - } - - function isAudioMuted() { - return localStorage.getItem(muteIdentifier) === 'true'; - } - - function toggleMute() { - const muteStatus = (!state.isAudioMuted()).toString(); - localStorage.setItem(muteIdentifier, muteStatus); - _updateMute(); - } - - function destroy() { - state.stopMusic(); - muteIcon.destroy(); - soundEffects.destroy(); - music.destroy(); - } - - const localState = { - // props - isMusicPlaying: false, - // methods - __constructor, - playSfx, - setScene, - setPauseOnBlur, - playMusic, - pauseMusic, - stopMusic, - getAudioContext, - getCurrentSong, - getAudioSource, - getCurrentVolume, - isAudioMuted, - toggleMute, - destroy, - }; - - return createState('AudioManager', state, { - localState, - }); -}; - -/** - * Audio manager instance, there should only be one. Implementation may change. - */ -export default createAudioManager; diff --git a/src/core/createAudioManager.ts b/src/core/createAudioManager.ts new file mode 100644 index 0000000..9016ce7 --- /dev/null +++ b/src/core/createAudioManager.ts @@ -0,0 +1,194 @@ +import { GAME, UI_DEFAULT } from 'configs/gameConfig'; +import { SPEAKER, SPEAKER_OFF } from 'configs/spriteConfig'; +import { MUSIC, SFX } from 'configs/audioConfig'; +import createState from 'utils/createState'; +import { ExtendedPhaserScene } from 'components/isScene'; + +export interface AudioManager { + isMusicPlaying: boolean; + + __constructor(): AudioManager, + playSfx(key: string): void, + setScene(newScene: ExtendedPhaserScene): AudioManager, + setPauseOnBlur(pauseOnBlur: boolean): AudioManager, + playMusic(key?: string): void, + pauseMusic(): void, + stopMusic(): void, + getAudioContext(key?: string): BaseAudioContext | undefined, + getCurrentSong: Phaser.Sound.NoAudioSound | Phaser.Sound.HTML5AudioSound | Phaser.Sound.WebAudioSound | undefined, + getAudioSource(key?: string): AudioBufferSourceNode | undefined, + getCurrentVolume(): number, + isAudioMuted(): boolean, + toggleMute(): void, + destroy(): void, +} + +function createAudioManager(parentScene: ExtendedPhaserScene): AudioManager { + if (!parentScene) throw new Error('A parent scene must be specified.'); + + const state = {} as AudioManager; + + let scene = parentScene; + let muteIcon: Phaser.GameObjects.Image; + let currentSong: Phaser.Sound.NoAudioSound | Phaser.Sound.HTML5AudioSound | Phaser.Sound.WebAudioSound | undefined; + + const muteIdentifier = `${GAME.TITLE.replace(/ /g, '_')}_isMuted`; // replace all spaces with _ for safety + const soundEffectsMap = new Map(); + const musicMap = new Map(); + const currentVolume = 0.7; + const defaultSongKey = MUSIC.BG_SCORE.KEY; + + function _updateMute() { + if (state.isAudioMuted()) { + muteIcon.setTexture(SPEAKER_OFF.KEY); + scene.sound.mute = true; + } else { + muteIcon.setTexture(SPEAKER.KEY); + scene.sound.mute = false; + } + } + + function _setupMute() { + muteIcon = scene.add.image(1850, 1040, SPEAKER.KEY); + muteIcon.setScrollFactor(0); + muteIcon.tint = UI_DEFAULT.tint; + muteIcon.depth = 3; + muteIcon.setInteractive(); + muteIcon.on('pointerup', state.toggleMute, state); + + _updateMute(); + } + + function __constructor(): AudioManager { + _setupMute(); + + Object.keys(MUSIC).forEach((objKey) => { + const music = MUSIC[objKey]; + musicMap.set(music.KEY, scene.sound.add(music.KEY)); + }); + + Object.keys(SFX).forEach((objKey) => { + const sfx = SFX[objKey]; + soundEffectsMap.set(sfx.KEY, scene.sound.add(sfx.KEY)); + }); + + state.setPauseOnBlur(true); + + return state; + } + + function setScene(newScene: ExtendedPhaserScene): AudioManager { + // TODO move from old to new, if scene is already defined + scene = newScene; + return state; + } + + function setPauseOnBlur(pauseOnBlur: boolean): AudioManager { + if (scene) { + scene.sound.pauseOnBlur = pauseOnBlur; // Keep audio playing even when losing focus. + } + return state; + } + + function playSfx(key: string) { + if (soundEffectsMap.has(key)) { + console.log('playing', key); + const sfx = soundEffectsMap.get(key) + if (sfx) sfx.play(); + } + } + + function pauseMusic() { + if (currentSong) { + currentSong.pause(); + } + state.isMusicPlaying = false; + } + + function playMusic(key: string = defaultSongKey) { + if (!state.isMusicPlaying && musicMap.has(key)) { + currentSong = musicMap.get(key); + if (currentSong) { + currentSong.volume = currentVolume; + currentSong.play(); + state.isMusicPlaying = true; + } + } + } + + function stopMusic() { + if (currentSong) { + currentSong.stop(); + currentSong = undefined; + } + state.isMusicPlaying = false; + } + + function getCurrentVolume() { + return currentVolume; + } + + function getCurrentSong() { + return currentSong; + } + + function getAudioContext(key: string = defaultSongKey): BaseAudioContext | undefined { + const music = musicMap.get(key) + if (music && music instanceof Phaser.Sound.WebAudioSound) { + return music.source.context; + } + } + + function getAudioSource(key: string = defaultSongKey): AudioBufferSourceNode | undefined { + const music = musicMap.get(key) + if (music && music instanceof Phaser.Sound.WebAudioSound) { + return music.source; + } + } + + function isAudioMuted() { + return localStorage.getItem(muteIdentifier) === 'true'; + } + + function toggleMute() { + const muteStatus = (!state.isAudioMuted()).toString(); + localStorage.setItem(muteIdentifier, muteStatus); + _updateMute(); + } + + function destroy() { + state.stopMusic(); + muteIcon.destroy(); + // soundEffects.destroy(); + // music.destroy(); + } + + const localState = { + // props + isMusicPlaying: false, + // methods + __constructor, + playSfx, + setScene, + setPauseOnBlur, + playMusic, + pauseMusic, + stopMusic, + getAudioContext, + getCurrentSong, + getAudioSource, + getCurrentVolume, + isAudioMuted, + toggleMute, + destroy, + }; + + return createState('AudioManager', state, { + localState, + }); +} + +/** + * Audio manager instance, there should only be one. Implementation may change. + */ +export default createAudioManager; diff --git a/src/core/createKeyboard.js b/src/core/createKeyboard.js deleted file mode 100644 index 9b9d6b9..0000000 --- a/src/core/createKeyboard.js +++ /dev/null @@ -1,41 +0,0 @@ -import canEmit from 'components/canEmit'; -import eventConfig from 'configs/eventConfig'; -import getFunctionUsage from 'utils/getFunctionUsage'; - -const createKeyboardInput = function createKeyboardInputFunc() { - const state = {}; - - function keyDownFn(e) { - state.emit(eventConfig.EVENTS.KEYBOARD.KEYDOWN, { key: e.key, repeat: e.repeat, keyCode: e.keyCode }); - } - - function keyUpFn(e) { - state.emit(eventConfig.EVENTS.KEYBOARD.KEYUP, { key: e.key, repeat: e.repeat, keyCode: e.keyCode }); - } - - function enable() { - document.addEventListener('keydown', keyDownFn); - document.addEventListener('keyup', keyUpFn); - } - - function disable() { - document.removeEventListener('keydown', keyDownFn); - document.removeEventListener('keyup', keyUpFn); - } - - const localState = { - // props - // methods - disable, - enable, - }; - - const canEmitState = canEmit(state); - const states = [{ state, name: 'state' }, { state: localState, name: 'localState' }, { state: canEmitState, name: 'canEmit' }]; - getFunctionUsage(states, 'Keyboard'); - return Object.assign(...states.map(s => s.state), { - // pipes and overrides - }); -}; - -export default createKeyboardInput; diff --git a/src/core/createKeyboard.ts b/src/core/createKeyboard.ts new file mode 100644 index 0000000..bdf8ca5 --- /dev/null +++ b/src/core/createKeyboard.ts @@ -0,0 +1,44 @@ +import canEmit, { EmitComponent } from 'components/events/canEmit'; +import { EVENTS } from 'configs/eventConfig'; +import createState from 'utils/createState'; + +export interface KeyboardInput extends EmitComponent { + disable: () => void; + enable: () => void; +} + +function createKeyboardInput(): KeyboardInput { + const state = {} as KeyboardInput; + + function keyDownFn(e: KeyboardEvent) { + state.emit(EVENTS.KEYBOARD.KEYDOWN, { key: e.key, repeat: e.repeat, keyCode: e.keyCode }); + } + + function keyUpFn(e: KeyboardEvent) { + state.emit(EVENTS.KEYBOARD.KEYUP, { key: e.key, repeat: e.repeat, keyCode: e.keyCode }); + } + + function enable() { + document.addEventListener(EVENTS.KEYBOARD.KEYDOWN, keyDownFn); + document.addEventListener(EVENTS.KEYBOARD.KEYUP, keyUpFn); + } + + function disable() { + document.removeEventListener(EVENTS.KEYBOARD.KEYDOWN, keyDownFn); + document.removeEventListener(EVENTS.KEYBOARD.KEYUP, keyUpFn); + } + + const localState = { + // props + // methods + disable, + enable, + }; + + return createState('KeyboardState', state, { + localState, + canEmit: canEmit(state), + }); +} + +export default createKeyboardInput; diff --git a/src/core/createListener.js b/src/core/createListener.js deleted file mode 100644 index 06e6378..0000000 --- a/src/core/createListener.js +++ /dev/null @@ -1,27 +0,0 @@ -import getUUID from 'utils/getUUID'; - -const createListener = function createListenerFunc(event, fn, once, emitState) { - const state = {}; - - function drop() { - if (state.dropped) return; - emitState.off(state); - state.dropped = true; - } - - return Object.assign(state, { - // props - id: getUUID(), - dropped: false, - once, - event, - fn: !once ? fn : (evt) => { - fn(evt); - state.drop(); - }, - // methods - drop, - }); -}; - -export default createListener; diff --git a/src/core/createListener.ts b/src/core/createListener.ts new file mode 100644 index 0000000..2f73242 --- /dev/null +++ b/src/core/createListener.ts @@ -0,0 +1,38 @@ +import { EmitComponent } from 'components/events/canEmit'; +import { EventData } from 'configs/eventConfig'; +import { v4 as uuidv4 } from 'uuid'; + +export interface Listener { + id: any; + dropped: boolean; + once: boolean; + event: string; + fn: (event: EventData[T]) => void; + drop: () => void; +} + +function createListener(event: T, fn: (event: EventData[T]) => void, once: boolean, emitState: EmitComponent): Listener { + const state = {} as Listener; + + function drop() { + if (state.dropped) return; + emitState.off(state); + state.dropped = true; + } + + return Object.assign(state, { + // props + id: uuidv4(), + dropped: false, + once, + event, + fn: !once ? fn : (evt: EventData[T]) => { + fn(evt); + state.drop(); + }, + // methods + drop, + }); +} + +export default createListener; diff --git a/src/core/createLoadingBar.js b/src/core/createLoadingBar.js deleted file mode 100644 index 60252d2..0000000 --- a/src/core/createLoadingBar.js +++ /dev/null @@ -1,112 +0,0 @@ -import hasPosition from 'components/hasPosition'; -import hasSize from 'components/hasSize'; -import pipe from 'utils/pipe'; - -/** - * A multipurpose loading bar that can be added to any scene. - */ -const createLoadingBar = function createLoadingBarFunc(originalScene) { - const state = {}; - const padding = 2; - const textPaddingFromBar = 10; - const parentScene = originalScene; - - let loaderBg; - let progressBar; - let text; - let currentProgress = 0; - - /** - * @private - */ - function updateProgressBar(progress) { - currentProgress = progress; - const pos = state.getPosition(); - progressBar.clear(); - progressBar.fillStyle(0xcccccc, 1); - progressBar.fillRect( - pos.x - state.getWidth() / 2, - pos.y - state.getHeight() / 2, - state.getWidth() * currentProgress, - state.getHeight(), - ); - } - - function onChange() { - const pos = state.getPosition(); - loaderBg.clear(); - loaderBg.fillStyle(0x444444, 1); - loaderBg.fillRect( - pos.x - state.getWidth() / 2 - padding, - pos.y - state.getHeight() / 2 - padding, - state.getWidth() + padding * 2, - state.getHeight() + padding * 2, - ); - - progressBar.clear(); - progressBar.fillStyle(0xcccccc, 1); - progressBar.fillRect( - pos.x - state.getWidth() / 2, - pos.y - state.getHeight() / 2, - state.getWidth() * currentProgress, - state.getHeight(), - ); - - text.x = pos.x; - text.y = pos.y - (text.height + textPaddingFromBar); - } - - /** - * @constructor - * @private - */ - function init() { - const pos = state.getPosition(); - loaderBg = parentScene.add.graphics(); - progressBar = parentScene.add.graphics(); - text = parentScene.add.text(pos.x, pos.y, 'Loading...', { - font: '16px Arial', - fill: '#eeeeee', - align: 'center', - }); - text.setOrigin(0.5, 1); - text.y -= text.height + textPaddingFromBar; - - parentScene.load.on('progress', updateProgressBar, state); - } - - function destroy() { - if (loaderBg) loaderBg.destroy(); - if (progressBar) progressBar.destroy(); - if (text) text.destroy(); - } - - const hasPositionState = hasPosition(state); - const hasSizeState = hasSize(state); - const localState = { - destroy, - }; - - const states = [ - { state, name: 'state' }, - { state: localState, name: 'localState' }, - { state: hasPositionState, name: 'hasPosition' }, - { state: hasSizeState, name: 'hasSize' }, - ]; - - const returnState = Object.assign(...states.map(s => s.state), { - // overrides and pipes. - setPosition: pipe( - hasPositionState.setPosition, - onChange, - ), - setSize: pipe( - hasSizeState.setSize, - onChange, - ), - }); - - init(); - return returnState; -}; -export default createLoadingBar; diff --git a/src/core/createLoadingBar.ts b/src/core/createLoadingBar.ts new file mode 100644 index 0000000..3da965f --- /dev/null +++ b/src/core/createLoadingBar.ts @@ -0,0 +1,123 @@ +import hasPosition, { Position, PositionComponent } from 'components/hasPosition'; +import hasSize, { Size, SizeComponent } from 'components/hasSize'; +import { ExtendedPhaserScene, LifeCycle } from 'components/isScene'; +import createState from 'utils/createState'; +import pipe from 'utils/pipe'; + +export interface LoadingBar extends PositionComponent, SizeComponent, LifeCycle { } + +/** + * A multipurpose loading bar that can be added to any scene. + */ +const createLoadingBar = function createLoadingBarFunc(originalScene: ExtendedPhaserScene): LoadingBar { + const state = {} as LoadingBar; + const padding = 2; + const textPaddingFromBar = 10; + const parentScene = originalScene; + + let loaderBg: Phaser.GameObjects.Graphics | undefined; + let progressBar: Phaser.GameObjects.Graphics | undefined; + let text: Phaser.GameObjects.Text | undefined; + let currentProgress = 0; + + /** + * @private + */ + function updateProgressBar(progress: number) { + currentProgress = progress; + const pos = state.getPosition(); + if (progressBar) { + progressBar.clear(); + progressBar.fillStyle(0xcccccc, 1); + progressBar.fillRect( + pos.x - state.getWidth() / 2, + pos.y - state.getHeight() / 2, + state.getWidth() * currentProgress, + state.getHeight(), + ); + } + } + + function onChange() { + const pos = state.getPosition(); + if (loaderBg) { + loaderBg.clear(); + loaderBg.fillStyle(0x444444, 1); + loaderBg.fillRect( + pos.x - state.getWidth() / 2 - padding, + pos.y - state.getHeight() / 2 - padding, + state.getWidth() + padding * 2, + state.getHeight() + padding * 2, + ); + } + + if (progressBar) { + progressBar.clear(); + progressBar.fillStyle(0xcccccc, 1); + progressBar.fillRect( + pos.x - state.getWidth() / 2, + pos.y - state.getHeight() / 2, + state.getWidth() * currentProgress, + state.getHeight(), + ); + } + + if (text) { + text.x = pos.x; + text.y = pos.y - (text.height + textPaddingFromBar); + } + } + + /** + * @constructor + * @private + */ + function init() { + const pos = state.getPosition(); + loaderBg = parentScene.add.graphics(); + progressBar = parentScene.add.graphics(); + text = parentScene.add.text(pos.x, pos.y, 'Loading...', { + font: '16px Arial', + backgroundColor: '#eeeeee', + align: 'center', + }); + text.setOrigin(0.5, 1); + text.y -= text.height + textPaddingFromBar; + + parentScene.load.on('progress', updateProgressBar, state); + } + + function destroy() { + if (loaderBg) loaderBg.destroy(); + if (progressBar) progressBar.destroy(); + if (text) text.destroy(); + } + + const localState = { + destroy, + setSize: (size: Size): Size => { + onChange(); + return size; + }, + setPosition: (pos: Position): Position => { + onChange(); + return pos; + } + }; + + const hasPositionState = hasPosition(state) + const hasSizeState = hasSize(state) + + const returnState = createState('LoadingBar', state, { + localState, + hasPosition: hasPositionState, + hasSize: hasSizeState, + }, { + setSize: pipe(hasSizeState.setSize, localState.setSize), + setPosition: pipe(hasPositionState.setPosition, localState.setPosition), + }); + + init(); + return returnState; +}; +export default createLoadingBar; diff --git a/src/core/createMessageBus.js b/src/core/createMessageBus.ts similarity index 55% rename from src/core/createMessageBus.js rename to src/core/createMessageBus.ts index d70572e..113e5f3 100644 --- a/src/core/createMessageBus.js +++ b/src/core/createMessageBus.ts @@ -1,8 +1,11 @@ -import canEmit from 'components/events/canEmit'; +import canEmit, { EmitComponent } from 'components/events/canEmit'; import createState from 'utils/createState'; -const createMessageBus = function createMessageBusFunc() { - const state = {}; +export interface MessageBus extends EmitComponent { +} + +function createMessageBus(): MessageBus { + const state = {} as MessageBus; const localState = { // props @@ -13,6 +16,6 @@ const createMessageBus = function createMessageBusFunc() { localState, canEmit: canEmit(state), }); -}; +} export default createMessageBus; diff --git a/src/entities/createButton.js b/src/entities/createButton.ts similarity index 53% rename from src/entities/createButton.js rename to src/entities/createButton.ts index 73bea99..e20b224 100644 --- a/src/entities/createButton.js +++ b/src/entities/createButton.ts @@ -1,30 +1,35 @@ -import canEmit from 'components/events/canEmit'; -import hasSize from 'components/hasSize'; -import hasPosition from 'components/hasPosition'; +import canEmit, { EmitComponent } from 'components/events/canEmit'; +import hasSize, { Size, SizeComponent } from 'components/hasSize'; +import hasPosition, { Position, PositionComponent } from 'components/hasPosition'; import pipe from 'utils/pipe'; -import eventConfig from 'configs/eventConfig'; import createState from 'utils/createState'; +import { EVENTS } from 'configs/eventConfig'; -const createButton = function createButtonFunc(parent) { - const state = {}; +export interface Button extends EmitComponent, PositionComponent, SizeComponent { + refresh: () => void; + setText: (val: string) => void; +} + +const createButton = function createButtonFunc(parent: Phaser.Scene): Button { + const state = {} as Button; const parentState = parent; - let background; - let zone; + let background: Phaser.GameObjects.Graphics | undefined; + let zone: Phaser.GameObjects.Zone | undefined; let text = 'My Button'; - let textElem; + let textElem: Phaser.GameObjects.Text | undefined; function init() { state.refresh(); } - function setText(val) { + function setText(val: string) { text = val; state.refresh(); } - function onClick(e) { - state.emit(eventConfig.EVENTS.BUTTON.CLICK, e); + function onClick(e: any) { + state.emit(EVENTS.BUTTON.CLICK, e); } function refresh() { @@ -40,13 +45,13 @@ const createButton = function createButtonFunc(parent) { background.strokeRect(state.getX(), state.getY(), state.getWidth(), state.getHeight()); background.fillRect(state.getX(), state.getY(), state.getWidth(), state.getHeight()); - zone.input.hitArea.setTo(state.getX(), state.getY(), state.getWidth(), state.getHeight()); - zone.setInteractive(); + zone?.input?.hitArea.setTo(state.getX(), state.getY(), state.getWidth(), state.getHeight()); + zone?.setInteractive(); if (!textElem) { textElem = parent.add.text(0, 0, '', { font: '64px Arial', - fill: '#eeeeee', + backgroundColor: '#eeeeee', align: 'center', }); } @@ -80,27 +85,34 @@ const createButton = function createButtonFunc(parent) { setText, refresh, destroy, + setPosition: (pos: Position): Position => { + state.refresh(); + return pos; + }, + setSize: (size: Size): Size => { + state.refresh(); + return size; + } }; - const states = { + + const hasPositionState = hasPosition(state) + const hasSizeState = hasSize(state) + return createState('Button', state, { localState, canEmit: canEmit(state), - hasPosition: hasPosition(state), - hasSize: hasSize(state), - }; - const overrides = { - // overrides - // manual pipe because the functions doesn't have the same name, and order of execution is important + hasPosition: hasPositionState, + hasSize: hasSizeState, + }, { setPosition: pipe( - states.hasPosition.setPosition, - localState.refresh, + hasPositionState.setPosition, + localState.setPosition ), setSize: pipe( - states.hasSize.setSize, - localState.refresh, + hasSizeState.setSize, + localState.setSize ), - }; - return createState('createButton', state, states, overrides); + }); }; export default createButton; diff --git a/src/entities/createPlayer.js b/src/entities/createPlayer.ts similarity index 58% rename from src/entities/createPlayer.js rename to src/entities/createPlayer.ts index 2efb070..709badd 100644 --- a/src/entities/createPlayer.js +++ b/src/entities/createPlayer.ts @@ -1,16 +1,21 @@ -import isGameEntity from 'components/entities/isGameEntity'; -import canEmit from 'components/events/canEmit'; -import hasPosition from 'components/hasPosition'; +import isGameEntity, { GameEntityState } from 'components/entities/isGameEntity'; +import canEmit, { EmitComponent } from 'components/events/canEmit'; +import hasPosition, { PositionComponent } from 'components/hasPosition'; import createState from 'utils/createState'; -import hasAudio from 'components/hasAudio'; -import audioConfig from 'configs/audioConfig'; +import hasAudio, { Audio } from 'components/hasAudio'; +import { SFX } from 'configs/audioConfig'; -const createPlayer = function createPlayerFunc() { +export interface Player extends PositionComponent, Audio, EmitComponent, GameEntityState { + name: string; + printInfo: () => void; +} + +const createPlayer = function createPlayerFunc(): Player { // variables and functions here are private unless listed below in localState. - const state = {}; + const state = {} as Player; function __constructor() { - state.playSfx(audioConfig.SFX.COIN.KEY); + state.playSfx(SFX.COIN.KEY); } function printInfo() { diff --git a/src/entities/createTriggerZone.js b/src/entities/createTriggerZone.js deleted file mode 100644 index 24e7588..0000000 --- a/src/entities/createTriggerZone.js +++ /dev/null @@ -1,92 +0,0 @@ -import Phaser from 'phaser'; -import hasPosition from 'components/hasPosition'; -import hasSize from 'components/hasSize'; -import isGameEntity from 'components/entities/isGameEntity'; -import createState from 'utils/createState'; - -const createTriggerZone = function createTriggerZoneFunc(originalScene) { - const state = {}; - - let parentScene = originalScene; - let triggerZone = new Phaser.GameObjects.Zone(parentScene, 0, 0, 0, 0); - const overlapsWith = []; - const overlappedEntities = []; - - function setScene(newScene) { - parentScene = newScene; - triggerZone.destroy(); - const { x, y } = state.getPosition(); - - triggerZone = new Phaser.GameObjects.Zone(parentScene, x, y, state.getWidth(), state.getHeight()); - } - - function setSize(size) { - triggerZone.setSize(size.w, size.h); - return size; - } - - function setPosition(pos) { - triggerZone.setPosition(pos.x, pos.y); - return pos; - } - - function setOverlaps(bodies) { - overlapsWith.length = 0; - overlapsWith.splice(0, 0, bodies); - } - - function addOverlapBody(body) { - overlapsWith.push(body); - } - - function isOverlappedByAny() { - return overlappedEntities.length > 0; - } - - /** - * It should be possible to optimize state to avoid a double loop (or is it?). - */ - function update() { - const previous = overlappedEntities; - overlappedEntities.length = 0; - parentScene.physics.overlap(triggerZone, overlapsWith, (zone, entity) => { - overlappedEntities.push(entity); - }); - - overlappedEntities.forEach((entity) => { - if (previous.indexOf(entity) === -1) { - state.onEntityEnteredRange(entity); - } - }); - - // If an entity was overlapped previously, but no longer, we emit an exit event. - previous.forEach((entity) => { - if (overlappedEntities.indexOf(entity) === -1) { - state.onEntityLeftRange(entity); - } - }); - } - - const localState = { - // props - // methods - setScene, - setSize, - setPosition, - setOverlaps, - addOverlapBody, - isOverlappedByAny, - update, - onEntityLeftRange: e => e, - onEntityEnteredRange: e => e, - }; - - return createState('createTriggerZone', state, { - localState, - isGameEntity: isGameEntity(state), - hasPosition: hasPosition(state), - hasSize: hasSize(state), - }); -}; - -export default createTriggerZone; diff --git a/src/fullscreen.js b/src/fullscreen.js deleted file mode 100644 index 425e1dc..0000000 --- a/src/fullscreen.js +++ /dev/null @@ -1,25 +0,0 @@ -document.getElementById('fullscreen_toggle').onclick = () => { - if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) { - if (document.exitFullscreen) { - document.exitFullscreen(); - } else if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else if (document.webkitExitFullscreen) { - document.webkitExitFullscreen(); - } else if (document.msExitFullscreen) { - document.msExitFullscreen(); - } - } else { - const element = document.getElementById('game'); - // const element = document.getElementsByTagName('canvas')[0]; - if (element.requestFullscreen) { - element.requestFullscreen(); - } else if (element.mozRequestFullScreen) { - element.mozRequestFullScreen(); - } else if (element.webkitRequestFullscreen) { - element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - } else if (element.msRequestFullscreen) { - element.msRequestFullscreen(); - } - } -}; diff --git a/src/fullscreen.ts b/src/fullscreen.ts new file mode 100644 index 0000000..d15f88e --- /dev/null +++ b/src/fullscreen.ts @@ -0,0 +1,30 @@ +const toggle = document?.getElementById('fullscreen_toggle') +if (toggle) { + toggle.onclick = () => { + if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } + } else { + const element = document.getElementById('game'); + if (element) { + // const element = document.getElementsByTagName('canvas')[0]; + if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else if (element.webkitRequestFullscreen) { + element.webkitRequestFullscreen(); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); + } + } + } + }; +} diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 504a842..0000000 --- a/src/index.js +++ /dev/null @@ -1,25 +0,0 @@ -import 'styles/main.scss'; -import Phaser from 'phaser'; -import gameConfig from 'configs/gameConfig'; - -import BootScene from 'scenes/Boot'; -import LoadScene from 'scenes/Load'; -import Game from 'scenes/Game'; -import resizeCanvas from 'utils/resizeCanvas'; -import store from './store'; -import createMessageBus from 'core/createMessageBus'; - -const phaserConfig = { - type: Phaser.WEBGL, - width: gameConfig.GAME.VIEWWIDTH, - height: gameConfig.GAME.VIEWHEIGHT, - backgroundColor: '#555555', - parent: 'game', - scene: [BootScene().scene, LoadScene().scene, Game().scene], -}; - -const game = new Phaser.Game(phaserConfig); -store.messageBus = createMessageBus(); -store.game = game; - -window.addEventListener('resize', resizeCanvas); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..f63b86e --- /dev/null +++ b/src/index.ts @@ -0,0 +1,54 @@ +import 'styles/main.scss'; +import Phaser from 'phaser'; +import { GAME } from 'configs/gameConfig'; + +import BootScene from 'scenes/Boot'; +import LoadScene from 'scenes/Load'; +import Game from 'scenes/Game'; +import resizeCanvas from 'utils/resizeCanvas'; +import store from './store'; +import createMessageBus from 'core/createMessageBus'; +import sayHello from 'utils/sayHello'; + +declare global { + interface Window { + } + interface Document { + msFullscreenElement?: Element; + webkitFullscreenElement?: Element; + mozFullScreenElement?: Element; + webkitExitFullscreen?: () => void; + mozCancelFullScreen?: () => void; + msExitFullscreen?: () => void; + mozRequestFullScreen?: () => void; + webkitRequestFullscreen?: () => void; + msRequestFullscreen?: () => void; + } + + interface Element { + mozRequestFullScreen?: () => void; + webkitRequestFullscreen?: () => void; + msRequestFullscreen?: () => void; + } + + export const GAME_BRANCH: string; + export const GAME_VERSION: string; + export const GAME_TIMESTAMP: string; + export const IS_DEV: boolean; +} + +sayHello(); +const phaserConfig = { + type: Phaser.WEBGL, + width: GAME.VIEWWIDTH, + height: GAME.VIEWHEIGHT, + backgroundColor: '#555555', + parent: 'game', + scene: [BootScene().scene, LoadScene().scene, Game().scene], +}; + +const game = new Phaser.Game(phaserConfig); +store.messageBus = createMessageBus(); +store.game = game; + +window.addEventListener('resize', resizeCanvas); diff --git a/src/scenes/Boot.js b/src/scenes/Boot.js deleted file mode 100644 index 6db624c..0000000 --- a/src/scenes/Boot.js +++ /dev/null @@ -1,29 +0,0 @@ -import gameConfig from 'configs/gameConfig'; -import resizeCanvas from 'utils/resizeCanvas'; -import isScene from 'components/isScene'; -import createState from 'utils/createState'; -import hasCamera from 'components/hasCamera'; - -const BootScene = function BootSceneFunc() { - const state = {}; - - // hook into phasers scene lifecycle. - function create() { - resizeCanvas(); - state.setSize(gameConfig.GAME.VIEWWIDTH, gameConfig.GAME.VIEWHEIGHT); - state.sceneManager.start(gameConfig.SCENES.LOAD); - } - - const localState = { - // methods - create, - }; - - return createState('Boot', state, { - localState, - isScene: isScene(state, gameConfig.SCENES.BOOT), - hasCamera: hasCamera(state), - }); -}; - -export default BootScene; diff --git a/src/scenes/Boot.ts b/src/scenes/Boot.ts new file mode 100644 index 0000000..67992c8 --- /dev/null +++ b/src/scenes/Boot.ts @@ -0,0 +1,31 @@ +import { GAME, SCENES } from 'configs/gameConfig'; +import resizeCanvas from 'utils/resizeCanvas'; +import isScene, { LifeCycle, SceneComponent } from 'components/isScene'; +import createState from 'utils/createState'; +import hasCamera, { Camera } from 'components/hasCamera'; + +export interface BootScene extends SceneComponent, Camera, LifeCycle { } + +const BootScene = function BootSceneFunc() { + const state: BootScene = {} as BootScene; + + // hook into phasers scene lifecycle. + function create() { + resizeCanvas(); + state.setSize(GAME.VIEWWIDTH, GAME.VIEWHEIGHT); + state?.sceneManager?.start(SCENES.LOAD); + } + + const localState = { + // methods + create, + }; + + return createState('Boot', state, { + localState, + isScene: isScene(state, SCENES.BOOT), + hasCamera: hasCamera(state), + }); +}; + +export default BootScene; diff --git a/src/scenes/Game.js b/src/scenes/Game.js deleted file mode 100644 index ff4c5c8..0000000 --- a/src/scenes/Game.js +++ /dev/null @@ -1,69 +0,0 @@ -import gameConfig from 'configs/gameConfig'; -import spriteConfig from 'configs/spriteConfig'; -import AudioManager from 'core/createAudioManager'; -import createPlayer from 'entities/createPlayer'; -import UI from 'scenes/UI'; -import canListen from 'components/events/canListen'; -import isScene from 'components/isScene'; -import createState from 'utils/createState'; -import store from 'root/store'; -import hasCamera from 'components/hasCamera'; - -/** - * Responsible for delegating the various levels, holding the various core systems and such. - */ -const Game = function GameFunc() { - const state = {}; - let audioManager; - let UIContainer; - let background; - - function cameraSetup() { - state.setViewport(0, 0, gameConfig.GAME.VIEWWIDTH, gameConfig.GAME.VIEWHEIGHT); - state.setZoom(0.8); - } - - - function init() { - // After assets are loaded. - UIContainer = UI(); - state.addScene(gameConfig.SCENES.UI, UIContainer.scene, true); - audioManager = AudioManager(UIContainer.scene); - store.audioManager = audioManager; - } - - function create() { - background = state.addImage(0, 0, spriteConfig.BACKGROUND.KEY); - background.setOrigin(0, 0); - audioManager.playMusic(); - cameraSetup(); - - const player = createPlayer(); - console.log(player); - } - - function update(time, delta) {} - - function destroy() { - if (background) state.removeChild(spriteConfig.BACKGROUND.KEY); - if (UIContainer) UIContainer.destroy(); - } - - const localState = { - // props - // methods - init, - create, - update, - destroy, - }; - - return createState('Game', state, { - localState, - canListen: canListen(state), - isScene: isScene(state, gameConfig.SCENES.GAME), - hasCamera: hasCamera(state), - }); -}; - -export default Game; diff --git a/src/scenes/Game.ts b/src/scenes/Game.ts new file mode 100644 index 0000000..c8f68c8 --- /dev/null +++ b/src/scenes/Game.ts @@ -0,0 +1,70 @@ +import { GAME, SCENES } from 'configs/gameConfig'; +import { BACKGROUND } from 'configs/spriteConfig'; +import createAudioManager, { AudioManager } from 'core/createAudioManager'; +import createPlayer from 'entities/createPlayer'; +import UI, { UIScene } from 'scenes/UI'; +import canListen, { ListenComponent } from 'components/events/canListen'; +import isScene, { SceneComponent } from 'components/isScene'; +import createState from 'utils/createState'; +import store from 'root/store'; +import hasCamera, { Camera } from 'components/hasCamera'; + +export interface GameScene extends SceneComponent, Camera, ListenComponent { } +/** + * Responsible for delegating the various levels, holding the various core systems and such. + */ +function Game(): GameScene { + const state = {} as GameScene; + let audioManager: AudioManager | undefined; + let UIContainer: UIScene | undefined; + let background: Phaser.GameObjects.Image | undefined; + + function cameraSetup() { + state.setViewport(0, 0, GAME.VIEWWIDTH, GAME.VIEWHEIGHT); + state.setZoom(0.8); + } + + + function init() { + // After assets are loaded. + UIContainer = UI(); + state.addScene(SCENES.UI, UIContainer.scene, true); + audioManager = createAudioManager(UIContainer.scene); + store.audioManager = audioManager; + } + + function create() { + background = state.addImage(0, 0, BACKGROUND.KEY); + background.setOrigin(0, 0); + audioManager?.playMusic(); + cameraSetup(); + + const player = createPlayer(); + console.log(player); + } + + function update() { } + + function destroy() { + if (background) state.removeChild(BACKGROUND.KEY); + if (UIContainer && UIContainer.destroy) UIContainer.destroy(); + } + + const localState = { + // props + // methods + init, + create, + update, + destroy, + }; + + return createState('Game', state, { + localState, + canListen: canListen(state), + isScene: isScene(state, SCENES.GAME), + hasCamera: hasCamera(state), + }); +} + +export default Game; diff --git a/src/scenes/Load.js b/src/scenes/Load.js deleted file mode 100644 index 217536b..0000000 --- a/src/scenes/Load.js +++ /dev/null @@ -1,75 +0,0 @@ -import gameConfig from 'configs/gameConfig'; -import createLoadingBar from 'core/createLoadingBar'; -import spriteConfig from 'configs/spriteConfig'; -import audioConfig from 'configs/audioConfig'; -import isScene from 'components/isScene'; -import createState from 'utils/createState'; - -const LoadScene = function LoadSceneFunc() { - const state = {}; - let loadingBar; - - function loadAudio() { - // load MUSIC - Object.keys(audioConfig.MUSIC).forEach((objKey) => { - const AUDIO = audioConfig.MUSIC[objKey]; - state.scene.load.audio(AUDIO.KEY, AUDIO.PATH); - }); - - // load SFX - Object.keys(audioConfig.SFX).forEach((objKey) => { - const SFX = audioConfig.SFX[objKey]; - state.scene.load.audio(SFX.KEY, SFX.PATH); - }); - } - - function loadSpritesheets() {} - - function loadMaps() {} - - function loadImages() { - Object.keys(spriteConfig).forEach((objKey) => { - const SPRITE = spriteConfig[objKey]; - state.scene.load.image(SPRITE.KEY, SPRITE.PATH); - }); - } - - function loadAssets() { - loadAudio(); - loadImages(); - loadSpritesheets(); - loadMaps(); - } - - // hook into phasers scene lifecycle. - function preload() { - loadingBar = createLoadingBar(state.scene); - loadingBar.setPosition({ x: gameConfig.GAME.VIEWWIDTH / 2, y: gameConfig.GAME.VIEWHEIGHT / 2 }); - loadingBar.setSize({ w: gameConfig.GAME.VIEWWIDTH * 0.4, h: gameConfig.GAME.VIEWHEIGHT * 0.025 }); - - state.scene.load.on('complete', () => { - state.sceneManager.start(gameConfig.SCENES.GAME); - state.scene.destroy(); - }); - - loadAssets(); - } - - function destroy() { - if (loadingBar) loadingBar.destroy(); - } - - const localState = { - // props - // methods - preload, - destroy, - }; - - return createState('LoadState', state, { - localState, - isScene: isScene(state, gameConfig.SCENES.LOAD), - }); -}; - -export default LoadScene; diff --git a/src/scenes/Load.ts b/src/scenes/Load.ts new file mode 100644 index 0000000..7030451 --- /dev/null +++ b/src/scenes/Load.ts @@ -0,0 +1,78 @@ +import { GAME, SCENES } from 'configs/gameConfig'; +import createLoadingBar, { LoadingBar } from 'core/createLoadingBar'; +import { MUSIC, SFX } from 'configs/audioConfig'; +import isScene, { SceneComponent } from 'components/isScene'; +import createState from 'utils/createState'; +import { BACKGROUND, SPEAKER, SPEAKER_OFF } from 'configs/spriteConfig'; + +export interface LoadSceneState extends SceneComponent { } + +function LoadScene(): LoadSceneState { + const state = {} as LoadSceneState; + let loadingBar: LoadingBar | undefined; + + function loadAudio() { + // load MUSIC + Object.keys(MUSIC).forEach((objKey) => { + const audio = MUSIC[objKey]; + state.scene.load.audio(audio.KEY, audio.PATH); + }); + + // load SFX + Object.keys(SFX).forEach((objKey) => { + const sfx = SFX[objKey]; + state.scene.load.audio(sfx.KEY, sfx.PATH); + }); + } + + function loadSpritesheets() { } + + function loadMaps() { } + + function loadImages() { + state.scene.load.image(BACKGROUND.KEY, BACKGROUND.PATH); + state.scene.load.image(SPEAKER.KEY, SPEAKER.PATH); + state.scene.load.image(SPEAKER_OFF.KEY, SPEAKER_OFF.PATH); + } + + function loadAssets() { + loadAudio(); + loadImages(); + loadSpritesheets(); + loadMaps(); + } + + // hook into phasers scene lifecycle. + function preload() { + loadingBar = createLoadingBar(state.scene); + loadingBar.setPosition({ x: GAME.VIEWWIDTH / 2, y: GAME.VIEWHEIGHT / 2 }); + loadingBar.setSize({ width: GAME.VIEWWIDTH * 0.4, height: GAME.VIEWHEIGHT * 0.025 }); + + state.scene.load.on('complete', () => { + state.sceneManager?.start(SCENES.GAME); + if (state.scene && state.scene.destroy) { + state.scene.destroy(); + } + }); + + loadAssets(); + } + + function destroy() { + if (loadingBar && loadingBar.destroy) loadingBar.destroy(); + } + + const localState = { + // props + // methods + preload, + destroy, + }; + + return createState('LoadState', state, { + localState, + isScene: isScene(state, SCENES.LOAD), + }); +} + +export default LoadScene; diff --git a/src/scenes/UI.js b/src/scenes/UI.ts similarity index 53% rename from src/scenes/UI.js rename to src/scenes/UI.ts index 3cfe330..94cbf9b 100644 --- a/src/scenes/UI.js +++ b/src/scenes/UI.ts @@ -1,34 +1,40 @@ -import Stats from 'stats-js'; +import Stats from 'stats.js'; import * as dat from 'dat.gui'; -import gameConfig from 'configs/gameConfig'; -import isScene from 'components/isScene'; +import { SCENES } from 'configs/gameConfig'; +import isScene, { SceneComponent } from 'components/isScene'; import createState from 'utils/createState'; /** * Layer/Scene for UI elements. */ -const UI = function UIFunc() { - const state = {}; - let gui; - let stats; +export interface UIScene extends SceneComponent { + guiData: { + name: string; + }; +} + +function UI(): UIScene { + const state = {} as UIScene; + let gui: dat.GUI | undefined; + let stats: Stats | undefined; function setupPerformanceStats() { stats = new Stats(); - stats.setMode(0); + stats.showPanel(0); - stats.domElement.style.position = 'absolute'; - stats.domElement.style.left = '0px'; - stats.domElement.style.top = '0px'; + stats.dom.style.position = 'absolute'; + stats.dom.style.left = '0px'; + stats.dom.style.top = '0px'; - document.body.appendChild(stats.domElement); + document.body.appendChild(stats.dom); // TODO cleanup listeners state.scene.events.on('preupdate', () => { - stats.begin(); + stats?.begin(); }); state.scene.events.on('postupdate', () => { - stats.end(); + stats?.end(); }); } @@ -51,12 +57,18 @@ const UI = function UIFunc() { } function destroy() { - gui.destroy(); - stats.end(); - document.body.removeChild(stats); + gui?.destroy(); + stats?.end(); + if (stats?.dom) { + document.body.removeChild(stats.dom); + } } const localState = { + // props + guiData: { + name: '' + }, // methods create, destroy, @@ -64,8 +76,8 @@ const UI = function UIFunc() { return createState('UIScene', state, { localState, - isScene: isScene(state, gameConfig.SCENES.UI), + isScene: isScene(state, SCENES.UI), }); -}; +} export default UI; diff --git a/src/store.js b/src/store.js deleted file mode 100644 index 2342459..0000000 --- a/src/store.js +++ /dev/null @@ -1,3 +0,0 @@ -const store = {}; - -export default store; diff --git a/src/store.ts b/src/store.ts new file mode 100644 index 0000000..a58ed75 --- /dev/null +++ b/src/store.ts @@ -0,0 +1,12 @@ +import { AudioManager } from "core/createAudioManager"; +import { MessageBus } from "core/createMessageBus"; + +export interface Store { + messageBus?: MessageBus; + game?: Phaser.Game; + audioManager?: AudioManager; +} + +const store: Store = {}; + +export default store; diff --git a/src/utils/createState.js b/src/utils/createState.ts similarity index 60% rename from src/utils/createState.js rename to src/utils/createState.ts index fe1f33b..960a59f 100644 --- a/src/utils/createState.js +++ b/src/utils/createState.ts @@ -1,9 +1,15 @@ import getFunctionUsage from './getFunctionUsage'; import pipe from './pipe'; -const createState = function createStateFunc(className = 'MyClass', mainState = {}, states = {}, overrides = {}) { - const stateList = []; - const pipes = {}; +export interface State { + state: any; + name: string; +} + +function createState(className = 'MyClass', mainState: T & { __constructor?: unknown}, states: { [key: string]: any } = {}, overrides = {}): T { + const stateList: Array = []; + const pipes: { [key: string]: Array<(a: unknown) => unknown> } = {}; + const finishedPipes: { [key: string]: (a: unknown) => unknown } = {}; // Loop over all states (components). Object.keys(states).forEach((stateKey) => { @@ -13,24 +19,22 @@ const createState = function createStateFunc(className = 'MyClass', mainState = name: stateKey, }); - // Loop over all properties on the state object. If functions, store them away for now. - Object.keys(state).forEach((propKey) => { + for(const propKey in state) { if (typeof state[propKey] === 'function') { if (!pipes[propKey]) { pipes[propKey] = []; } - pipes[propKey].push(state[propKey]); + pipes[propKey].push(state[propKey] as (a: unknown) => unknown); } - }); + } + // Loop over all properties on the state object. If functions, store them away for now. }); // Loop over all functions stored in pipes, check for multiple usages of the same name. // Automatically set up a pipe() structure for these. Object.keys(pipes).forEach((propKey) => { if (pipes[propKey].length > 1) { - pipes[propKey] = pipe(...pipes[propKey]); - } else { - delete pipes[propKey]; + finishedPipes[propKey] = pipe(...pipes[propKey]); } }); @@ -38,9 +42,9 @@ const createState = function createStateFunc(className = 'MyClass', mainState = // Creates a piped init/constructor that runs each __constructor() function in the different states. // This allows a created class/state to have a constructor that is ran at create time. - const init = pipe(...stateList.map(s => s.state.__constructor).filter(c => c)); + const init = pipe(...stateList.map(s => (s.state.__constructor as (a: unknown) => unknown)).filter(c => c)); - Object.assign(mainState, ...stateList.map(s => s.state), pipes, overrides); + Object.assign(mainState, ...stateList.map(s => s.state), finishedPipes, overrides); // Cleans up any constructor still on the mainstate. if (mainState.__constructor) { @@ -48,9 +52,9 @@ const createState = function createStateFunc(className = 'MyClass', mainState = } // actually calls the piped init constructor from above. - init(); + init(undefined); - return mainState; -}; + return mainState as T; +} export default createState; diff --git a/src/utils/getFunctionUsage.js b/src/utils/getFunctionUsage.ts similarity index 65% rename from src/utils/getFunctionUsage.js rename to src/utils/getFunctionUsage.ts index 1589326..1764a58 100644 --- a/src/utils/getFunctionUsage.js +++ b/src/utils/getFunctionUsage.ts @@ -1,25 +1,26 @@ -import devConfig from 'configs/devConfig'; +import { COMPOSITION_INFO } from 'configs/devConfig'; +import { State } from './createState'; -const alreadyLogged = []; +const alreadyLogged: Array = []; /* eslint-disable */ -const updateFunctionUsage = function updateFunctionUsageFunc(name, state, functionMap) { +const updateFunctionUsage = function updateFunctionUsageFunc(name: string, state: any, functionMap: Map>) { for (const fun in state) { if (functionMap.has(fun)) { - functionMap.get(fun).push({ name }); + functionMap.get(fun)?.push(name); } else { - functionMap.set(fun, [{ name }]); + functionMap.set(fun, [name]); } } }; -const isInFilter = function isInFilterFunc(COMPOSITION_INFO, val, source) { +const isInFilter = function isInFilterFunc(val: Array, source: string) { let isInFilter = true; if (COMPOSITION_INFO.ENABLE_FILTER) { isInFilter = false; if (COMPOSITION_INFO.FILTER) { COMPOSITION_INFO.FILTER.every(f => { - if (val.find(s => s.name === f)) { + if (val.find(s => s === f)) { isInFilter = true; return false; } @@ -37,25 +38,24 @@ const isInFilter = function isInFilterFunc(COMPOSITION_INFO, val, source) { return isInFilter && inFactoryFilter; }; -const getFunctionUsage = function getFunctionUsageFunc(states, source) { +const getFunctionUsage = function getFunctionUsageFunc(states: Array, source: string) { if (alreadyLogged.find(l => l === source)) { return; } alreadyLogged.push(source); - if (devConfig && devConfig.COMPOSITION_INFO && devConfig.COMPOSITION_INFO.ENABLE) { - const { COMPOSITION_INFO } = devConfig; + if (COMPOSITION_INFO && COMPOSITION_INFO.ENABLE) { // map all states - const functionMap = new Map(); + const functionMap = new Map>(); states.forEach(s => { updateFunctionUsage(s.name, s.state, functionMap); }); // print info - functionMap.forEach((val, key, map) => { - let inFilter = isInFilter(COMPOSITION_INFO, val, source); + functionMap.forEach((val, key) => { + let inFilter = isInFilter(val, source); if (inFilter && val.length > 1) { console.log( - `%c${source} %cneeds to pipe %c${key} %c=>${val.reduce((acc, curr) => `${acc} ${curr.name},`, '')}`, + `%c${source} %cneeds to pipe %c${key} %c=>${val.reduce((acc: string, name: string) => `${acc} ${name},`, '')}`, 'color: yellow', 'color: inherits', 'color: yellow', diff --git a/src/utils/getUUID.js b/src/utils/getUUID.js deleted file mode 100644 index f30cb75..0000000 --- a/src/utils/getUUID.js +++ /dev/null @@ -1,12 +0,0 @@ -/* eslint-disable no-bitwise */ - -/** - * Taken from: https://stackoverflow.com/a/2117523 - */ -const getUUID = function getUIdFunc() { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => - (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)); -}; -/* eslint-enable no-bitwise */ - -export default getUUID; diff --git a/src/utils/pipe.js b/src/utils/pipe.ts similarity index 52% rename from src/utils/pipe.js rename to src/utils/pipe.ts index 2d93968..0b13c27 100644 --- a/src/utils/pipe.js +++ b/src/utils/pipe.ts @@ -1,6 +1,6 @@ -const pipe = function pipeFunc(...fns) { - const emptyFunc = v => v; +function pipe(...fns: Array<(t: T) => T>): (t: T) => T { + const emptyFunc: (t: T) => T = v => v; return initialVal => fns.reduce((val, fn) => (fn ? fn(val) : emptyFunc(val)), initialVal); -}; +} export default pipe; diff --git a/src/utils/resizeCanvas.js b/src/utils/resizeCanvas.js deleted file mode 100644 index 3a84bbd..0000000 --- a/src/utils/resizeCanvas.js +++ /dev/null @@ -1,18 +0,0 @@ -import gameConfig from 'configs/gameConfig'; - -const resizeCanvas = function resizeCanvasFunc() { - const canvas = document.querySelector('#game>canvas'); - const windowWidth = window.innerWidth; - const windowHeight = window.innerHeight; - const windowRatio = windowWidth / windowHeight; - const gameRatio = gameConfig.GAME.VIEWWIDTH / gameConfig.GAME.VIEWHEIGHT; - if (windowRatio < gameRatio) { - canvas.style.width = `${windowWidth}px`; - canvas.style.height = `${windowWidth / gameRatio}px`; - } else { - canvas.style.width = `${windowHeight * gameRatio}px`; - canvas.style.height = `${windowHeight}px`; - } -}; - -export default resizeCanvas; diff --git a/src/utils/resizeCanvas.ts b/src/utils/resizeCanvas.ts new file mode 100644 index 0000000..1db340d --- /dev/null +++ b/src/utils/resizeCanvas.ts @@ -0,0 +1,20 @@ +import { GAME } from 'configs/gameConfig'; + +const resizeCanvas = function resizeCanvasFunc() { + const canvas = document.querySelector('#game>canvas') as HTMLCanvasElement; + const windowWidth = window.innerWidth; + const windowHeight = window.innerHeight; + const windowRatio = windowWidth / windowHeight; + const gameRatio = GAME.VIEWWIDTH / GAME.VIEWHEIGHT; + if (canvas && canvas.style) { + if (windowRatio < gameRatio) { + canvas.style.width = `${windowWidth}px`; + canvas.style.height = `${windowWidth / gameRatio}px`; + } else { + canvas.style.width = `${windowHeight * gameRatio}px`; + canvas.style.height = `${windowHeight}px`; + } + } +}; + +export default resizeCanvas; diff --git a/src/utils/sayHello.ts b/src/utils/sayHello.ts new file mode 100644 index 0000000..97073d2 --- /dev/null +++ b/src/utils/sayHello.ts @@ -0,0 +1,16 @@ +export default function sayHello() { + if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { + const args = [ + ` %c %c %c v${GAME_VERSION}; ${GAME_BRANCH} - ${GAME_TIMESTAMP} %c %c`, + 'background: #99ddff; padding:5px 0;', + 'background: #99ddff; padding:5px 0;', + 'color: #99ddff; background: #030307; padding:5px 0;', + 'background: #99ddff; padding:5px 0;', + 'background: #99ddff; padding:5px 0;', + ]; + + window.console.log.apply(console, args); + } else if (window.console) { + window.console.log(`${GAME_VERSION}; ${GAME_BRANCH}; ${GAME_TIMESTAMP}`); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7462087 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,67 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "target": "esnext", + "allowJs": true, + "declaration": true, + "useDefineForClassFields": true, + "outDir": "types", + "declarationMap": true, + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "jsx": "preserve", + "sourceMap": true, + "resolveJsonModule": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "noEmit": true, + "skipLibCheck": true, + "paths": { + "configs*": [ + "src/configs*" + ], + "core*": [ + "src/core*" + ], + "styles*": [ + "styles*" + ], + "assets*": [ + "assets*" + ], + "scenes*": [ + "src/scenes*" + ], + "entities*": [ + "src/entities*" + ], + "components*": [ + "src/components*" + ], + "utils*": [ + "src/utils*" + ], + "root*": [ + "src*" + ], + }, + "lib": [ + "esnext", + "dom" + ] + }, + "include": [ + "src/**/*", + // "test/vitest/**/*", + ], + "exclude": [ + "types/**/*", + "node_modules/**/*" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} \ No newline at end of file diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..57bf760 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "module": "esnext", + "moduleResolution": "node" + }, + "include": [ + "vite.config.ts" + ] +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..0465220 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,82 @@ + +import { defineConfig, UserConfigFn, UserConfig } from 'vite'; +import stripCode from 'rollup-plugin-strip-code'; +import { resolve } from 'path'; +import { execSync } from 'child_process'; +import dts from 'vite-plugin-dts'; +import { setDefaultResultOrder } from 'dns' +setDefaultResultOrder('verbatim') + +const getConfig: UserConfigFn = ({ mode }) => { + const baseConfig: UserConfig = { + build: { + lib: { + entry: resolve(__dirname, 'src/index.ts'), + name: 'phaser-boilerplate', + formats: ['es'], + fileName: (format) => `phaser-boilerplate.${format}.js`, + }, + outDir: 'lib', + }, + base: './', + plugins: [ + dts({ + tsconfigPath: "./tsconfig.json", + copyDtsFiles: true, + include: ["src/**/*"] + }), + ], + resolve: { + alias: { + configs: resolve(__dirname, "./src/configs"), + core: resolve(__dirname, "./src/core"), + styles: resolve(__dirname, "./styles"), + assets: resolve(__dirname, "./assets"), + scenes: resolve(__dirname, "./src/scenes"), + entities: resolve(__dirname, "./src/entities"), + components: resolve(__dirname, "./src/components"), + utils: resolve(__dirname, "./src/utils"), + root: resolve(__dirname, "./src"), + }, + }, + // test: { + // globals: true, + // environment: 'happy-dom', + // coverage: { + // reporter: ['text', 'json', 'html'] + // }, + // exclude: [ + // ...configDefaults.exclude, + // '/test/**/*', + // 'scripts/**/*', + // ], + // }, + define: { + 'IS_DEV': mode === 'development', + 'GAME_VERSION': JSON.stringify(process.env.npm_package_version), + 'GAME_BRANCH': JSON.stringify(execSync('git rev-parse --abbrev-ref HEAD').toString().trimEnd()), + 'GAME_TIMESTAMP': JSON.stringify(new Date().toLocaleString()), + }, + server: { + port: 3000, + proxy: { + }, + } + }; + + if (mode === 'production') { + return Object.assign(baseConfig, { + plugins: [...baseConfig.plugins, + stripCode({ + start_comment: 'develblock:start', + end_comment: 'develblock:end', + }), + ], + }); + } + + return baseConfig; +} + +// https://vitejs.dev/config/ +export default defineConfig(getConfig); \ No newline at end of file