diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f86755a..6bd23e2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,13 +24,13 @@ jobs:
uses: actions/checkout@master
- name: Setup node env 🏗
- uses: actions/setup-node@v2.1.5
+ uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node }}
check-latest: true
- name: Cache node_modules 📦
- uses: actions/cache@v2.1.4
+ uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 287e9ad..dca9db5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -11,7 +11,7 @@ jobs:
name: create release on tag
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@master
# This action generates changelog which then the release action consumes
- name: Conventional Changelog Action
diff --git a/.gitignore b/.gitignore
index e8f682b..a222d1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,3 +88,6 @@ sw.*
# Vim swap files
*.swp
+
+# Vercel cli
+.vercel
diff --git a/README.md b/README.md
index 9606165..0d1842c 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,22 @@
A diff viewer that gives you sharable diff view links but does not store your data. (This takes inspiration from typescript playground how it stores your code in url itself) but the for very large data we will be doing end to end encryption just like `excalidraw` so you can still have sharable links without worrying if you should store your enterprise data or not.
+# Data Privacy and security
+
## :bangbang: No data sent to server
-You can take a look at the source code itself. All your data is kept as hash fragment in URL which never makes its way to server. Totally avoiding man in middle and XSS attacks to steal your data or any data breach. The data always stays in your URL and browser and never makes its way on the wire. Thats the main motive behind developing this tool. More about reasoning, why and how can be found in [Motivation](#motivation) section below.
+
+- You can take a look at the source code itself.
+- All your data is kept as hash fragment in URL which never makes its way to server. Totally avoiding man in middle and XSS attacks to steal your data or any data breach.
+- The data always stays in your URL and browser and never makes its way on the wire. Thats the main motive behind developing this tool.
+- More about reasoning, why and how can be found in [Motivation](#motivation) section below.
+
+## End to End Encryption
+
+- If the calculated diff data is larger 10000 characters then your data is first encrypted on browser and the encrypted data is stored on server.
+- The key to decrypt the data is added as hash fragment in the url, also each diff view is encrypted with different key
+- Every diff view is assigned cryptographically strong unique identifier making it impossible to guess diff view identifiers for hackers
+- The data is always decrypted in browser cause the hash fragement is never sent to server by browsers, so server has no way to decrypt the data
+- even if someone gets hold of your data using man in middle attack they cannot decrypt it as decryption key is available only in browser.
# Formats currently supported
@@ -14,7 +28,7 @@ You can take a look at the source code itself. All your data is kept as hash fra
1. Images
2. Audio wave format
-## Resoning for building yet another diff viewer tool
+## Reason for building yet another diff viewer tool
I realise we are missing a diff viewer that is
@@ -49,12 +63,14 @@ In the chase of one such tool I ended up creating one as I did not find any that
This is open source and has very easy user interface. Here is the link to the tool https://diffviewer.vercel.app/
It has following benefits
-1. Since the tool does not store your data on its server there is no server required in the tool
+1. Since the tool does not always store your data on its server there is no server required in the tool
2. The tool is blazing fast
3. Most importantly the link can be shared with anyone without security concerns(Unless you share link itself over some insecure network)
4. As the link contains data whomever you share link with can get data too
-5. Also note that the data is put with hash in url so server can not read the data
+5. Also note that the data is put with hash in url so server can not read the data or encryption key
+6. For very large data comparison take a look at [End to End Encryption](#end-to-end-encryption) section above
+[Here is sample e2e encryption link](https://diffviewer.vercel.app/v2/diff?id=permanent-42812281783313231307#9zgCeVnkruc3DPEKpEE8GQ)
[Here is a link to sample diff view](https://diffviewer.vercel.app/v2/diff#H4sIAAAAAAAAA61dXZPUuJL9KwQv-3LHUZLr8z6pu2GAaXqGoIkh5u5sbMi2ylaXbRX-6KL6xv3vq5SrGWDIYy_FA_PBKaASSamTmSdT_35aFu3Tfz797z_rJ0_-Tf948uTPpzb78-k_n4h_PP7_1jZt97-1rgz9_J9PX1tX__n0E1zqL9B3hWvcIXcu--wzptK2HPCy-_SBmUr3ujZlVJvusw_nps5MM3z6V1f_lNhaN8fPPmD3_6uzrDFtO3xILBZRPIvW80jIzZ9P6WP_-cc3TJKsSdeNbTu33dIfyxl241yh628btasCKJQ3Ky9N1PTn2CPnm0hsIhkvIzkD9sTYHs3bclXo7GA4Y9IBlSrpHx62xmRR6irGoEv7-H_88qzjSJBJC7IHLdCcNehlX28bkznepMvS6DbTpfm2UUXyiMeqcg-2LHXkmpyx6mLUqJVfn1kkF_GISQvWpJu-afSRN-iZX8PUleW37amyEzxX-8bW3bax_iuXR7BUP_tf_sVfz99sEv4AiUiuIhGvgE1L1qbfdVkik8yTG1vb1H3bpvvMVAFeKLPXUe7uGUtehP_elr3N0L4T62gWiaWMNjGwZsVa80InieWteX_s_ElpGD-XH07wUu3bPjIZ5xImnCBvwnztF8Wvz2YNTFmzprwr9McOejdbtp3RjDFddYJXKvM_eaxc5y8BsNeGFfrQG-wZlt5rb6K5d9yrObBrw9r13pSJNcDR6caVtmacwiE9wWu117n_d279BjaRPe86ms-iVVgwuQRGiRlr1VvTJwbcsRe1_-MOuukK_W3DGv3XJzaqK0xlts5_ww5ctW9ceRz35Svvyxdz8hExWjHB04cbbVtIIBpbJUfG63UB1KrSR5eW5CzO3oTeGu8l5jLCq8WThxvdpMBN_GLqurFpwVh0d4ITZdMPwJhpW8-78NUiCqu0kcgcnjv8yzW6AI5Cpxdtqm3GGPRQ6VQPH0hVYZP-nBtJ0B0bb8gmKQSyh6cOF5kpgYe4LUxz5ByEbgc0U9suBRfSBB8uZ2tPFebRxpsyh0eHpww_W1NmLVyb3633ad82ZutX5p5go2yRn8npPP9ZLSOxHuMKgicLz_wVAhbmvU137bctyQ6EbZU3AZgxzaF5P72mu5WMQTRBAJ7Q6BTdQZ7mUdDDbbI8_fSBXDXm3jRJrUfu19GTI-fLiPg2cQa423jO8NrcIz99XRpbt1Vfdw9MpLf76xOF6lvduUwjgjqN1kkhKc7z15CMltA0njbc6qQB4dF7f1OWhrmD2sOA2sdgj3ZhsTvjLMVxtPTnaOljCYmctuQZwztXVeAOunJVwoV7XRrAO6Ur_RA2XdRz1kwLXxci2syIImyQy5Y8RbimswDiiDf0hx0MFxvt9o_4ThX7c-_UpbfGu24fF8WIe0ueIFyUFvmHF7pmN5vOA1iq0nuEyrTAmPGYdR5ojljMRpip5MnBC6trcHBudbP1X5Txc-2AVqrtm3vjg4h6Z5A_uBkhB0vvBDzXFqt1tEGOQPLk4NpvEsS0rwofFTTM4uzSAa1VYvPSJcaz6-huf9Z1tFhEfo2Ivy3RtSp5knDb6cbbBDbcS308sHFrWwyoU52tj3tIsMf528wfG7EMQfiIQTxP-MNfQ8icy1LvTMms0TEZ0L3KnP_ZutLNznRnHSPvDfzlKhaUpIPHiGcMF2SCsSAeDxm8fmt2jF_YPeIfVGbazNxHaX3WxltJymRFdBktkFGILxxA6sf_3XeNYShQmZ3gRpkkcAT-DpoW1Ul_ijytE_MohmvEc4SfLfJ0l7osdPVta7ZJAFvVGk_kDIgbpgV1dIDm8xAICRg6xDxBeG_rDNyoF54PVZZhCAc9oN0p-eP_AVdo3C3EfmmWnqB6gwRanpjnCG8NcAlXugH8oElPcK_SCqXmpm01Ch02xN3ikSA1BjkE1-ToHro21d57ZjYbvHvE7ymTZdq9aVr3k4_k69xE2wbaN0q4Kd8TU0bBGypRjBTzxOGt6-8tSmnl_qQw4V6jA3hQOv3Q28Z0hW3pV57lxSmEkLNF5P0ePlM8eaAqCm_R62OdOeZEpWUAPyqduP7M20iEhFz4F3LcMc8YnnlSh3zdW5ebhjMlawb0OKVaNMnfrXzYKmbhTIklPE88Z_AkqEaViNuCzXW3LWEPPhwySel4PjfNOSyjlfcMwm8zZAjPFK5sY8sS1L2ujc0LNn5IdydYzBT5gtL__ujcTMzbe4PoQppvIlT7inmu8EI3dscbdaO7Y2sZ7pNXAyqE6vemrs-rrYiFv1QXxE5H_ADPFC5dAosQL1yWuLL7tjVJPqBCKorwvj8cWqypliKpmLJEVeM5TxJe-y3SZijp80wfMi4c8iSOQBGrru86l9qu03wpZeLxkaFsTEZJ5N3mPFH4wxR99sXX-PoE6cZvoyNTSjnuTrCYTyykjIWtVGYVK0qRCIEyCnOeLrzRXWMfLOKnrm0dw0_3SQDFgjJY_pvpDOUVJqQa_fHxjG4ZR2t0guY8O3jp_wTvp4BDMKblbqCiCqBYqrYkun22d_MbTvi7Zx1toFiBJwY3xkdnLVidF96n2zqnIIEhdPlfnxAr1brcoULKpBCPtAp-34WMMArF5zxTuMgazxXAbfTSNY1N2IKrLh5xsVb7wnUu6VMcj09cs3hFNWS_bqSbgZ6CJw0vKbpBvs_1LScvyQIoNspzhpxKyuel6sTSe3Pv--J5tEYB0pxnDpcm3YGU8DNX66JnzEmyARVabd3H2hzOcxAxuTry5P5UreCZ4hnDM5vuwOK8a3qg_sm6EyySz7P2CRcYTUyZLEIRQlA2aAP3HM8drnWKMt3Py4rVnBnCRKpEX2ciysxZB2guhuXxxHuFLqUFUC24DIRD702S_HTpWNVZc_AfSAgX2SSqOuEQUdlYrkJea40CiQXPHt4VJtF9CejDM5d53sYqZ7ITLIyqvUP_fn7n_XZIm-CE1oInDX98mfP9W0Kr6Vxl-m-bcUxOsNgqv0xAOjfRXxNVFX7PzUhPAg3iWcMbksCRkg-4hUIzbHXfeUjkwV-fVwsnmeYi5LMELN8teMLw2vrvjTLclPNgDk6ZDKgo_h_5kYnSmA3VkOlaXaGIYsEThrcjodFtZQ7-VDAuoR1QYVXrKZ7WgHRPzArHC-J1lMlaIoe94EnCW5cWBu85k-mCSz12ARR3qm87z7yrqDtP5OiNCbLNGSWzkEWgGNFksFz0vE3ddmu_-Iv9nNOZR1zsVGbuPUHsvLM4NwtEvk7Eoe46Q1HFgqcM721Zma6DkXljbMsYdsgHVJSqO9gOl8ImSlKpFLYI9WQJb1meMNwQM4N1Cd22TAW2SgZUVGrQC4-k6yYeKjH35hAX8mbNkQdc8uTheWNQPsh2R9Ji3X_bLlM94qIOcujUdA7lhSau1tp7dgpuiT-gPbjk-cOtbQ0KKt57_8YJttpDAIVTaenZb6LrHfCAE24qT1Yl6VLXsY8CkT08iXhnqwo59EvD5FG6xGixV-3uuB-_mMZWhnKq_iitiNsh8rDkycP7BtVb3rsmY5Oqh8OAig8qO9ZZ3QI6NEUZSNaQsnukfLTk-cMf_Ug6NX1tuIacY6XT0qOiUW3h9j_tG5D0nhQYrUmBOgv9EXNoEM8brnUDtWeUE0-Z_PBuN6CiVd60xrPWzOqzAglPvRcLUm7CvMmSJw2_-N8K1StfeM7GBUZ3eQBFpw6e2yF3PZZ49PEdeQCi3VC4sOS5wjXlb4Ah3lGTKIbN1e2qTx8Qvdr64DdxbnfW4khBQgxJFbARZ8AzheeVQXrAF_7_2Tjc5AMq7lXR52aQmaB8ycQIiWg3yQLX_naFeeIlTxaeef4MVuu1qRntpndv9YM4qLTw59CZmpojzlol760H1aZEHmHFE4Tbom_oVEMhXbO1HVNnafMBFR_9tmtJ9LjX9TnqM0-7Z94hRLAuseKZwS_abwF_naM-vWeaehI5x5ANqDg-5rRGii2jfGdG7VKz0HgoYMJkhboh7i0IZd94mGEIfkE8Jh7UvC009nQTcj8nbSDdrDAqX_EU4ZVDVXFPxFOOIdgqgHJGJSPdlT4kOlNItxAhH0zkDTHRFZA6jjC3301mdmyWYXd_gqVQRx__ukPQmZy1Rp6GSgrzNvNojS7WFc8TfKxd9TVKazWm-Cp_9wUpPcFSqvo4prCd6LgFEbn1wFCRVTxd8F_aQPFZ31QkIGTihiR5xGUc8lvt3p0djw_5rRlptlbQLJ48PDP1EbgGT1FrmzHOwV9IAZVzVfn1snvY6jpBCy2jsFCSunLQ7briWcONzuu-4g36bbu1JbdIlRtQuVB6vy_R7TqtGrH2QSqJoYkNwdPE04WXfbVtLDhNz1OXfNucwnhILif0Vk8UnXnOLdehbARzj2ueMTxD_a6XVF9lNU3JgMqV2lLk3Zy7OKdtFq2iNWILa54tPM9Qe4duyiNnjEkHVK5VadvuJ09Vvec-1yJPuCnMo2sJKQLXPFF4YVyDkt433s0y5by8IkxuVGb88lhHtb3jeXdRUNyH62iJYog1zxYumsy2dyAtrI8l0_iuO8KkVn07UmudkuQRoYpHS4M72tY8V3jmGlSVfEc8nNOiZt2AykQddeEcSYXZfMIIyabsm2cHYraMFoj2rAFDcAfcS-QOpmFUGN0-gDJVe1NH1n337pIxmRFyIsgKnhFc24cHRN7eNK7PSnfPHJjd_hGXmfJb7OianUFebWRdfFgqFhGFCnhZeC7wukctUTfpq_LecBmRskptgKU5Na1peGimJa0o17uMVmOp-TXiA3WNFumivPdxDaf40QMqxwqs47HCasiMSkpcI0vAWAXdZMCQn03DiQAPW8JkrvYJSouOG0EqpTVtsQWyYcNf_1ee2NdQXPG-sO2O42fpYUBloVJdRTrl-x0mqkXWpDUnz7xCN8yG5wCv0kInDtCz10Rb0sbtv22SLR9xadU2QxNWRteHyiKbGTVCSUQ2N_z9P6K2emNSdtxSsQ-gvFPUNHt2US7oXjxtphYo2N-w4W__d7oujiBk-5c1JKFg7pmHAZU7v9ea3NFcH5N29v5c_Qt1fFKQPcP6lw3PBC4bm1tYQ73y1z1bwk_SAZWlqhOUhB8jAoHVDKJzlM3ZAO1iTzNRwBK91sfEcck2XQ6orNSHXtdd6n_tmQkq4mendDykBRueFlz4fYLKWG_Nl8rnzw1qCJO1J2k--ORLpaMMjTo8qXzlbxx0b24AF3CZu_9yKtTXnlp_1ab7ORs4BFC6QXrpfyc0OGFKYxCpFYkNUPIdOjc0b8lVukUNTyTPNDXbQ9glj7jcK5fVbkeV-9ruLD9cbloouho6a0i8CMODDSgr-L9xEI7-qruCDa3rAMoPk2O3abcrCZvj0NAloPxXzHjG8KvD9K3uXPuQPhyZumOtP31ANv5Y-a_8kV-saXfTLIy-mfmz9bhUf9b_8_QfTxt2bmMM2gZeVabMUPu-0dQfzbCHdkBnP2R-XmhmXS-iUGqAQxtB9vfFVzz0b31rQarFJRGaEyyU_2akmTs7J7IKWmBK9MB5BAJwvNvdEcZFut3rhuNFbfWIS7VvSNh4DgOP1yHFM5cR7NyfA0dBOZ4c2UPqf86x59WAxkr739UzvtqmZ9fxN9Fy41krHCXFb7g3pkM5xSYU5DrO9-2TTx-Yq2CQa3Rnz1Sfel8eyzCJScbIn0swYuHnvuxw29e9YXedjyQCulCd21OKMUofznJ61Ge8CV0q0QIO_QIN1b-6JjENkG2_JY7NBLF1E8ClOvj7dpCPnJ3P9oyCgnLvIiRuMwQauTJHzrvjfZ1pA7hSmQ_-EvfxBwgZveteDRwJhrMSMPIbAwfn3aS_Vbbl5uZV3gSPrj3rs_Vu2HZnGkW0aLEODYd4QM4cSH2u-vIeFR6ujbnnckDk7jy4UW3XZ9aFMUZnamO8A6cAg_LacKwHGF9040MFVI28KrS_a5gwo0oHVKs7XSZ9dfasZ6qqztdhvCYk53MwfuX6CIf-3Oj0RcP1DewqneYeTSYJTcd6djcRKdL9SYIlOwEyw5e6Bso_Ep65PeMVkrsBTdW-b8y9K_tz-o9JxrgYpjHJOZyUBbq8bjUWKbzwjplLb7V5ALO_OrzOHSIjaBQBuTkSLkGWOgfjFcIM2h5VutInV7rPWQVgWqXpgJvxtoFJp2gzD-NKBF1HMAiMQdj-aodntDmuWdLuCduq3D5UPvQ_j_-Q1CI0f45UIuWMP0PPK-LCiKe6mh2YZaoA5mrvSHLhA9pzpRabQT4bjwn_JBhKe2tKf-nDEUbPD7ZmLqKW-m7agtRLYbCZj2VPU3--u2Dk18gvEfYMMegkeqYrq4HTftWYUtfMGmV2QO2kRZpQnJBRSBaPZO5isOd-8xFniTr4LywbSDhN2J3K6_5M6XnIqpJsREAvgMre_uooUVr10mh2Do5OArhTnXaJRp5g4sMJ0YbibzFS-RIgp3DRZw3wBK9NnnMaOb9pCCyVbpGkedK6-EsnTKSl4T7fuTIvGuo9QfmeK703JWdNng5opR5slVi0OFOzI8slPdIBx2gK0GB86Vk-kpb6YLrj7tBkP6D1lDGnE-Rj3pUtJDk12OEggdjqrfN_hE0Bebv035hbnSYJoFN3zlU_QG9FTYTzTbSgFBacuQQaCS9dbbdwFPJzm7GCuMQEcK-SvqX5Ce3BGHSMpuWFKY9AqUZPs-EgBQko9pXu0FiIY_WVLP1z6pYN6AeVFjbVuesam_RQSz9lZtFsfcqOjE3IAhfQz42uISn1XDv7aoN-MU08zU8faEbmiY8FDlIOnQ5UqoQzQmc837kqaOQKDB10s3VcmJrmA9qqwh1osOb24JodIglj3fpDPTn8gP2rAgwfeK395VqjA3Vp6u6BrYwlA9r5iOi8NIJ3d-S-F9Ec0YQ5uFZf6qZC9O1W1_mBc3ZFO6C9Mh91hcWyE1pRZiHwIcGPgDEdMOfa1jXwCd4TFq6qODVWcoJ_bMdQMIiO0UiqBzw84rfTHWwY8ofC1jkTNSTlCT4onaSU6Yn0WbXKxZouJNLOwpkXAiUUOtMWsOhfJZlhCyrlCf6oSqzGmFZ7DWOlwrQYCu_g-ylgzoquQdb02rPxih2yshvQozqYpPYE5NyXvUi7EGZoLmGgCvKlv6O6ww2NsmYScfdVAB_U0flfZeHgrwm2-CVZUYPnSD47BozunTU0zhPwbccVV7vUQ2KmMpOZtDov6bsJN6kIsR1y1wJQuReUswJKs-va5gVzl-a7AAqhctsVfcILZ8eSBnKYPbLB0zPnYBLbRWVL4KbDbHC2kVgnj7iQ6mDb9PsTvcPQvziihVnBtDVoC3pBKnE0w-fZf13UXe9qbgB_pgdYxMrUuc7yHzB5bb2mafUregcGLxLP3S6PnopCqYzmnk9KEsLEXO11lxZn9ziFJyTjYfwsns0IUm-_6Nrcgyvnt7ToTFO6mnFsd-7TB8RC2bozKPE2KVwIoTc1D2J-DWT0V2P0-p1jI7u0I0ws_SId9_pcYzzF8aszo8w1nHcMjKFp2xq_KaCbmgbGcfO2k0dcrPwKtZ3OG43eIpp2lsK-W9NLI3AGfwzmvF8FAQi6gtyuZacFpwMq1urenxXXILnFtIwcSRNmNIpfxjgjBybe6KbzBBk4iNdUHSk5EleVJ5imM9qkNDRN_ABfIpqgEpxHcZiLNdJtF4MJje912RWoVvxed5Xrc8b3HQ4nWGhVGdP16KmbKYosak-ZUWV1AaM8QOZuSVAF4iJ6Pqa2teu4N2La_K9PiMSHe2E825kzuMXycUARsTtYJAJlPO80UBro1pAP4BpwqvYEi1Rt_c-PPm46Oq8xTHomceAcVSAkmLHyqrWZA7vvRu85PYmtCBOZquDTphO1JOQfNhGlVKEtaOP9Vpp6h4op_qSxfRFOD6gwqk0tJVyoXpSe3zJNod58eBkCvm86B9HezbHp4PNRV56pc7suJYxGNk5ze1Or4uuhV2Iz9sIpeEjqeaXrHj7M-JKmGRrmAjbFgIqcItnqvFkR5Bt84LehwAk_6APyj56YG1jPuyGxKjtFJq1OsCjUod86lLAbrU_607Qgefd6ZBYykgRSTzHSr9_W7pCxioV2QIVVhxjUJka7PmbhuTIfBeJHJkGb8VvXwifLnmf02hWT0WrMgIo7ldKbdGUJvN00QjSj1E-IMuZQpw443rO-TC1irzc6ZycwZVUAxe5HzdQMHm42DxEG9HIx6Jegt0DR2Jjbjqp3THyRtQMqypH7aHxS9WIRukAXY52tAryicOWSBFhyoDYB9twMqKhG-icnRX2LQY5OOWE44kKiybQ6hQ8tFX1D87yY9q8yfcRFrbLKPZxdp6QiZXinbB1jcXAMZkm9Km0LjHqvbcdrSezhBAunqqOPttJzu_RCH5jYEEf9zi332tgSTgWl6N0w-boyGVCxV9qh6HxiEDtbhn23wp27c-DgvM_Gc7EuTeW_dJYzvKdJHnHxQbVFT85hCwfGjHoG0gXPSKwJo1iQ5Lq4NyV02temsIyD0zvCRKP87wkih2kyjNAu4GO9BZRhgFLrtUW07XeXGzYTtLsfUNGO3z6TXs5dh5CVUsQSDpYTIBt07UzdaPSU10vdtuwY_iKAolMpiuqmvXxFs2b9D_LZME_HJ0uGoA60UtJNytE22wZQ9KqvUbJ70rNKsyAoCb2hcNisABnvd0MXJWLVOn1-b0vu-c-u8u454OLekwPUGTrGRamiH1Koiwhm8AXoePhliFogr-50jXzbXfvpA-Kgij4Zm8M2jZaKaE7hD92t37nzLmrboSGat4UGz2Dp9gSLj6GPN4fjSSbMlgsjDOldbTitbA7G_71B0dwzw3Xu7jMPieMPGQ0cuPU66OrhEEMBJlD_7vd13dk71Cbu79u6KzTrt--bvz4hHv6S0J0tWCDiI8Ye0o1nvHVvvvJmXycc_b2py4zJNu7zEyxnU2bRTuz0mocpH5JWDfIfULUszc7fKRlIzr3U9G4Sd5iKAZXiM7Ujm0SdsA_XsxAW0dvA39tzc6tLC2bl3dLIKE6N3gZQShXuJ3DLTmDbQYKxidaUCoYVPtDWeqW74ognL1y5vunYNxPS9ATLWN1ZPdJ8PKkqFtE0zdnI6zAx8BMvTelgWPSW5IvftqdoCJNz1epygmMYDfIoQ0KqdBIMw0UCr3n5mAelTd-6Q9JzU4ySZkDlQhVpvJydnV4MISsps9DiCDC8NTTR4TEsVaW_-iaf09T0EZdLlTba5m3omfzu3Bw9I7cJRTC4QihqfecaVKnU1b5lK7BdeoLlSplyr-EBGhNnSEnyxkC9oc9GDcfhwXZIVS_qynETDXc6gHKtjG66glpaQWg06UlGKqksR17ugd25tm1RKa_hRoFWuYfkRvlf36NHC6cNMKIyFwmEY9hoAx56uGxg39B703Z7T2wYR3A4wVI_qpnO89NxPOgwlqNMG-XkUB7hF9Ow_TblXQBlMqqXmcbg6NQsQhc4FP9IQOBe6qNBid-jP-bsy5_tgNKARpgunabOnIUZMnEYawqLxGioO1qaMMaIcdB3YYxRIzNFg5m22x8w1ow6i2mOkRh5h2MO3lh7qf21gSRnZr933FyzIhtQSX2rcN7cWPA9dHAEDw2fuRIz0KnWFkib8LMtHfO-kN4SJreqPqLywpShX9RMPLzCM3L-way5K9fATOKVDuMeLKcDTNNPH5C5ovxKeA0zrb_3ulnTuyIkP4fT8-YzPjp4XlWomfjW9Q_MYHDTEiaLUbHphGdKZXiqXc5nEXylNJ7xvvmWRv-jxfndNDVjSntPmLR-SajJodJUOTHIr00QA8fhOQcSA8NwJwZPjtEIXdQAZVviywxPywZU3v3Ah1eXwyhNEUaZwR3He-qLEj9jVZYHxz2ZpJMTLHefZhyf0-1JFIdmfC0ieIAE6vf-mvv_rexIAgXm7mnbAZWlOhQusjVHPCfeo8Ta4jAfdAP3HJps2Cd4edJCVwk7uZlW6PETspr2LOGUlZoJiniCqnEBE3KoyUbjN5QuMq7WkGgPyVqRFd_tq8PsFGrDhUl5ELY9rywclvD8I1vfNoYw6VSt23EN3GjP6mx4e5l-wCgHuIFfzVfvaHydJugzvy2Yc1M3Ayr39PR8W2QOBdQT6AFlrWneCD2YjYWKc94kf_1DbUjXWd0xk-jT6gTLD94km5nwFA8IRUf7HlahYiJirOCJgT23utE_wQYBEtJyW649BFA2KklS2PU97e6ZbcKFul5EnwbRDiMZy6J9TW7n6T-f_kZDc2tdPnnn9_swrfERuirobetsQP7zf73yDBOBowAA)
## TODO/Upcoming features
@@ -68,8 +84,15 @@ Please check all To dos and upcoming things [here](https://github.com/technikhil
$ npm install
# serve with hot reload at localhost:3000
+# Note that the command below will serve only via nuxt server and
+# wont run vercel functions used for e2e encryption link generation
$ npm run dev
+# if you want to run vercel function during development
+# then first create a vercel project from this repo by logging in on vercel.com
+# then run following command and follow the instructions on terminal
+$ npx vercel dev
+
# build for production and launch server
$ npm run build
$ npm run start
@@ -79,14 +102,19 @@ $ npm run generate
```
## Self Host
+
This guide provides detailed instructions on how to self-host the offline-diff-viewer application using Docker and Docker Compose. Self-hosting allows you to run the application on your own server, providing you with full control over its environment and configuration.
### Building and Running the Docker Container
+
1. Build the Docker Image
+
```bash
$ docker build -t offline-diff-viewer .
```
+
2. Run the Docker Container via docker run command
+
```bash
$ docker run -d \
--name offline-diff-viewer \
@@ -100,6 +128,7 @@ $ docker run -d \
```
### Running the Container with Docker Compose
+
```bash
$ docker compose up -d --build
-```
\ No newline at end of file
+```
diff --git a/api/createLink.js b/api/createLink.js
new file mode 100644
index 0000000..6162a88
--- /dev/null
+++ b/api/createLink.js
@@ -0,0 +1,27 @@
+import { getPool } from './db/index.js'
+import { insertRecord } from './db/insertRecord.js'
+
+export const config = { runtime: 'nodejs' }
+
+export default async function handler(req, res) {
+ try {
+ const result = await insertRecord({
+ data: req.body.data,
+ id: req.body.id,
+ })
+ if (result) {
+ res.status(200).json({
+ success: true,
+ })
+ } else {
+ throw new Error('Failed to insert record')
+ }
+ } catch (error) {
+ console.error(error)
+ res.status(500).json({ message: error.message || 'Internal server error' })
+ }
+}
+
+process.on('SIGTERM', () => {
+ getPool().end()
+})
diff --git a/api/db/dbConstants.js b/api/db/dbConstants.js
new file mode 100644
index 0000000..ff94333
--- /dev/null
+++ b/api/db/dbConstants.js
@@ -0,0 +1 @@
+export const DB_SCHEMA = process.env.DB_SCHEMA
diff --git a/api/db/getRecordById.js b/api/db/getRecordById.js
new file mode 100644
index 0000000..763ea25
--- /dev/null
+++ b/api/db/getRecordById.js
@@ -0,0 +1,18 @@
+import { DB_SCHEMA } from './dbConstants.js'
+import { getPool } from './index.js'
+
+export async function getRecordById(id) {
+ const client = await getPool().connect()
+ try {
+ const res = await client.query(
+ `SELECT data, "creationTimestamp" FROM "${DB_SCHEMA}".e2e_data WHERE id = $1;`,
+ [id]
+ )
+ return res.rows
+ } catch (error) {
+ console.error(error)
+ return null
+ } finally {
+ await client.release()
+ }
+}
diff --git a/api/db/getTop10Records.js b/api/db/getTop10Records.js
new file mode 100644
index 0000000..597f1fe
--- /dev/null
+++ b/api/db/getTop10Records.js
@@ -0,0 +1,17 @@
+import { DB_SCHEMA } from './dbConstants.js'
+import { getPool } from './index.js'
+
+export async function getTop10Records() {
+ const client = await getPool().connect()
+ try {
+ const res = await client.query(
+ `SELECT data, id, "creationTimestamp" FROM "${DB_SCHEMA}".e2e_data limit 10;`
+ )
+ return res.rows
+ } catch (error) {
+ console.error(error)
+ return null
+ } finally {
+ await client.release()
+ }
+}
diff --git a/api/db/index.js b/api/db/index.js
new file mode 100644
index 0000000..659c84e
--- /dev/null
+++ b/api/db/index.js
@@ -0,0 +1,19 @@
+import { Pool } from 'pg'
+
+let pool = null
+
+export function getPool() {
+ if (!pool || !pool.connected) {
+ pool = new Pool({
+ user: process.env.DB_USER,
+ host: process.env.DB_HOST,
+ database: process.env.DB_NAME,
+ password: process.env.DB_PASSWORD,
+ port: process.env.DB_PORT,
+ max: 5, // Maximum number of connections in the pool
+ idleTimeoutMillis: 30000, // Close idle connections after 30 seconds
+ connectionTimeoutMillis: 2000, // How long to wait for a connection from the pool
+ })
+ }
+ return pool
+}
diff --git a/api/db/insertRecord.js b/api/db/insertRecord.js
new file mode 100644
index 0000000..43cdf43
--- /dev/null
+++ b/api/db/insertRecord.js
@@ -0,0 +1,17 @@
+import { DB_SCHEMA } from './dbConstants.js'
+import { getPool } from './index.js'
+export async function insertRecord({ data, id }) {
+ const client = await getPool().connect()
+ try {
+ await client.query(
+ `INSERT INTO "${DB_SCHEMA}".e2e_data(data, id) VALUES ($1, $2);`,
+ [data, id]
+ )
+ return true
+ } catch (error) {
+ console.error(error)
+ return false
+ } finally {
+ await client.release()
+ }
+}
diff --git a/api/getLink.js b/api/getLink.js
new file mode 100644
index 0000000..a0d9545
--- /dev/null
+++ b/api/getLink.js
@@ -0,0 +1,18 @@
+import { getRecordById } from './db/getRecordById.js'
+import { getPool } from './db/index.js'
+
+export const config = { runtime: 'nodejs' }
+
+export default async function handler(req, res) {
+ try {
+ const records = await getRecordById(req.query.id)
+ res.json(records)
+ } catch (error) {
+ console.error(error)
+ res.status(500).json({ message: error.message || 'Internal server error' })
+ }
+}
+
+process.on('SIGTERM', () => {
+ getPool().end()
+})
diff --git a/components/buttons/copyLink.vue b/components/buttons/copyLink.vue
index 9fe85ea..d29730a 100644
--- a/components/buttons/copyLink.vue
+++ b/components/buttons/copyLink.vue
@@ -2,16 +2,18 @@
+
diff --git a/components/navbar.vue b/components/navbar.vue
index 0493cef..a93d7f0 100644
--- a/components/navbar.vue
+++ b/components/navbar.vue
@@ -17,7 +17,6 @@