From e1b844cee0d4ee2919d98b43c4e719261ae8e213 Mon Sep 17 00:00:00 2001 From: Mazen Touati <14861869+sunchayn@users.noreply.github.com> Date: Sat, 17 Jan 2026 20:50:00 +0100 Subject: [PATCH] feat(history): add history viewer and rewind (#38) * feat(ui): add `input group` base component * feat(history): add history viewer and rewind * test: update selector snapshot * test: add PW base page * style: apply TS style fixes * chore(history): request history wiki * chore(history): remove unwanted symbol * chore: fix type * style: apply TS style fixes --- .gitattributes | 2 +- package-lock.json | 44 +-- package.json | 6 +- .../dropdown-menu/AppDropdownMenuLabel.vue | 2 +- .../base/input-group/AppInputGroup.vue | 34 ++ .../base/input-group/AppInputGroupAddon.vue | 40 ++ .../base/input-group/AppInputGroupButton.vue | 21 + .../base/input-group/AppInputGroupInput.vue | 33 ++ .../base/input-group/AppInputGroupText.vue | 21 + .../input-group/AppInputGroupTextarea.vue | 21 + .../js/components/base/input-group/index.ts | 59 +++ .../components/base/textarea/AppTextarea.vue | 33 ++ .../js/components/base/textarea/index.ts | 1 + .../KeyValueParameters/KeyValueParameters.vue | 33 +- .../RequestBody/RequestBodyFormData.vue | 39 +- .../domain/Client/Request/RequestBuilder.vue | 9 +- .../Request/RequestHeader/RequestHeaders.vue | 128 ------ .../Request/RequestHeaders/RequestHeaders.vue | 81 ++++ .../RequestParameters/RequestParameters.vue | 69 +--- .../components/domain/Client/Request/index.ts | 2 +- .../ResponseBody/ResponseDumpAndDie.vue | 14 + .../ResponseStatus/History/HistoryItem.vue | 93 +++++ .../ResponseStatus/History/RequestHistory.vue | 230 +++++++++++ .../ResponseStatus/ResponseStatus.vue | 33 +- .../js/composables/request/useHttpClient.ts | 29 +- .../js/composables/request/useRequestBody.ts | 86 +--- .../composables/ui/useKeyValueParameters.ts | 263 +++++-------- resources/js/interfaces/history/index.ts | 2 +- resources/js/interfaces/http/request.ts | 13 +- resources/js/interfaces/index.ts | 4 +- resources/js/interfaces/ui/index.ts | 7 +- .../js/interfaces/ui/key-value-parameters.ts | 19 +- .../stores/request/useRequestBuilderStore.ts | 70 +++- .../stores/request/useRequestExecutorStore.ts | 1 + .../js/stores/request/useRequestStore.ts | 1 + .../stores/request/useRequestsHistoryStore.ts | 21 +- .../tests/components/RequestHeaders.test.ts | 93 ++--- .../Client/Request/RequestBuilder.test.ts | 10 +- .../ResponseBody/ResponseDumpAndDie.test.ts | 30 ++ .../History/HistoryItem.test.ts | 66 ++++ .../History/RequestHistory.test.ts | 221 +++++++++++ .../ResponseStatus/ResponseStatus.test.ts | 142 +++++-- .../tests/composables/useHttpClient.test.ts | 102 ++++- .../composables/useKeyValueParameters.test.ts | 349 ++++++++-------- .../tests/composables/useRequestBody.test.ts | 16 +- .../stores/useRequestBuilderStore.test.ts | 149 ++++++- .../js/tests/stores/useRequestStore.test.ts | 19 +- .../stores/useRequestsHistoryStore.test.ts | 40 +- .../content-type-header-generator.test.ts | 162 ++++++++ .../tests/utils/generateCurlCommand.test.ts | 19 +- .../request/content-type-header-generator.ts | 121 ++++++ resources/js/utils/request/curl-generator.ts | 32 +- .../js/utils/request/request-url-builder.ts | 6 +- resources/js/utils/request/request-utils.ts | 12 +- tests/E2E/pages/BasePage.ts | 111 ++++++ tests/E2E/tests/dd.spec.ts | 2 +- tests/E2E/tests/fixtures.ts | 12 + tests/E2E/tests/history.spec.ts | 372 ++++++++++++++++++ tools/eslint/.eslintrc.cjs | 2 +- resources/tsconfig.json => tsconfig.json | 17 +- vite.config.js | 4 +- wiki/user-guide/README.md | 23 ++ wiki/user-guide/assets/history-viewer.png | Bin 0 -> 258665 bytes 63 files changed, 2804 insertions(+), 892 deletions(-) create mode 100644 resources/js/components/base/input-group/AppInputGroup.vue create mode 100644 resources/js/components/base/input-group/AppInputGroupAddon.vue create mode 100644 resources/js/components/base/input-group/AppInputGroupButton.vue create mode 100644 resources/js/components/base/input-group/AppInputGroupInput.vue create mode 100644 resources/js/components/base/input-group/AppInputGroupText.vue create mode 100644 resources/js/components/base/input-group/AppInputGroupTextarea.vue create mode 100644 resources/js/components/base/input-group/index.ts create mode 100644 resources/js/components/base/textarea/AppTextarea.vue create mode 100644 resources/js/components/base/textarea/index.ts delete mode 100644 resources/js/components/domain/Client/Request/RequestHeader/RequestHeaders.vue create mode 100644 resources/js/components/domain/Client/Request/RequestHeaders/RequestHeaders.vue create mode 100644 resources/js/components/domain/Client/Response/ResponseStatus/History/HistoryItem.vue create mode 100644 resources/js/components/domain/Client/Response/ResponseStatus/History/RequestHistory.vue create mode 100644 resources/js/tests/components/domain/Client/Response/ResponseStatus/History/HistoryItem.test.ts create mode 100644 resources/js/tests/components/domain/Client/Response/ResponseStatus/History/RequestHistory.test.ts create mode 100644 resources/js/tests/utils/content-type-header-generator.test.ts create mode 100644 resources/js/utils/request/content-type-header-generator.ts create mode 100644 tests/E2E/pages/BasePage.ts create mode 100644 tests/E2E/tests/fixtures.ts create mode 100644 tests/E2E/tests/history.spec.ts rename resources/tsconfig.json => tsconfig.json (60%) create mode 100644 wiki/user-guide/assets/history-viewer.png diff --git a/.gitattributes b/.gitattributes index c35172c..8d5c7dc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -20,7 +20,7 @@ /vendor export-ignore /vite.config.js export-ignore /components.json export-ignore -/resources/tsconfig.json export-ignore +/tsconfig.json export-ignore /package.json export-ignore /package-lock.json export-ignore /CONTRIBUTING.md export-ignore diff --git a/package-lock.json b/package-lock.json index 068ca63..10c60d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,6 @@ { "name": "nimbus", + "version": "0.3.0-alpha", "lockfileVersion": 3, "requires": true, "packages": { @@ -19,7 +20,7 @@ "pinia-plugin-persistedstate": "^4.7.1", "pretty-bytes": "^7.0.1", "pretty-ms": "^9.3.0", - "reka-ui": "^2.5.0", + "reka-ui": "^2.7.0", "tw-animate-css": "^1.3.8", "vee-validate": "^4.15.0", "vue-codemirror": "^6.1.1", @@ -275,7 +276,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.3.tgz", "integrity": "sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", @@ -290,7 +290,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.0.tgz", "integrity": "sha512-wZxW+9XDytH3SKvS8cQzMyQCaaazH8XL1EMHleHe00wVzsv7NBQKVW2yzEHrRhmM7ZOhVdItPbvlRBvMp9ej7A==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", @@ -313,7 +312,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", "license": "MIT", - "peer": true, "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } @@ -323,7 +321,6 @@ "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.6.tgz", "integrity": "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", @@ -419,7 +416,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -466,7 +462,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -1291,8 +1286,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@lezer/highlight": { "version": "1.2.1", @@ -2372,7 +2366,6 @@ "integrity": "sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -2425,7 +2418,6 @@ "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/types": "8.46.1", @@ -2785,7 +2777,6 @@ "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "3.2.4", "fflate": "^0.8.2", @@ -2880,7 +2871,6 @@ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz", "integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.28.4", "@vue/compiler-core": "3.5.22", @@ -3046,7 +3036,6 @@ "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -3386,7 +3375,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3990,7 +3978,6 @@ "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", "license": "MIT", - "peer": true, "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", @@ -4882,7 +4869,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -4939,7 +4925,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5128,7 +5113,6 @@ "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "globals": "^13.24.0", @@ -7992,7 +7976,6 @@ "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz", "integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==", "license": "MIT", - "peer": true, "dependencies": { "@vue/devtools-api": "^7.7.2" }, @@ -8110,7 +8093,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -8150,7 +8132,6 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -8180,7 +8161,6 @@ "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "prettier": ">=2.0", "typescript": ">=2.9", @@ -8650,9 +8630,9 @@ } }, "node_modules/reka-ui": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.5.1.tgz", - "integrity": "sha512-QJGB3q21wQ1Kw28HhhNDpjfFe8qpePX1gK4FTBRd68XTh9aEnhR5bTJnlV0jxi8FBPh0xivZBeNFUc3jiGx7mQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.7.0.tgz", + "integrity": "sha512-m+XmxQN2xtFzBP3OAdIafKq7C8OETo2fqfxcIIxYmNN2Ch3r5oAf6yEYCIJg5tL/yJU2mHqF70dCCekUkrAnXA==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.6.13", @@ -9575,8 +9555,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.14.tgz", "integrity": "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tailwindcss-animate": { "version": "1.0.7", @@ -9696,7 +9675,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9986,7 +9964,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10176,7 +10153,6 @@ "integrity": "sha512-oLnWs9Hak/LOlKjeSpOwD6JMks8BeICEdYMJBf6P4Lac/pO9tKiv/XhXnAM7nNfSkZahjlCZu9sS50zL8fSnsw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -10304,7 +10280,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -10318,7 +10293,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -10411,7 +10385,6 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.22", "@vue/compiler-sfc": "3.5.22", @@ -10574,7 +10547,6 @@ "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@volar/typescript": "2.4.15", "@vue/language-core": "2.2.12" @@ -11043,4 +11015,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index bc576c5..536e1c1 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "style:check": "eslint --config tools/eslint/.eslintrc.cjs --ignore-path tools/eslint/.eslintignore resources/js --ext .js,.ts,.vue", "style:fix": "npm run style:check -- --fix", - "type:check": "vue-tsc --noEmit --project ./resources/tsconfig.json", + "type:check": "vue-tsc --noEmit --project tsconfig.json", "vite": "vite --config vite.config.js", "build": "npm run type:check && npm run vite -- build && cp -a ./resources/dist-static/. ./resources/dist", "build:dev": "npm run vite -- build --mode=development && cp -a ./resources/dist-static/. ./resources/dist", @@ -77,10 +77,10 @@ "pinia-plugin-persistedstate": "^4.7.1", "pretty-bytes": "^7.0.1", "pretty-ms": "^9.3.0", - "reka-ui": "^2.5.0", + "reka-ui": "^2.7.0", "tw-animate-css": "^1.3.8", "vee-validate": "^4.15.0", "vue-codemirror": "^6.1.1", "vue-sonner": "^2.0.8" } -} \ No newline at end of file +} diff --git a/resources/js/components/base/dropdown-menu/AppDropdownMenuLabel.vue b/resources/js/components/base/dropdown-menu/AppDropdownMenuLabel.vue index 2219156..7d8b183 100644 --- a/resources/js/components/base/dropdown-menu/AppDropdownMenuLabel.vue +++ b/resources/js/components/base/dropdown-menu/AppDropdownMenuLabel.vue @@ -22,7 +22,7 @@ const forwardedProps = useForwardProps(delegatedProps);