Files
ente/web/docs/dependencies.md
Manav Rathi a8c270433a Web deps
2025-07-02 15:33:35 +05:30

306 lines
13 KiB
Markdown

# Dependencies
## Dev
These are some global dev dependencies in the root `package.json`. These set the
baseline for how our code be in all the workspaces in this (yarn) monorepo.
- [prettier](https://prettier.io) - Formatter
- [eslint](https://eslint.org) - Linter
- [typescript](https://www.typescriptlang.org/) - Type checker
They also need some support packages, which come from the leaf
`ente-build-config` package:
- [@eslint/js](https://eslint.org/) provides JavaScript ESLint functionality,
and provides the configuration recommended the by ESLint team.
- [typescript-eslint](https://typescript-eslint.io/packages/typescript-eslint/)
\- provides TypeScript ESLint functionality and provides a set of recommended
configurations (`typescript-eslint` is the new entry point, our yet-unmigrated
packages use the older method of separately including
[@typescript-eslint/parser](https://typescript-eslint.io/packages/eslint-plugin/)
\- which tells ESLint how to read TypeScript syntax - and
[@typescript-eslint/eslint-plugin](https://typescript-eslint.io/packages/eslint-plugin/)
\- which provides the TypeScript rules and presets).
- [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react),
[eslint-plugin-react-hooks](https://reactjs.org/) \- Some React specific
ESLint rules and configurations that are used by the workspaces that have
React code.
- [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh)
\- A plugin to ensure that React components are exported in a way that they
can be HMR-ed.
- [prettier-plugin-organize-imports](https://github.com/simonhaenisch/prettier-plugin-organize-imports)
\- A Prettier plugin to sort imports.
- [prettier-plugin-packagejson](https://github.com/matzkoh/prettier-plugin-packagejson)
\- A Prettier plugin to also prettify `package.json`.
The root `package.json` also has a convenience dev dependency:
- [concurrently](https://github.com/open-cli-tools/concurrently) for spawning
parallel tasks when we invoke various yarn scripts.
> [!NOTE]
>
> We need to repeat some of the dependencies in multiple `package.json`s to
> avoid spurious missing peer dependency warnings.
>
> For example, ideally we'd just have specified the react dependencies in
> _ente-base_, but that leads to missing peer dependency warnings in our other
> packages, so we need to need to repeat them. For now, we manually ensure that
> all of them use the same version.
>
> Additionally, we pin the versions of the react types using the resolutions
> field in the top level `package.json`, to avoid type errors because of
> multiple versions of react types being in scope.
## Cryptography
We use [libsodium](https://libsodium.gitbook.io/doc/) for our cryptography
primitives. We use its WebAssembly target, accessible via JavaScript wrappers
maintained by the original authors of libsodium themselves -
[libsodium-wrappers](https://github.com/jedisct1/libsodium.js).
More precisely, we use the sumo variant, "libsodium-wrappers-sumo", since the
standard variant does not provide the `crypto_pwhash_*` functions.
## Meta frameworks
### Next.js
[Next.js](https://nextjs.org) (package:
[next](https://github.com/vercel/next.js)) provides the meta framework for both
the photos and the auth app, and also for some of the sidecar apps like accounts
and cast.
We use a limited subset of Next.js. The main thing we get out of it is a
reasonable set of defaults for bundling our app into a static export which we
can then deploy to our webserver. In addition, the Next.js page router is
convenient. Overall our apps can be described as regular React SPAs, and are not
particularly tied to Next.js.
### Vite
For some of our newer code, we have started to use [Vite](https://vitejs.dev).
It is likely the future (both generally, and for our code) since Next.js is
becoming less suitable for SPAs and static SSR with their push towards RSC and
dynamic SSR.
## UI
### React
[React](https://react.dev) (package: [react](https://github.com/facebook/react))
is our core framework. We also import its a sibling
[react-dom](https://github.com/facebook/react) package that renders JSX to the
DOM.
### MUI and Material Icons
We use [MUI](https://mui.com)'s
[@mui/material](https://mui.com/material-ui/getting-started/installation/) as
our base React component library (In our code and documentation, we use the name
"MUI" to refer to the the combination of both MUI's "Material UI" and "System"
packages that we use).
MUI uses [Emotion](https://emotion.sh/) as its preferred CSS-in-JS library, for
which we need to install install two Emotion packages (`@emotion/react` and
`@emotion/styled`) as peer dependencies.
We also use MUI's
[@mui/material-icons](https://mui.com/material-ui/material-icons/) package,
which provides Material icons exported as React components (a `SvgIcon`).
> [!NOTE]
>
> For a similar reason as with react,
>
> - the `@mui/material` dependency is also repeated at more places - the one in
> _ente-base_ is the canonical one.
> - we need to add an explicit dependency to `mui/system` in _ente-new_ even
> though we don't directly depend on it.
### Date pickers
[@mui/x-date-pickers](https://mui.com/x/react-date-pickers/getting-started/) is
used to get a date/time picker component. This is the community version of the
DateTimePicker component provided by MUI.
[dayjs](https://github.com/iamkun/dayjs) is used as the date library that that
`@mui/x-date-pickers` will internally use to manipulate dates.
### Translations
For showing the app's UI in multiple languages, we use the
[i18next](https://www.i18next.com), specifically its three components
- [i18next](https://github.com/i18next/i18next): The core `i18next` library.
- [react-i18next](https://github.com/i18next/react-i18next): React specific
support in `i18next`.
- [i18next-http-backend](https://github.com/i18next/i18next-http-backend): Adds
support for initializing `i18next` with JSON file containing the translation
in a particular language, fetched at runtime.
Note that inspite of the "next" in the name of the library, it has nothing to do
with Next.js.
[get-user-locale](https://github.com/wojtekmaj/get-user-locale) is used for
enumerating the user's locale's to find the best match.
For more details, see [translations.md](translations.md).
### Font
Inter Variable (with support for weights 100 - 90) is used as the primary font,
via [@fontsource-variable/inter](https://fontsource.org/fonts/inter/install).
### UI components
- [react-window](https://github.com/bvaughn/react-window) is used for lazy-ily
rendering large lists of dynamically created content, each item being of a
variable height. It is usually used in tandem with its sibling package,
[react-virtualized-auto-sizer](https://github.com/bvaughn/react-virtualized-auto-sizer)
which allows the lazy list to resize itself automatically to fill the entire
remaining space available in the container.
- [formik](https://github.com/jaredpalmer/formik) provides an easier to use
abstraction for dealing with form state, validation and submission states when
using React.
- [react-select](https://react-select.com/) is used for search dropdowns.
- [react-otp-input](https://github.com/devfolioco/react-otp-input) is used to
render a segmented OTP input field for 2FA authentication.
## Utilities
- [comlink](https://github.com/GoogleChromeLabs/comlink) provides a minimal
layer on top of web workers to make them more easier to use.
- [idb](https://github.com/jakearchibald/idb) provides a promise API over the
browser-native IndexedDB APIs. Older code (the file and collection store),
uses [localForage](https://github.com/localForage/localForage) for IndexedDB
access.
> For more details about IDB and its role, see [storage.md](storage.md).
- [zod](https://github.com/colinhacks/zod) is used for runtime typechecking
(e.g. verifying that API responses match the expected TypeScript shape).
- [nanoid](https://github.com/ai/nanoid) is used for generating unique
identifiers. For one particular use case, we also need
[uuid](https://github.com/uuidjs/uuid) for UUID v4 generation.
- [bs58](https://github.com/cryptocoinjs/bs58) is used for base-58 conversion
(used for encoding the collection key to use as the hash in the share URL).
- [debounce](https://github.com/sindresorhus/debounce) and its
promise-supporting sibling
[p-debounce](https://github.com/sindresorhus/p-debounce) are used for
debouncing operations (See also: `[Note: Throttle and debounce]`).
- [bip39](https://github.com/bitcoinjs/bip39) is used for generating the 24-word
recovery key mnemonic.
- [zxcvbn](https://github.com/dropbox/zxcvbn) is used for password strength
estimation.
- [fast-srp-hap](https://github.com/homebridge/fast-srp) is used for the maths
underlying the SRP protocol.
## Media
- [@ffmpeg/ffmpeg](https://github.com/ffmpegwasm/ffmpeg.wasm) is used to run
FFmpeg in the browser using WebAssembly (Wasm). Note that this is
substantially slower than native ffmpeg (the desktop app can, and does, bundle
the faster native ffmpeg implementation too).
- [exifreader](https://github.com/mattiasw/ExifReader) is used for Exif parsing.
- [jszip](https://github.com/Stuk/jszip) is used for reading zip files in the
web code (Live photos are zip files under the hood). Note that the desktop app
uses also has a ZIP parser (that one supports streaming).
- [file-type](https://github.com/sindresorhus/file-type) is used for MIME type
detection. We are at an old version 16.5.4 because v17 onwards the package
became ESM only - for our limited use case, the custom Webpack configuration
that it'd entail is not worth the upgrade.
- [heic-convert](https://github.com/catdad-experiments/heic-convert) is used for
converting HEIC files (which browsers don't natively support) into JPEG. For
(much more) details, see [heic.md](heic.md).
## Photos app specific
- [photoswipe](https://photoswipe.com) provides the base image viewer on top of
which we've built our file viewer.
- For streaming video (HLS), we use three libraries:
1. [media-chrome](https://github.com/muxinc/media-chrome) provides custom
video controls which we use when playing HLS playlists (we use custom
controls to provide a standardized UX across browsers, but really the
main reason is that Safari's default video controls are on the verge of
unusable, especially for streaming playback),
2. [hls-video-element](https://github.com/muxinc/media-elements/tree/main/packages/hls-video-element)
provides a custom web component element that glues media-chrome and
hls.js together, and
3. [hls.js](https://github.com/video-dev/hls.js/) (indirect dependency via
hls-video-element) is needed on HLS playback on Chrome and Firefox (which
do not have native support for HLS playlists).
- [react-dropzone](https://github.com/react-dropzone/react-dropzone/) is a React
hook to create a drag-and-drop input zone.
- [sanitize-filename](https://github.com/parshap/node-sanitize-filename) is for
converting arbitrary strings into strings that are suitable for being used as
filenames.
- [chrono-node](https://github.com/wanasit/chrono) is used for parsing natural
language queries into dates for showing search results.
- [ml-matrix](https://github.com/mljs/matrix) is mathematical matrix abstraction
by the machine learning code. It is used alongwith
[similarity-transformation](https://github.com/shaileshpandit/similarity-transformation-js)
during face alignment.
- [react-top-loading-bar](https://github.com/klendi/react-top-loading-bar) is
used for showing a progress indicator for global actions (This shouldn't be
used always, it is only meant as a fallback when there isn't an otherwise
suitable place for showing a local activity indicator).
## Auth app specific
- [otpauth](https://github.com/hectorm/otpauth) is used for the generation of
the actual OTP from the user's TOTP/HOTP secret.
- However, otpauth doesn't support steam OTPs. For these, we need to compute the
SHA-1, and we use the same library, `jssha` that `otpauth` uses since it is
already part of our bundle (transitively).
## Pinned
- `otpauth` is pinned to 9.2.4 since subsequent versions changed the underlying
hash library, which requires a change in the steam OTP generation code.
- `react-dropzone` is pinned to the 14.2.10, the last version in the 14.2
series, since if we use 14.3 onwards (I tested till 14.3.5) then we are unable
to get back a path from the file by using the `webUtils.getPathForFile`
function provided by Electron. See:
https://github.com/react-dropzone/react-dropzone/issues/1411
- `@stripe/stripe-js` is pinned to the latest 1.x (it works as it is currently,
migrating to newer major versions requires headspace since it _might_ also
require museum changes).
- `file-type` is pinned to 16.5.4 since subsequent versions are ESM only.