diff --git a/.ts-prune/artifacts/tsprune-false-positives.conf b/.ts-prune/artifacts/tsprune-false-positives.conf index 0c8ca4d90..11fc0f27d 100644 --- a/.ts-prune/artifacts/tsprune-false-positives.conf +++ b/.ts-prune/artifacts/tsprune-false-positives.conf @@ -91,7 +91,7 @@ packages/shared-types/src/React.ts:8 - ReactElementKey packages/shared-types/src/JSON.ts:8 - JSONData (used in module) packages/shared-types/src/Numbers.ts:11 - Count packages/shared-types/src/Numbers.ts:14 - MsValue -packages/shared-types/src/Numbers.ts:15 - TimestampInMs +packages/shared-types/src/Numbers.ts:15 - MsTimestamp packages/shared-types/src/Numbers.ts:8 - Quantity packages/shared-types/src/Numbers.ts:9 - Percentage packages/shared-types/src/Numbers.ts:7 - Limit diff --git a/package.json b/package.json index 4f1f8a885..434f3e3fb 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "@rtm/shared-lib": "*", "@rtm/shared-types": "*", "@vercel/speed-insights": "^1.0.10", - "bentocache": "1.0.0-beta.8", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "cmdk": "^1.0.0", @@ -152,5 +151,5 @@ "engines": { "node": "^20.x" }, - "packageManager": "pnpm@9.0.4" + "packageManager": "pnpm@9.0.5" } diff --git a/packages/prebuilder/package.json b/packages/prebuilder/package.json index 78d8d98f2..036a81e5c 100644 --- a/packages/prebuilder/package.json +++ b/packages/prebuilder/package.json @@ -22,5 +22,5 @@ "@rtm/shared-types": "*", "typescript": "^5.4.4" }, - "packageManager": "pnpm@9.0.4" + "packageManager": "pnpm@9.0.5" } diff --git a/packages/prebuilder/src/dx/watcher.ts b/packages/prebuilder/src/dx/watcher.ts index f2dcc6d6e..8e65cc29f 100644 --- a/packages/prebuilder/src/dx/watcher.ts +++ b/packages/prebuilder/src/dx/watcher.ts @@ -1,13 +1,13 @@ /* v8 ignore start */ // Stryker disable all -import type { TimestampInMs, MsValue } from '@rtm/shared-types/Numbers'; +import type { MsTimestamp, MsValue } from '@rtm/shared-types/Numbers'; import { watch } from 'chokidar'; import type { Path } from '../types/Metadatas'; -let lastEventTimestamp: TimestampInMs | null = null; +let lastEventTimestamp: MsTimestamp | null = null; const DEBOUNCE_THRESHOLD_IN_MS: MsValue = 10; diff --git a/packages/prebuilder/src/main.ts b/packages/prebuilder/src/main.ts index 7cb155836..c9fcaa6ea 100644 --- a/packages/prebuilder/src/main.ts +++ b/packages/prebuilder/src/main.ts @@ -6,7 +6,7 @@ import formatMessage from './config/formatMessage'; // NOTE: formatMessage import MUST be at the top of the file import type { MaybeUndefined, MaybeNull, Couple } from '@rtm/shared-types/CustomUtilityTypes'; -import type { TimestampInMs } from '@rtm/shared-types/Numbers'; +import type { MsTimestamp } from '@rtm/shared-types/Numbers'; import { dirname, join } from 'path'; import { ArgError } from 'arg'; @@ -50,23 +50,23 @@ const BENCHMARK_ACCURACY = 5; const HANDLED_ERRORS_TYPES = [FeedbackError, BuilderError, ArgumentsValidatorError, ArgError]; let clocks = {} as Partial<{ - pagesTaxonomyCheckersStartTime: TimestampInMs; - blogTaxonomyCheckersStartTime: TimestampInMs; - pagesTaxonomyCheckersEndTime: TimestampInMs; - blogTaxonomyCheckersEndTime: TimestampInMs; - lpTaxonomyCheckersStartTime: TimestampInMs; - lpTaxonomyCheckersEndTime: TimestampInMs; - localesCheckersStartTime: TimestampInMs; - localesCheckersEndTime: TimestampInMs; - pagesCodegenStartTime: TimestampInMs; - utilsCodegenStartTime: TimestampInMs; - blogCodegenStartTime: TimestampInMs; - pagesCodegenEndTime: TimestampInMs; - utilsCodegenEndTime: TimestampInMs; - blogCodegenEndTime: TimestampInMs; - lpCodegenStartTime: TimestampInMs; - lpCodegenEndTime: TimestampInMs; - globalStartTime: TimestampInMs; + pagesTaxonomyCheckersStartTime: MsTimestamp; + blogTaxonomyCheckersStartTime: MsTimestamp; + pagesTaxonomyCheckersEndTime: MsTimestamp; + blogTaxonomyCheckersEndTime: MsTimestamp; + lpTaxonomyCheckersStartTime: MsTimestamp; + lpTaxonomyCheckersEndTime: MsTimestamp; + localesCheckersStartTime: MsTimestamp; + localesCheckersEndTime: MsTimestamp; + pagesCodegenStartTime: MsTimestamp; + utilsCodegenStartTime: MsTimestamp; + blogCodegenStartTime: MsTimestamp; + pagesCodegenEndTime: MsTimestamp; + utilsCodegenEndTime: MsTimestamp; + blogCodegenEndTime: MsTimestamp; + lpCodegenStartTime: MsTimestamp; + lpCodegenEndTime: MsTimestamp; + globalStartTime: MsTimestamp; }>; function resetBenchmarkClocks(): void { @@ -108,7 +108,7 @@ function printPrebuildReport({ // eslint-disable-next-line @typescript-eslint/no-magic-numbers const IGNORED = -1 as const; - const computeDelay = (maybeStart: MaybeUndefined, maybeEnd: MaybeUndefined) => + const computeDelay = (maybeStart: MaybeUndefined, maybeEnd: MaybeUndefined) => // eslint-disable-next-line @typescript-eslint/no-magic-numbers maybeStart === undefined || maybeEnd === undefined ? IGNORED : (Math.abs(maybeEnd - maybeStart) / 1e3).toFixed(BENCHMARK_ACCURACY); diff --git a/packages/shared-lib/package.json b/packages/shared-lib/package.json index 678b44696..46a5ef77b 100644 --- a/packages/shared-lib/package.json +++ b/packages/shared-lib/package.json @@ -106,5 +106,5 @@ "@types/hast": "^3.0.4", "vitest": "^1.4.0" }, - "packageManager": "pnpm@9.0.4" + "packageManager": "pnpm@9.0.5" } diff --git a/packages/shared-types/src/Numbers.ts b/packages/shared-types/src/Numbers.ts index eeb739b2d..89711aa2a 100644 --- a/packages/shared-types/src/Numbers.ts +++ b/packages/shared-types/src/Numbers.ts @@ -12,7 +12,7 @@ export type Count = number; export type PxValue = number; export type MsValue = number; -export type TimestampInMs = number; +export type MsTimestamp = number; // Stryker restore all /* v8 ignore stop */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f32e7513b..8eb14a159 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -74,9 +74,6 @@ importers: '@vercel/speed-insights': specifier: ^1.0.10 version: 1.0.10(next@14.2.2(@babel/core@7.24.4)(@opentelemetry/api@1.8.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) - bentocache: - specifier: 1.0.0-beta.8 - version: 1.0.0-beta.8(tslib@2.6.2) class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -582,15 +579,6 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@boringnode/bus@0.5.0': - resolution: {integrity: sha512-b0jtcAv/IgDrFz10kNJJT5+pyNTdSNxsPCudbnDe4PQ6KzfMQRQQolqFe0uotlmsVmWCBxUN5MyV06vdQ4MeRQ==} - engines: {node: '>=20.11.1'} - peerDependencies: - ioredis: ^5.0.0 - peerDependenciesMeta: - ioredis: - optional: true - '@commitlint/config-conventional@19.2.2': resolution: {integrity: sha512-mLXjsxUVLYEGgzbxbxicGPggDuyWNkf25Ht23owXIH+zV2pv1eJuzLK3t1gDY5Gp6pxdE60jZnWUY5cvgL3ufw==} engines: {node: '>=v18'} @@ -965,10 +953,6 @@ packages: resolution: {integrity: sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==} engines: {node: '>= 0.4'} - '@lukeed/ms@2.0.2': - resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} - engines: {node: '>=8'} - '@mdx-js/esbuild@2.3.0': resolution: {integrity: sha512-r/vsqsM0E+U4Wr0DK+0EfmABE/eg+8ITW4DjvYdh3ve/tK2safaqHArNnaqbOk1DjYGrhxtoXoGaM3BY8fGBTA==} peerDependencies: @@ -1043,10 +1027,6 @@ packages: cpu: [x64] os: [win32] - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1203,9 +1183,6 @@ packages: '@panva/hkdf@1.1.1': resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} - '@paralleldrive/cuid2@2.2.2': - resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} - '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1213,10 +1190,6 @@ packages: '@polka/url@1.0.0-next.25': resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} - '@poppinss/utils@6.7.3': - resolution: {integrity: sha512-zQnhVG4Q+n6+V1vrL/TF1Oy8ZcVVGUs49Sj5OBgoari/q42UiG/rht1DRvoeWd9bT1BBDwxO2vcfxj6C0u/Dgg==} - engines: {node: '>=18.16.0'} - '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -1911,9 +1884,6 @@ packages: '@types/babel__traverse@7.20.5': resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} - '@types/bytes@3.1.4': - resolution: {integrity: sha512-A0uYgOj3zNc4hNjHc5lYUfJQ/HVyBXiUMKdXd7ysclaE6k9oJdavQzODHuwjpUu2/boCP8afjQYi8z/GtvNCWA==} - '@types/conventional-commits-parser@5.0.0': resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} @@ -1968,9 +1938,6 @@ packages: '@types/parse5@6.0.3': resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} - '@types/pluralize@0.0.33': - resolution: {integrity: sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==} - '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -2301,9 +2268,6 @@ packages: resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} hasBin: true - async-mutex@0.5.0: - resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} - at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} @@ -2335,23 +2299,6 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - bentocache@1.0.0-beta.8: - resolution: {integrity: sha512-TnAiQZpmKpS9GyDxsyrQnC8Oa/wGb1p0AIv3nV5artAL9JU3DYQG+uuinIAJSqc3dnKSOYyemfpRguLyrupfNw==} - peerDependencies: - '@aws-sdk/client-dynamodb': ^3.438.0 - ioredis: ^5.3.2 - knex: ^3.0.1 - kysely: ^0.27.3 - peerDependenciesMeta: - '@aws-sdk/client-dynamodb': - optional: true - ioredis: - optional: true - knex: - optional: true - kysely: - optional: true - binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} @@ -2384,10 +2331,6 @@ packages: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -2414,10 +2357,6 @@ packages: caniuse-lite@1.0.30001610: resolution: {integrity: sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==} - case-anything@2.1.13: - resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==} - engines: {node: '>=12.13'} - ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -2463,10 +2402,6 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} - chunkify@5.0.0: - resolution: {integrity: sha512-G8dj/3/Gm+1yL4oWSdwIxihZWFlgC4V2zYtIApacI0iPIRKBHlBGOGAiDUBZgrj4H8MBA8g8fPFwnJrWF3wl7Q==} - engines: {node: '>=18'} - class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} @@ -3151,10 +3086,6 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} - flattie@1.1.1: - resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} - engines: {node: '>=8'} - for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -3411,10 +3342,6 @@ packages: hastscript@8.0.0: resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} - hexoid@1.0.0: - resolution: {integrity: sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==} - engines: {node: '>=8'} - homedir-polyfill@1.0.3: resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} engines: {node: '>=0.10.0'} @@ -4498,10 +4425,6 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - p-timeout@6.1.2: - resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} - engines: {node: '>=14.16'} - pagefind@1.1.0: resolution: {integrity: sha512-1nmj0/vfYcMxNEQj0YDRp6bTVv9hI7HLdPhK/vBBYlrnwjATndQvHyicj5Y7pUHrpCFZpFnLVQXIF829tpFmaw==} hasBin: true @@ -4595,10 +4518,6 @@ packages: pkg-types@1.0.3: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} - pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -4975,10 +4894,6 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} - safe-stable-stringify@2.4.3: - resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} - engines: {node: '>=10'} - safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -4992,9 +4907,6 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} - secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -5051,10 +4963,6 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - slash@5.1.0: - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} - engines: {node: '>=14.16'} - slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -5063,10 +4971,6 @@ packages: resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} engines: {node: '>=18'} - slugify@1.6.6: - resolution: {integrity: sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==} - engines: {node: '>=8.0.0'} - source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} @@ -5300,9 +5204,6 @@ packages: resolution: {integrity: sha512-rqy30BSpxPznbbTcAcci90oZ1YR4DqvKcNXNerG5gQBU2v4jk0cygheiul5J6ExIMrgDVuanv/MkGfqZbKrNNg==} engines: {node: 10.* || >= 12.*} - truncatise@0.0.8: - resolution: {integrity: sha512-cXzueh9pzBCsLzhToB4X4gZCb3KYkrsAcBAX97JnazE74HOl3cpBJYEV7nabHeG/6/WXCU5Yujlde/WPBUwnsg==} - ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -5388,11 +5289,6 @@ packages: typed-rest-client@1.8.11: resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} - typescript-log@2.0.0: - resolution: {integrity: sha512-TyW8lmURJSo0yjBovEhESpah3haDYBgsnQRocBF4MQSDJSYs/DOmhjo2cpSrGyvD9OaX++dbbonq9TkIQeA+Bw==} - peerDependencies: - tslib: ^2.0.0 - typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} @@ -5991,12 +5887,6 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@boringnode/bus@0.5.0': - dependencies: - '@paralleldrive/cuid2': 2.2.2 - '@poppinss/utils': 6.7.3 - object-hash: 3.0.0 - '@commitlint/config-conventional@19.2.2': dependencies: '@commitlint/types': 19.0.3 @@ -6425,8 +6315,6 @@ snapshots: dependencies: call-bind: 1.0.7 - '@lukeed/ms@2.0.2': {} - '@mdx-js/esbuild@2.3.0(esbuild@0.20.2)': dependencies: '@mdx-js/mdx': 2.3.0 @@ -6500,8 +6388,6 @@ snapshots: '@next/swc-win32-x64-msvc@14.2.2': optional: true - '@noble/hashes@1.4.0': {} - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -6650,30 +6536,11 @@ snapshots: '@panva/hkdf@1.1.1': {} - '@paralleldrive/cuid2@2.2.2': - dependencies: - '@noble/hashes': 1.4.0 - '@pkgjs/parseargs@0.11.0': optional: true '@polka/url@1.0.0-next.25': {} - '@poppinss/utils@6.7.3': - dependencies: - '@lukeed/ms': 2.0.2 - '@types/bytes': 3.1.4 - '@types/pluralize': 0.0.33 - bytes: 3.1.2 - case-anything: 2.1.13 - flattie: 1.1.1 - pluralize: 8.0.0 - safe-stable-stringify: 2.4.3 - secure-json-parse: 2.7.0 - slash: 5.1.0 - slugify: 1.6.6 - truncatise: 0.0.8 - '@protobufjs/aspromise@1.1.2': {} '@protobufjs/base64@1.1.2': {} @@ -7439,8 +7306,6 @@ snapshots: dependencies: '@babel/types': 7.24.0 - '@types/bytes@3.1.4': {} - '@types/conventional-commits-parser@5.0.0': dependencies: '@types/node': 20.12.7 @@ -7496,8 +7361,6 @@ snapshots: '@types/parse5@6.0.3': {} - '@types/pluralize@0.0.33': {} - '@types/prop-types@15.7.12': {} '@types/react-dom@18.2.25': @@ -7920,10 +7783,6 @@ snapshots: astring@1.8.6: {} - async-mutex@0.5.0: - dependencies: - tslib: 2.6.2 - at-least-node@1.0.0: {} autoprefixer@10.4.19(postcss@8.4.38): @@ -7952,19 +7811,6 @@ snapshots: base64-js@1.5.1: {} - bentocache@1.0.0-beta.8(tslib@2.6.2): - dependencies: - '@boringnode/bus': 0.5.0 - '@poppinss/utils': 6.7.3 - async-mutex: 0.5.0 - chunkify: 5.0.0 - hexoid: 1.0.0 - lru-cache: 10.2.0 - p-timeout: 6.1.2 - typescript-log: 2.0.0(tslib@2.6.2) - transitivePeerDependencies: - - tslib - binary-extensions@2.3.0: {} bl@4.1.0: @@ -8004,8 +7850,6 @@ snapshots: dependencies: streamsearch: 1.1.0 - bytes@3.1.2: {} - cac@6.7.14: {} cachedir@2.3.0: {} @@ -8029,8 +7873,6 @@ snapshots: caniuse-lite@1.0.30001610: {} - case-anything@2.1.13: {} - ccount@2.0.1: {} chai@4.4.1: @@ -8087,8 +7929,6 @@ snapshots: optionalDependencies: fsevents: 2.3.3 - chunkify@5.0.0: {} - class-variance-authority@0.7.0: dependencies: clsx: 2.0.0 @@ -9009,8 +8849,6 @@ snapshots: flatted@3.3.1: {} - flattie@1.1.1: {} - for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -9360,8 +9198,6 @@ snapshots: property-information: 6.5.0 space-separated-tokens: 2.0.2 - hexoid@1.0.0: {} - homedir-polyfill@1.0.3: dependencies: parse-passwd: 1.0.0 @@ -10807,8 +10643,6 @@ snapshots: dependencies: p-limit: 3.1.0 - p-timeout@6.1.2: {} - pagefind@1.1.0: optionalDependencies: '@pagefind/darwin-arm64': 1.1.0 @@ -10899,8 +10733,6 @@ snapshots: mlly: 1.6.1 pathe: 1.1.2 - pluralize@8.0.0: {} - possible-typed-array-names@1.0.0: {} postcss-import@15.1.0(postcss@8.4.38): @@ -11311,8 +11143,6 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 - safe-stable-stringify@2.4.3: {} - safer-buffer@2.1.2: {} scheduler@0.23.0: @@ -11326,8 +11156,6 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 - secure-json-parse@2.7.0: {} - semver@6.3.1: {} semver@7.6.0: @@ -11385,8 +11213,6 @@ snapshots: slash@3.0.0: {} - slash@5.1.0: {} - slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.1 @@ -11397,8 +11223,6 @@ snapshots: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 - slugify@1.6.6: {} - source-map-js@1.2.0: {} source-map-support@0.5.21: @@ -11643,8 +11467,6 @@ snapshots: true-myth@4.1.1: {} - truncatise@0.0.8: {} - ts-api-utils@1.3.0(typescript@5.4.5): dependencies: typescript: 5.4.5 @@ -11741,10 +11563,6 @@ snapshots: tunnel: 0.0.6 underscore: 1.13.6 - typescript-log@2.0.0(tslib@2.6.2): - dependencies: - tslib: 2.6.2 - typescript@5.4.5: {} ufo@1.5.3: {} diff --git a/src/cache/generic.ts b/src/cache/generic.ts new file mode 100644 index 000000000..f04a0ffb4 --- /dev/null +++ b/src/cache/generic.ts @@ -0,0 +1,65 @@ +import type { MaybeUndefined } from '@rtm/shared-types/CustomUtilityTypes'; +import type { MsTimestamp, MsValue } from '@rtm/shared-types/Numbers'; + +namespace GenericInMemoryCache { + export const data = {} as DataCache; +} + +export const keysFactory = { + discordProfilePicture: (id: string) => `discord:pp:${id}` +}; + +function invalidateExpiredCacheData(key: string) { + if (GenericInMemoryCache.data[key] === undefined) return; + + const clock = GenericInMemoryCache.data[key].clock; + if (!clock) return; + + const { cachedAt, ttl } = clock; + if (Math.abs(Date.now() - cachedAt) > ttl) delete GenericInMemoryCache.data[key]; +} + +export function get(key: string) { + invalidateExpiredCacheData(key); + return GenericInMemoryCache.data[key]?.value; +} + +export function set(key: string, data: Data, ttl: MsValue) { + function setClock(key: string, ttl: MsValue) { + GenericInMemoryCache.data[key].clock = { + cachedAt: Date.now(), + ttl + }; + } + + if (!GenericInMemoryCache.data[key]) GenericInMemoryCache.data[key] = {} as DataCacheEntry; + + GenericInMemoryCache.data[key].value = typeof data === 'object' ? structuredClone(data) : data; + + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + if (ttl > 0) setClock(key, ttl); +} + +export async function getOrSet(key: string, data: () => Promise, ttl: MsValue) { + const value: MaybeUndefined = get(key); + if (value !== undefined) return value; + + const mountedData = await data(); + set(key, mountedData, ttl); + return get(key); +} + +export function clearAll() { + for (const key of Object.keys(GenericInMemoryCache.data)) delete GenericInMemoryCache.data[key]; +} + +type Data = boolean | string | number | object | null; + +type Clock = { cachedAt: MsTimestamp; ttl: MsValue }; + +type DataCacheEntry = { + clock: Clock; + value: Data; +}; + +type DataCache = Record; diff --git a/src/config/Auth/__tests__/prebuild.authOptions.test.ts b/src/config/Auth/__tests__/prebuild.authOptions.test.ts index 484182f95..5127b9ce4 100644 --- a/src/config/Auth/__tests__/prebuild.authOptions.test.ts +++ b/src/config/Auth/__tests__/prebuild.authOptions.test.ts @@ -1,7 +1,7 @@ import type { IDiscordApi } from '@/meta/discordapi'; import { beforeEach, afterEach, describe, expect, it, vi } from 'vitest'; -import bentocache, { keysFactory } from '@/config/bentocache'; +import { keysFactory, clearAll, get, set } from '@/cache/generic'; import discordApi from '@/meta/discordapi'; import { getDiscordProfilePicture, getSession } from '../authOptions'; @@ -15,7 +15,7 @@ describe('getDiscordProfilePicture (rate limited)', () => { afterEach(() => { vi.restoreAllMocks(); - bentocache.clearAll(); + clearAll(); }); it('should cache a fallback ImageURL, given unhappy path (all is valid, but we got rate limited and empty cache)', async () => { @@ -42,7 +42,7 @@ describe('getDiscordProfilePicture (rate limited)', () => { fakeDiscordApi ); - const cachedURL = await bentocache.get(keysFactory.discordProfilePicture(FAKE_ID)); + const cachedURL = get(keysFactory.discordProfilePicture(FAKE_ID)); const fallbackAvatarRegex = /^https:\/\/cdn\.discordapp\.com\/embed\/avatars\/[0-5]\.png$/; expect(cachedURL).toMatch(fallbackAvatarRegex); @@ -54,7 +54,8 @@ describe('getDiscordProfilePicture (rate limited)', () => { it('should return the cached ImageURL as fallback, given unhappy path (all is valid, but we got rate limited)', async () => { vi.stubEnv('DISCORD_BOT_TOKEN', 'FAKE'); - bentocache.set(keysFactory.discordProfilePicture('FAKE_ID'), 'FAKE_URL'); + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + set(keysFactory.discordProfilePicture('FAKE_ID'), 'FAKE_URL', 660_000); const FAKE_ID = 'FAKE_ID'; const fakeDiscordApi: IDiscordApi = discordApi; @@ -77,7 +78,7 @@ describe('getDiscordProfilePicture (rate limited)', () => { fakeDiscordApi ); - const cachedURL = await bentocache.get(keysFactory.discordProfilePicture(FAKE_ID)); + const cachedURL = get(keysFactory.discordProfilePicture(FAKE_ID)); expect(cachedURL).toBe('FAKE_URL'); expect(gotSession).toStrictEqual({ @@ -162,7 +163,7 @@ describe('getDiscordProfilePicture', () => { describe('Caching test', () => { beforeEach(() => { vi.unstubAllEnvs(); - bentocache.clearAll(); + clearAll(); vi.resetModules(); }); @@ -198,7 +199,7 @@ describe('Caching test', () => { fakeDiscordApi ); - const cachedURL = await bentocache.get(keysFactory.discordProfilePicture(FAKE_ID)); + const cachedURL = get(keysFactory.discordProfilePicture(FAKE_ID)); expect(cachedURL).toBe('https://cdn.discordapp.com/avatars/FAKE_ID/a_FAKE_AVATAR.gif'); expect(gotSession).toStrictEqual({ user: { ...session.user, image: gotSession?.user?.image }, @@ -238,7 +239,7 @@ describe('Caching test', () => { fakeDiscordApi ); - const cachedURL = await bentocache.get(keysFactory.discordProfilePicture(FAKE_ID)); + const cachedURL = get(keysFactory.discordProfilePicture(FAKE_ID)); expect(cachedURL).toBe(undefined); expect(gotSession).toStrictEqual(session); }); @@ -275,7 +276,7 @@ describe('Caching test', () => { fakeDiscordApi ); - const cachedURL = await bentocache.get(keysFactory.discordProfilePicture(FAKE_ID)); + const cachedURL = get(keysFactory.discordProfilePicture(FAKE_ID)); expect(cachedURL).toBe(undefined); expect(gotSession).toStrictEqual(session); }); @@ -312,7 +313,7 @@ describe('Caching test', () => { fakeDiscordApi ); - const cachedURL = await bentocache.get(keysFactory.discordProfilePicture(FAKE_ID)); + const cachedURL = get(keysFactory.discordProfilePicture(FAKE_ID)); expect(cachedURL).toBe(undefined); expect(gotSession).toStrictEqual(session); }); diff --git a/src/config/Auth/authOptions.ts b/src/config/Auth/authOptions.ts index 8e314a3a6..655d00e00 100644 --- a/src/config/Auth/authOptions.ts +++ b/src/config/Auth/authOptions.ts @@ -1,14 +1,14 @@ import type { MaybeNull } from '@rtm/shared-types/CustomUtilityTypes'; import type { NextAuthOptions, Session } from 'next-auth'; import type { IDiscordApi } from '@/meta/discordapi'; +import type { Href } from '@rtm/shared-types/Next'; import type { JWT } from 'next-auth/jwt'; import DiscordProvider from 'next-auth/providers/discord'; +import { keysFactory, getOrSet } from '@/cache/generic'; import ROUTES_ROOTS from '##/config/routes'; import discordApi from '@/meta/discordapi'; -import bentocache, { keysFactory } from '../bentocache'; - export async function getDiscordProfilePicture(sub: string, __discordApi: IDiscordApi): Promise> { const freshProfile = await __discordApi.getFreshProfile(sub); @@ -31,7 +31,12 @@ export async function getSession(session: Session, token: JWT, __discordApi: IDi // Stryker Workaround 1. Empty object mutant is pointless. // Stryker disable next-line ObjectLiteral - const imageURL = await bentocache.getOrSet(keysFactory.discordProfilePicture(id), () => getDiscordProfilePicture(id, __discordApi), { ttl: '11m' }); // TTL: https://discord.com/developers/docs/topics/rate-limits#invalid-request-limit-aka-cloudflare-bans + const imageURL = (await getOrSet( + keysFactory.discordProfilePicture(id), + () => getDiscordProfilePicture(id, __discordApi), + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + 660_000 + )) as MaybeNull; // TTL: https://discord.com/developers/docs/topics/rate-limits#invalid-request-limit-aka-cloudflare-bans if (imageURL === null) return session; diff --git a/src/config/bentocache.ts b/src/config/bentocache.ts deleted file mode 100644 index 06a8f8d7f..000000000 --- a/src/config/bentocache.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* v8 ignore start */ -// Stryker disable all - -import { memoryDriver } from 'bentocache/drivers/memory'; -import { BentoCache, bentostore } from 'bentocache'; - -export const keysFactory = { - discordProfilePicture: (id: string) => `discord:pp:${id}` -}; - -const bentocache = new BentoCache({ - stores: { - default: bentostore().useL1Layer(memoryDriver()) - }, - - gracePeriod: { - duration: '6h', - enabled: true - }, - default: 'default' -}); - -export default bentocache; - -// Stryker restore all -/* v8 ignore stop */ diff --git a/src/meta/discordapi.ts b/src/meta/discordapi.ts index e312072a6..b1bf59ed5 100644 --- a/src/meta/discordapi.ts +++ b/src/meta/discordapi.ts @@ -1,7 +1,10 @@ /* v8 ignore start */ // Stryker disable all -import bentocache, { keysFactory } from '@/config/bentocache'; +import type { MaybeNull } from '@rtm/shared-types/CustomUtilityTypes'; +import type { Href } from '@rtm/shared-types/Next'; + +import { keysFactory, get } from '@/cache/generic'; type FreshProfile = { epicFail?: boolean; avatar: string; id: string }; @@ -21,7 +24,7 @@ class DiscordApi implements IDiscordApi { }) ).json(); } catch { - const cachedURL = await bentocache.get(keysFactory.discordProfilePicture(sub)); + const cachedURL = get(keysFactory.discordProfilePicture(sub)) as MaybeNull; if (cachedURL) return { avatar: cachedURL, id: sub }; const randint = Math.floor(Math.random() * MAX_DEFAULT_AVATAR_ID); return { avatar: `https://cdn.discordapp.com/embed/avatars/${randint}.png`, epicFail: true, id: sub };