From fd4801619f08f25823b17798d8708cd2d0818648 Mon Sep 17 00:00:00 2001 From: sharevb Date: Sat, 1 Jun 2024 18:28:51 +0200 Subject: [PATCH 1/4] feat(new tool): File Hasher Fix #528 --- components.d.ts | 10 +- package.json | 3 +- pnpm-lock.yaml | 24 ++- src/composable/queryParams.ts | 31 +++- src/tools/file-hasher/file-hasher.vue | 227 ++++++++++++++++++++++++++ src/tools/file-hasher/index.ts | 38 +++++ src/tools/index.ts | 16 +- 7 files changed, 331 insertions(+), 18 deletions(-) create mode 100644 src/tools/file-hasher/file-hasher.vue create mode 100644 src/tools/file-hasher/index.ts diff --git a/components.d.ts b/components.d.ts index f2c3146f..f5189565 100644 --- a/components.d.ts +++ b/components.d.ts @@ -78,6 +78,7 @@ declare module '@vue/runtime-core' { Encryption: typeof import('./src/tools/encryption/encryption.vue')['default'] EtaCalculator: typeof import('./src/tools/eta-calculator/eta-calculator.vue')['default'] FavoriteButton: typeof import('./src/components/FavoriteButton.vue')['default'] + FileHasher: typeof import('./src/tools/file-hasher/file-hasher.vue')['default'] FormatTransformer: typeof import('./src/components/FormatTransformer.vue')['default'] GitMemo: typeof import('./src/tools/git-memo/git-memo.vue')['default'] 'GitMemo.content': typeof import('./src/tools/git-memo/git-memo.content.md')['default'] @@ -127,23 +128,18 @@ declare module '@vue/runtime-core' { MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] - NCode: typeof import('naive-ui')['NCode'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NDivider: typeof import('naive-ui')['NDivider'] NEllipsis: typeof import('naive-ui')['NEllipsis'] - NFormItem: typeof import('naive-ui')['NFormItem'] - NGi: typeof import('naive-ui')['NGi'] - NGrid: typeof import('naive-ui')['NGrid'] NH1: typeof import('naive-ui')['NH1'] NH3: typeof import('naive-ui')['NH3'] NIcon: typeof import('naive-ui')['NIcon'] - NInputNumber: typeof import('naive-ui')['NInputNumber'] - NLabel: typeof import('naive-ui')['NLabel'] + NInputGroup: typeof import('naive-ui')['NInputGroup'] + NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel'] NLayout: typeof import('naive-ui')['NLayout'] NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NMenu: typeof import('naive-ui')['NMenu'] - NScrollbar: typeof import('naive-ui')['NScrollbar'] NSpin: typeof import('naive-ui')['NSpin'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] diff --git a/package.json b/package.json index c6cb7757..b8d9671f 100644 --- a/package.json +++ b/package.json @@ -61,10 +61,11 @@ "figlet": "^1.7.0", "figue": "^1.2.0", "fuse.js": "^6.6.2", + "hash-wasm": "^4.11.0", "highlight.js": "^11.7.0", "iarna-toml-esm": "^3.0.5", "ibantools": "^4.3.3", - "js-base64": "^3.7.6", + "js-base64": "^3.7.7", "json5": "^2.2.3", "jwt-decode": "^3.1.2", "libphonenumber-js": "^1.10.28", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8619d8c0..8656c349 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -83,6 +83,9 @@ dependencies: fuse.js: specifier: ^6.6.2 version: 6.6.2 + hash-wasm: + specifier: ^4.11.0 + version: 4.11.0 highlight.js: specifier: ^11.7.0 version: 11.7.0 @@ -93,7 +96,7 @@ dependencies: specifier: ^4.3.3 version: 4.3.3 js-base64: - specifier: ^3.7.6 + specifier: ^3.7.7 version: 3.7.7 json5: specifier: ^2.2.3 @@ -3354,7 +3357,7 @@ packages: dependencies: '@unhead/dom': 0.5.1 '@unhead/schema': 0.5.1 - '@vueuse/shared': 10.8.0(vue@3.3.4) + '@vueuse/shared': 10.10.0(vue@3.3.4) unhead: 0.5.1 vue: 3.3.4 transitivePeerDependencies: @@ -3987,19 +3990,19 @@ packages: - vue dev: false - /@vueuse/shared@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} + /@vueuse/shared@10.10.0(vue@3.3.4): + resolution: {integrity: sha512-2aW33Ac0Uk0U+9yo3Ypg9s5KcR42cuehRWl7vnUHadQyFvCktseyxxEPBi1Eiq4D2yBGACOnqLZpx1eMc7g5Og==} dependencies: - vue-demi: 0.14.5(vue@3.3.4) + vue-demi: 0.14.7(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue dev: false - /@vueuse/shared@10.8.0(vue@3.3.4): - resolution: {integrity: sha512-dUdy6zwHhULGxmr9YUg8e+EnB39gcM4Fe2oKBSrh3cOsV30JcMPtsyuspgFCUo5xxFNaeMf/W2yyKfST7Bg8oQ==} + /@vueuse/shared@10.3.0(vue@3.3.4): + resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} dependencies: - vue-demi: 0.14.7(vue@3.3.4) + vue-demi: 0.14.5(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -5972,6 +5975,10 @@ packages: function-bind: 1.1.2 dev: true + /hash-wasm@4.11.0: + resolution: {integrity: sha512-HVusNXlVqHe0fzIzdQOGolnFN6mX/fqcrSAOcTBXdvzrXVHwTz11vXeKRmkR5gTuwVpvHZEIyKoePDvuAR+XwQ==} + dev: false + /hasown@2.0.0: resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} engines: {node: '>= 0.4'} @@ -9449,6 +9456,7 @@ packages: /workbox-google-analytics@7.0.0: resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained dependencies: workbox-background-sync: 7.0.0 workbox-core: 7.0.0 diff --git a/src/composable/queryParams.ts b/src/composable/queryParams.ts index 9699abbc..9e184610 100644 --- a/src/composable/queryParams.ts +++ b/src/composable/queryParams.ts @@ -1,7 +1,8 @@ import { useRouteQuery } from '@vueuse/router'; import { computed } from 'vue'; +import { useStorage } from '@vueuse/core'; -export { useQueryParam }; +export { useQueryParam, useQueryParamOrStorage }; const transformers = { number: { @@ -33,3 +34,31 @@ function useQueryParam({ name, defaultValue }: { name: string; defaultValue: }, }); } + +function useQueryParamOrStorage({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue?: T }) { + const type = typeof defaultValue; + const transformer = transformers[type as keyof typeof transformers] ?? transformers.string; + + const storageRef = useStorage(storageName, defaultValue); + const storageDefaultValue = storageRef.value ?? defaultValue; + + const proxy = useRouteQuery(name, transformer.toQuery(storageDefaultValue as never)); + + const ref = computed({ + get() { + return transformer.fromQuery(proxy.value) as unknown as T; + }, + set(value) { + proxy.value = transformer.toQuery(value as never); + }, + }); + + watch( + ref, + (newValue) => { + storageRef.value = newValue; + }, + ); + + return ref; +} diff --git a/src/tools/file-hasher/file-hasher.vue b/src/tools/file-hasher/file-hasher.vue new file mode 100644 index 00000000..bea24fb8 --- /dev/null +++ b/src/tools/file-hasher/file-hasher.vue @@ -0,0 +1,227 @@ + + + diff --git a/src/tools/file-hasher/index.ts b/src/tools/file-hasher/index.ts new file mode 100644 index 00000000..501087f2 --- /dev/null +++ b/src/tools/file-hasher/index.ts @@ -0,0 +1,38 @@ +import { EyeOff } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'File Hasher', + path: '/file-hasher', + description: 'Compute Hash of files', + keywords: ['file', 'hash', + 'digest', + 'crypto', + 'security', + 'text', + 'MD5', + 'SHA1', + 'SHA256', + 'SHA224', + 'SHA512', + 'SHA384', + 'SHA3', + 'RIPEMD160', + 'ADLER32', + 'BLAKE2B', + 'BLAKE2S', + 'BLAKE3', + 'CRC32', + 'CRC32C', + 'KECCAK', + 'PBKDF2', + 'SM3', + 'WHIRLPOOL', + 'XXHASH128', + 'XXHASH3', + 'XXHASH32', + 'XXHASH64'], + component: () => import('./file-hasher.vue'), + icon: EyeOff, + createdAt: new Date('2024-05-11'), +}); diff --git a/src/tools/index.ts b/src/tools/index.ts index aa861c93..52fd6217 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -1,6 +1,7 @@ import { tool as base64FileConverter } from './base64-file-converter'; import { tool as base64StringConverter } from './base64-string-converter'; import { tool as basicAuthGenerator } from './basic-auth-generator'; +import { tool as fileHasher } from './file-hasher'; import { tool as asciiTextDrawer } from './ascii-text-drawer'; @@ -85,7 +86,20 @@ import { tool as yamlViewer } from './yaml-viewer'; export const toolsByCategory: ToolCategory[] = [ { name: 'Crypto', - components: [tokenGenerator, hashText, bcrypt, uuidGenerator, ulidGenerator, cypher, bip39, hmacGenerator, rsaKeyPairGenerator, passwordStrengthAnalyser, pdfSignatureChecker], + components: [ + tokenGenerator, + hashText, + fileHasher, + bcrypt, + uuidGenerator, + ulidGenerator, + cypher, + bip39, + hmacGenerator, + rsaKeyPairGenerator, + passwordStrengthAnalyser, + pdfSignatureChecker, + ], }, { name: 'Converter', From 7e9613d11ea5f77dcb926a0a9e7edd2b490e4d13 Mon Sep 17 00:00:00 2001 From: ShareVB Date: Sun, 9 Jun 2024 12:32:10 +0200 Subject: [PATCH 2/4] chore: fix strange corepack message Fix corepack claiming strange thing : UsageError: This project is configured to use yarn because /home/runner/work/it-tools/it-tools/package.json has a "packageManager" field --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index b8d9671f..9a916fc6 100644 --- a/package.json +++ b/package.json @@ -139,5 +139,6 @@ "vitest": "^0.34.0", "workbox-window": "^7.0.0", "zx": "^7.2.1" - } + }, + "packageManager": "pnpm@8.15.3" } From a0c51c9f68ea067e2aca2cb1beb854aa1d39949f Mon Sep 17 00:00:00 2001 From: ShareVB Date: Sun, 9 Jun 2024 12:42:45 +0200 Subject: [PATCH 3/4] fix: inverted done state --- src/tools/file-hasher/file-hasher.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/file-hasher/file-hasher.vue b/src/tools/file-hasher/file-hasher.vue index bea24fb8..04efcf20 100644 --- a/src/tools/file-hasher/file-hasher.vue +++ b/src/tools/file-hasher/file-hasher.vue @@ -135,9 +135,8 @@ async function onUpload(uploadedFile: File) { status.value = 'processing'; try { - status.value = 'done'; - hashes.value = await hashFileAsync(uploadedFile); + status.value = 'done'; } catch (e) { status.value = 'error'; From 9b22ee00f4de74f3c911214d706507c39055a1d9 Mon Sep 17 00:00:00 2001 From: ShareVB Date: Sun, 14 Jul 2024 23:28:55 +0200 Subject: [PATCH 4/4] fix: update queryParams --- src/composable/queryParams.ts | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/composable/queryParams.ts b/src/composable/queryParams.ts index 9e184610..7cc8cc0d 100644 --- a/src/composable/queryParams.ts +++ b/src/composable/queryParams.ts @@ -17,6 +17,12 @@ const transformers = { fromQuery: (value: string) => value.toLowerCase() === 'true', toQuery: (value: boolean) => (value ? 'true' : 'false'), }, + object: { + fromQuery: (value: string) => { + return JSON.parse(value); + }, + toQuery: (value: object) => JSON.stringify(value), + }, }; function useQueryParam({ name, defaultValue }: { name: string; defaultValue: T }) { @@ -35,30 +41,26 @@ function useQueryParam({ name, defaultValue }: { name: string; defaultValue: }); } -function useQueryParamOrStorage({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue?: T }) { +function useQueryParamOrStorage({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue: T }) { const type = typeof defaultValue; const transformer = transformers[type as keyof typeof transformers] ?? transformers.string; const storageRef = useStorage(storageName, defaultValue); - const storageDefaultValue = storageRef.value ?? defaultValue; + const proxyDefaultValue = transformer.toQuery(defaultValue as never); + const proxy = useRouteQuery(name, proxyDefaultValue); - const proxy = useRouteQuery(name, transformer.toQuery(storageDefaultValue as never)); + const r = ref(defaultValue); - const ref = computed({ - get() { - return transformer.fromQuery(proxy.value) as unknown as T; - }, - set(value) { + watch(r, + (value) => { proxy.value = transformer.toQuery(value as never); + storageRef.value = value as never; }, - }); + { deep: true }); - watch( - ref, - (newValue) => { - storageRef.value = newValue; - }, - ); + r.value = (proxy.value && proxy.value !== proxyDefaultValue + ? transformer.fromQuery(proxy.value) as unknown as T + : storageRef.value as T) as never; - return ref; + return r; }