diff --git a/krampoline/.eslintrc.cjs b/krampoline/.eslintrc.cjs index 739d6b2..d20bab1 100644 --- a/krampoline/.eslintrc.cjs +++ b/krampoline/.eslintrc.cjs @@ -6,6 +6,8 @@ module.exports = { }, // 권장 규칙 모음(패키지) extends: [ + // 'airbnb-base', + 'plugin:@typescript-eslint/recommended', 'eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime', @@ -28,5 +30,15 @@ module.exports = { 'react-hooks/rules-of-hooks': 'error', 'react-hooks/exhaustive-deps': 'warn', 'react/prop-types': ['off'], + '@typescript-eslint/explicit-module-boundary-types': 'error', // 모듈 경계에서 명시적 타입 요구 + '@typescript-eslint/no-explicit-any': 'error', // 명시적인 any 타입 사용 금지 + '@typescript-eslint/no-unused-vars': 'error', // 사용되지 않는 변수 금지 }, -}; + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + }, + }; +} diff --git a/krampoline/index.html b/krampoline/index.html index db09242..29092bf 100644 --- a/krampoline/index.html +++ b/krampoline/index.html @@ -9,6 +9,6 @@
- + diff --git a/krampoline/package-lock.json b/krampoline/package-lock.json index fea0983..07607b6 100644 --- a/krampoline/package-lock.json +++ b/krampoline/package-lock.json @@ -16,10 +16,14 @@ "vite-plugin-svgr": "^4.2.0" }, "devDependencies": { - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", + "@types/node": "^20.14.1", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.12.0", + "@typescript-eslint/parser": "^7.12.0", "@vitejs/plugin-react": "^4.2.1", "eslint": "^8.57.0", + "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-prettier": "^5.1.3", @@ -27,6 +31,7 @@ "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-refresh": "^0.4.6", "prettier": "3.2.5", + "typescript": "^5.4.5", "vite": "^5.2.0" } }, @@ -1380,6 +1385,15 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/node": { + "version": "20.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.1.tgz", + "integrity": "sha512-T2MzSGEu+ysB/FkWfqmhV3PLyQlowdptmmgD20C6QxsS8Fmv5SjpZ1ayXaEC0S21/h5UJ9iA6W/5vSNU5l00OA==", + "devOptional": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -1387,9 +1401,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.3.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", - "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -1410,6 +1424,227 @@ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", + "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/type-utils": "7.12.0", + "@typescript-eslint/utils": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", + "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", + "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", + "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/utils": "7.12.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", + "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", + "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", + "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", + "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.12.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -1533,6 +1768,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -1702,6 +1946,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browserslist": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", @@ -1841,6 +2097,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -2023,6 +2285,18 @@ "node": ">=0.4.0" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2334,6 +2608,25 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, "node_modules/eslint-config-prettier": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", @@ -2757,6 +3050,34 @@ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2790,6 +3111,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3022,6 +3355,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -3374,6 +3727,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -3702,6 +4064,28 @@ "yallist": "^3.0.2" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -4513,6 +4897,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -4728,6 +5121,30 @@ "node": ">=4" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -4854,6 +5271,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -4869,6 +5299,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true + }, "node_modules/update-browserslist-db": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", @@ -5882,6 +6318,15 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/node": { + "version": "20.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.1.tgz", + "integrity": "sha512-T2MzSGEu+ysB/FkWfqmhV3PLyQlowdptmmgD20C6QxsS8Fmv5SjpZ1ayXaEC0S21/h5UJ9iA6W/5vSNU5l00OA==", + "devOptional": true, + "requires": { + "undici-types": "~5.26.4" + } + }, "@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", @@ -5889,9 +6334,9 @@ "dev": true }, "@types/react": { - "version": "18.3.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", - "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "dev": true, "requires": { "@types/prop-types": "*", @@ -5912,6 +6357,128 @@ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==" }, + "@typescript-eslint/eslint-plugin": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", + "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/type-utils": "7.12.0", + "@typescript-eslint/utils": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/parser": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", + "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", + "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", + "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "7.12.0", + "@typescript-eslint/utils": "7.12.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/types": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", + "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", + "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, + "@typescript-eslint/utils": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", + "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", + "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.12.0", + "eslint-visitor-keys": "^3.4.3" + } + }, "@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", @@ -5999,6 +6566,12 @@ "is-string": "^1.0.7" } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -6132,6 +6705,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, "browserslist": { "version": "4.23.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", @@ -6213,6 +6795,12 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, "convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -6334,6 +6922,15 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -6653,6 +7250,18 @@ } } }, + "eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + } + }, "eslint-config-prettier": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", @@ -6893,6 +7502,30 @@ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -6923,6 +7556,15 @@ "flat-cache": "^3.0.4" } }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -7077,6 +7719,20 @@ "gopd": "^1.0.1" } }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -7311,6 +7967,12 @@ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -7549,6 +8211,22 @@ "yallist": "^3.0.2" } }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -8094,6 +8772,12 @@ "object-inspect": "^1.13.1" } }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", @@ -8244,6 +8928,22 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "requires": {} + }, "tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -8339,6 +9039,12 @@ "possible-typed-array-names": "^1.0.0" } }, + "typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "devOptional": true + }, "unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -8351,6 +9057,12 @@ "which-boxed-primitive": "^1.0.2" } }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true + }, "update-browserslist-db": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", diff --git a/krampoline/package.json b/krampoline/package.json index d0bf25c..6a9388c 100644 --- a/krampoline/package.json +++ b/krampoline/package.json @@ -19,10 +19,14 @@ "vite-plugin-svgr": "^4.2.0" }, "devDependencies": { - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", + "@types/node": "^20.14.1", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.12.0", + "@typescript-eslint/parser": "^7.12.0", "@vitejs/plugin-react": "^4.2.1", "eslint": "^8.57.0", + "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", "eslint-plugin-prettier": "^5.1.3", @@ -30,6 +34,7 @@ "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-refresh": "^0.4.6", "prettier": "3.2.5", + "typescript": "^5.4.5", "vite": "^5.2.0" } } diff --git a/krampoline/src/App.jsx b/krampoline/src/App.tsx similarity index 100% rename from krampoline/src/App.jsx rename to krampoline/src/App.tsx diff --git a/krampoline/src/Router.jsx b/krampoline/src/Router.tsx similarity index 59% rename from krampoline/src/Router.jsx rename to krampoline/src/Router.tsx index e2c865e..7dfc9d6 100644 --- a/krampoline/src/Router.jsx +++ b/krampoline/src/Router.tsx @@ -9,22 +9,34 @@ import SelectPage from './pages/SelectPage'; import OnboardingPage from './pages/WaitingPage'; const Router = () => { - const [homeComponent, setHomeComponent] = useState(); + const [isLoading, setIsLoading] = useState(true); + const [homeComponent, setHomeComponent] = useState( + + ); useEffect(() => { - setTimeout(() => { - setHomeComponent(); + const timer = setTimeout(() => { + setIsLoading(false); + + const userId = sessionStorage.getItem('userId'); + userId ? setHomeComponent() : setHomeComponent(); }, 1500); + + return () => clearTimeout(timer); }, []); return ( - + : homeComponent + } + /> } /> } /> } /> - } /> } /> diff --git a/krampoline/src/assets/index.js b/krampoline/src/assets/index.ts similarity index 81% rename from krampoline/src/assets/index.js rename to krampoline/src/assets/index.ts index 5c50631..afe7124 100644 --- a/krampoline/src/assets/index.js +++ b/krampoline/src/assets/index.ts @@ -23,6 +23,25 @@ import ImgTurtle from './img/img_turtle.svg?react'; // svg 더 추가하게 되면 ,(콤마)로 이어서 쓰기 export { - Bomb, ICPlatinum, IcArrowBack, IcCloseGray, IcCorrectBlue, IcCorrectGray, IcCup, IcFailBlue, IcFailGray, IcFish, IcHomeButton, IcLogo, IcLogoGray, IcMyInfo, IcQuizBack, Ichome, ImgBlueBadge, ImgHint, ImgTurtle, KaKaoAuth, SuccessIcon + Bomb, + ICPlatinum, + IcArrowBack, + IcCloseGray, + IcCorrectBlue, + IcCorrectGray, + IcCup, + IcFailBlue, + IcFailGray, + IcFish, + IcHomeButton, + IcLogo, + IcLogoGray, + IcMyInfo, + IcQuizBack, + Ichome, + ImgBlueBadge, + ImgHint, + ImgTurtle, + KaKaoAuth, + SuccessIcon, }; - diff --git a/krampoline/src/common/Header/Header.jsx b/krampoline/src/common/Header/Header.tsx similarity index 100% rename from krampoline/src/common/Header/Header.jsx rename to krampoline/src/common/Header/Header.tsx diff --git a/krampoline/src/common/Modal/HintModal.jsx b/krampoline/src/common/Modal/HintModal.tsx similarity index 65% rename from krampoline/src/common/Modal/HintModal.jsx rename to krampoline/src/common/Modal/HintModal.tsx index dc321bb..49475d8 100644 --- a/krampoline/src/common/Modal/HintModal.jsx +++ b/krampoline/src/common/Modal/HintModal.tsx @@ -1,7 +1,8 @@ +import { ModalProps } from '../../types/CommonType/commonType'; import HintModalForm from './HintModalForm'; import ModalPortal from './ModalPortal'; -const HintModal = ({ onClose }) => { +const HintModal = ({ onClose }: ModalProps) => { return ( diff --git a/krampoline/src/common/Modal/HintModalForm.jsx b/krampoline/src/common/Modal/HintModalForm.tsx similarity index 92% rename from krampoline/src/common/Modal/HintModalForm.jsx rename to krampoline/src/common/Modal/HintModalForm.tsx index 0f80d78..6619f33 100644 --- a/krampoline/src/common/Modal/HintModalForm.jsx +++ b/krampoline/src/common/Modal/HintModalForm.tsx @@ -3,11 +3,12 @@ import { IcCloseGray, ImgHint } from '../../assets'; // import { useEffect } from 'react'; import { useEffect, useState } from 'react'; import getHint from '../../libs/apis/getHint'; +import { ModalProps } from '../../types/CommonType/commonType'; const TITLE = '제주도 앞바다에 사는 생물들'; -const HintModalForm = ({ onClose }) => { - const [updataedContent, setUpdatedContent] = useState(''); +const HintModalForm = ({ onClose }: ModalProps) => { + const [updataedContent, setUpdatedContent] = useState(''); useEffect(() => { const hintBox = async () => { try { @@ -20,7 +21,6 @@ const HintModalForm = ({ onClose }) => { hintBox(); }, []); - return ( diff --git a/krampoline/src/common/Modal/ModalPortal.jsx b/krampoline/src/common/Modal/ModalPortal.jsx deleted file mode 100644 index e792b74..0000000 --- a/krampoline/src/common/Modal/ModalPortal.jsx +++ /dev/null @@ -1,8 +0,0 @@ -import ReactDOM from 'react-dom'; - -const ModalPortal = ({ children }) => { - const el = document.getElementById('modal'); - return ReactDOM.createPortal(children, el); -}; - -export default ModalPortal; diff --git a/krampoline/src/common/Modal/ModalPortal.tsx b/krampoline/src/common/Modal/ModalPortal.tsx new file mode 100644 index 0000000..b2f4671 --- /dev/null +++ b/krampoline/src/common/Modal/ModalPortal.tsx @@ -0,0 +1,8 @@ +import ReactDOM from 'react-dom'; +import { ChildrenProps } from '../../types/CommonType/commonType'; +const ModalPortal = ({ children }: ChildrenProps) => { + const el: HTMLElement | null = document.getElementById('modal'); + return ReactDOM.createPortal(children, el as Element | DocumentFragment); +}; + +export default ModalPortal; diff --git a/krampoline/src/common/OnButton/index.jsx b/krampoline/src/common/OnButton/index.tsx similarity index 74% rename from krampoline/src/common/OnButton/index.jsx rename to krampoline/src/common/OnButton/index.tsx index 7fde43b..c922be4 100644 --- a/krampoline/src/common/OnButton/index.jsx +++ b/krampoline/src/common/OnButton/index.tsx @@ -1,6 +1,7 @@ import styled, { css } from 'styled-components'; +import { OnButtonProps } from '../../types/CommonType/commonType'; -const OnButton = ({ children, isQuiz, disabled, handleFn }) => { +const OnButton = ({ children, isQuiz, disabled, handleFn }: OnButtonProps) => { return ( ; +const RetryButton = ({ children }: RetryButtonProps) => { + return ; }; const Button = styled.button` diff --git a/krampoline/src/component/Select/SelectHeader.jsx b/krampoline/src/component/Select/SelectHeader.tsx similarity index 100% rename from krampoline/src/component/Select/SelectHeader.jsx rename to krampoline/src/component/Select/SelectHeader.tsx diff --git a/krampoline/src/component/Select/SelectTag.jsx b/krampoline/src/component/Select/SelectTag.tsx similarity index 87% rename from krampoline/src/component/Select/SelectTag.jsx rename to krampoline/src/component/Select/SelectTag.tsx index 06d8ee0..df267df 100644 --- a/krampoline/src/component/Select/SelectTag.jsx +++ b/krampoline/src/component/Select/SelectTag.tsx @@ -1,8 +1,11 @@ -import React from 'react'; import styled from 'styled-components'; import { INTEREST_CATEGORY } from '../../constants/selectCategory'; +import { SelectTagProps } from '../../types/ComponentType/componentType'; -const SelectTag = ({ selectedCategory, handleClickCategory }) => { +const SelectTag = ({ + selectedCategory, + handleClickCategory, +}: SelectTagProps) => { return ( {INTEREST_CATEGORY.map((data, idx) => { @@ -49,7 +52,7 @@ const CategoryWrapper = styled.div` gap: 1.2rem; `; -const CategoryImg = styled.p` +const CategoryImg = styled.p<{ $isClicked: boolean }>` display: flex; justify-content: center; align-items: center; diff --git a/krampoline/src/constants/oAuth.js b/krampoline/src/constants/oAuth.ts similarity index 100% rename from krampoline/src/constants/oAuth.js rename to krampoline/src/constants/oAuth.ts diff --git a/krampoline/src/constants/selectCategory.js b/krampoline/src/constants/selectCategory.js deleted file mode 100644 index dcbe8b6..0000000 --- a/krampoline/src/constants/selectCategory.js +++ /dev/null @@ -1,12 +0,0 @@ -export const INTEREST_CATEGORY = [ - { img: '🗑️', desc: '플라스틱 오염' }, - { img: '🔥', desc: '수온 상승' }, - { img: '🚧', desc: '해안 개발' }, - { img: '🐠️', desc: '산호초 파괴' }, - { img: '🧪', desc: '화학 물질' }, - { img: '👾', desc: '침입 외래종' }, - { img: '🎣️', desc: '무분별한 어업' }, - { img: '🌊', desc: '비선택적 어획' }, - { img: '👨‍🔬', desc: '해양 산성화' }, - ]; - \ No newline at end of file diff --git a/krampoline/src/constants/selectCategory.ts b/krampoline/src/constants/selectCategory.ts new file mode 100644 index 0000000..247dbe3 --- /dev/null +++ b/krampoline/src/constants/selectCategory.ts @@ -0,0 +1,11 @@ +export const INTEREST_CATEGORY = [ + { img: '🗑️', desc: '플라스틱 오염' }, + { img: '🔥', desc: '수온 상승' }, + { img: '🚧', desc: '해안 개발' }, + { img: '🐠️', desc: '산호초 파괴' }, + { img: '🧪', desc: '화학 물질' }, + { img: '👾', desc: '침입 외래종' }, + { img: '🎣️', desc: '무분별한 어업' }, + { img: '🌊', desc: '비선택적 어획' }, + { img: '👨‍🔬', desc: '해양 산성화' }, +]; diff --git a/krampoline/src/libs/api.js b/krampoline/src/libs/api.ts similarity index 100% rename from krampoline/src/libs/api.js rename to krampoline/src/libs/api.ts diff --git a/krampoline/src/libs/apis/SelectPage/getKeywords.js b/krampoline/src/libs/apis/SelectPage/getKeywords.ts similarity index 88% rename from krampoline/src/libs/apis/SelectPage/getKeywords.js rename to krampoline/src/libs/apis/SelectPage/getKeywords.ts index 6e5253a..65dcef7 100644 --- a/krampoline/src/libs/apis/SelectPage/getKeywords.js +++ b/krampoline/src/libs/apis/SelectPage/getKeywords.ts @@ -1,6 +1,6 @@ import { api } from '../../api'; -const getKeywords = async (selectedCategory) => { +const getKeywords = async (selectedCategory: string[]) => { try { const { data } = await api.post('/api/v1/quiz', { keywords: [ diff --git a/krampoline/src/libs/apis/SelectPage/getQuizContents.js b/krampoline/src/libs/apis/SelectPage/getQuizContents.ts similarity index 78% rename from krampoline/src/libs/apis/SelectPage/getQuizContents.js rename to krampoline/src/libs/apis/SelectPage/getQuizContents.ts index fee6fe2..3b02d4b 100644 --- a/krampoline/src/libs/apis/SelectPage/getQuizContents.js +++ b/krampoline/src/libs/apis/SelectPage/getQuizContents.ts @@ -1,6 +1,6 @@ import { api } from '../../api'; -const getQuizContent = async (quizId) => { +const getQuizContent = async (quizId: number) => { const { data } = await api.get(`/api/v1/quiz/${quizId}`); const { content } = data.data; diff --git a/krampoline/src/libs/apis/getHint.js b/krampoline/src/libs/apis/getHint.ts similarity index 100% rename from krampoline/src/libs/apis/getHint.js rename to krampoline/src/libs/apis/getHint.ts diff --git a/krampoline/src/libs/apis/postAnswer.js b/krampoline/src/libs/apis/postAnswer.ts similarity index 90% rename from krampoline/src/libs/apis/postAnswer.js rename to krampoline/src/libs/apis/postAnswer.ts index 02e0f44..3a55461 100644 --- a/krampoline/src/libs/apis/postAnswer.js +++ b/krampoline/src/libs/apis/postAnswer.ts @@ -1,6 +1,6 @@ import { api } from '../api'; -export const postAnswer = async (corretIc) => { +export const postAnswer = async (corretIc: boolean) => { try { const quizId = sessionStorage.getItem('quizId'); const userId = !sessionStorage.getItem('userId') diff --git a/krampoline/src/libs/hooks/useKakaoLogin.jsx b/krampoline/src/libs/hooks/useKakaoLogin.tsx similarity index 100% rename from krampoline/src/libs/hooks/useKakaoLogin.jsx rename to krampoline/src/libs/hooks/useKakaoLogin.tsx diff --git a/krampoline/src/main.jsx b/krampoline/src/main.tsx similarity index 53% rename from krampoline/src/main.jsx rename to krampoline/src/main.tsx index 1970fe4..9e08198 100644 --- a/krampoline/src/main.jsx +++ b/krampoline/src/main.tsx @@ -2,4 +2,6 @@ import ReactDOM from 'react-dom/client'; import App from './App.jsx'; -ReactDOM.createRoot(document.getElementById('root')).render(); +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + +); diff --git a/krampoline/src/pages/Home.jsx b/krampoline/src/pages/Home.tsx similarity index 98% rename from krampoline/src/pages/Home.jsx rename to krampoline/src/pages/Home.tsx index 40fd092..a768744 100644 --- a/krampoline/src/pages/Home.jsx +++ b/krampoline/src/pages/Home.tsx @@ -29,7 +29,7 @@ const Home = () => { fetchPoint(); }, []); - const navigate = useNavigate('/'); + const navigate = useNavigate(); return ( diff --git a/krampoline/src/pages/Mypage.jsx b/krampoline/src/pages/Mypage.tsx similarity index 96% rename from krampoline/src/pages/Mypage.jsx rename to krampoline/src/pages/Mypage.tsx index 99f0a6a..2851066 100644 --- a/krampoline/src/pages/Mypage.jsx +++ b/krampoline/src/pages/Mypage.tsx @@ -5,7 +5,7 @@ import ProfileCard from '../component/Mypage/ProfileCard'; const Mypage = () => { const location = useLocation(); - const handleCopyClipBoard = async (text) => { + const handleCopyClipBoard = async (text: string) => { try { await navigator.clipboard.writeText(text); alert('클립보드에 링크가 복사되었어요.'); diff --git a/krampoline/src/pages/QuizPage.jsx b/krampoline/src/pages/QuizPage.tsx similarity index 92% rename from krampoline/src/pages/QuizPage.jsx rename to krampoline/src/pages/QuizPage.tsx index 8cd9fc2..84b6b89 100644 --- a/krampoline/src/pages/QuizPage.jsx +++ b/krampoline/src/pages/QuizPage.tsx @@ -15,6 +15,8 @@ const QuizPage = () => { const [modalOn, setModalOn] = useState(false); const mainContents = sessionStorage.getItem('contents'); + if (!mainContents) return; + const handleClickHint = async () => { setModalOn(true); }; @@ -43,8 +45,9 @@ const QuizPage = () => { // ? console.log(res); true 뜸 // ? navigate('/result'); 이렇게 해도 작동 잘 됌 , state : correct 왜 넣은지 모르겠음 // ? console.log(correct); 찍으면 undefiend 뜸 - const { correct } = await postAnswer(); - navigate('/result', { state: correct }); + const res = await postAnswer(correctIc); + console.log(res); + navigate('/result'); } catch (error) { throw new Error(String(error)); } @@ -74,7 +77,11 @@ const QuizPage = () => { /> - + 제출 diff --git a/krampoline/src/pages/ResultPage.jsx b/krampoline/src/pages/ResultPage.tsx similarity index 100% rename from krampoline/src/pages/ResultPage.jsx rename to krampoline/src/pages/ResultPage.tsx diff --git a/krampoline/src/pages/SelectPage.jsx b/krampoline/src/pages/SelectPage.tsx similarity index 90% rename from krampoline/src/pages/SelectPage.jsx rename to krampoline/src/pages/SelectPage.tsx index 930b384..51c57a9 100644 --- a/krampoline/src/pages/SelectPage.jsx +++ b/krampoline/src/pages/SelectPage.tsx @@ -9,9 +9,9 @@ import getQuizContent from '../libs/apis/SelectPage/getQuizContents'; const SelectPage = () => { const navigate = useNavigate(); - const [selectedCategory, setSelectedCategory] = useState([]); + const [selectedCategory, setSelectedCategory] = useState([]); - const handleClickCategory = (desc) => { + const handleClickCategory = (desc: string) => { if (selectedCategory.includes(desc)) { setSelectedCategory( selectedCategory.filter((category) => category !== desc) @@ -33,7 +33,7 @@ const SelectPage = () => { sessionStorage.setItem('quizId', quizId); } if (content) { - sessionStorage.setItem('contents', content); + sessionStorage.setItem('contents', content.content); navigate('/quiz'); } } catch (error) { diff --git a/krampoline/src/pages/WaitingPage.jsx b/krampoline/src/pages/WaitingPage.tsx similarity index 81% rename from krampoline/src/pages/WaitingPage.jsx rename to krampoline/src/pages/WaitingPage.tsx index 0f853dd..6efa9d0 100644 --- a/krampoline/src/pages/WaitingPage.jsx +++ b/krampoline/src/pages/WaitingPage.tsx @@ -1,12 +1,16 @@ import styled from 'styled-components'; import Contents from '../common/Waiting/Contents'; -const WaitingPage = ({ isLoading }) => { +interface WaitingProps { + isLoadingPage: boolean; +} + +const WaitingPage = ({ isLoadingPage }: WaitingProps) => { return ( void; +} + +export interface OnButtonProps { + children: React.ReactNode; + isQuiz: boolean; + disabled: boolean; + handleFn: () => void; +} + +export interface ModalProps { + onClose: () => void; +} + +export interface QuestionProps { + mainQuestion: string; + subQuestion: string; + isQuiz: boolean; +} + +export interface ContentsProps { + textArr: string[]; +} diff --git a/krampoline/src/types/ComponentType/componentType.ts b/krampoline/src/types/ComponentType/componentType.ts new file mode 100644 index 0000000..d989fd7 --- /dev/null +++ b/krampoline/src/types/ComponentType/componentType.ts @@ -0,0 +1,11 @@ +export interface SelectAnswerProps { + correctIc: boolean; + failIc: boolean; + handleClickCorrectBtn: () => void; + handleClickFailBtn: () => void; +} + +export interface SelectTagProps { + selectedCategory: string[]; + handleClickCategory: (desc: string) => void; +} diff --git a/krampoline/tsconfig.json b/krampoline/tsconfig.json new file mode 100644 index 0000000..3441128 --- /dev/null +++ b/krampoline/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + // svgr 플러그인 추가 + "types": ["vite-plugin-svgr/client", "node", "vite/client"], + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + // 프로그램에 포함할 파일 이름이나 패턴 배열 지정 + "include": ["src"], + // 프로젝트 참조 - 빌드 및 편집기 상호 작용 시간을 크게 개선, 구성 요소 간의 논리적 분리 강화, 새롭고 향상된 방식으로 코드 구성 가능 + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/krampoline/tsconfig.node.json b/krampoline/tsconfig.node.json new file mode 100644 index 0000000..22ee9cb --- /dev/null +++ b/krampoline/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "node", // 이 부분을 node로 변경합니다. + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/krampoline/vite.config.js b/krampoline/vite.config.ts similarity index 87% rename from krampoline/vite.config.js rename to krampoline/vite.config.ts index 93b45e6..31eadb6 100644 --- a/krampoline/vite.config.js +++ b/krampoline/vite.config.ts @@ -7,10 +7,9 @@ export default defineConfig({ plugins: [react(), svgr()], base: '', resolve: { - extensions: ['.js', '.jsx'], + extensions: ['.ts', '.tsx'], // 여기서 .ts와 .tsx 확장자에 .을 추가합니다. alias: [{ find: '@', replacement: resolve(__dirname, './src') }], }, - server: { host: 'localhost', port: 3000,