From 84878bb7e10281d5a4ea7328a61031d65988b783 Mon Sep 17 00:00:00 2001 From: JUNG TAEWON <153927840+hafskjfha@users.noreply.github.com> Date: Sat, 20 Dec 2025 21:57:12 +0900 Subject: [PATCH 01/12] Bump version from 0.1.0 to 1.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a85eb37..8d25d46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kkuko-utils", - "version": "0.1.0", + "version": "1.3.0", "private": true, "scripts": { "dev": "next dev --turbopack", From 4d119bb4754be9bf26dbfd52a4496f80af423e04 Mon Sep 17 00:00:00 2001 From: Vercel Date: Sat, 20 Dec 2025 13:26:52 +0000 Subject: [PATCH 02/12] Fix React Server Components CVE vulnerabilities Updated dependencies to fix Next.js and React CVE vulnerabilities. The fix-react2shell-next tool automatically updated the following packages to their secure versions: - next - react-server-dom-webpack - react-server-dom-parcel - react-server-dom-turbopack All package.json files have been scanned and vulnerable versions have been patched to the correct fixed versions based on the official React advisory. Co-authored-by: Vercel --- package-lock.json | 426 ++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 226 insertions(+), 202 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ed5fb7..55fd8cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "kkuko-utils", - "version": "0.1.0", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kkuko-utils", - "version": "0.1.0", + "version": "1.3.0", "dependencies": { "@codemirror/lang-javascript": "^6.2.3", "@codemirror/language": "^6.11.0", @@ -46,7 +46,7 @@ "es-toolkit": "^1.37.2", "framer-motion": "^12.5.0", "lucide-react": "^0.474.0", - "next": "^15.1.0", + "next": "15.1.11", "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -3088,22 +3088,14 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", - "optional": true, - "engines": { - "node": ">=18" - } - }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", - "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -3115,16 +3107,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.3" + "@img/sharp-libvips-darwin-arm64": "1.0.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", - "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "darwin" @@ -3136,16 +3129,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.3" + "@img/sharp-libvips-darwin-x64": "1.0.4" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", - "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -3155,12 +3149,13 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", - "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" @@ -3170,12 +3165,13 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", - "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", "cpu": [ "arm" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -3185,27 +3181,13 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", - "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", "cpu": [ "arm64" ], - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", - "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", - "cpu": [ - "ppc64" - ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -3215,12 +3197,13 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", - "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", "cpu": [ "s390x" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -3230,12 +3213,13 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", - "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -3245,12 +3229,13 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", - "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", "cpu": [ "arm64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -3260,12 +3245,13 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", - "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", "cpu": [ "x64" ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" @@ -3275,12 +3261,13 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", - "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", "cpu": [ "arm" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -3292,16 +3279,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.3" + "@img/sharp-libvips-linux-arm": "1.0.5" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", - "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -3313,37 +3301,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.3" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", - "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.3" + "@img/sharp-libvips-linux-arm64": "1.0.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", - "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", "cpu": [ "s390x" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -3355,16 +3323,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.3" + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", - "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -3376,16 +3345,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.3" + "@img/sharp-libvips-linux-x64": "1.0.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", - "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", "cpu": [ "arm64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -3397,16 +3367,17 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", - "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", "cpu": [ "x64" ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" @@ -3418,38 +3389,21 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", - "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", "cpu": [ "wasm32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.5.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "@emnapi/runtime": "^1.2.0" }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", - "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, @@ -3458,12 +3412,13 @@ } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", - "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", "cpu": [ "ia32" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -3476,12 +3431,13 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", - "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", "cpu": [ "x64" ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" @@ -4164,9 +4120,9 @@ } }, "node_modules/@next/env": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.9.tgz", - "integrity": "sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==", + "version": "15.1.11", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.11.tgz", + "integrity": "sha512-yp++FVldfLglEG5LoS2rXhGypPyoSOyY0kxZQJ2vnlYJeP8o318t5DrDu5Tqzr03qAhDWllAID/kOCsXNLcwKw==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -4180,9 +4136,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.7.tgz", - "integrity": "sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.9.tgz", + "integrity": "sha512-sQF6MfW4nk0PwMYYq8xNgqyxZJGIJV16QqNDgaZ5ze9YoVzm4/YNx17X0exZudayjL9PF0/5RGffDtzXapch0Q==", "cpu": [ "arm64" ], @@ -4196,9 +4152,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.7.tgz", - "integrity": "sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.9.tgz", + "integrity": "sha512-fp0c1rB6jZvdSDhprOur36xzQvqelAkNRXM/An92sKjjtaJxjlqJR8jiQLQImPsClIu8amQn+ZzFwl1lsEf62w==", "cpu": [ "x64" ], @@ -4212,9 +4168,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.7.tgz", - "integrity": "sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.9.tgz", + "integrity": "sha512-77rYykF6UtaXvxh9YyRIKoaYPI6/YX6cy8j1DL5/1XkjbfOwFDfTEhH7YGPqG/ePl+emBcbDYC2elgEqY2e+ag==", "cpu": [ "arm64" ], @@ -4228,9 +4184,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.7.tgz", - "integrity": "sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.9.tgz", + "integrity": "sha512-uZ1HazKcyWC7RA6j+S/8aYgvxmDqwnG+gE5S9MhY7BTMj7ahXKunpKuX8/BA2M7OvINLv7LTzoobQbw928p3WA==", "cpu": [ "arm64" ], @@ -4244,9 +4200,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.7.tgz", - "integrity": "sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.9.tgz", + "integrity": "sha512-gQIX1d3ct2RBlgbbWOrp+SHExmtmFm/HSW1Do5sSGMDyzbkYhS2sdq5LRDJWWsQu+/MqpgJHqJT6ORolKp/U1g==", "cpu": [ "x64" ], @@ -4260,9 +4216,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.7.tgz", - "integrity": "sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.9.tgz", + "integrity": "sha512-fJOwxAbCeq6Vo7pXZGDP6iA4+yIBGshp7ie2Evvge7S7lywyg7b/SGqcvWq/jYcmd0EbXdb7hBfdqSQwTtGTPg==", "cpu": [ "x64" ], @@ -4276,9 +4232,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.7.tgz", - "integrity": "sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.9.tgz", + "integrity": "sha512-crfbUkAd9PVg9nGfyjSzQbz82dPvc4pb1TeP0ZaAdGzTH6OfTU9kxidpFIogw0DYIEadI7hRSvuihy2NezkaNQ==", "cpu": [ "arm64" ], @@ -4292,9 +4248,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.5.7", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.7.tgz", - "integrity": "sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==", + "version": "15.1.9", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.9.tgz", + "integrity": "sha512-SBB0oA4E2a0axUrUwLqXlLkSn+bRx9OWU6LheqmRrO53QEAJP7JquKh3kF0jRzmlYOWFZtQwyIWJMEJMtvvDcQ==", "cpu": [ "x64" ], @@ -6471,6 +6427,12 @@ "@supabase/storage-js": "2.7.1" } }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", @@ -8334,6 +8296,17 @@ "dev": true, "license": "MIT" }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -8719,6 +8692,20 @@ "dev": true, "license": "MIT" }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8737,6 +8724,17 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -9377,6 +9375,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", "optional": true, "engines": { "node": ">=8" @@ -11343,6 +11342,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT", + "optional": true + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -14140,13 +14146,15 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.5.9", - "resolved": "https://registry.npmjs.org/next/-/next-15.5.9.tgz", - "integrity": "sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==", + "version": "15.1.11", + "resolved": "https://registry.npmjs.org/next/-/next-15.1.11.tgz", + "integrity": "sha512-UiVJaOGhKST58AadwbFUZThlNBmYhKqaCs8bVtm4plTxsgKq0mJ0zTsp7t7j/rzsbAEj9WcAMdZCztjByi4EoQ==", "license": "MIT", "dependencies": { - "@next/env": "15.5.9", + "@next/env": "15.1.11", + "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", + "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" @@ -14158,19 +14166,19 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.5.7", - "@next/swc-darwin-x64": "15.5.7", - "@next/swc-linux-arm64-gnu": "15.5.7", - "@next/swc-linux-arm64-musl": "15.5.7", - "@next/swc-linux-x64-gnu": "15.5.7", - "@next/swc-linux-x64-musl": "15.5.7", - "@next/swc-win32-arm64-msvc": "15.5.7", - "@next/swc-win32-x64-msvc": "15.5.7", - "sharp": "^0.34.3" + "@next/swc-darwin-arm64": "15.1.9", + "@next/swc-darwin-x64": "15.1.9", + "@next/swc-linux-arm64-gnu": "15.1.9", + "@next/swc-linux-arm64-musl": "15.1.9", + "@next/swc-linux-x64-gnu": "15.1.9", + "@next/swc-linux-x64-musl": "15.1.9", + "@next/swc-win32-arm64-msvc": "15.1.9", + "@next/swc-win32-x64-msvc": "15.1.9", + "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.51.1", + "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", @@ -15755,15 +15763,16 @@ } }, "node_modules/sharp": { - "version": "0.34.4", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz", - "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==", + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", "hasInstallScript": true, + "license": "Apache-2.0", "optional": true, "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.0", - "semver": "^7.7.2" + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -15772,28 +15781,25 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.4", - "@img/sharp-darwin-x64": "0.34.4", - "@img/sharp-libvips-darwin-arm64": "1.2.3", - "@img/sharp-libvips-darwin-x64": "1.2.3", - "@img/sharp-libvips-linux-arm": "1.2.3", - "@img/sharp-libvips-linux-arm64": "1.2.3", - "@img/sharp-libvips-linux-ppc64": "1.2.3", - "@img/sharp-libvips-linux-s390x": "1.2.3", - "@img/sharp-libvips-linux-x64": "1.2.3", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", - "@img/sharp-libvips-linuxmusl-x64": "1.2.3", - "@img/sharp-linux-arm": "0.34.4", - "@img/sharp-linux-arm64": "0.34.4", - "@img/sharp-linux-ppc64": "0.34.4", - "@img/sharp-linux-s390x": "0.34.4", - "@img/sharp-linux-x64": "0.34.4", - "@img/sharp-linuxmusl-arm64": "0.34.4", - "@img/sharp-linuxmusl-x64": "0.34.4", - "@img/sharp-wasm32": "0.34.4", - "@img/sharp-win32-arm64": "0.34.4", - "@img/sharp-win32-ia32": "0.34.4", - "@img/sharp-win32-x64": "0.34.4" + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" } }, "node_modules/shebang-command": { @@ -15921,6 +15927,16 @@ "url": "https://github.com/steveukx/git-js?sponsor=1" } }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -16016,6 +16032,14 @@ "node": ">=8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", diff --git a/package.json b/package.json index 76557d5..0721201 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "es-toolkit": "^1.37.2", "framer-motion": "^12.5.0", "lucide-react": "^0.474.0", - "next": "^15.1.0", + "next": "15.1.11", "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", From 8a274deea1018feb102b5e26fd1d267ef8e2497b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 20 Dec 2025 13:38:43 +0000 Subject: [PATCH 03/12] [skip ci] - (v1.4.0) --- CHANGELOG.md | 9 +++++++++ package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..aa6015f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# [v1.4.0](https://github.com/SolidLoop-studio/kkuko-utils/compare/v1.3.0...v1.4.0) - 2025-12-20 + +## fix +- ([b91fdd2](https://github.com/SolidLoop-studio/kkuko-utils/commit/b91fdd2)) - 릴리즈 nodejs 버전 업데이트 +- ([e603226](https://github.com/SolidLoop-studio/kkuko-utils/commit/e603226)) - 서비스 제공자 이름 변경, 코드 라이센스 변경 + +## feat +- ([768ef96](https://github.com/SolidLoop-studio/kkuko-utils/commit/768ef96)) - implement automated release workflow and update dependencies + diff --git a/package.json b/package.json index 0721201..f9a191a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kkuko-utils", - "version": "1.3.0", + "version": "1.4.0", "private": true, "scripts": { "dev": "next dev --turbopack", From 59f5d7f2719c31576a0b6eb0331a9934b3ad9ecf Mon Sep 17 00:00:00 2001 From: AS7AR Date: Thu, 25 Dec 2025 18:36:55 +0900 Subject: [PATCH 04/12] =?UTF-8?q?feat:=20Open=20API=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=EB=B0=8F=20api=20docs=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 +- .idea/.gitignore | 10 + .idea/copilot.data.migration.ask2agent.xml | 6 + .idea/discord.xml | 7 + .idea/inspectionProfiles/Project_Default.xml | 6 + .idea/kkuko-utils.iml | 8 + .idea/misc.xml | 14 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + app/api/words/README.md | 59 +++ app/api/words/search/route.ts | 97 ++++ app/auth/auth.tsx | 4 +- app/word/api/page.tsx | 249 ++++++++++ app/word/page.tsx | 26 +- app/word/search/hooks/useWordSearch.ts | 22 +- package-lock.json | 456 ++++++++++--------- package.json | 2 +- 17 files changed, 755 insertions(+), 231 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/copilot.data.migration.ask2agent.xml create mode 100644 .idea/discord.xml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/kkuko-utils.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 app/api/words/README.md create mode 100644 app/api/words/search/route.ts create mode 100644 app/word/api/page.tsx diff --git a/.gitignore b/.gitignore index 7553d92..938355a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /.pnp .pnp.* .yarn/* +/.next !.yarn/patches !.yarn/plugins !.yarn/releases @@ -42,4 +43,7 @@ next-env.d.ts # Test app/test/ -app/api/test \ No newline at end of file +app/api/test + +# Idea +/.idea \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..9879198 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# 디폴트 무시된 파일 +/shelf/ +/workspace.xml +# 쿼리 파일을 포함한 무시된 디폴트 폴더 +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# 에디터 기반 HTTP 클라이언트 요청 +/httpRequests/ diff --git a/.idea/copilot.data.migration.ask2agent.xml b/.idea/copilot.data.migration.ask2agent.xml new file mode 100644 index 0000000..1f2ea11 --- /dev/null +++ b/.idea/copilot.data.migration.ask2agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..30bab2a --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/kkuko-utils.iml b/.idea/kkuko-utils.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/kkuko-utils.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..2b59431 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..0614563 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/api/words/README.md b/app/api/words/README.md new file mode 100644 index 0000000..9c89860 --- /dev/null +++ b/app/api/words/README.md @@ -0,0 +1,59 @@ + +--- + +## 엔드포인트 +- **URL**: `/api/words/search` +- **Method**: `GET` +- **Description**: 모드별 필터링 및 정렬 옵션을 적용한 단어 리스트 반환 + +--- + +## 쿼리 파라미터 + +### 1. 필수 및 공통 옵션 +| 파라미터 | 타입 | 설명 | 기본값 | +| :--- | :--- | :--- | :--- | +| `mode` | `string` | 게임 모드 (`kor-start`, `kor-end`, `kung`, `hunmin`, `jaqi`) | `kor-start` | +| `q` | `string` | **검색어.** 모드에 따라 시작자, 끝자, 또는 초성으로 동작 | - | +| `limit` | `number` | 최대 검색 결과 수 | `100` | +| `sortBy` | `string` | 정렬 기준 (`abc`: 가나다순, `length`: 글자수순, `attack`: 한방단어) | `length` | + +### 2. 세부 필터링 (Advanced Options) +| 파라미터 | 타입 | 설명 | 기본값 | +| :--- | :--- | :--- | :--- | +| `manner` | `string` | 단어 필터 (`man`: 매너어, `jen`: 전어, `eti`: 에티켓) | `man` | +| `minLength` | `number` | 최소 글자 수 | `2` | +| `maxLength` | `number` | 최대 글자 수 | `100` | +| `duem` | `boolean` | 두음법칙 적용 여부 (`true`/`false`) | `true` | +| `mission` | `string` | 포함해야 할 특정 글자 (미션 파괴용) | `""` | +| `themeId` | `number` | `jaqi` 모드 사용 시 필수 테마 고유 ID | - | + +--- + +## 예제 + +### A. 일반적인 끝말잇기 (시작 단어 찾기) +`가`로 시작하는 매너어 50개 검색 (글자수 순 정렬) +```http request +GET /api/words/search?mode=kor-start&q=가&manner=man&limit=50&sortBy=length +``` +### B. 쿵쿵따 모드 +`나`로 시작하는 3글자 단어 검색 (자동으로 3글자로 설정) +```http request +GET /api/words/search?mode=hunmin&q=ㄱㄴ +``` +### C. 훈민정음 (초성 퀴즈) +`ㄱㄴ` 초성을 가진 단어 검색 +```http request +GET /api/words/search?mode=hunmin&q=ㄱㄴ +``` + +## Response Status Code + + * 200: OK + * 400: Bad Request + * 필수 파라미터(q) 누락 + * 훈민정음 모드에서 2글자가 아닌 쿼리 전송 + * 주제어 모드에서 themeId 누락 + * 500: Internal Server Error + * 서버 내부 또는 데이터베이스 오류. \ No newline at end of file diff --git a/app/api/words/search/route.ts b/app/api/words/search/route.ts new file mode 100644 index 0000000..46e71a8 --- /dev/null +++ b/app/api/words/search/route.ts @@ -0,0 +1,97 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { SCM } from '@/app/lib/supabaseClient'; +import { advancedQueryType } from '@/app/types/type'; +import { GameMode } from '@/app/word/search/types'; + +export async function GET(request: NextRequest) { + const { searchParams } = new URL(request.url); + + const mode = (searchParams.get('mode') || 'kor-start') as GameMode; + const q = searchParams.get('q') || ''; + const mission = searchParams.get('mission') || ''; + const minLength = parseInt(searchParams.get('minLength') || '2'); + const maxLength = parseInt(searchParams.get('maxLength') || '100'); + const sortBy = (searchParams.get('sortBy') || 'length') as 'abc' | 'length' | 'attack'; + const duem = searchParams.get('duem') !== 'false'; + const miniInfo = searchParams.get('miniInfo') === 'true'; + const manner = searchParams.get('manner') || 'man'; + const ingjung = searchParams.get('ingjung') !== 'false'; + const displayLimit = parseInt(searchParams.get('limit') || '100'); + const themeId = searchParams.get('themeId'); + + try { + let query: advancedQueryType; + + if (mode === 'kor-start' || mode === 'kor-end') { + const start = mode === 'kor-start' ? q : searchParams.get('start') || undefined; + const end = mode === 'kor-end' ? q : searchParams.get('end') || undefined; + + if (mode === 'kor-start' && !start) return createErrorResponse('시작 초성이 필요합니다.'); + if (mode === 'kor-end' && !end) return createErrorResponse('끝 초성이 필요합니다.'); + + query = { + mode, + start: start?.trim(), + end: end?.trim(), + mission, + ingjung, + man: manner === 'man', + jen: manner === 'jen', + eti: manner === 'eti', + duem, + miniInfo, + length_min: minLength, + length_max: maxLength, + sort_by: sortBy, + limit: isNaN(displayLimit) ? 100 : displayLimit + }; + } else if (mode === 'kung') { + if (!q) return createErrorResponse('단어가 필요합니다.'); + query = { + mode: 'kung', + start: q.trim().slice(0, 3), + mission, + ingjung, + man: manner === 'man', + jen: manner === 'jen', + eti: manner === 'eti', + duem, + miniInfo, + length_min: 3, + length_max: 3, + sort_by: sortBy, + limit: isNaN(displayLimit) ? 100 : displayLimit + }; + } else if (mode === 'hunmin') { + if (q.trim().length !== 2) return createErrorResponse('훈민정음 쿼리는 2글자여야 합니다.'); + query = { + mode: 'hunmin', + query: q.trim(), + mission, + limit: isNaN(displayLimit) ? 100 : displayLimit + }; + } else if (mode === 'jaqi') { + if (!themeId) return createErrorResponse('테마 ID가 필요합니다.'); + query = { + mode: 'jaqi', + query: q.trim(), + theme: Number(themeId), + limit: isNaN(displayLimit) ? 100 : displayLimit + }; + } else { + return createErrorResponse('유효하지 않은 모드입니다.'); + } + + const { data, error } = await SCM.get().wordsByAdvancedQuery(query); + + if (error) throw error; + + return NextResponse.json(data); + } catch (error) { + return NextResponse.json({ error: error }, { status: 500 }); + } +} + +function createErrorResponse(message: string) { + return NextResponse.json({ error: message }, { status: 400 }); +} \ No newline at end of file diff --git a/app/auth/auth.tsx b/app/auth/auth.tsx index 7565392..bf907c2 100644 --- a/app/auth/auth.tsx +++ b/app/auth/auth.tsx @@ -13,8 +13,8 @@ import { Input } from "@/app/components/ui/input"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/app/components/ui/card"; import { Alert, AlertDescription } from "@/app/components/ui/alert"; import ErrorModal from '../components/ErrModal'; -import type { ErrorMessage } from "../types/type"; -import { SCM } from "../lib/supabaseClient"; +import type { ErrorMessage } from "@/types/type"; +import { SCM } from "@/lib/supabaseClient"; const AuthPage = () => { const router = useRouter(); diff --git a/app/word/api/page.tsx b/app/word/api/page.tsx new file mode 100644 index 0000000..99466cd --- /dev/null +++ b/app/word/api/page.tsx @@ -0,0 +1,249 @@ +import { + AlertCircle, + Code, + List, + Search, + Settings, + Terminal, + Braces, + FileJson +} from "lucide-react"; + +export async function generateMetadata() { + return { + title: "끄코 유틸리티 - 오픈DB API", + description: `끄코 유틸리티 - 오픈DB API`, + openGraph: { + title: "끄코 유틸리티 - 오픈DB API", + description: "끄코 유틸리티 - 오픈DB API", + type: "website", + url: "https://kkuko-utils.vercel.app/word/api", + siteName: "끄코 유틸리티", + locale: "ko_KR", + }, + }; +} + +export default function OpenAPIDocsPage() { + return ( +
+
+
+
+ +

+ Open API +

+
+

+ 오픈 DB의 단어 검색 기능을 API에서 만나보세요. +

+
+ +
+
+
+ +
+

기본 정보

+
+
+ GET + + /api/words/search + +
+

+ 모드별 필터링 및 정렬 옵션을 적용하여 오픈DB의 단어 리스트를 반환합니다. +

+
+ +
+
+
+
+ +
+

쿼리 파라미터

+
+ +

+ 1. 필수 및 공통 옵션 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
파라미터타입설명기본값
modestring게임 모드 (kor-start, kor-end, kung, hunmin, jaqi)kor-start
qstring검색어. 모드에 따라 시작자, 끝자, 또는 초성-
limitnumber최대 검색 결과 수100
sortBystring정렬 기준 (abc, length, attack)length
+
+ +

+ 2. 세부 필터링 (Advanced) +

+
+ + + + + + + + + + + {[ + { p: "manner", t: "string", d: "단어 필터 (man, jen, eti)", v: "man" }, + { p: "minLength", t: "number", d: "최소 글자 수", v: "2" }, + { p: "maxLength", t: "number", d: "최대 글자 수", v: "100" }, + { p: "duem", t: "boolean", d: "두음법칙 적용 여부", v: "true" }, + { p: "mission", t: "string", d: "포함해야 할 특정 글자", v: '""' }, + { p: "themeId", t: "number", d: "jaqi 모드 사용 시 필수 테마 ID", v: "-" }, + ].map((row, i) => ( + + + + + + + ))} + +
파라미터타입설명기본값
{row.p}{row.t}{row.d}{row.v}
+
+
+
+ +
+
+
+
+ +
+

Response Body

+
+ +
+
+

Success (Array)

+
    +
  • + word: string + 검색된 단어의 명칭 +
  • +
  • + nextWordCount: number + 해당 단어 이후에 이어질 수 있는 단어의 개수 +
  • +
+
+
+
+ +
+
+ +

Example

+
+
+{`[
+  {
+    "word": "사과",
+    "nextWordCount": 15
+  },
+  {
+    "word": "해질녘",
+    "nextWordCount": 0
+  }
+]`}
+                        
+
+
+ +
+
+ +

API 사용 예제

+
+ +
+
+

A. 일반적인 끝말잇기 (시작 단어 찾기)

+
+ GET /api/words/search?mode=kor-start&q=가&manner=man&limit=50&sortBy=length +
+
+ +
+

B. 쿵쿵따 모드

+
+ GET /api/words/search?mode=kung&q=나 +
+
+ +
+

C. 훈민정음 (초성 퀴즈)

+
+ GET /api/words/search?mode=hunmin&q=ㄱㄴ +
+
+
+
+ +
+
+ +

Response Status Code

+
+
    +
  • + 200: + OK +
  • +
  • + 400: +
    + Bad Request +

    필수 파라미터 누락 또는 유효하지 않은 요청

    +
    +
  • +
  • + 500: + Internal Server Error +
  • +
+
+
+
+ ); +} \ No newline at end of file diff --git a/app/word/page.tsx b/app/word/page.tsx index 41ad728..b2179d4 100644 --- a/app/word/page.tsx +++ b/app/word/page.tsx @@ -1,14 +1,14 @@ import Link from "next/link"; -import { - Search, - Download, - Plus, - Upload, - FileText, - Clock, - ChevronRight, +import { + Search, + Download, + Plus, + Upload, + FileText, + Clock, + ChevronRight, Database, - BarChart3 + BarChart3, AlignStartVertical } from "lucide-react"; export async function generateMetadata() { @@ -83,6 +83,14 @@ const features = [ color: "from-indigo-500 to-blue-500", bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" }, + { + title: "Open API", + description: "오픈 DB의 단어 검색 기능을 API에서 만나보세요.", + link: "/word/api", + icon: AlignStartVertical, + color: "from-indigo-400 to-yellow-600", + bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" + } ]; export default function OpenDBHomePage() { diff --git a/app/word/search/hooks/useWordSearch.ts b/app/word/search/hooks/useWordSearch.ts index ca7b3d1..bc8aca0 100644 --- a/app/word/search/hooks/useWordSearch.ts +++ b/app/word/search/hooks/useWordSearch.ts @@ -32,7 +32,7 @@ export const useWordSearch = () => { useEffect(() => { const modeParam = searchParams.get('mode'); const qParam = searchParams.get('q'); - + if (modeParam || qParam) { // mode 파라미터 처리 let targetMode: GameMode = 'kor-start'; @@ -43,26 +43,26 @@ export const useWordSearch = () => { } else if (modeParam === 'k') { targetMode = 'kung'; } - + setMode(targetMode); setSearchType('advanced'); - + // q 파라미터 처리 if (qParam) { setManner(''); // manner을 빈 문자열로 설정 - + if (targetMode === 'kor-start' || targetMode === 'kung') { setStartLetter(qParam); } else if (targetMode === 'kor-end') { setEndLetter(qParam); } - + // 쿵쿵따 모드인 경우 길이 설정 if (targetMode === 'kung') { setMinLength(3); setMaxLength(3); } - + // 자동 검색 트리거 setAutoSearchTriggered(true); } @@ -84,10 +84,10 @@ export const useWordSearch = () => { setLoading(true); setSearchPerformed(true); setResults([]); - + try { let query: advancedQueryType; - + if (mode === 'kor-start' || mode === 'kor-end') { if (mode === 'kor-start' && startLetter.trim() === '') return; if (mode === 'kor-end' && endLetter.trim() === '') return; @@ -160,10 +160,10 @@ export const useWordSearch = () => { setLoading(true); setSearchPerformed(true); setResults([]); - + try { if (simpleQuery.trim() === '') return; - + const { data, error } = await SCM.get().wordsByQuery(simpleQuery.trim()); if (error) { console.error('검색 오류:', error); @@ -199,4 +199,4 @@ export const useWordSearch = () => { handleSearch, handleSimpleSearch }; -}; +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 55fd8cf..116be5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "kkuko-utils", - "version": "1.3.0", + "version": "1.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kkuko-utils", - "version": "1.3.0", + "version": "1.4.0", "dependencies": { "@codemirror/lang-javascript": "^6.2.3", "@codemirror/language": "^6.11.0", @@ -46,7 +46,7 @@ "es-toolkit": "^1.37.2", "framer-motion": "^12.5.0", "lucide-react": "^0.474.0", - "next": "15.1.11", + "next": "^15.5.9", "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -2822,9 +2822,10 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", - "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -3088,10 +3089,20 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", "cpu": [ "arm64" ], @@ -3107,13 +3118,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", "cpu": [ "x64" ], @@ -3129,13 +3140,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", "cpu": [ "arm64" ], @@ -3149,9 +3160,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", "cpu": [ "x64" ], @@ -3165,9 +3176,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", "cpu": [ "arm" ], @@ -3181,9 +3192,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", "cpu": [ "arm64" ], @@ -3196,10 +3207,42 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", "cpu": [ "s390x" ], @@ -3213,9 +3256,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", "cpu": [ "x64" ], @@ -3229,9 +3272,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", "cpu": [ "arm64" ], @@ -3245,9 +3288,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", "cpu": [ "x64" ], @@ -3261,9 +3304,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", "cpu": [ "arm" ], @@ -3279,13 +3322,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" + "@img/sharp-libvips-linux-arm": "1.2.4" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", "cpu": [ "arm64" ], @@ -3301,13 +3344,57 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", "cpu": [ "s390x" ], @@ -3323,13 +3410,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", "cpu": [ "x64" ], @@ -3345,13 +3432,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" + "@img/sharp-libvips-linux-x64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ "arm64" ], @@ -3367,13 +3454,13 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ "x64" ], @@ -3389,20 +3476,20 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ "wasm32" ], "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.2.0" + "@emnapi/runtime": "^1.7.0" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -3411,10 +3498,29 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ "ia32" ], @@ -3431,9 +3537,9 @@ } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", "cpu": [ "x64" ], @@ -4120,9 +4226,9 @@ } }, "node_modules/@next/env": { - "version": "15.1.11", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.11.tgz", - "integrity": "sha512-yp++FVldfLglEG5LoS2rXhGypPyoSOyY0kxZQJ2vnlYJeP8o318t5DrDu5Tqzr03qAhDWllAID/kOCsXNLcwKw==", + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.9.tgz", + "integrity": "sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -4136,9 +4242,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.9.tgz", - "integrity": "sha512-sQF6MfW4nk0PwMYYq8xNgqyxZJGIJV16QqNDgaZ5ze9YoVzm4/YNx17X0exZudayjL9PF0/5RGffDtzXapch0Q==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.7.tgz", + "integrity": "sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==", "cpu": [ "arm64" ], @@ -4152,9 +4258,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.9.tgz", - "integrity": "sha512-fp0c1rB6jZvdSDhprOur36xzQvqelAkNRXM/An92sKjjtaJxjlqJR8jiQLQImPsClIu8amQn+ZzFwl1lsEf62w==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.7.tgz", + "integrity": "sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==", "cpu": [ "x64" ], @@ -4168,9 +4274,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.9.tgz", - "integrity": "sha512-77rYykF6UtaXvxh9YyRIKoaYPI6/YX6cy8j1DL5/1XkjbfOwFDfTEhH7YGPqG/ePl+emBcbDYC2elgEqY2e+ag==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.7.tgz", + "integrity": "sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==", "cpu": [ "arm64" ], @@ -4184,9 +4290,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.9.tgz", - "integrity": "sha512-uZ1HazKcyWC7RA6j+S/8aYgvxmDqwnG+gE5S9MhY7BTMj7ahXKunpKuX8/BA2M7OvINLv7LTzoobQbw928p3WA==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.7.tgz", + "integrity": "sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==", "cpu": [ "arm64" ], @@ -4200,9 +4306,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.9.tgz", - "integrity": "sha512-gQIX1d3ct2RBlgbbWOrp+SHExmtmFm/HSW1Do5sSGMDyzbkYhS2sdq5LRDJWWsQu+/MqpgJHqJT6ORolKp/U1g==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.7.tgz", + "integrity": "sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==", "cpu": [ "x64" ], @@ -4216,9 +4322,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.9.tgz", - "integrity": "sha512-fJOwxAbCeq6Vo7pXZGDP6iA4+yIBGshp7ie2Evvge7S7lywyg7b/SGqcvWq/jYcmd0EbXdb7hBfdqSQwTtGTPg==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.7.tgz", + "integrity": "sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==", "cpu": [ "x64" ], @@ -4232,9 +4338,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.9.tgz", - "integrity": "sha512-crfbUkAd9PVg9nGfyjSzQbz82dPvc4pb1TeP0ZaAdGzTH6OfTU9kxidpFIogw0DYIEadI7hRSvuihy2NezkaNQ==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.7.tgz", + "integrity": "sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==", "cpu": [ "arm64" ], @@ -4248,9 +4354,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.1.9", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.9.tgz", - "integrity": "sha512-SBB0oA4E2a0axUrUwLqXlLkSn+bRx9OWU6LheqmRrO53QEAJP7JquKh3kF0jRzmlYOWFZtQwyIWJMEJMtvvDcQ==", + "version": "15.5.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.7.tgz", + "integrity": "sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==", "cpu": [ "x64" ], @@ -6427,12 +6533,6 @@ "@supabase/storage-js": "2.7.1" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "license": "Apache-2.0" - }, "node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", @@ -8296,17 +8396,6 @@ "dev": true, "license": "MIT" }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -8692,20 +8781,6 @@ "dev": true, "license": "MIT" }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8724,17 +8799,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "optional": true, - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -11342,13 +11406,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "license": "MIT", - "optional": true - }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -14146,15 +14203,13 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.1.11", - "resolved": "https://registry.npmjs.org/next/-/next-15.1.11.tgz", - "integrity": "sha512-UiVJaOGhKST58AadwbFUZThlNBmYhKqaCs8bVtm4plTxsgKq0mJ0zTsp7t7j/rzsbAEj9WcAMdZCztjByi4EoQ==", + "version": "15.5.9", + "resolved": "https://registry.npmjs.org/next/-/next-15.5.9.tgz", + "integrity": "sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==", "license": "MIT", "dependencies": { - "@next/env": "15.1.11", - "@swc/counter": "0.1.3", + "@next/env": "15.5.9", "@swc/helpers": "0.5.15", - "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" @@ -14166,19 +14221,19 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.1.9", - "@next/swc-darwin-x64": "15.1.9", - "@next/swc-linux-arm64-gnu": "15.1.9", - "@next/swc-linux-arm64-musl": "15.1.9", - "@next/swc-linux-x64-gnu": "15.1.9", - "@next/swc-linux-x64-musl": "15.1.9", - "@next/swc-win32-arm64-msvc": "15.1.9", - "@next/swc-win32-x64-msvc": "15.1.9", - "sharp": "^0.33.5" + "@next/swc-darwin-arm64": "15.5.7", + "@next/swc-darwin-x64": "15.5.7", + "@next/swc-linux-arm64-gnu": "15.5.7", + "@next/swc-linux-arm64-musl": "15.5.7", + "@next/swc-linux-x64-gnu": "15.5.7", + "@next/swc-linux-x64-musl": "15.5.7", + "@next/swc-win32-arm64-msvc": "15.5.7", + "@next/swc-win32-x64-msvc": "15.5.7", + "sharp": "^0.34.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", + "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", @@ -15763,16 +15818,16 @@ } }, "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "hasInstallScript": true, "license": "Apache-2.0", "optional": true, "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { "node": "^18.17.0 || ^20.3.0 || >=21.0.0" @@ -15781,25 +15836,30 @@ "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" } }, "node_modules/shebang-command": { @@ -15927,16 +15987,6 @@ "url": "https://github.com/steveukx/git-js?sponsor=1" } }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", - "license": "MIT", - "optional": true, - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -16032,14 +16082,6 @@ "node": ">=8" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", diff --git a/package.json b/package.json index f9a191a..8345a5c 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "es-toolkit": "^1.37.2", "framer-motion": "^12.5.0", "lucide-react": "^0.474.0", - "next": "15.1.11", + "next": "^15.5.9", "next-themes": "^0.4.6", "react": "^19.0.0", "react-dom": "^19.0.0", From 30e83f3b5a985aaf82582c960bc269f008305772 Mon Sep 17 00:00:00 2001 From: AS7AR Date: Thu, 25 Dec 2025 18:42:43 +0900 Subject: [PATCH 05/12] feat: renamed following Naming Conventions --- app/api/words/search/route.ts | 108 +++++++++++++++++----------------- app/word/api/page.tsx | 69 ++++++++++------------ 2 files changed, 85 insertions(+), 92 deletions(-) diff --git a/app/api/words/search/route.ts b/app/api/words/search/route.ts index 46e71a8..7446279 100644 --- a/app/api/words/search/route.ts +++ b/app/api/words/search/route.ts @@ -6,83 +6,83 @@ import { GameMode } from '@/app/word/search/types'; export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); - const mode = (searchParams.get('mode') || 'kor-start') as GameMode; - const q = searchParams.get('q') || ''; - const mission = searchParams.get('mission') || ''; - const minLength = parseInt(searchParams.get('minLength') || '2'); - const maxLength = parseInt(searchParams.get('maxLength') || '100'); - const sortBy = (searchParams.get('sortBy') || 'length') as 'abc' | 'length' | 'attack'; - const duem = searchParams.get('duem') !== 'false'; - const miniInfo = searchParams.get('miniInfo') === 'true'; - const manner = searchParams.get('manner') || 'man'; - const ingjung = searchParams.get('ingjung') !== 'false'; + const gameMode = (searchParams.get('mode') || 'kor-start') as GameMode; + const searchQuery = searchParams.get('q') || ''; + const missionLetter = searchParams.get('mission') || ''; + const minimumLength = parseInt(searchParams.get('minLength') || '2'); + const maximumLength = parseInt(searchParams.get('maxLength') || '100'); + const sortOrder = (searchParams.get('sortBy') || 'length') as 'abc' | 'length' | 'attack'; + const isDuemApplied = searchParams.get('duem') !== 'false'; + const hasMiniInfo = searchParams.get('miniInfo') === 'true'; + const mannerMode = searchParams.get('manner') || 'man'; + const isAcceptedOnly = searchParams.get('ingjung') !== 'false'; const displayLimit = parseInt(searchParams.get('limit') || '100'); const themeId = searchParams.get('themeId'); try { - let query: advancedQueryType; + let searchOptions: advancedQueryType; - if (mode === 'kor-start' || mode === 'kor-end') { - const start = mode === 'kor-start' ? q : searchParams.get('start') || undefined; - const end = mode === 'kor-end' ? q : searchParams.get('end') || undefined; + if (gameMode === 'kor-start' || gameMode === 'kor-end') { + const startLetter = gameMode === 'kor-start' ? searchQuery : searchParams.get('start') || undefined; + const endLetter = gameMode === 'kor-end' ? searchQuery : searchParams.get('end') || undefined; - if (mode === 'kor-start' && !start) return createErrorResponse('시작 초성이 필요합니다.'); - if (mode === 'kor-end' && !end) return createErrorResponse('끝 초성이 필요합니다.'); + if (gameMode === 'kor-start' && !startLetter) return handleErrorResponse('시작 초성이 필요합니다.'); + if (gameMode === 'kor-end' && !endLetter) return handleErrorResponse('끝 초성이 필요합니다.'); - query = { - mode, - start: start?.trim(), - end: end?.trim(), - mission, - ingjung, - man: manner === 'man', - jen: manner === 'jen', - eti: manner === 'eti', - duem, - miniInfo, - length_min: minLength, - length_max: maxLength, - sort_by: sortBy, + searchOptions = { + mode: gameMode, + start: startLetter?.trim(), + end: endLetter?.trim(), + mission: missionLetter, + ingjung: isAcceptedOnly, + man: mannerMode === 'man', + jen: mannerMode === 'jen', + eti: mannerMode === 'eti', + duem: isDuemApplied, + miniInfo: hasMiniInfo, + length_min: minimumLength, + length_max: maximumLength, + sort_by: sortOrder, limit: isNaN(displayLimit) ? 100 : displayLimit }; - } else if (mode === 'kung') { - if (!q) return createErrorResponse('단어가 필요합니다.'); - query = { + } else if (gameMode === 'kung') { + if (!searchQuery) return handleErrorResponse('단어가 필요합니다.'); + searchOptions = { mode: 'kung', - start: q.trim().slice(0, 3), - mission, - ingjung, - man: manner === 'man', - jen: manner === 'jen', - eti: manner === 'eti', - duem, - miniInfo, + start: searchQuery.trim().slice(0, 3), + mission: missionLetter, + ingjung: isAcceptedOnly, + man: mannerMode === 'man', + jen: mannerMode === 'jen', + eti: mannerMode === 'eti', + duem: isDuemApplied, + miniInfo: hasMiniInfo, length_min: 3, length_max: 3, - sort_by: sortBy, + sort_by: sortOrder, limit: isNaN(displayLimit) ? 100 : displayLimit }; - } else if (mode === 'hunmin') { - if (q.trim().length !== 2) return createErrorResponse('훈민정음 쿼리는 2글자여야 합니다.'); - query = { + } else if (gameMode === 'hunmin') { + if (searchQuery.trim().length !== 2) return handleErrorResponse('훈민정음 쿼리는 2글자여야 합니다.'); + searchOptions = { mode: 'hunmin', - query: q.trim(), - mission, + query: searchQuery.trim(), + mission: missionLetter, limit: isNaN(displayLimit) ? 100 : displayLimit }; - } else if (mode === 'jaqi') { - if (!themeId) return createErrorResponse('테마 ID가 필요합니다.'); - query = { + } else if (gameMode === 'jaqi') { + if (!themeId) return handleErrorResponse('테마 ID가 필요합니다.'); + searchOptions = { mode: 'jaqi', - query: q.trim(), + query: searchQuery.trim(), theme: Number(themeId), limit: isNaN(displayLimit) ? 100 : displayLimit }; } else { - return createErrorResponse('유효하지 않은 모드입니다.'); + return handleErrorResponse('유효하지 않은 모드입니다.'); } - const { data, error } = await SCM.get().wordsByAdvancedQuery(query); + const { data, error } = await SCM.get().wordsByAdvancedQuery(searchOptions); if (error) throw error; @@ -92,6 +92,6 @@ export async function GET(request: NextRequest) { } } -function createErrorResponse(message: string) { +function handleErrorResponse(message: string) { return NextResponse.json({ error: message }, { status: 400 }); } \ No newline at end of file diff --git a/app/word/api/page.tsx b/app/word/api/page.tsx index 99466cd..26910c7 100644 --- a/app/word/api/page.tsx +++ b/app/word/api/page.tsx @@ -24,7 +24,23 @@ export async function generateMetadata() { }; } -export default function OpenAPIDocsPage() { +export default function OpenApiDocsPage() { + const commonParameters = [ + { name: "mode", type: "string", description: "게임 모드 (kor-start, kor-end, kung, hunmin, jaqi)", defaultValue: "kor-start" }, + { name: "q", type: "string", description: "검색어. 모드에 따라 시작자, 끝자, 또는 초성", defaultValue: "-" }, + { name: "limit", type: "number", description: "최대 검색 결과 수", defaultValue: "100" }, + { name: "sortBy", type: "string", description: "정렬 기준 (abc, length, attack)", defaultValue: "length" }, + ]; + + const advancedParameters = [ + { parameterName: "manner", type: "string", description: "단어 필터 (man, jen, eti)", defaultValue: "man" }, + { parameterName: "minLength", type: "number", description: "최소 글자 수", defaultValue: "2" }, + { parameterName: "maxLength", type: "number", description: "최대 글자 수", defaultValue: "100" }, + { parameterName: "duem", type: "boolean", description: "두음법칙 적용 여부", defaultValue: "true" }, + { parameterName: "mission", type: "string", description: "포함해야 할 특정 글자", defaultValue: '""' }, + { parameterName: "themeId", type: "number", description: "jaqi 모드 사용 시 필수 테마 Id", defaultValue: "-" }, + ]; + return (
@@ -81,30 +97,14 @@ export default function OpenAPIDocsPage() { - - mode - string - 게임 모드 (kor-start, kor-end, kung, hunmin, jaqi) - kor-start - - - q - string - 검색어. 모드에 따라 시작자, 끝자, 또는 초성 - - - - - limit - number - 최대 검색 결과 수 - 100 - - - sortBy - string - 정렬 기준 (abc, length, attack) - length - + {commonParameters.map((param, index) => ( + + {param.name} + {param.type} + {param.description} + {param.defaultValue} + + ))}
@@ -123,19 +123,12 @@ export default function OpenAPIDocsPage() { - {[ - { p: "manner", t: "string", d: "단어 필터 (man, jen, eti)", v: "man" }, - { p: "minLength", t: "number", d: "최소 글자 수", v: "2" }, - { p: "maxLength", t: "number", d: "최대 글자 수", v: "100" }, - { p: "duem", t: "boolean", d: "두음법칙 적용 여부", v: "true" }, - { p: "mission", t: "string", d: "포함해야 할 특정 글자", v: '""' }, - { p: "themeId", t: "number", d: "jaqi 모드 사용 시 필수 테마 ID", v: "-" }, - ].map((row, i) => ( - - {row.p} - {row.t} - {row.d} - {row.v} + {advancedParameters.map((param, index) => ( + + {param.parameterName} + {param.type} + {param.description} + {param.defaultValue} ))} From b791e38f84c18d43f90e692e5b5a4729dc3ec003 Mon Sep 17 00:00:00 2001 From: AS7AR Date: Sat, 27 Dec 2025 17:15:39 +0900 Subject: [PATCH 06/12] feat: split API page --- .idea/.gitignore | 10 --- .idea/copilot.data.migration.ask2agent.xml | 6 -- .idea/discord.xml | 7 -- .idea/inspectionProfiles/Project_Default.xml | 6 -- .idea/kkuko-utils.iml | 8 -- .idea/misc.xml | 14 ---- .idea/modules.xml | 8 -- .idea/vcs.xml | 6 -- app/header.tsx | 4 +- app/openapi/page.tsx | 83 ++++++++++++++++++++ app/{word/api => openapi/word}/page.tsx | 10 +-- app/word/page.tsx | 20 +---- 12 files changed, 92 insertions(+), 90 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/copilot.data.migration.ask2agent.xml delete mode 100644 .idea/discord.xml delete mode 100644 .idea/inspectionProfiles/Project_Default.xml delete mode 100644 .idea/kkuko-utils.iml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml create mode 100644 app/openapi/page.tsx rename app/{word/api => openapi/word}/page.tsx (97%) diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 9879198..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# 디폴트 무시된 파일 -/shelf/ -/workspace.xml -# 쿼리 파일을 포함한 무시된 디폴트 폴더 -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# 에디터 기반 HTTP 클라이언트 요청 -/httpRequests/ diff --git a/.idea/copilot.data.migration.ask2agent.xml b/.idea/copilot.data.migration.ask2agent.xml deleted file mode 100644 index 1f2ea11..0000000 --- a/.idea/copilot.data.migration.ask2agent.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml deleted file mode 100644 index 30bab2a..0000000 --- a/.idea/discord.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 03d9549..0000000 --- a/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/kkuko-utils.iml b/.idea/kkuko-utils.iml deleted file mode 100644 index c956989..0000000 --- a/.idea/kkuko-utils.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 2b59431..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 0614563..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/header.tsx b/app/header.tsx index b433cea..be9c37d 100644 --- a/app/header.tsx +++ b/app/header.tsx @@ -69,6 +69,7 @@ const Header = () => { { href: "/manager-tool", label: "단어장 관리 도구", isActive: pathname.includes('manager-tool') }, { href: "/words-docs", label: "단어장 공유", isActive: pathname.includes('words-docs') }, { href: "/word", label: "오픈DB", isActive: pathname==='/word' || pathname.includes('/word/') }, + { href: "/openapi", label: "오픈API", isActive: pathname.includes('/openapi') }, { href: "/extra-features", label: "기타 기능", @@ -78,7 +79,8 @@ const Header = () => { !(pathname === "/") && !(pathname.includes('admin')) && !(pathname.includes('/word/')) && - pathname !=='/word' + pathname !=='/word' && + !pathname.includes('/openapi') } ]; diff --git a/app/openapi/page.tsx b/app/openapi/page.tsx new file mode 100644 index 0000000..7b5f438 --- /dev/null +++ b/app/openapi/page.tsx @@ -0,0 +1,83 @@ +import {AlignStartVertical, ChevronRight, DoorOpen} from "lucide-react"; +import Link from "next/link"; + +export async function generateMetadata() { + return { + title: "끄코 유틸리티 - 오픈API", + description: `끄코 유틸리티 - 오픈API 홈`, + openGraph: { + title: "끄코 유틸리티 - 오픈API", + description: "끄코 유틸리티 - 오픈API 홈", + type: "website", + url: "https://kkuko-utils.vercel.app/openapi", + siteName: "끄코 유틸리티", + locale: "ko_KR", + }, + }; +} + +const features = [ + { + title: "Word Search API", + description: "단어 검색 기능을 API에서 만나보세요.", + link: "/openapi/word", + icon: AlignStartVertical, + color: "from-indigo-400 to-yellow-600", + bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" + } +] + +export default function OpenAPIHomePage() { + return ( +
+ {/* 헤더 */} +
+
+
+ +

+ 오픈 API +

+
+

+ 끄코 유틸리티의 기능을 API에서 만나보세요. +

+
+ + {/* 기능 카드 그리드 */} +
+ {features.map((feature, idx) => { + const IconComponent = feature.icon; + + return ( + +
+
+
+ +
+ +
+ +

+ {feature.title} +

+ +

+ {feature.description} +

+ +
+ + 시작하기 → + +
+
+ + ); + })} +
+
+
+ ); +} \ No newline at end of file diff --git a/app/word/api/page.tsx b/app/openapi/word/page.tsx similarity index 97% rename from app/word/api/page.tsx rename to app/openapi/word/page.tsx index 26910c7..294be06 100644 --- a/app/word/api/page.tsx +++ b/app/openapi/word/page.tsx @@ -11,13 +11,13 @@ import { export async function generateMetadata() { return { - title: "끄코 유틸리티 - 오픈DB API", - description: `끄코 유틸리티 - 오픈DB API`, + title: "끄코 유틸리티 - 오픈API 단어", + description: `끄코 유틸리티 - 오픈API 단어`, openGraph: { - title: "끄코 유틸리티 - 오픈DB API", - description: "끄코 유틸리티 - 오픈DB API", + title: "끄코 유틸리티 - 오픈API 단어", + description: "끄코 유틸리티 - 오픈API 단어", type: "website", - url: "https://kkuko-utils.vercel.app/word/api", + url: "https://kkuko-utils.vercel.app/openapi/word", siteName: "끄코 유틸리티", locale: "ko_KR", }, diff --git a/app/word/page.tsx b/app/word/page.tsx index b2179d4..4e1b2bb 100644 --- a/app/word/page.tsx +++ b/app/word/page.tsx @@ -1,15 +1,5 @@ import Link from "next/link"; -import { - Search, - Download, - Plus, - Upload, - FileText, - Clock, - ChevronRight, - Database, - BarChart3, AlignStartVertical -} from "lucide-react"; +import {BarChart3, ChevronRight, Clock, Database, Download, FileText, Plus, Search, Upload} from "lucide-react"; export async function generateMetadata() { return { @@ -83,14 +73,6 @@ const features = [ color: "from-indigo-500 to-blue-500", bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" }, - { - title: "Open API", - description: "오픈 DB의 단어 검색 기능을 API에서 만나보세요.", - link: "/word/api", - icon: AlignStartVertical, - color: "from-indigo-400 to-yellow-600", - bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" - } ]; export default function OpenDBHomePage() { From cfe0eff10a25d89c726fa805d81bc3de8e089f9a Mon Sep 17 00:00:00 2001 From: AS7AR Date: Sat, 27 Dec 2025 18:30:21 +0900 Subject: [PATCH 07/12] =?UTF-8?q?fix:=20=EC=98=A4=ED=83=88=EC=9E=90=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/AutoLogin.tsx | 10 +-- app/ErrorPage.tsx | 4 +- app/admin/add-words/AddWordsHome.tsx | 8 +-- app/admin/del-words/DelWordsHome.tsx | 6 +- app/admin/logs/AdminLogsHome.tsx | 2 +- app/admin/logs/AdminLogsWrapper.tsx | 2 +- app/admin/request-words/AdminRequestHome.tsx | 8 +-- app/admin/request-words/AdminWrapper.tsx | 8 +-- app/api/auth/update_nickname/route.ts | 4 +- app/auth/auth.tsx | 14 ++--- app/auth/page.tsx | 4 +- app/header.tsx | 43 ++++++++----- app/lib/CombinationsManger.ts | 6 +- app/lib/supabase/ISupabaseClientManager.ts | 6 +- app/lib/supabase/SupabaseClientManager.ts | 2 +- app/manager-tool/arrange/ArrangeHome.tsx | 62 +++++++++---------- app/manager-tool/arrange/HelpModal.tsx | 6 +- app/profile/ProfileHome.tsx | 6 +- app/profile/[username]/ProfilePage.tsx | 2 +- app/programs/[id]/ProgramDetailPage.tsx | 6 +- app/providers.tsx | 1 + app/release-note/page.tsx | 1 + app/word-combiner/WordCombinerClient.tsx | 32 +++++----- app/word-combiner/WordCombinerHelpModal.tsx | 6 +- app/word-combiner/page.tsx | 1 + app/word/lib.ts | 2 +- app/word/logs/LogsHome.tsx | 2 +- .../search/components/SimpleSearchOptions.tsx | 1 + app/words-docs/WordsDocsHome.tsx | 2 +- app/words-docs/WordsDocsHomePage.tsx | 6 +- app/words-docs/[id]/DocsDataHome.tsx | 10 +-- app/words-docs/[id]/DocsDataPage.tsx | 18 +++--- app/words-docs/[id]/Table.tsx | 2 +- app/words-docs/[id]/TableWorkFunc.tsx | 30 ++++----- app/words-docs/[id]/logs/DocsLogPage.tsx | 10 +-- app/words-docs/[id]/page.tsx | 3 +- 36 files changed, 174 insertions(+), 162 deletions(-) diff --git a/app/AutoLogin.tsx b/app/AutoLogin.tsx index db9cfb3..8d30791 100644 --- a/app/AutoLogin.tsx +++ b/app/AutoLogin.tsx @@ -14,15 +14,15 @@ const AutoLogin = () => { if (!data || !data.session || error) return; - const { data: ddata, error: err } = await SCM.get().userById(data.session.user.id); + const { data: dbdata, error: err } = await SCM.get().userById(data.session.user.id); - if (err || !ddata) return; + if (err || !dbdata) return; dispatch( userAction.setInfo({ - username: ddata.nickname, - role: ddata.role ?? "guest", - uuid: ddata.id, + username: dbdata.nickname, + role: dbdata.role ?? "guest", + uuid: dbdata.id, }) ); } diff --git a/app/ErrorPage.tsx b/app/ErrorPage.tsx index 5a1054b..1ac6b1e 100644 --- a/app/ErrorPage.tsx +++ b/app/ErrorPage.tsx @@ -6,7 +6,7 @@ import type { ErrorMessage } from "./types/type"; import { useRouter } from "next/navigation"; const ErrorPage:React.FC<{e:ErrorMessage}> = ({e}) => { - const [errork,setError] = useState(null); + const [error,setError] = useState(null); const router = useRouter(); const goBack = () => { @@ -19,7 +19,7 @@ const ErrorPage:React.FC<{e:ErrorMessage}> = ({e}) => { return (
- {errork && setError(null)} /> } + {error && setError(null)} /> }
diff --git a/app/auth/page.tsx b/app/auth/page.tsx index 102b7fb..7055cf7 100644 --- a/app/auth/page.tsx +++ b/app/auth/page.tsx @@ -16,10 +16,10 @@ export async function generateMetadata() { }; } -const OAuthpage: React.FC = () => { +const OAuthPage: React.FC = () => { return ( ) } -export default OAuthpage; \ No newline at end of file +export default OAuthPage; \ No newline at end of file diff --git a/app/header.tsx b/app/header.tsx index be9c37d..9a9678f 100644 --- a/app/header.tsx +++ b/app/header.tsx @@ -64,24 +64,33 @@ const Header = () => { setTheme(theme === 'dark' ? 'light' : 'dark'); } + type NavItem = { + href: string; + label: string; + match: (pathname: string) => boolean; + }; + + const navDefs: NavItem[] = [ + { href: "/word-combiner", label: "단어조합기", match: p => p === "/word-combiner" }, + { href: "/manager-tool", label: "단어장 관리 도구", match: p => p.includes("/manager-tool") }, + { href: "/words-docs", label: "단어장 공유", match: p => p.includes("/words-docs") }, + { href: "/word", label: "오픈DB", match: p => p === "/word" || p.includes("/word/") }, + { href: "/openapi", label: "오픈API", match: p => p=== "/openapi" || p.includes("/openapi") }, + ]; + + const activeIndex = navDefs.findIndex(item => item.match(pathname)); + const navItems = [ - { href: "/word-combiner", label: "단어조합기", isActive: pathname === "/word-combiner" }, - { href: "/manager-tool", label: "단어장 관리 도구", isActive: pathname.includes('manager-tool') }, - { href: "/words-docs", label: "단어장 공유", isActive: pathname.includes('words-docs') }, - { href: "/word", label: "오픈DB", isActive: pathname==='/word' || pathname.includes('/word/') }, - { href: "/openapi", label: "오픈API", isActive: pathname.includes('/openapi') }, - { - href: "/extra-features", - label: "기타 기능", - isActive: !(pathname === "/word-combiner") && - !(pathname.includes('manager-tool')) && - !(pathname.includes('words-docs')) && - !(pathname === "/") && - !(pathname.includes('admin')) && - !(pathname.includes('/word/')) && - pathname !=='/word' && - !pathname.includes('/openapi') - } + ...navDefs.map((item, i) => ({ + href: item.href, + label: item.label, + isActive: i === activeIndex, + })), + { + href: "/extra-features", + label: "기타 기능", + isActive: activeIndex === -1, + }, ]; return ( diff --git a/app/lib/CombinationsManger.ts b/app/lib/CombinationsManger.ts index 3f0949f..a820158 100644 --- a/app/lib/CombinationsManger.ts +++ b/app/lib/CombinationsManger.ts @@ -145,7 +145,7 @@ class CombinationManager { } /** - * 단어 사전의 단어들의 글자 출현 횟수 countting 함수 (나중에 단어들의 점수로 활용됨) + * 단어 사전의 단어들의 글자 출현 횟수 counting 함수 (나중에 단어들의 점수로 활용됨) */ private countLetter() { this.letterCount = {}; // letterCount 초기화 @@ -158,7 +158,7 @@ class CombinationManager { } /** - * 사용가능한 음절들을 countting하는 함수(음절 문자열에서 replace하는것 보다 효율적일듯) + * 사용가능한 음절들을 counting하는 함수(음절 문자열에서 replace하는것 보다 효율적일듯) */ private countSyllable() { this.syllableCount = {}; @@ -190,7 +190,7 @@ class CombinationManager { * 남아 있는 음절들을 정렬하여 반환하는 함수 * @returns {string} 정렬된 음절 문자열 */ - public remainstr(): string { + public remainStr(): string { const result = []; for (const [syllable, count] of Object.entries(this.syllableCount)) { if (count > 0) { diff --git a/app/lib/supabase/ISupabaseClientManager.ts b/app/lib/supabase/ISupabaseClientManager.ts index 57f10cc..c6bedf2 100644 --- a/app/lib/supabase/ISupabaseClientManager.ts +++ b/app/lib/supabase/ISupabaseClientManager.ts @@ -58,7 +58,7 @@ export interface IGetManager{ docsWords({ name, duem, typez }: { name: string; duem: boolean; typez: "letter" | "theme";} | {name: number; duem: boolean; typez: "ect";}): Promise<{data: null, error: PostgrestError} | {data: {words: word[], waitWords: ({ word: string; request_type: "add" | "delete"; requested_by: string | null; })[]}, error: null}> allWaitWords(c?:"add" | "delete"): Promise>; wordsThemes(wordIds: number[]): Promise> - allWords({ includeAddReq, includeDeleteReq, includeInjung, includeNoInjung, onlyWordChain, lenf }: { includeAddReq?: boolean; includeDeleteReq?: boolean; includeInjung?: boolean; includeNoInjung?: boolean; onlyWordChain?: boolean; lenf?: boolean; }): Promise<{ data: { word: string; noin_canuse: boolean; k_canuse: boolean; status: "ok" | "add" | "delete"; }[]; error: null } | {data: null; error: PostgrestError; }> + allWords({ includeAddReq, includeDeleteReq, includeInjung, includeNoInjung, onlyWordChain, lenf }: { includeAddReq?: boolean; includeDeleteReq?: boolean; includeInjung?: boolean; includeNoInjung?: boolean; onlyWordChain?: boolean; lenf?: boolean; }): Promise<{ data: { word: string; noin_canuse: boolean; k_CanUse: boolean; status: "ok" | "add" | "delete"; }[]; error: null } | {data: null; error: PostgrestError; }> letterDocs(): Promise>; addWaitDocs(): Promise>; releaseNote(): Promise>; @@ -66,7 +66,7 @@ export interface IGetManager{ session(): Promise<{data: {session: Session}, error: null} | {data: { session: null}, error: AuthError} | { data: {session: null}, error: null}>; usersByNickname(userName: string): Promise>; usersLikeByNickname(q: string): Promise>; - userByNickname(nicknmae: string): Promise>; + userByNickname(nickname: string): Promise>; monthlyConRankByUserId(userId: string): Promise>; monthlyContributionsByUserId(userId: string): Promise> starredDocsById(userId: string): Promise>; @@ -85,7 +85,7 @@ export interface IGetManager{ firstWordCountByLetters(letter: string): Promise; lastWordCountByLetters(letter: string): Promise; wordsByQuery(query: string): Promise<{data: string[], error: null} | {data: null; error: PostgrestError}>; - logsByFillter({filterState, filterType, from, to}:{filterState?: "approved" | "rejected" | "pending" | "all", filterType: "delete" | "add" | "all", from: number, to: number}): Promise> + logsByFilter({filterState, filterType, from, to}:{filterState?: "approved" | "rejected" | "pending" | "all", filterType: "delete" | "add" | "all", from: number, to: number}): Promise> docsLogsByFilter({ docsName, logType, from, to }: { docsName?: string; logType: 'add' | 'delete' | 'all'; from: number; to: number; }): Promise>; notice(): Promise>; wordsThemesByWordId(wordIds: number[]): Promise>; diff --git a/app/lib/supabase/SupabaseClientManager.ts b/app/lib/supabase/SupabaseClientManager.ts index 480e82d..362748e 100644 --- a/app/lib/supabase/SupabaseClientManager.ts +++ b/app/lib/supabase/SupabaseClientManager.ts @@ -590,7 +590,7 @@ class GetManager implements IGetManager { return result; } - public async logsByFillter({ filterState, filterType, from, to }: { filterState: 'approved' | 'rejected' | 'pending' | 'all'; filterType: 'delete' | 'add' | 'all'; from: number; to: number; }) { + public async logsByFilter({ filterState, filterType, from, to }: { filterState: 'approved' | 'rejected' | 'pending' | 'all'; filterType: 'delete' | 'add' | 'all'; from: number; to: number; }) { let query = this.supabase .from('logs') .select(` diff --git a/app/manager-tool/arrange/ArrangeHome.tsx b/app/manager-tool/arrange/ArrangeHome.tsx index 0369c00..8bc7a65 100644 --- a/app/manager-tool/arrange/ArrangeHome.tsx +++ b/app/manager-tool/arrange/ArrangeHome.tsx @@ -140,12 +140,12 @@ const FileSector = ({ fileContent, fileInputRef, handleFileUpload, file, lineCou }; -const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalView }: +const ToolSector = ({ fileContent, setFileContent, setLineCount, setErrorModalView }: { fileContent: string, setFileContent: React.Dispatch>, setLineCount: React.Dispatch>, - seterrorModalView: React.Dispatch> + setErrorModalView: React.Dispatch> } ) => { const [undoStack, setUndoStack] = useState([]); @@ -163,7 +163,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setRedoStack([]); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -171,7 +171,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -192,7 +192,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi } } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -200,7 +200,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -221,7 +221,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi } } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -229,7 +229,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -249,7 +249,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setLineCount(updatedContent.split("\n").length); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -257,7 +257,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -280,7 +280,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setLineCount(updatedContent.split("\n").length); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -288,7 +288,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -312,7 +312,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setRemoveWord(""); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -320,7 +320,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -342,7 +342,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setReplaceValue(""); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -350,7 +350,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -377,7 +377,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setLineCount(temp.length); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -385,7 +385,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -406,7 +406,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi console.log(updatedContent) } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -414,7 +414,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -450,7 +450,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setLineCount(updatedContent.split("\n").length); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -458,7 +458,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -495,14 +495,14 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setPatternToDelete(""); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, inputValue: `DeleteByPattern | ${fileContent}` }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -522,14 +522,14 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setLineCount(updatedContent.length); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, inputValue: `SortByLength | ${fileContent}` }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -560,7 +560,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi console.log(updatedContent) } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -568,7 +568,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -587,14 +587,14 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, seterrorModalVi setLineCount(updatedContent.split("\n").length); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, inputValue: `ConvertToLowercase | ${fileContent}` }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string, @@ -1052,7 +1052,7 @@ const ArrangeHome = () => { fileContent={fileContent} setFileContent={setFileContent} setLineCount={setLineCount} - seterrorModalView={seterrorModalView} + setErrorModalView={seterrorModalView} />
diff --git a/app/manager-tool/arrange/HelpModal.tsx b/app/manager-tool/arrange/HelpModal.tsx index 1c1df45..4317ed7 100644 --- a/app/manager-tool/arrange/HelpModal.tsx +++ b/app/manager-tool/arrange/HelpModal.tsx @@ -1,11 +1,11 @@ import React, { useEffect, useRef } from 'react'; import HelpModal from '@/app/components/HelpModal'; -interface HelpModalprop { +interface HelpModalProp { wantGo?: 1 | 2 | 3 | 4; } -const HelpModalB = ({ wantGo }: HelpModalprop) => { +const HelpModalB = ({ wantGo }: HelpModalProp) => { // 각 섹션에 대한 const sortRef1 = useRef(null); const sortRef2 = useRef(null); @@ -114,7 +114,7 @@ const HelpModalB = ({ wantGo }: HelpModalprop) => { ) } -export default function HelpModalC({ wantGo }: HelpModalprop) { +export default function HelpModalC({ wantGo }: HelpModalProp) { return ( diff --git a/app/profile/ProfileHome.tsx b/app/profile/ProfileHome.tsx index 8eb50aa..d120611 100644 --- a/app/profile/ProfileHome.tsx +++ b/app/profile/ProfileHome.tsx @@ -51,7 +51,7 @@ export default function ProfileHomePage() { const [searchInput, setSearchInput] = useState(""); const [resultUsers, setResultUsers] = useState([]); const [isLoading, setIsLoading] = useState(false); - const [errorModalView, seterrorModalView] = useState(null); + const [errorModalView, setErrorModalView] = useState(null); const handleSearch = async () => { setIsLoading(true); @@ -60,7 +60,7 @@ export default function ProfileHomePage() { if (error){ setIsLoading(false); setResultUsers([]); - seterrorModalView({ + setErrorModalView({ ErrName: error.name, ErrMessage: error.message, ErrStackRace: error.code, @@ -210,7 +210,7 @@ export default function ProfileHomePage() { {errorModalView && ( seterrorModalView(null)} + onClose={() => setErrorModalView(null)} /> )} diff --git a/app/profile/[username]/ProfilePage.tsx b/app/profile/[username]/ProfilePage.tsx index 4f74a25..1327735 100644 --- a/app/profile/[username]/ProfilePage.tsx +++ b/app/profile/[username]/ProfilePage.tsx @@ -213,7 +213,7 @@ const ProfilePage = ({ userName }: { userName: string }) => { setMonthlyContributions(filledContributions); setLoading(null); - loadTabsData(getUserData.id); + await loadTabsData(getUserData.id); }; getData(); diff --git a/app/programs/[id]/ProgramDetailPage.tsx b/app/programs/[id]/ProgramDetailPage.tsx index 6431e44..879fc72 100644 --- a/app/programs/[id]/ProgramDetailPage.tsx +++ b/app/programs/[id]/ProgramDetailPage.tsx @@ -32,7 +32,7 @@ const programInfoFetcher = async (id: string): Promise<{data: {data: Program}, e } } -const ProgramRelaseFetcher = async (_: string, { arg }: { arg: { repo: string } }): Promise<{data: {latest: GitHubRelease, all: GitHubRelease[]}, error: null} | {data: null, error: FetchError}> => { +const ProgramReleaseFetcher = async (_: string, { arg }: { arg: { repo: string } }): Promise<{data: {latest: GitHubRelease, all: GitHubRelease[]}, error: null} | {data: null, error: FetchError}> => { try { const repo = arg.repo; const encodedRepo = encodeURIComponent(repo); @@ -69,7 +69,7 @@ export default function ProgramDetailPage() { const [error, setError] = useState(null); const [showAllReleases, setShowAllReleases] = useState(false); const {data: infoData, isLoading} = useSWR(`/api/programs/info?id=${programId}`, () => programInfoFetcher(programId), { dedupingInterval: 300_000, revalidateIfStale: false }); - const { trigger, data: mutateData, isMutating } = useSWRMutation(`/api/programs/releases?id=${programId}`, ProgramRelaseFetcher); + const { trigger, data: mutateData, isMutating } = useSWRMutation(`/api/programs/releases?id=${programId}`, ProgramReleaseFetcher); useEffect(()=>{ const updateFunc = async () => { @@ -79,7 +79,7 @@ export default function ProgramDetailPage() { } else if (infoData.data) { setProgram(infoData.data.data); setError(null); - trigger({repo: infoData.data.data.github_repo}); + await trigger({repo: infoData.data.data.github_repo}); } } } diff --git a/app/providers.tsx b/app/providers.tsx index 905a4e0..922b2c1 100644 --- a/app/providers.tsx +++ b/app/providers.tsx @@ -3,6 +3,7 @@ import { Provider } from "react-redux"; import { store } from "./store/store"; import { ThemeProvider } from 'next-themes' +import React from "react"; export function Providers({ children }: { children: React.ReactNode }) { return ( diff --git a/app/release-note/page.tsx b/app/release-note/page.tsx index fa59e0b..691d291 100644 --- a/app/release-note/page.tsx +++ b/app/release-note/page.tsx @@ -1,4 +1,5 @@ import ReleaseNote from "./ReleaseNote"; +import React from "react"; export async function generateMetadata() { return { diff --git a/app/word-combiner/WordCombinerClient.tsx b/app/word-combiner/WordCombinerClient.tsx index c98ea9f..c77117f 100644 --- a/app/word-combiner/WordCombinerClient.tsx +++ b/app/word-combiner/WordCombinerClient.tsx @@ -1,6 +1,6 @@ "use client" import React, { useState } from 'react'; -import type { SixCharString, FiveCharString, ErrorMessage } from '../types/type'; +import type { SixCharString, FiveCharString, ErrorMessage } from '@/types/type'; import CombinationManager from '../lib/CombinationsManger'; import ErrorModal from '../components/ErrModal'; import HelpModal from './WordCombinerHelpModal'; @@ -12,7 +12,7 @@ interface WordCombinerWithData { } export default function WordCombinerClient({ prop }: { prop: WordCombinerWithData }) { - const [nomalJOKAK, setNomalJOKAK] = useState(""); + const [normalJOKAK, setNormalJOKAK] = useState(""); const [highJOKAK, setHighJOKAK] = useState(""); const [rareJOKAK, setRareJOKAK] = useState(""); const [inputHtml, setInputHtml] = useState(""); @@ -31,7 +31,7 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat const parser = new DOMParser(); const doc = parser.parseFromString(htmlString, 'text/html'); - let nomal = ""; // 일반 + let normal = ""; // 일반 let high = ""; // 고급 let rare = ""; // 희귀 @@ -58,11 +58,11 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat rare += chName.repeat(tCount); } else if (charName.includes("글자 조각")) { const chName = charName.replace("글자 조각 - ", ""); - nomal += chName.repeat(tCount); + normal += chName.repeat(tCount); } }); setInputHtml(""); - setNomalJOKAK(nomal); + setNormalJOKAK(normal); setHighJOKAK(high); setRareJOKAK(rare); setActiveTab('normal'); @@ -89,12 +89,12 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat try { setLoading(true); setTimeout(() => { - const manger6 = new CombinationManager(nomalJOKAK.replace(/\s+/g, '').split('').sort().join(''), len6WordsData); + const manger6 = new CombinationManager(normalJOKAK.replace(/\s+/g, '').split('').sort().join(''), len6WordsData); setLen6Date(manger6.getBests()); - const manger5 = new CombinationManager(manger6.remainstr(), len5WordsData); + const manger5 = new CombinationManager(manger6.remainStr(), len5WordsData); setLen5Data(manger5.getBests()); setLoading(false); - setNomalJOKAK(manger5.remainstr()); + setNormalJOKAK(manger5.remainStr()); }, 1) } catch (err: unknown) { if (err instanceof Error) { @@ -123,10 +123,10 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat setTimeout(() => { const manger6 = new CombinationManager(highJOKAK.replace(/\s+/g, '').split('').sort().join(''), len6WordsData); setLen6Date(manger6.getBests()); - const manger5 = new CombinationManager(manger6.remainstr(), len5WordsData); + const manger5 = new CombinationManager(manger6.remainStr(), len5WordsData); setLen5Data(manger5.getBests()); setLoading(false); - setHighJOKAK(manger5.remainstr()); + setHighJOKAK(manger5.remainStr()); }, 1) } catch (err: unknown) { if (err instanceof Error) { @@ -155,10 +155,10 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat setTimeout(() => { const manger6 = new CombinationManager(rareJOKAK.replace(/\s+/g, '').split('').sort().join(''), len6WordsData); setLen6Date(manger6.getBests()); - const manger5 = new CombinationManager(manger6.remainstr(), len5WordsData); + const manger5 = new CombinationManager(manger6.remainStr(), len5WordsData); setLen5Data(manger5.getBests()); setLoading(false); - setRareJOKAK(manger5.remainstr()); + setRareJOKAK(manger5.remainStr()); }, 1) } catch (err: unknown) { if (err instanceof Error) { @@ -193,7 +193,7 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat const getCurrentValue = () => { switch(activeTab) { - case 'normal': return nomalJOKAK; + case 'normal': return normalJOKAK; case 'high': return highJOKAK; case 'rare': return rareJOKAK; case 'html': return inputHtml; @@ -203,11 +203,11 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat const getCurrentSetter = () => { switch(activeTab) { - case 'normal': return setNomalJOKAK; + case 'normal': return setNormalJOKAK; case 'high': return setHighJOKAK; case 'rare': return setRareJOKAK; case 'html': return setInputHtml; - default: return setNomalJOKAK; + default: return setNormalJOKAK; } }; @@ -309,7 +309,7 @@ export default function WordCombinerClient({ prop }: { prop: WordCombinerWithDat
일반 - {nomalJOKAK.length} + {normalJOKAK.length}
고급 diff --git a/app/word-combiner/WordCombinerHelpModal.tsx b/app/word-combiner/WordCombinerHelpModal.tsx index aa8ab86..ca14f8f 100644 --- a/app/word-combiner/WordCombinerHelpModal.tsx +++ b/app/word-combiner/WordCombinerHelpModal.tsx @@ -7,7 +7,7 @@ import { Play } from 'lucide-react'; const HelpModalA = ({ wantGo }: { wantGo?: 1 | 2 | 3; }) => { // 각 섹션에 대한 ref - const nomalHelp = useRef(null); + const normalHelp = useRef(null); const HTMLHelp = useRef(null); const chromeHTML = useRef(null); @@ -36,7 +36,7 @@ const HelpModalA = ({ wantGo }: { wantGo?: 1 | 2 | 3; }) => {
  • @@ -64,7 +64,7 @@ const HelpModalA = ({ wantGo }: { wantGo?: 1 | 2 | 3; }) => { {/* 기본 사용법 */}
    -

    +

    1 기본적인 사용법

    diff --git a/app/word-combiner/page.tsx b/app/word-combiner/page.tsx index 8d79f4e..e70e20e 100644 --- a/app/word-combiner/page.tsx +++ b/app/word-combiner/page.tsx @@ -1,4 +1,5 @@ import WordCombinerPage from "./WordCombinerPage"; +import React from "react"; export async function generateMetadata() { return { diff --git a/app/word/lib.ts b/app/word/lib.ts index fff60b2..0d174a3 100644 --- a/app/word/lib.ts +++ b/app/word/lib.ts @@ -1,6 +1,6 @@ "use client"; -import { SCM } from "../lib/supabaseClient"; +import { SCM } from "@/lib/supabaseClient"; export const fetcher = async () => { const { data, error } = await SCM.get().allThemes(); diff --git a/app/word/logs/LogsHome.tsx b/app/word/logs/LogsHome.tsx index f116c4c..f7e0f8d 100644 --- a/app/word/logs/LogsHome.tsx +++ b/app/word/logs/LogsHome.tsx @@ -97,7 +97,7 @@ export default function LogPage() { const from = (currentPage - 1) * itemsPerPage; const to = from + itemsPerPage - 1; - const { data: LogsData, error: LogsDataError, count } = await SCM.get().logsByFillter({ + const { data: LogsData, error: LogsDataError, count } = await SCM.get().logsByFilter({ filterState: currentFilterState, filterType: currentFilterType, from, to diff --git a/app/word/search/components/SimpleSearchOptions.tsx b/app/word/search/components/SimpleSearchOptions.tsx index d71a94e..d7463e9 100644 --- a/app/word/search/components/SimpleSearchOptions.tsx +++ b/app/word/search/components/SimpleSearchOptions.tsx @@ -1,4 +1,5 @@ import { Search, Loader2 } from 'lucide-react'; +import React from "react"; interface SimpleSearchOptionsProps { simpleQuery: string; diff --git a/app/words-docs/WordsDocsHome.tsx b/app/words-docs/WordsDocsHome.tsx index 14b466c..768982e 100644 --- a/app/words-docs/WordsDocsHome.tsx +++ b/app/words-docs/WordsDocsHome.tsx @@ -9,7 +9,7 @@ import { convertQwertyToHangul } from "es-hangul"; import { useSelector } from "react-redux"; import type { RootState } from "../store/store"; import LoginRequiredModal from "../components/LoginRequiredModal"; -import { SCM } from "../lib/supabaseClient"; +import { SCM } from "@/lib/supabaseClient"; import CompleteModal from "../components/CompleteModal"; interface Document { diff --git a/app/words-docs/WordsDocsHomePage.tsx b/app/words-docs/WordsDocsHomePage.tsx index ad3ebf3..31035c5 100644 --- a/app/words-docs/WordsDocsHomePage.tsx +++ b/app/words-docs/WordsDocsHomePage.tsx @@ -18,7 +18,7 @@ type DocsType = { export default function WordsDocsHomePage(){ const { loadingState, updateLoadingState } = useLoadingState(); const [errorMessage,setErrorMessage] = useState(null); - const [docsDatas, setDocsDatas] = useState(null); + const [docsData, setDocsData] = useState(null); // Data 자체가 복수형 useEffect(()=>{ const getData = async () => { @@ -36,7 +36,7 @@ export default function WordsDocsHomePage(){ id: `${id}`, name, maker: users?.nickname ?? "알수없음", last_update, is_manager: false, typez, created_at })); - setDocsDatas(docs); + setDocsData(docs); updateLoadingState(100, "완료"); } getData(); @@ -46,7 +46,7 @@ export default function WordsDocsHomePage(){ if (errorMessage) return - if (docsDatas) return + if (docsData) return return null } \ No newline at end of file diff --git a/app/words-docs/[id]/DocsDataHome.tsx b/app/words-docs/[id]/DocsDataHome.tsx index 99f6ea9..491a5f7 100644 --- a/app/words-docs/[id]/DocsDataHome.tsx +++ b/app/words-docs/[id]/DocsDataHome.tsx @@ -56,7 +56,7 @@ const DocsDataHome = ({ id, data, metaData, starCount }: DocsPageProp) => { const user = useSelector((state: RootState) => state.user); const [isUserStarreda, setIsUserStarreda] = useState(false); const [loginNeedModalOpen, setLoginNeedModalOpen] = useState(false); - const [errorModalView, seterrorModalView] = useState(null); + const [errorModalView, setErrorModalView] = useState(null); // 유저 즐겨찾기 상태 업데이트 useEffect(() => { @@ -227,7 +227,7 @@ const DocsDataHome = ({ id, data, metaData, starCount }: DocsPageProp) => { URL.revokeObjectURL(url); }; - const hadnleDocsStar = async () => { + const handleDocsStar = async () => { if (!user.uuid) { return setLoginNeedModalOpen(true); } @@ -243,7 +243,7 @@ const DocsDataHome = ({ id, data, metaData, starCount }: DocsPageProp) => { } const makeError = (error: PostgrestError) => { - seterrorModalView({ + setErrorModalView({ ErrName: error.name, ErrMessage: error.message, ErrStackRace: error.stack, @@ -321,7 +321,7 @@ const DocsDataHome = ({ id, data, metaData, starCount }: DocsPageProp) => { ? "bg-yellow-400 text-yellow-900 hover:bg-yellow-300" : "bg-white/20 text-white hover:bg-white/30 backdrop-blur-sm" }`} - onClick={hadnleDocsStar} + onClick={handleDocsStar} > { )} {errorModalView && ( seterrorModalView(null)} + onClose={() => setErrorModalView(null)} error={errorModalView} /> )} diff --git a/app/words-docs/[id]/DocsDataPage.tsx b/app/words-docs/[id]/DocsDataPage.tsx index 991aab5..10ec070 100644 --- a/app/words-docs/[id]/DocsDataPage.tsx +++ b/app/words-docs/[id]/DocsDataPage.tsx @@ -23,14 +23,14 @@ export default function DocsDataPage({id}:{id:number}){ const [errorMessage,setErrorMessage] = useState(null); const [wordsData,setWordsData] = useState<{words:wordsDataType[], metadata:{title:string, lastUpdate:string, typez: "letter" | "theme" | "ect"}, starCount: string[]} | null>(null); - const makeError = (erorr: PostgrestError) => { - setErrorMessage(`문서 정보 데이터 로드중 오류.\nErrorName: ${erorr.name ?? "알수없음"}\nError Message: ${erorr.message ?? "없음"}\nError code: ${erorr.code}`) + const makeError = (error: PostgrestError) => { + setErrorMessage(`문서 정보 데이터 로드중 오류.\nErrorName: ${error.name ?? "알수없음"}\nError Message: ${error.message ?? "없음"}\nError code: ${error.code}`) updateLoadingState(100,"ERR"); return; } useEffect(()=>{ - const getDatas = async () => { + const getData = async () => { updateLoadingState(10,"문서 정보 가져오는 중...") const {data: docsData, error: docsDataError} = await SCM.get().docsInfoByDocsId(id); if (docsDataError) return makeError(docsDataError); @@ -40,16 +40,16 @@ export default function DocsDataPage({id}:{id:number}){ if (docsData.typez === "letter"){ updateLoadingState(40, "문서에 들어간 단어 정보 가져오는 중..."); - const {data, error: LetterDatasError} = await SCM.get().docsWords({name: docsData.name, duem: docsData.duem, typez: "letter"}); - if (LetterDatasError) return makeError(LetterDatasError); - const {words: LetterDatas1, waitWords: LetterDatas2} = data; + const {data, error: LetterDataError} = await SCM.get().docsWords({name: docsData.name, duem: docsData.duem, typez: "letter"}); + if (LetterDataError) return makeError(LetterDataError); + const {words: LetterData1, waitWords: LetterData2} = data; await new Promise(resolve => setTimeout(resolve, 1)) updateLoadingState(70, "데이터를 가공중...") // 삭제 요청인 단어는 제외 - const wordsNotInB = LetterDatas1.filter(a => !LetterDatas2.some(b => b.word === a.word)).map((p)=>({word: p.word, status: "ok" as const, maker: undefined})); - const wordsData = [...wordsNotInB, ...LetterDatas2.filter(({word})=>word.length > 1).map(({word,requested_by,request_type})=>({word, status: request_type, maker:requested_by}))] + const wordsNotInB = LetterData1.filter(a => !LetterData2.some(b => b.word === a.word)).map((p)=>({word: p.word, status: "ok" as const, maker: undefined})); + const wordsData = [...wordsNotInB, ...LetterData2.filter(({word})=>word.length > 1).map(({word,requested_by,request_type})=>({word, status: request_type, maker:requested_by}))] const p = {title: docsData.name, lastUpdate: docsData.last_update, typez:docsData.typez} setWordsData({words: wordsData, metadata: p, starCount:docsStarData.map(({user_id})=>user_id)}); await SCM.update().docView(docsData.id); @@ -99,7 +99,7 @@ export default function DocsDataPage({id}:{id:number}){ return; } } - getDatas(); + getData(); },[]) if (isNotFound) return ; diff --git a/app/words-docs/[id]/Table.tsx b/app/words-docs/[id]/Table.tsx index f114c98..34ccccc 100644 --- a/app/words-docs/[id]/Table.tsx +++ b/app/words-docs/[id]/Table.tsx @@ -194,7 +194,7 @@ const Table = ({ CancelDeleteRequest, RequestDelete, DeleteByAdmin, - } = useWorkFunc({ makeError, setIsProcessing, user, CompleWork, isProcessing }); + } = useWorkFunc({ makeError, setIsProcessing, user, CompWork: CompleWork, isProcessing }); return (
    diff --git a/app/words-docs/[id]/TableWorkFunc.tsx b/app/words-docs/[id]/TableWorkFunc.tsx index a8671de..36a3a3c 100644 --- a/app/words-docs/[id]/TableWorkFunc.tsx +++ b/app/words-docs/[id]/TableWorkFunc.tsx @@ -2,7 +2,7 @@ import { SCM } from '@/app/lib/supabaseClient'; import type { PostgrestError } from "@supabase/supabase-js"; import { isNoin } from "@/app/lib/lib"; import type { RootState } from '@/app/store/store'; -import { useCallback } from 'react'; +import React, { useCallback } from 'react'; interface DocsLogData { readonly word: string; @@ -19,22 +19,22 @@ interface WordLogData { readonly state: "approved" | "rejected"; } -type DocsLogDatas = DocsLogData[]; -type WordLogDatas = WordLogData[]; +type DocsLogArrayOfData = DocsLogData[]; +type WordLogArrayOfData = WordLogData[]; -export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, CompleWork }: { +export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, CompWork }: { makeError: (error: PostgrestError) => void, setIsProcessing: React.Dispatch>, user: RootState['user'], - CompleWork: () => void, + CompWork: () => void, isProcessing: boolean }) => { - const WriteDocsLog = useCallback(async (logsData: DocsLogDatas) => { + const WriteDocsLog = useCallback(async (logsData: DocsLogArrayOfData) => { const { error: insertDocsLogDataError } = await SCM.add().docsLog(logsData); if (insertDocsLogDataError) { throw insertDocsLogDataError } }, []); - const WriteWordLog = useCallback(async (logsData: WordLogDatas) => { + const WriteWordLog = useCallback(async (logsData: WordLogArrayOfData) => { const { error: insertWordLogDataError } = await SCM.add().wordLog(logsData); if (insertWordLogDataError) { throw insertWordLogDataError } }, []); @@ -123,7 +123,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co if (deleteWaitWordDataError) return makeError(deleteWaitWordDataError); setIsProcessing(false); - CompleWork(); + CompWork(); } catch (error) { makeError(error as PostgrestError); setIsProcessing(false); @@ -155,7 +155,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co await WriteWordLog([insertWordLogData]); setIsProcessing(false); - CompleWork(); + CompWork(); return; }, []); @@ -233,7 +233,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co setIsProcessing(false); - CompleWork(); + CompWork(); return; }, []); @@ -262,7 +262,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co await WriteWordLog([insertWordLogData]); setIsProcessing(false); - CompleWork(); + CompWork(); return; }, []); @@ -281,7 +281,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co if (deleteWaitWordDataError) { return makeError(deleteWaitWordDataError); } setIsProcessing(false); - CompleWork(); + CompWork(); return; }, []); @@ -300,7 +300,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co if (deleteWaitWordDataError) { return makeError(deleteWaitWordDataError); } setIsProcessing(false); - CompleWork(); + CompWork(); return; }, []); @@ -374,7 +374,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co } setIsProcessing(false); - CompleWork(); + CompWork(); return; }, []); @@ -405,7 +405,7 @@ export const useWorkFunc = ({ makeError, setIsProcessing, user, isProcessing, Co if (!insertWaitWordDataA) return; setIsProcessing(false); - CompleWork(); + CompWork(); return; }, []); diff --git a/app/words-docs/[id]/logs/DocsLogPage.tsx b/app/words-docs/[id]/logs/DocsLogPage.tsx index 4bb5152..4a5163e 100644 --- a/app/words-docs/[id]/logs/DocsLogPage.tsx +++ b/app/words-docs/[id]/logs/DocsLogPage.tsx @@ -18,10 +18,10 @@ type log = { export default function DocsLogPage({id}:{id: number}){ const [isNotFound,setIsNotFound] = useState(false); const [errorMessage,setErrorMessage] = useState(null); - const [logsData, setLogsDatas] = useState<{logs:log[], docsName: string}|null>(null); + const [logsData, setLogsData] = useState<{logs:log[], docsName: string}|null>(null); const { loadingState, updateLoadingState } = useLoadingState(); - const hanldeError = (error: PostgrestError) => { + const handleError = (error: PostgrestError) => { setErrorMessage(`문서 정보 데이터 로드중 오류.\nErrorName: ${error.name ?? "알수없음"}\nError Message: ${error.message ?? "없음"}\nError code: ${error.code}`); updateLoadingState(100,"ERR"); } @@ -32,12 +32,12 @@ export default function DocsLogPage({id}:{id: number}){ // 문서 정보 가져오기 const {data: docsData, error: docsDataError} = await SCM.get().docsInfoByDocsId(id); if (docsData === null) return setIsNotFound(true); - if (docsDataError){ return hanldeError(docsDataError); } + if (docsDataError){ return handleError(docsDataError); } updateLoadingState(40,"로그 가져오는 중..."); // 문서 로그 가져오기 const {data: logData, error: logDataError} = await SCM.get().docsLogs(id); - if (logDataError){ return hanldeError(logDataError); } + if (logDataError){ return handleError(logDataError); } updateLoadingState(90,"데이터 가공중..."); const logsData = logData?.map((log) => ({ @@ -48,7 +48,7 @@ export default function DocsLogPage({id}:{id: number}){ type: log.type, })); - setLogsDatas({logs:logsData ?? [], docsName: docsData?.name}); + setLogsData({logs:logsData ?? [], docsName: docsData?.name}); updateLoadingState(100,"완료!"); } getData() diff --git a/app/words-docs/[id]/page.tsx b/app/words-docs/[id]/page.tsx index 305653b..9075a9c 100644 --- a/app/words-docs/[id]/page.tsx +++ b/app/words-docs/[id]/page.tsx @@ -21,8 +21,7 @@ const DocsDataHomePage = async ({ params }: { params: Promise<{ id: string }> }) const {id} = await params; const nid = Number(id) - if (isNaN(nid)) return - return + return isNaN(nid) ? : } From 105519582cef6fabf4e7b5b4943a735f72d4dc89 Mon Sep 17 00:00:00 2001 From: AS7AR Date: Sun, 4 Jan 2026 22:12:32 +0900 Subject: [PATCH 08/12] fix: --- app/api/words/search/route.ts | 2 +- app/header.tsx | 2 +- app/openapi/word/page.tsx | 2 +- app/word/page.tsx | 10 +++++++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/app/api/words/search/route.ts b/app/api/words/search/route.ts index 7446279..7b29461 100644 --- a/app/api/words/search/route.ts +++ b/app/api/words/search/route.ts @@ -71,7 +71,7 @@ export async function GET(request: NextRequest) { limit: isNaN(displayLimit) ? 100 : displayLimit }; } else if (gameMode === 'jaqi') { - if (!themeId) return handleErrorResponse('테마 ID가 필요합니다.'); + if (!themeId) return handleErrorResponse('주제 ID가 필요합니다.'); searchOptions = { mode: 'jaqi', query: searchQuery.trim(), diff --git a/app/header.tsx b/app/header.tsx index 9a9678f..6810fb1 100644 --- a/app/header.tsx +++ b/app/header.tsx @@ -75,7 +75,7 @@ const Header = () => { { href: "/manager-tool", label: "단어장 관리 도구", match: p => p.includes("/manager-tool") }, { href: "/words-docs", label: "단어장 공유", match: p => p.includes("/words-docs") }, { href: "/word", label: "오픈DB", match: p => p === "/word" || p.includes("/word/") }, - { href: "/openapi", label: "오픈API", match: p => p=== "/openapi" || p.includes("/openapi") }, + // { href: "/openapi", label: "오픈API", match: p => p=== "/openapi" || p.includes("/openapi") }, ]; const activeIndex = navDefs.findIndex(item => item.match(pathname)); diff --git a/app/openapi/word/page.tsx b/app/openapi/word/page.tsx index 294be06..764a267 100644 --- a/app/openapi/word/page.tsx +++ b/app/openapi/word/page.tsx @@ -38,7 +38,7 @@ export default function OpenApiDocsPage() { { parameterName: "maxLength", type: "number", description: "최대 글자 수", defaultValue: "100" }, { parameterName: "duem", type: "boolean", description: "두음법칙 적용 여부", defaultValue: "true" }, { parameterName: "mission", type: "string", description: "포함해야 할 특정 글자", defaultValue: '""' }, - { parameterName: "themeId", type: "number", description: "jaqi 모드 사용 시 필수 테마 Id", defaultValue: "-" }, + { parameterName: "themeId", type: "number", description: "자음 퀴즈 모드 사용 시 필수 테마 Id", defaultValue: "-" }, ]; return ( diff --git a/app/word/page.tsx b/app/word/page.tsx index 4e1b2bb..f008c07 100644 --- a/app/word/page.tsx +++ b/app/word/page.tsx @@ -1,5 +1,5 @@ import Link from "next/link"; -import {BarChart3, ChevronRight, Clock, Database, Download, FileText, Plus, Search, Upload} from "lucide-react"; +import {BarChart3, ChevronRight, Clock, Code, Database, Download, FileText, Plus, Search, Upload} from "lucide-react"; export async function generateMetadata() { return { @@ -73,6 +73,14 @@ const features = [ color: "from-indigo-500 to-blue-500", bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" }, + { + title: "오픈 API", + description: "끄코 유틸을 API에서 만나보세요", + link: "/openapi/word", + icon: Code, + color: "from-indigo-500 to-yellow-500", + bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" + }, ]; export default function OpenDBHomePage() { From e8a2f2e17942885fdc9e25353399aed33d8856fd Mon Sep 17 00:00:00 2001 From: AS7AR Date: Sat, 10 Jan 2026 18:19:32 +0900 Subject: [PATCH 09/12] fix: lint Error --- app/manager-tool/arrange/HelpModal.tsx | 2 +- app/words-docs/[id]/DocsDataHome.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/manager-tool/arrange/HelpModal.tsx b/app/manager-tool/arrange/HelpModal.tsx index 8426dff..0847d3b 100644 --- a/app/manager-tool/arrange/HelpModal.tsx +++ b/app/manager-tool/arrange/HelpModal.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef } from 'react'; import HelpModal from '@/app/components/HelpModal'; -interface HelpModalprop { +interface HelpModalProp { wantGo?: 1 | 2 | 3 | 4 | 5; } diff --git a/app/words-docs/[id]/DocsDataHome.tsx b/app/words-docs/[id]/DocsDataHome.tsx index 083e8e8..72cfbf4 100644 --- a/app/words-docs/[id]/DocsDataHome.tsx +++ b/app/words-docs/[id]/DocsDataHome.tsx @@ -58,7 +58,7 @@ const DocsDataHome = ({ id, data, metaData, starCount, isSpecial }: DocsPageProp const specialIds = [208, 223, 238]; const [isUserStarreda, setIsUserStarreda] = useState(false); const [loginNeedModalOpen, setLoginNeedModalOpen] = useState(false); - const [errorModalView, seterrorModalView] = useState(null); + const [errorModalView, setErrorModalView] = useState(null); const [charLastUpdates, setCharLastUpdates] = useState>({}); // 유저 즐겨찾기 상태 업데이트 @@ -350,7 +350,7 @@ const DocsDataHome = ({ id, data, metaData, starCount, isSpecial }: DocsPageProp ? "bg-yellow-400 text-yellow-900 hover:bg-yellow-300" : "bg-white/20 text-white hover:bg-white/30 backdrop-blur-sm" }`} - onClick={hadnleDocsStar} + onClick={handleDocsStar} > Date: Sat, 10 Jan 2026 18:22:03 +0900 Subject: [PATCH 10/12] fix: openapi link path --- app/word/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/word/page.tsx b/app/word/page.tsx index f008c07..289355f 100644 --- a/app/word/page.tsx +++ b/app/word/page.tsx @@ -76,7 +76,7 @@ const features = [ { title: "오픈 API", description: "끄코 유틸을 API에서 만나보세요", - link: "/openapi/word", + link: "/openapi/", icon: Code, color: "from-indigo-500 to-yellow-500", bgColor: "group-hover:bg-indigo-50 dark:group-hover:bg-indigo-950/20" From 6e6576970c06ff37ae2aa4e05eb26762fb98bc5d Mon Sep 17 00:00:00 2001 From: AS7AR Date: Sun, 11 Jan 2026 17:20:36 +0900 Subject: [PATCH 11/12] fix: k_CanUse to k_canuse --- app/lib/supabase/ISupabaseClientManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/supabase/ISupabaseClientManager.ts b/app/lib/supabase/ISupabaseClientManager.ts index eda8c4c..8f7801e 100644 --- a/app/lib/supabase/ISupabaseClientManager.ts +++ b/app/lib/supabase/ISupabaseClientManager.ts @@ -59,7 +59,7 @@ export interface IGetManager{ docsWords({ name, duem, typez }: { name: string; duem: boolean; typez: "letter" | "theme";} | {name: number; duem: boolean; typez: "ect";}): Promise<{data: null, error: PostgrestError} | {data: {words: okWord[], waitWords: ({ word: string; request_type: "add" | "delete"; requested_by: string | null; })[]}, error: null}> allWaitWords(c?:"add" | "delete"): Promise>; wordsThemes(wordIds: number[]): Promise> - allWords({ includeAddReq, includeDeleteReq, includeInjung, includeNoInjung, onlyWordChain, lenf }: { includeAddReq?: boolean; includeDeleteReq?: boolean; includeInjung?: boolean; includeNoInjung?: boolean; onlyWordChain?: boolean; lenf?: boolean; }): Promise<{ data: { word: string; noin_canuse: boolean; k_CanUse: boolean; status: "ok" | "add" | "delete"; }[]; error: null } | {data: null; error: PostgrestError; }> + allWords({ includeAddReq, includeDeleteReq, includeInjung, includeNoInjung, onlyWordChain, lenf }: { includeAddReq?: boolean; includeDeleteReq?: boolean; includeInjung?: boolean; includeNoInjung?: boolean; onlyWordChain?: boolean; lenf?: boolean; }): Promise<{ data: { word: string; noin_canuse: boolean; k_canuse: boolean; status: "ok" | "add" | "delete"; }[]; error: null } | {data: null; error: PostgrestError; }> letterDocs(): Promise>; addWaitDocs(): Promise>; releaseNote(): Promise>; From cef72b30fde685bdb11aa5a64c4a3ff781049eea Mon Sep 17 00:00:00 2001 From: JUNG TAEWON <153927840+hafskjfha@users.noreply.github.com> Date: Sun, 18 Jan 2026 18:35:04 +0900 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20=EC=B2=A0=EC=9E=90=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=88=84=EB=9D=BD=EB=90=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/manager-tool/arrange/ArrangeHome.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/manager-tool/arrange/ArrangeHome.tsx b/app/manager-tool/arrange/ArrangeHome.tsx index e0ea7bb..d5425ed 100644 --- a/app/manager-tool/arrange/ArrangeHome.tsx +++ b/app/manager-tool/arrange/ArrangeHome.tsx @@ -612,7 +612,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, setErrorModalVi setLineCount(updatedContent.split("\n").length); } catch (err) { if (err instanceof Error) { - seterrorModalView({ + setErrorModalView({ ErrName: err.name, ErrMessage: err.message, ErrStackRace: err.stack, @@ -620,7 +620,7 @@ const ToolSector = ({ fileContent, setFileContent, setLineCount, setErrorModalVi }); } else { - seterrorModalView({ + setErrorModalView({ ErrName: null, ErrMessage: null, ErrStackRace: err as string,