Merge branch 'main' into cast

This commit is contained in:
Neeraj Gupta 2024-02-13 09:35:00 +05:30 committed by GitHub
commit de163b79db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 216 additions and 258 deletions

View file

@ -1,11 +0,0 @@
version = 1
[[analyzers]]
name = "javascript"
enabled = true
[analyzers.meta]
plugins = ["react"]
environment = ["browser"]
style_guide = "standard"
dialect = "typescript"

View file

@ -1,6 +1,3 @@
import { setupSentry } from '@ente/shared/sentry/config/sentry.config.base';
const DEFAULT_SENTRY_DSN =
'https://e2ccc39d811640b49602323774220955@sentry.ente.io/13';
setupSentry(DEFAULT_SENTRY_DSN);
setupSentry('https://ad075e4713480307bb8bc0811547c65e@sentry.ente.io/8');

View file

@ -0,0 +1,98 @@
# Sample configuration file
#
# All variables are commented out by default. Copy paste this into a new file
# called `.env.local`, or create a new file with that name and add the
# environment variables you need into it. That `.env.local` file will be
# .gitignored, so you can freely customize how the app runs in your local setup.
#
# - `.env.local` is picked up by next when NODE_ENV is development
#
# - `.env` is picked up always
#
# You don't necessarily need to use these files, these variables can be provided
# as environment variables when running yarn dev too. e.g.
#
# NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:3000 yarn dev:photos
#
# Variables prefixed with NEXT_PUBLIC_ (in our case, all of them) are made
# available when next runs our code in the browser. For more details, see
# https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables
#
# By default, the app is configured to connect to the production instance etc.
# This is usually a good default, for example someone might want to run the
# client locally but still use their actual ente account.
#
# Even though it connects to the production instances, when invoked with `yarn
# dev:*`, next will behave as if NODE_ENV was set to 'development' (otherwise
# this is assumed to be 'production'). There are some other cases too when we
# assume we're in a dev environment (e.g. the NEXT_PUBLIC_APP_ENV env var below.
# For the full list of rules that decide what counts as a dev build, see the
# `isDevDeployment` function).
#
# We have some development related conveniences tied to the dev build:
# 1. Logs go to the browser console instead of the log file
# 2. Sentry crash reporting etc is disabled
#
# The variables below thus serve as ways to customize which API instance we
# connect to for various purposes. These variables are only honoured when we're
# in a development environment.
# The ente API endpoint
# NEXT_PUBLIC_ENTE_ENDPOINT=http://localhost:3000
# The ente API endpoint for payments related functionality
# NEXT_PUBLIC_ENTE_PAYMENT_ENDPOINT = http://localhost:3001
# The URL for the shared albums deployment
#
# Currently the shared albums code is intermixed with the photos app code; when
# deploying, we add an a CNAME alias from "albums.ente.io" -> "/shared-album".
#
# Enhancement: Consider splitting this into a separate app/ in this repository.
# NEXT_PUBLIC_ENTE_ALBUM_ENDPOINT = http://localhost:3002
# The URL of the family plans web app deployment
#
# Currently the source code for the family plan related pages is in a separate
# repository (https://github.com/ente-io/families). The mobile app also uses
# these pages.
#
# Enhancement: Consider moving that into the app/ folder in this repository.
# NEXT_PUBLIC_ENTE_FAMILY_PORTAL_ENDPOINT = http://localhost:3003
# This in not useful when running locally. It is used to provide us a way to
# mark certain deployments as "staging" by setting environment variables in the
# CI job that deploys them on a remote server. See the `isDevDeployment`
# function.
#
# By default, the photos web app gets deployed to "web.ente.io".
# NEXT_PUBLIC_ENTE_WEB_ENDPOINT = http://localhost:3000
# Set this to true to disable reporting of crashes to Sentry.
#
# Crash reporting is disabled if the user has opted out. This provides another
# way to disable crash reporting, say for local test branches.
# NEXT_PUBLIC_DISABLE_SENTRY=true
# Set this to disable the upload of files via CF Workers
#
# CF workers provide us with a way of make the file uploads faster. The why and
# how is explained here: https://ente.io/blog/tech/making-uploads-faster/
#
# By default, that's the route we take. This flag can be set to true to disable
# that route, and instead directly upload to the S3-compatible URLs provided by
# our API server.
#
# Note the double negative.
# NEXT_PUBLIC_DISABLE_CF_UPLOAD_PROXY = true
# This is an alternative to run as a development build.
#
# You likely don't need this if you're running on your machine, because when
# invoked with `next dev` (as is the case for `yarn dev:photos` etc), next will
# behave as if NODE_ENV was set to 'development'.
# NEXT_PUBLIC_APP_ENV = development
# The path of the JSON file which contains the expected results of our
# integration tests. See `upload.test.ts` for more details.
# NEXT_PUBLIC_EXPECTED_JSON_PATH = /path/to/dataset/expected.json

View file

@ -70,11 +70,6 @@
"transformation-matrix": "^2.15.0",
"uuid": "^9.0.0",
"vscode-uri": "^3.0.7",
"workbox-precaching": "^6.1.5",
"workbox-recipes": "^6.1.5",
"workbox-routing": "^6.1.5",
"workbox-strategies": "^6.1.5",
"workbox-window": "^6.1.5",
"xml-js": "^1.6.11",
"yup": "^0.29.3",
"zxcvbn": "^4.4.2"

View file

@ -210,7 +210,7 @@
"SEARCH_TYPE": {
"COLLECTION": "Album",
"LOCATION": "Locatie",
"CITY": "",
"CITY": "Locatie",
"DATE": "Datum",
"FILE_NAME": "Bestandsnaam",
"THING": "Inhoud",
@ -626,7 +626,7 @@
"MAGIC_SEARCH_STATUS": "Magische Zoekfunctie Status",
"INDEXED_ITEMS": "Geïndexeerde bestanden",
"CACHE_DIRECTORY": "Cache map",
"FREEHAND": "",
"APPLY_CROP": "",
"PHOTO_EDIT_REQUIRED_TO_SAVE": ""
"FREEHAND": "Losse hand",
"APPLY_CROP": "Bijsnijden toepassen",
"PHOTO_EDIT_REQUIRED_TO_SAVE": "Tenminste één transformatie of kleuraanpassing moet worden uitgevoerd voordat u opslaat."
}

View file

@ -1,66 +0,0 @@
{
"short_name": "Ente Photos",
"name": "Ente Photos | Safe home for your Photos",
"icons": [
{
"src": "/images/ente/192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "/images/ente/256.png",
"type": "image/png",
"sizes": "256x256"
},
{
"src": "/images/ente/512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": "/",
"background_color": "#191919",
"display": "standalone",
"scope": "/",
"theme_color": "#111",
"description": "ente provides a simple way to back up your memories.",
"prefer_related_applications": true,
"related_applications": [
{
"platform": "play",
"url": "https://play.google.com/store/apps/details?id=io.ente.photos",
"id": "io.ente.photos"
},
{
"platform": "itunes",
"url": "https://apps.apple.com/in/app/ente-photos/id1542026904"
}
],
"screenshots": [
{
"src": "/pwa/slide-1.jpg",
"type": "image/jpeg",
"sizes": "417x760"
},
{
"src": "/pwa/slide-2.jpg",
"type": "image/jpeg",
"sizes": "378x690"
},
{
"src": "/pwa/slide-3.jpg",
"type": "image/jpeg",
"sizes": "378x690"
},
{
"src": "/pwa/slide-4.jpg",
"type": "image/jpeg",
"sizes": "378x690"
},
{
"src": "/pwa/slide-5.jpg",
"type": "image/jpeg",
"sizes": "378x690"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

View file

@ -1,5 +1,3 @@
import { setupSentry } from '@ente/shared/sentry/config/sentry.config.base';
const DEFAULT_SENTRY_DSN =
'https://bd3656fc40d74d5e8f278132817963a3@sentry.ente.io/2';
setupSentry(DEFAULT_SENTRY_DSN);
setupSentry('https://cbed7333f2810fbbdb692dcd76d8ca1a@sentry.ente.io/2');

View file

@ -39,30 +39,38 @@ export default function AddParticipant({
[emailList, collection.sharees]
);
const collectionShare: AddParticipantFormProps['callback'] = async (
const collectionShare: AddParticipantFormProps['callback'] = async ({
email,
emails,
setFieldError,
resetForm
) => {
try {
for (const email of emails) {
if (email === user.email) {
setFieldError(t('SHARE_WITH_SELF'));
break;
} else if (
collection?.sharees?.find((value) => value.email === email)
) {
setFieldError(t('ALREADY_SHARED', { email }));
break;
} else {
await shareCollection(collection, email, type);
await syncWithRemote(false, true);
}
}) => {
// if email is provided, means user has custom entered email, so, will need to validate for self sharing
// and already shared
if (email) {
if (email === user.email) {
throw new Error(t('SHARE_WITH_SELF'));
} else if (
collection?.sharees?.find((value) => value.email === email)
) {
throw new Error(t('ALREADY_SHARED', { email: email }));
}
// set emails to array of one email
emails = [email];
}
for (const email of emails) {
if (
email === user.email ||
collection?.sharees?.find((value) => value.email === email)
) {
// can just skip this email
continue;
}
try {
await shareCollection(collection, email, type);
await syncWithRemote(false, true);
} catch (e) {
const errorMessage = handleSharingErrors(e);
throw new Error(errorMessage);
}
resetForm();
} catch (e) {
const errorMessage = handleSharingErrors(e);
setFieldError(errorMessage);
}
};

View file

@ -1,5 +1,5 @@
import React, { useMemo, useState } from 'react';
import { Formik, FormikHelpers, FormikState } from 'formik';
import { Formik, FormikHelpers } from 'formik';
import * as Yup from 'yup';
import SubmitButton from '@ente/shared/components/SubmitButton';
import TextField from '@mui/material/TextField';
@ -18,11 +18,7 @@ interface formValues {
selectedOptions: string[];
}
export interface AddParticipantFormProps {
callback: (
emails: string[],
setFieldError: (errorMessage: string) => void,
resetForm: (nextState?: Partial<FormikState<formValues>>) => void
) => Promise<void>;
callback: (props: { email?: string; emails?: string[] }) => Promise<void>;
fieldType: 'text' | 'email' | 'password';
placeholder: string;
buttonText: string;
@ -43,7 +39,6 @@ export interface AddParticipantFormProps {
export default function AddParticipantForm(props: AddParticipantFormProps) {
const { submitButtonProps } = props;
const { sx: buttonSx, ...restSubmitButtonProps } = submitButtonProps ?? {};
const [disableInput, setDisableInput] = useState(false);
const [loading, SetLoading] = useState(false);
@ -51,26 +46,20 @@ export default function AddParticipantForm(props: AddParticipantFormProps) {
values: formValues,
{ setFieldError, resetForm }: FormikHelpers<formValues>
) => {
SetLoading(true);
if (values.inputValue !== '') {
await props.callback(
[values.inputValue],
(message) => setFieldError('inputValue', message),
resetForm
);
} else if (values.selectedOptions.length !== 0) {
await props.callback(
values.selectedOptions,
(message) => setFieldError('inputValue', message),
resetForm
);
try {
SetLoading(true);
if (values.inputValue !== '') {
await props.callback({ email: values.inputValue });
} else if (values.selectedOptions.length !== 0) {
await props.callback({ emails: values.selectedOptions });
}
SetLoading(false);
props.onClose();
resetForm();
} catch (e) {
setFieldError('inputValue', e?.message);
SetLoading(false);
}
setDisableInput(false);
SetLoading(false);
props.onClose();
};
const validationSchema = useMemo(() => {
@ -129,7 +118,7 @@ export default function AddParticipantForm(props: AddParticipantFormProps) {
error={Boolean(errors.inputValue)}
helperText={errors.inputValue}
value={values.inputValue}
disabled={loading || disableInput}
disabled={loading}
autoFocus={!props.disableAutoFocus}
autoComplete={props.autoComplete}
/>

View file

@ -5,7 +5,7 @@ import { ALL_SECTION } from 'constants/collection';
import { AppContext } from 'pages/_app';
import { createContext, useContext, useEffect, useState } from 'react';
import { getDuplicates, Duplicate } from 'services/deduplicationService';
import { getLocalFiles, trashFiles } from 'services/fileService';
import { getLocalFiles, syncFiles, trashFiles } from 'services/fileService';
import { SelectedState } from 'types/gallery';
import { ApiError } from '@ente/shared/error';
@ -20,13 +20,17 @@ import { PHOTOS_PAGES as PAGES } from '@ente/shared/constants/pages';
import router from 'next/router';
import { getKey, SESSION_KEYS } from '@ente/shared/storage/sessionStorage';
import { styled } from '@mui/material';
import { getLocalCollections } from 'services/collectionService';
import {
getAllLatestCollections,
getLocalCollections,
} from 'services/collectionService';
import EnteSpinner from '@ente/shared/components/EnteSpinner';
import { VerticallyCentered } from '@ente/shared/components/Container';
import Typography from '@mui/material/Typography';
import useMemoSingleThreaded from '@ente/shared/hooks/useMemoSingleThreaded';
import InMemoryStore, { MS_KEYS } from '@ente/shared/storage/InMemoryStore';
import { HttpStatusCode } from 'axios';
import { syncTrash } from 'services/trashService';
export const DeduplicateContext = createContext<DeduplicateContextType>(
DefaultDeduplicateContext
@ -118,6 +122,17 @@ export default function Deduplicate() {
startLoading();
const selectedFiles = getSelectedFiles(selected, duplicateFiles);
await trashFiles(selectedFiles);
// trashFiles above does an API request, we still need to update our
// local state.
//
// Enhancement: This can be done in a more granular manner. Also, it
// is better to funnel these syncs instead of adding these here and
// there in an ad-hoc manner. For now, this fixes the issue with the
// UI not updating if the user deletes only some of the duplicates.
const collections = await getAllLatestCollections();
await syncFiles('normal', collections, () => {});
await syncTrash(collections, () => {});
} catch (e) {
if (
e instanceof ApiError &&

View file

@ -1,11 +1,15 @@
import { DataStream } from 'types/upload';
import ImportService from 'services/importService';
import ElectronAPIs from '@ente/shared/electron';
import { FILE_READER_CHUNK_SIZE, PICKED_UPLOAD_TYPE } from 'constants/upload';
import { getFileStream, getElectronFileStream } from 'services/readerService';
import { getFileNameSize } from '@ente/shared/logging/web';
import isElectron from 'is-electron';
import { getImportSuggestion } from 'utils/upload';
// This was for used to verify that converting from the browser readable stream
// to the node readable stream correctly handles files that align on the 4 MB
// data boundary. This expects a zip file containing random files of various
// sizes starting from 1M to 20M.
export const testZipFileReading = async () => {
try {
if (!isElectron()) {
@ -17,12 +21,12 @@ export const testZipFileReading = async () => {
'upload test failed NEXT_PUBLIC_FILE_READING_TEST_ZIP_PATH missing'
);
}
const files = await ImportService.getElectronFilesFromGoogleZip(
const files = await ElectronAPIs.getElectronFilesFromGoogleZip(
process.env.NEXT_PUBLIC_FILE_READING_TEST_ZIP_PATH
);
if (!files?.length) {
throw Error(
`testZipFileReading Check failed ❌
`testZipFileReading Check failed ❌
No files selected`
);
}
@ -73,6 +77,8 @@ export const testZipFileReading = async () => {
}
};
// This was used when fixing a bug around handling a zip file that has a photo
// at the root.
export const testZipWithRootFileReadingTest = async () => {
try {
if (!isElectron()) {
@ -84,7 +90,7 @@ export const testZipWithRootFileReadingTest = async () => {
'upload test failed NEXT_PUBLIC_ZIP_WITH_ROOT_FILE_PATH missing'
);
}
const files = await ImportService.getElectronFilesFromGoogleZip(
const files = await ElectronAPIs.getElectronFilesFromGoogleZip(
process.env.NEXT_PUBLIC_ZIP_WITH_ROOT_FILE_PATH
);

View file

@ -7,6 +7,4 @@ export const isDisableSentryFlagSet = () => {
return process.env.NEXT_PUBLIC_DISABLE_SENTRY === 'true';
};
export const getSentryDSN = () => process.env.NEXT_PUBLIC_SENTRY_DSN;
export const getSentryRelease = () => process.env.SENTRY_RELEASE;

View file

@ -1,11 +1,5 @@
import { getData, LS_KEYS } from '../storage/localStorage';
export const getEndpoint = () => {
let endpoint = getData(LS_KEYS.API_ENDPOINT);
if (endpoint) {
return endpoint;
}
endpoint = process.env.NEXT_PUBLIC_ENTE_ENDPOINT;
const endpoint = process.env.NEXT_PUBLIC_ENTE_ENDPOINT;
if (isDevDeployment() && endpoint) {
return endpoint;
}
@ -94,20 +88,6 @@ export const getFamilyPortalURL = () => {
return `https://family.ente.io`;
};
// getAuthenticatorURL returns the endpoint for the authenticator which can be used to
// view authenticator codes.
export const getAuthURL = () => {
const authURL = process.env.NEXT_PUBLIC_ENTE_AUTH_ENDPOINT;
if (isDevDeployment() && authURL) {
return authURL;
}
return `https://auth.ente.io`;
};
export const getSentryTunnelURL = () => {
return `https://sentry-reporter.ente.io`;
};
/*
It's a dev deployment (and should use the environment override for endpoints ) in three cases:
1. when the URL opened is that of the staging web app, or

View file

@ -1,33 +1,27 @@
import * as Sentry from '@sentry/nextjs';
import { getSentryTunnelURL } from '@ente/shared/network/api';
import { getSentryUserID } from '@ente/shared/sentry/utils';
import { runningInBrowser } from '@ente/shared/platform';
import { getHasOptedOutOfCrashReports } from '@ente/shared/storage/localStorage/helpers';
import { getIsSentryEnabled } from '@ente/shared/sentry/utils';
import {
getAppEnv,
getSentryDSN,
getSentryRelease,
} from '@ente/shared/apps/env';
import { getAppEnv, getSentryRelease } from '@ente/shared/apps/env';
export const setupSentry = async (DEFAULT_SENTRY_DSN: string) => {
export const setupSentry = async (dsn: string) => {
const HAS_OPTED_OUT_OF_CRASH_REPORTING =
runningInBrowser() && getHasOptedOutOfCrashReports();
if (!HAS_OPTED_OUT_OF_CRASH_REPORTING) {
const SENTRY_DSN = getSentryDSN() ?? DEFAULT_SENTRY_DSN;
const APP_ENV = getAppEnv();
const IS_ENABLED = getIsSentryEnabled();
const SENTRY_RELEASE = getSentryRelease();
Sentry.init({
dsn: SENTRY_DSN,
dsn,
enabled: IS_ENABLED,
environment: APP_ENV,
release: SENTRY_RELEASE,
attachStacktrace: true,
autoSessionTracking: false,
tunnel: getSentryTunnelURL(),
tunnel: 'https://sentry-reporter.ente.io',
beforeSend(event) {
event.request = event.request || {};
const currentURL = new URL(document.location.href);

33
scripts/deploy.sh Executable file
View file

@ -0,0 +1,33 @@
#!/bin/sh
# This script is run by the Cloudflare Pages integration when deploying the apps
# in this repository. The app to build is decided based on the the value of the
# CF_PAGES_BRANCH environment variable.
#
# Ref: https://developers.cloudflare.com/pages/how-to/build-commands-branches/
#
# The CF Pages configuration is set to use `out/` as the build output directory,
# so once we're done building we copy the app specific output to `out/`.
set -o errexit
set -o xtrace
rm -rf out
if test "$CF_PAGES_BRANCH" = "auth-release"
then
# By default, for preview deployments the NEXT_PUBLIC_APP_ENV is set to
# "test" in the CF environment variables. For production deployments of the
# auth app, reset this to "production".
#
# This is not needed for the default `yarn export:photos` case, because
# there the actual production deployment runs without NEXT_PUBLIC_APP_ENV
# being set to anything (and the other preview deployments have
# NEXT_PUBLIC_APP_ENV set to "test", as is correct).
export NEXT_PUBLIC_APP_ENV=production
yarn export:auth
cp -R apps/auth/out .
else
yarn export:photos
cp -R apps/photos/out .
fi

View file

@ -24,13 +24,10 @@
"NEXT_PUBLIC_ENTE_PAYMENT_ENDPOINT",
"NEXT_PUBLIC_ENTE_ALBUM_ENDPOINT",
"NEXT_PUBLIC_ENTE_FAMILY_PORTAL_ENDPOINT",
"NEXT_PUBLIC_ENTE_AUTH_ENDPOINT",
"NEXT_PUBLIC_ENTE_WEB_ENDPOINT",
"NEXT_PUBLIC_IS_TEST_APP",
"NODE_ENV",
"SENTRY_RELEASE",
"SENTRY_AUTH_TOKEN",
"NEXT_PUBLIC_SENTRY_DSN",
"NEXT_PUBLIC_SENTRY_ENV"
"SENTRY_AUTH_TOKEN"
]
}

View file

@ -936,11 +936,6 @@
resolved "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz"
integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==
"@types/trusted-types@^2.0.2":
version "2.0.2"
resolved "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz"
integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
"@types/uuid@^9.0.2":
version "9.0.2"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.2.tgz#ede1d1b1e451548d44919dc226253e32a6952c4b"
@ -2619,11 +2614,6 @@ i18next@^23.4.1:
dependencies:
"@babel/runtime" "^7.22.5"
idb@^6.0.0:
version "6.1.3"
resolved "https://registry.npmjs.org/idb/-/idb-6.1.3.tgz"
integrity sha512-oIRDpVcs5KXpI1hRnTJUwkY63RB/7iqu9nSNuzXN8TLHjs7oO20IoPFbBTsqxIL5IjzIUDi+FXlVcK4zm26J8A==
idb@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b"
@ -4727,69 +4717,6 @@ word-wrap@^1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==
workbox-cacheable-response@6.3.0:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.3.0.tgz"
integrity sha512-oYCRGF6PFEmJJkktdxYw/tcrU8N5u/2ihxVSHd+9sNqjNMDiXLqsewcEG544f1yx7gq5/u6VcvUA5N62KzN1GQ==
dependencies:
workbox-core "6.3.0"
workbox-core@6.3.0:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-core/-/workbox-core-6.3.0.tgz"
integrity sha512-SufToEV3SOLwwz3j+P4pgkfpzLRUlR17sX3p/LrMHP/brYKvJQqjTwtSvaCkkAX0RPHX2TFHmN8xhPP1bpmomg==
workbox-expiration@6.3.0:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.3.0.tgz"
integrity sha512-teYuYfM3HFbwAD/nlZDw/dCMOrCKjsAiMRhz0uOy9IkfBb7vBynO3xf118lY62X6BfqjZdeahiHh10N0/aYICg==
dependencies:
idb "^6.0.0"
workbox-core "6.3.0"
workbox-precaching@6.3.0, workbox-precaching@^6.1.5:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.3.0.tgz"
integrity sha512-bND3rUxiuzFmDfeKywdvOqK0LQ5LLbOPk0eX22PlMQNOOduHRxzglMpgHo/MR6h+8cPJ3GpxT8hZ895/7bHMqQ==
dependencies:
workbox-core "6.3.0"
workbox-routing "6.3.0"
workbox-strategies "6.3.0"
workbox-recipes@^6.1.5:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.3.0.tgz"
integrity sha512-f0AZyxd48E4t+PV+ifgIf8WodfJqRj8/E0t+PwppDIdTPyD59cIh0HZBtgPKFdIMVnltodpMz4zioxym1H3GjQ==
dependencies:
workbox-cacheable-response "6.3.0"
workbox-core "6.3.0"
workbox-expiration "6.3.0"
workbox-precaching "6.3.0"
workbox-routing "6.3.0"
workbox-strategies "6.3.0"
workbox-routing@6.3.0, workbox-routing@^6.1.5:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.3.0.tgz"
integrity sha512-asajX5UPkaoU4PB9pEpxKWKkcpA+KJQUEeYU6NlK0rXTCpdWQ6iieMRDoBTZBjTzUdL3j3s1Zo2qCOSvtXSYGg==
dependencies:
workbox-core "6.3.0"
workbox-strategies@6.3.0, workbox-strategies@^6.1.5:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.3.0.tgz"
integrity sha512-SYZt40y+Iu5nA+UEPQOrAuAMMNTxtUBPLCIaMMb4lcADpBYrNP1CD+/s2QsrxzS651a8hfi06REKt+uTp1tqfw==
dependencies:
workbox-core "6.3.0"
workbox-window@^6.1.5:
version "6.3.0"
resolved "https://registry.npmjs.org/workbox-window/-/workbox-window-6.3.0.tgz"
integrity sha512-CFP84assX9srH/TOx4OD8z4EBPO/Cq4WKdV2YLcJIFJmVTS/cB63XKeidKl2KJk8qOOLVIKnaO7BLmb0MxGFtA==
dependencies:
"@types/trusted-types" "^2.0.2"
workbox-core "6.3.0"
wrap-ansi@^6.2.0:
version "6.2.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz"