diff --git a/Makefile b/Makefile
index 52be5d8055..3f5d70c92f 100644
--- a/Makefile
+++ b/Makefile
@@ -17,4 +17,7 @@ prod:
 	docker-compose -f ./docker/docker-compose.yml up --build -V --remove-orphans
 
 prod-scale:
-	docker-compose -f ./docker/docker-compose.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans
\ No newline at end of file
+	docker-compose -f ./docker/docker-compose.yml up --build -V --scale immich-server=3 --scale immich-microservices=3 --remove-orphans
+
+api:
+	cd ./server && npm run api:generate
\ No newline at end of file
diff --git a/mobile/lib/modules/sharing/ui/month_group_title.dart b/mobile/lib/modules/sharing/ui/month_group_title.dart
index ba766721aa..5ea00d1532 100644
--- a/mobile/lib/modules/sharing/ui/month_group_title.dart
+++ b/mobile/lib/modules/sharing/ui/month_group_title.dart
@@ -96,13 +96,16 @@ class MonthGroupTitle extends HookConsumerWidget {
                       color: Colors.grey,
                     ),
             ),
-            Padding(
-              padding: const EdgeInsets.only(left: 8.0),
-              child: Text(
-                _getSimplifiedMonth(),
-                style: TextStyle(
-                  fontSize: 24,
-                  color: Theme.of(context).primaryColor,
+            GestureDetector(
+              onTap: _handleTitleIconClick,
+              child: Padding(
+                padding: const EdgeInsets.only(left: 8.0),
+                child: Text(
+                  _getSimplifiedMonth(),
+                  style: TextStyle(
+                    fontSize: 24,
+                    color: Theme.of(context).primaryColor,
+                  ),
                 ),
               ),
             ),
diff --git a/mobile/lib/modules/sharing/ui/selection_thumbnail_image.dart b/mobile/lib/modules/sharing/ui/selection_thumbnail_image.dart
index 24be821066..a81b5416df 100644
--- a/mobile/lib/modules/sharing/ui/selection_thumbnail_image.dart
+++ b/mobile/lib/modules/sharing/ui/selection_thumbnail_image.dart
@@ -26,17 +26,21 @@ class SelectionThumbnailImage extends HookConsumerWidget {
     var isAlbumExist = ref.watch(assetSelectionProvider).isAlbumExist;
 
     Widget _buildSelectionIcon(AssetResponseDto asset) {
-      if (selectedAsset.contains(asset) && !isAlbumExist) {
+      var isSelected = selectedAsset.map((item) => item.id).contains(asset.id);
+      var isNewlySelected =
+          newAssetsForAlbum.map((item) => item.id).contains(asset.id);
+
+      if (isSelected && !isAlbumExist) {
         return Icon(
           Icons.check_circle,
           color: Theme.of(context).primaryColor,
         );
-      } else if (selectedAsset.contains(asset) && isAlbumExist) {
+      } else if (isSelected && isAlbumExist) {
         return const Icon(
           Icons.check_circle,
           color: Color.fromARGB(255, 233, 233, 233),
         );
-      } else if (newAssetsForAlbum.contains(asset) && isAlbumExist) {
+      } else if (isNewlySelected && isAlbumExist) {
         return Icon(
           Icons.check_circle,
           color: Theme.of(context).primaryColor,
@@ -50,17 +54,21 @@ class SelectionThumbnailImage extends HookConsumerWidget {
     }
 
     BoxBorder drawBorderColor() {
-      if (selectedAsset.contains(asset) && !isAlbumExist) {
+      var isSelected = selectedAsset.map((item) => item.id).contains(asset.id);
+      var isNewlySelected =
+          newAssetsForAlbum.map((item) => item.id).contains(asset.id);
+
+      if (isSelected && !isAlbumExist) {
         return Border.all(
           color: Theme.of(context).primaryColorLight,
           width: 10,
         );
-      } else if (selectedAsset.contains(asset) && isAlbumExist) {
+      } else if (isSelected && isAlbumExist) {
         return Border.all(
           color: const Color.fromARGB(255, 190, 190, 190),
           width: 10,
         );
-      } else if (newAssetsForAlbum.contains(asset) && isAlbumExist) {
+      } else if (isNewlySelected && isAlbumExist) {
         return Border.all(
           color: Theme.of(context).primaryColorLight,
           width: 10,
@@ -71,10 +79,15 @@ class SelectionThumbnailImage extends HookConsumerWidget {
 
     return GestureDetector(
       onTap: () {
+        var isSelected =
+            selectedAsset.map((item) => item.id).contains(asset.id);
+        var isNewlySelected =
+            newAssetsForAlbum.map((item) => item.id).contains(asset.id);
+
         if (isAlbumExist) {
           // Operation for existing album
-          if (!selectedAsset.contains(asset)) {
-            if (newAssetsForAlbum.contains(asset)) {
+          if (!isSelected) {
+            if (isNewlySelected) {
               ref
                   .watch(assetSelectionProvider.notifier)
                   .removeSelectedAdditionalAssets([asset]);
@@ -86,7 +99,7 @@ class SelectionThumbnailImage extends HookConsumerWidget {
           }
         } else {
           // Operation for new album
-          if (selectedAsset.contains(asset)) {
+          if (isSelected) {
             ref
                 .watch(assetSelectionProvider.notifier)
                 .removeSelectedNewAssets([asset]);
diff --git a/mobile/openapi/.openapi-generator/FILES b/mobile/openapi/.openapi-generator/FILES
index 9818927be1..4aba072ed0 100644
--- a/mobile/openapi/.openapi-generator/FILES
+++ b/mobile/openapi/.openapi-generator/FILES
@@ -37,6 +37,7 @@ doc/ServerPingResponse.md
 doc/ServerVersionReponseDto.md
 doc/SignUpDto.md
 doc/SmartInfoResponseDto.md
+doc/ThumbnailFormat.md
 doc/UpdateAlbumDto.md
 doc/UpdateDeviceInfoDto.md
 doc/UpdateUserDto.md
@@ -90,6 +91,7 @@ lib/model/server_ping_response.dart
 lib/model/server_version_reponse_dto.dart
 lib/model/sign_up_dto.dart
 lib/model/smart_info_response_dto.dart
+lib/model/thumbnail_format.dart
 lib/model/update_album_dto.dart
 lib/model/update_device_info_dto.dart
 lib/model/update_user_dto.dart
@@ -97,4 +99,4 @@ lib/model/user_count_response_dto.dart
 lib/model/user_response_dto.dart
 lib/model/validate_access_token_response_dto.dart
 pubspec.yaml
-test/validate_access_token_response_dto_test.dart
+test/thumbnail_format_test.dart
diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md
index 1e9edfc0a0..95a02aed9a 100644
--- a/mobile/openapi/README.md
+++ b/mobile/openapi/README.md
@@ -136,6 +136,7 @@ Class | Method | HTTP request | Description
  - [ServerVersionReponseDto](doc//ServerVersionReponseDto.md)
  - [SignUpDto](doc//SignUpDto.md)
  - [SmartInfoResponseDto](doc//SmartInfoResponseDto.md)
+ - [ThumbnailFormat](doc//ThumbnailFormat.md)
  - [UpdateAlbumDto](doc//UpdateAlbumDto.md)
  - [UpdateDeviceInfoDto](doc//UpdateDeviceInfoDto.md)
  - [UpdateUserDto](doc//UpdateUserDto.md)
diff --git a/mobile/openapi/doc/AssetApi.md b/mobile/openapi/doc/AssetApi.md
index 89455a9e6a..dc01b3282e 100644
--- a/mobile/openapi/doc/AssetApi.md
+++ b/mobile/openapi/doc/AssetApi.md
@@ -311,7 +311,7 @@ This endpoint does not need any parameter.
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
 # **getAssetThumbnail**
-> Object getAssetThumbnail(assetId)
+> Object getAssetThumbnail(assetId, format)
 
 
 
@@ -327,9 +327,10 @@ import 'package:openapi/api.dart';
 
 final api_instance = AssetApi();
 final assetId = assetId_example; // String | 
+final format = ; // ThumbnailFormat | 
 
 try {
-    final result = api_instance.getAssetThumbnail(assetId);
+    final result = api_instance.getAssetThumbnail(assetId, format);
     print(result);
 } catch (e) {
     print('Exception when calling AssetApi->getAssetThumbnail: $e\n');
@@ -341,6 +342,7 @@ try {
 Name | Type | Description  | Notes
 ------------- | ------------- | ------------- | -------------
  **assetId** | **String**|  | 
+ **format** | [**ThumbnailFormat**](.md)|  | [optional] 
 
 ### Return type
 
diff --git a/mobile/openapi/doc/ThumbnailFormat.md b/mobile/openapi/doc/ThumbnailFormat.md
new file mode 100644
index 0000000000..5cd36c673f
--- /dev/null
+++ b/mobile/openapi/doc/ThumbnailFormat.md
@@ -0,0 +1,14 @@
+# openapi.model.ThumbnailFormat
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart
index 9d632532f1..6661ff267d 100644
--- a/mobile/openapi/lib/api.dart
+++ b/mobile/openapi/lib/api.dart
@@ -64,6 +64,7 @@ part 'model/server_ping_response.dart';
 part 'model/server_version_reponse_dto.dart';
 part 'model/sign_up_dto.dart';
 part 'model/smart_info_response_dto.dart';
+part 'model/thumbnail_format.dart';
 part 'model/update_album_dto.dart';
 part 'model/update_device_info_dto.dart';
 part 'model/update_user_dto.dart';
diff --git a/mobile/openapi/lib/api/asset_api.dart b/mobile/openapi/lib/api/asset_api.dart
index 7d541c69f7..f83ef32fb0 100644
--- a/mobile/openapi/lib/api/asset_api.dart
+++ b/mobile/openapi/lib/api/asset_api.dart
@@ -346,7 +346,9 @@ class AssetApi {
   /// Parameters:
   ///
   /// * [String] assetId (required):
-  Future<Response> getAssetThumbnailWithHttpInfo(String assetId,) async {
+  ///
+  /// * [ThumbnailFormat] format:
+  Future<Response> getAssetThumbnailWithHttpInfo(String assetId, { ThumbnailFormat? format, }) async {
     // ignore: prefer_const_declarations
     final path = r'/asset/thumbnail/{assetId}'
       .replaceAll('{assetId}', assetId);
@@ -358,6 +360,10 @@ class AssetApi {
     final headerParams = <String, String>{};
     final formParams = <String, String>{};
 
+    if (format != null) {
+      queryParams.addAll(_queryParams('', 'format', format));
+    }
+
     const contentTypes = <String>[];
 
 
@@ -375,8 +381,10 @@ class AssetApi {
   /// Parameters:
   ///
   /// * [String] assetId (required):
-  Future<Object?> getAssetThumbnail(String assetId,) async {
-    final response = await getAssetThumbnailWithHttpInfo(assetId,);
+  ///
+  /// * [ThumbnailFormat] format:
+  Future<Object?> getAssetThumbnail(String assetId, { ThumbnailFormat? format, }) async {
+    final response = await getAssetThumbnailWithHttpInfo(assetId,  format: format, );
     if (response.statusCode >= HttpStatus.badRequest) {
       throw ApiException(response.statusCode, await _decodeBodyBytes(response));
     }
diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart
index ae695c9698..c7223998fd 100644
--- a/mobile/openapi/lib/api_client.dart
+++ b/mobile/openapi/lib/api_client.dart
@@ -252,6 +252,8 @@ class ApiClient {
           return SignUpDto.fromJson(value);
         case 'SmartInfoResponseDto':
           return SmartInfoResponseDto.fromJson(value);
+        case 'ThumbnailFormat':
+          return ThumbnailFormatTypeTransformer().decode(value);
         case 'UpdateAlbumDto':
           return UpdateAlbumDto.fromJson(value);
         case 'UpdateDeviceInfoDto':
diff --git a/mobile/openapi/lib/api_helper.dart b/mobile/openapi/lib/api_helper.dart
index 325446498a..4e0c1e1572 100644
--- a/mobile/openapi/lib/api_helper.dart
+++ b/mobile/openapi/lib/api_helper.dart
@@ -64,6 +64,9 @@ String parameterToString(dynamic value) {
   if (value is DeviceTypeEnum) {
     return DeviceTypeEnumTypeTransformer().encode(value).toString();
   }
+  if (value is ThumbnailFormat) {
+    return ThumbnailFormatTypeTransformer().encode(value).toString();
+  }
   return value.toString();
 }
 
diff --git a/mobile/openapi/lib/model/thumbnail_format.dart b/mobile/openapi/lib/model/thumbnail_format.dart
new file mode 100644
index 0000000000..59091814f0
--- /dev/null
+++ b/mobile/openapi/lib/model/thumbnail_format.dart
@@ -0,0 +1,85 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+part of openapi.api;
+
+
+class ThumbnailFormat {
+  /// Instantiate a new enum with the provided [value].
+  const ThumbnailFormat._(this.value);
+
+  /// The underlying value of this enum member.
+  final String value;
+
+  @override
+  String toString() => value;
+
+  String toJson() => value;
+
+  static const JPEG = ThumbnailFormat._(r'JPEG');
+  static const WEBP = ThumbnailFormat._(r'WEBP');
+
+  /// List of all possible values in this [enum][ThumbnailFormat].
+  static const values = <ThumbnailFormat>[
+    JPEG,
+    WEBP,
+  ];
+
+  static ThumbnailFormat? fromJson(dynamic value) => ThumbnailFormatTypeTransformer().decode(value);
+
+  static List<ThumbnailFormat>? listFromJson(dynamic json, {bool growable = false,}) {
+    final result = <ThumbnailFormat>[];
+    if (json is List && json.isNotEmpty) {
+      for (final row in json) {
+        final value = ThumbnailFormat.fromJson(row);
+        if (value != null) {
+          result.add(value);
+        }
+      }
+    }
+    return result.toList(growable: growable);
+  }
+}
+
+/// Transformation class that can [encode] an instance of [ThumbnailFormat] to String,
+/// and [decode] dynamic data back to [ThumbnailFormat].
+class ThumbnailFormatTypeTransformer {
+  factory ThumbnailFormatTypeTransformer() => _instance ??= const ThumbnailFormatTypeTransformer._();
+
+  const ThumbnailFormatTypeTransformer._();
+
+  String encode(ThumbnailFormat data) => data.value;
+
+  /// Decodes a [dynamic value][data] to a ThumbnailFormat.
+  ///
+  /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
+  /// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
+  /// cannot be decoded successfully, then an [UnimplementedError] is thrown.
+  ///
+  /// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
+  /// and users are still using an old app with the old code.
+  ThumbnailFormat? decode(dynamic data, {bool allowNull = true}) {
+    if (data != null) {
+      switch (data.toString()) {
+        case r'JPEG': return ThumbnailFormat.JPEG;
+        case r'WEBP': return ThumbnailFormat.WEBP;
+        default:
+          if (!allowNull) {
+            throw ArgumentError('Unknown enum value to decode: $data');
+          }
+      }
+    }
+    return null;
+  }
+
+  /// Singleton [ThumbnailFormatTypeTransformer] instance.
+  static ThumbnailFormatTypeTransformer? _instance;
+}
+
diff --git a/mobile/openapi/test/thumbnail_format_test.dart b/mobile/openapi/test/thumbnail_format_test.dart
new file mode 100644
index 0000000000..9fb4c53878
--- /dev/null
+++ b/mobile/openapi/test/thumbnail_format_test.dart
@@ -0,0 +1,21 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+import 'package:openapi/api.dart';
+import 'package:test/test.dart';
+
+// tests for ThumbnailFormat
+void main() {
+
+  group('test ThumbnailFormat', () {
+
+  });
+
+}
diff --git a/server/apps/immich/src/api-v1/album/album-repository.ts b/server/apps/immich/src/api-v1/album/album-repository.ts
index b07e93c8e7..6336a2574b 100644
--- a/server/apps/immich/src/api-v1/album/album-repository.ts
+++ b/server/apps/immich/src/api-v1/album/album-repository.ts
@@ -84,7 +84,7 @@ export class AlbumRepository implements IAlbumRepository {
     });
   }
 
-  getList(ownerId: string, getAlbumsDto: GetAlbumsDto): Promise<AlbumEntity[]> {
+  async getList(ownerId: string, getAlbumsDto: GetAlbumsDto): Promise<AlbumEntity[]> {
     const filteringByShared = typeof getAlbumsDto.shared == 'boolean';
     const userId = ownerId;
     let query = this.albumRepository.createQueryBuilder('album');
@@ -132,35 +132,44 @@ export class AlbumRepository implements IAlbumRepository {
       query = query
         .leftJoinAndSelect('album.sharedUsers', 'sharedUser')
         .leftJoinAndSelect('sharedUser.userInfo', 'userInfo')
-        .where('album.ownerId = :ownerId', { ownerId: userId })
-        .orWhere((qb) => {
-          const subQuery = qb
-            .subQuery()
-            .select('userAlbum.albumId')
-            .from(UserAlbumEntity, 'userAlbum')
-            .where('userAlbum.sharedUserId = :sharedUserId', { sharedUserId: userId })
-            .getQuery();
-          return `album.id IN ${subQuery}`;
-        });
+        .where('album.ownerId = :ownerId', { ownerId: userId });
+      // .orWhere((qb) => {
+      //   const subQuery = qb
+      //     .subQuery()
+      //     .select('userAlbum.albumId')
+      //     .from(UserAlbumEntity, 'userAlbum')
+      //     .where('userAlbum.sharedUserId = :sharedUserId', { sharedUserId: userId })
+      //     .getQuery();
+      //   return `album.id IN ${subQuery}`;
+      // });
     }
-    return query.orderBy('album.createdAt', 'DESC').getMany();
+    // Get information of assets in albums
+    query = query
+      .leftJoinAndSelect('album.assets', 'assets')
+      .leftJoinAndSelect('assets.assetInfo', 'assetInfo')
+      .orderBy('"assetInfo"."createdAt"::timestamptz', 'ASC');
+    const albums = await query.getMany();
+
+    albums.sort((a, b) => new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf());
+
+    return albums;
   }
 
   async get(albumId: string): Promise<AlbumEntity | undefined> {
-    const album = await this.albumRepository.findOne({
-      where: { id: albumId },
-      relations: ['sharedUsers', 'sharedUsers.userInfo', 'assets', 'assets.assetInfo'],
-    });
+    let query = this.albumRepository.createQueryBuilder('album');
+
+    const album = await query
+      .where('album.id = :albumId', { albumId })
+      .leftJoinAndSelect('album.sharedUsers', 'sharedUser')
+      .leftJoinAndSelect('sharedUser.userInfo', 'userInfo')
+      .leftJoinAndSelect('album.assets', 'assets')
+      .leftJoinAndSelect('assets.assetInfo', 'assetInfo')
+      .orderBy('"assetInfo"."createdAt"::timestamptz', 'ASC')
+      .getOne();
 
     if (!album) {
       return;
     }
-    // TODO: sort in query
-    const sortedSharedAsset = album.assets?.sort(
-      (a, b) => new Date(a.assetInfo.createdAt).valueOf() - new Date(b.assetInfo.createdAt).valueOf(),
-    );
-
-    album.assets = sortedSharedAsset;
 
     return album;
   }
diff --git a/server/apps/immich/src/api-v1/asset/asset.controller.ts b/server/apps/immich/src/api-v1/asset/asset.controller.ts
index 2a7b30ab53..1ca5da30b7 100644
--- a/server/apps/immich/src/api-v1/asset/asset.controller.ts
+++ b/server/apps/immich/src/api-v1/asset/asset.controller.ts
@@ -43,6 +43,7 @@ import { AssetFileUploadDto } from './dto/asset-file-upload.dto';
 import { CreateAssetDto } from './dto/create-asset.dto';
 import { AssetFileUploadResponseDto } from './response-dto/asset-file-upload-response.dto';
 import { DeleteAssetResponseDto, DeleteAssetStatusEnum } from './response-dto/delete-asset-response.dto';
+import { GetAssetThumbnailDto } from './dto/get-asset-thumbnail.dto';
 
 @UseGuards(JwtAuthGuard)
 @ApiBearerAuth()
@@ -109,8 +110,11 @@ export class AssetController {
   }
 
   @Get('/thumbnail/:assetId')
-  async getAssetThumbnail(@Param('assetId') assetId: string): Promise<any> {
-    return this.assetService.getAssetThumbnail(assetId);
+  async getAssetThumbnail(
+    @Param('assetId') assetId: string,
+    @Query(new ValidationPipe({ transform: true })) query: GetAssetThumbnailDto,
+  ): Promise<any> {
+    return this.assetService.getAssetThumbnail(assetId, query);
   }
 
   @Get('/allObjects')
diff --git a/server/apps/immich/src/api-v1/asset/asset.service.ts b/server/apps/immich/src/api-v1/asset/asset.service.ts
index e92e3c855b..b0d954ee19 100644
--- a/server/apps/immich/src/api-v1/asset/asset.service.ts
+++ b/server/apps/immich/src/api-v1/asset/asset.service.ts
@@ -23,6 +23,7 @@ import { AssetResponseDto, mapAsset } from './response-dto/asset-response.dto';
 import { AssetFileUploadDto } from './dto/asset-file-upload.dto';
 import { CreateAssetDto } from './dto/create-asset.dto';
 import { DeleteAssetResponseDto, DeleteAssetStatusEnum } from './response-dto/delete-asset-response.dto';
+import { GetAssetThumbnailDto, GetAssetThumbnailFormatEnum } from './dto/get-asset-thumbnail.dto';
 
 const fileInfo = promisify(stat);
 
@@ -187,7 +188,7 @@ export class AssetService {
     }
   }
 
-  public async getAssetThumbnail(assetId: string) {
+  public async getAssetThumbnail(assetId: string, query: GetAssetThumbnailDto) {
     let fileReadStream: ReadStream;
 
     const asset = await this.assetRepository.findOne({ where: { id: assetId } });
@@ -197,16 +198,25 @@ export class AssetService {
     }
 
     try {
-      if (asset.webpPath && asset.webpPath.length > 0) {
-        await fs.access(asset.webpPath, constants.R_OK | constants.W_OK);
-        fileReadStream = createReadStream(asset.webpPath);
-      } else {
+      if (query.format == GetAssetThumbnailFormatEnum.JPEG) {
         if (!asset.resizePath) {
           throw new NotFoundException('resizePath not set');
         }
 
         await fs.access(asset.resizePath, constants.R_OK | constants.W_OK);
         fileReadStream = createReadStream(asset.resizePath);
+      } else {
+        if (asset.webpPath && asset.webpPath.length > 0) {
+          await fs.access(asset.webpPath, constants.R_OK | constants.W_OK);
+          fileReadStream = createReadStream(asset.webpPath);
+        } else {
+          if (!asset.resizePath) {
+            throw new NotFoundException('resizePath not set');
+          }
+
+          await fs.access(asset.resizePath, constants.R_OK | constants.W_OK);
+          fileReadStream = createReadStream(asset.resizePath);
+        }
       }
 
       return new StreamableFile(fileReadStream);
diff --git a/server/apps/immich/src/api-v1/asset/dto/get-asset-thumbnail.dto.ts b/server/apps/immich/src/api-v1/asset/dto/get-asset-thumbnail.dto.ts
new file mode 100644
index 0000000000..9f75369d7d
--- /dev/null
+++ b/server/apps/immich/src/api-v1/asset/dto/get-asset-thumbnail.dto.ts
@@ -0,0 +1,19 @@
+import { ApiProperty } from '@nestjs/swagger';
+import { Transform } from 'class-transformer';
+import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
+
+export enum GetAssetThumbnailFormatEnum {
+  JPEG = 'JPEG',
+  WEBP = 'WEBP',
+}
+
+export class GetAssetThumbnailDto {
+  @IsOptional()
+  @ApiProperty({
+    enum: GetAssetThumbnailFormatEnum,
+    default: GetAssetThumbnailFormatEnum.WEBP,
+    required: false,
+    enumName: 'ThumbnailFormat',
+  })
+  format = GetAssetThumbnailFormatEnum.WEBP;
+}
diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json
index a70db8f2c1..432a76012d 100644
--- a/server/immich-openapi-specs.json
+++ b/server/immich-openapi-specs.json
@@ -1 +1 @@
-{"openapi":"3.0.0","paths":{"/user":{"get":{"operationId":"getAllUsers","parameters":[{"name":"isAll","required":true,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserResponseDto"}}}}}},"tags":["User"],"security":[{"bearer":[]}]},"post":{"operationId":"createUser","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]},"put":{"operationId":"updateUser","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]}},"/user/me":{"get":{"operationId":"getMyUserInfo","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]}},"/user/count":{"get":{"operationId":"getUserCount","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCountResponseDto"}}}}},"tags":["User"]}},"/user/profile-image":{"post":{"operationId":"createProfileImage","parameters":[],"requestBody":{"required":true,"description":"A new avatar for the user","content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CreateProfileImageDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProfileImageResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]}},"/user/profile-image/{userId}":{"get":{"operationId":"getProfileImage","parameters":[{"name":"userId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["User"]}},"/asset/upload":{"post":{"operationId":"uploadFile","parameters":[],"requestBody":{"required":true,"description":"Asset Upload Information","content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/AssetFileUploadDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetFileUploadResponseDto"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/download":{"get":{"operationId":"downloadFile","parameters":[{"name":"aid","required":true,"in":"query","schema":{"title":"Device Asset ID","type":"string"}},{"name":"did","required":true,"in":"query","schema":{"title":"Device ID","type":"string"}},{"name":"isThumb","required":false,"in":"query","schema":{"title":"Is serve thumbnail (resize) file","type":"boolean"}},{"name":"isWeb","required":false,"in":"query","schema":{"title":"Is request made from web","type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/file":{"get":{"operationId":"serveFile","parameters":[{"name":"aid","required":true,"in":"query","schema":{"title":"Device Asset ID","type":"string"}},{"name":"did","required":true,"in":"query","schema":{"title":"Device ID","type":"string"}},{"name":"isThumb","required":false,"in":"query","schema":{"title":"Is serve thumbnail (resize) file","type":"boolean"}},{"name":"isWeb","required":false,"in":"query","schema":{"title":"Is request made from web","type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/thumbnail/{assetId}":{"get":{"operationId":"getAssetThumbnail","parameters":[{"name":"assetId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/allObjects":{"get":{"operationId":"getCuratedObjects","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CuratedObjectsResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/allLocation":{"get":{"operationId":"getCuratedLocations","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CuratedLocationsResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/searchTerm":{"get":{"operationId":"getAssetSearchTerms","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/search":{"post":{"operationId":"searchAsset","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchAssetDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AssetResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset":{"get":{"operationId":"getAllAssets","summary":"","description":"Get all AssetEntity belong to the user","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AssetResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]},"delete":{"operationId":"deleteAsset","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAssetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DeleteAssetResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/{deviceId}":{"get":{"operationId":"getUserAssetsByDeviceId","summary":"","description":"Get all asset of a device that are in the database, ID only.","parameters":[{"name":"deviceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/assetById/{assetId}":{"get":{"operationId":"getAssetById","summary":"","description":"Get a single asset's information","parameters":[{"name":"assetId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponseDto"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/check":{"post":{"operationId":"checkDuplicateAsset","summary":"","description":"Check duplicated asset before uploading - for Web upload used","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckDuplicateAssetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckDuplicateAssetResponseDto"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/auth/login":{"post":{"operationId":"login","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginCredentialDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponseDto"}}}}},"tags":["Authentication"]}},"/auth/admin-sign-up":{"post":{"operationId":"adminSignUp","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignUpDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSignupResponseDto"}}}},"400":{"description":"The server already has an admin"}},"tags":["Authentication"]}},"/auth/validateToken":{"post":{"operationId":"validateAccessToken","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateAccessTokenResponseDto"}}}}},"tags":["Authentication"],"security":[{"bearer":[]}]}},"/device-info":{"post":{"operationId":"createDeviceInfo","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceInfoDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceInfoResponseDto"}}}}},"tags":["Device Info"],"security":[{"bearer":[]}]},"patch":{"operationId":"updateDeviceInfo","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceInfoDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceInfoResponseDto"}}}}},"tags":["Device Info"],"security":[{"bearer":[]}]}},"/server-info":{"get":{"operationId":"getServerInfo","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerInfoResponseDto"}}}}},"tags":["Server Info"]}},"/server-info/ping":{"get":{"operationId":"pingServer","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerPingResponse"}}}}},"tags":["Server Info"]}},"/server-info/version":{"get":{"operationId":"getServerVersion","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerVersionReponseDto"}}}}},"tags":["Server Info"]}},"/album":{"post":{"operationId":"createAlbum","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlbumDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]},"get":{"operationId":"getAllAlbums","parameters":[{"name":"shared","required":false,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}/users":{"put":{"operationId":"addUsersToAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddUsersDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}/assets":{"put":{"operationId":"addAssetsToAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddAssetsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]},"delete":{"operationId":"removeAssetFromAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveAssetsDto"}}}},"responses":{"200":{"description":""}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}":{"get":{"operationId":"getAlbumInfo","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]},"delete":{"operationId":"deleteAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Album"],"security":[{"bearer":[]}]},"patch":{"operationId":"updateAlbumInfo","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlbumDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}/user/{userId}":{"delete":{"operationId":"removeUserFromAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}},{"name":"userId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Album"],"security":[{"bearer":[]}]}}},"info":{"title":"Immich","description":"Immich API","version":"1.17.0","contact":{}},"tags":[],"servers":[{"url":"/api"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http","name":"JWT","description":"Enter JWT token","in":"header"}},"schemas":{"UserResponseDto":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"createdAt":{"type":"string"},"profileImagePath":{"type":"string"},"shouldChangePassword":{"type":"boolean"},"isAdmin":{"type":"boolean"}},"required":["id","email","firstName","lastName","createdAt","profileImagePath","shouldChangePassword","isAdmin"]},"CreateUserDto":{"type":"object","properties":{"email":{"type":"string","example":"testuser@email.com"},"password":{"type":"string","example":"password"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"}},"required":["email","password","firstName","lastName"]},"UserCountResponseDto":{"type":"object","properties":{"userCount":{"type":"integer"}},"required":["userCount"]},"UpdateUserDto":{"type":"object","properties":{"id":{"type":"string"},"password":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"isAdmin":{"type":"boolean"},"shouldChangePassword":{"type":"boolean"},"profileImagePath":{"type":"string"}},"required":["id"]},"CreateProfileImageDto":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]},"CreateProfileImageResponseDto":{"type":"object","properties":{"userId":{"type":"string"},"profileImagePath":{"type":"string"}},"required":["userId","profileImagePath"]},"AssetFileUploadDto":{"type":"object","properties":{"assetData":{"type":"string","format":"binary"}},"required":["assetData"]},"AssetFileUploadResponseDto":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"CuratedObjectsResponseDto":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string"},"resizePath":{"type":"string"},"deviceAssetId":{"type":"string"},"deviceId":{"type":"string"}},"required":["id","object","resizePath","deviceAssetId","deviceId"]},"CuratedLocationsResponseDto":{"type":"object","properties":{"id":{"type":"string"},"city":{"type":"string"},"resizePath":{"type":"string"},"deviceAssetId":{"type":"string"},"deviceId":{"type":"string"}},"required":["id","city","resizePath","deviceAssetId","deviceId"]},"SearchAssetDto":{"type":"object","properties":{"searchTerm":{"type":"string"}},"required":["searchTerm"]},"AssetTypeEnum":{"type":"string","enum":["IMAGE","VIDEO","AUDIO","OTHER"]},"ExifResponseDto":{"type":"object","properties":{"id":{"type":"string","nullable":true,"default":null},"make":{"type":"string","nullable":true,"default":null},"model":{"type":"string","nullable":true,"default":null},"imageName":{"type":"string","nullable":true,"default":null},"exifImageWidth":{"type":"number","nullable":true,"default":null},"exifImageHeight":{"type":"number","nullable":true,"default":null},"fileSizeInByte":{"type":"number","nullable":true,"default":null},"orientation":{"type":"string","nullable":true,"default":null},"dateTimeOriginal":{"format":"date-time","type":"string","nullable":true,"default":null},"modifyDate":{"format":"date-time","type":"string","nullable":true,"default":null},"lensModel":{"type":"string","nullable":true,"default":null},"fNumber":{"type":"number","nullable":true,"default":null},"focalLength":{"type":"number","nullable":true,"default":null},"iso":{"type":"number","nullable":true,"default":null},"exposureTime":{"type":"number","nullable":true,"default":null},"latitude":{"type":"number","nullable":true,"default":null},"longitude":{"type":"number","nullable":true,"default":null},"city":{"type":"string","nullable":true,"default":null},"state":{"type":"string","nullable":true,"default":null},"country":{"type":"string","nullable":true,"default":null}}},"SmartInfoResponseDto":{"type":"object","properties":{"id":{"type":"string"},"tags":{"nullable":true,"type":"array","items":{"type":"string"}},"objects":{"nullable":true,"type":"array","items":{"type":"string"}}}},"AssetResponseDto":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/AssetTypeEnum"},"id":{"type":"string"},"deviceAssetId":{"type":"string"},"ownerId":{"type":"string"},"deviceId":{"type":"string"},"originalPath":{"type":"string"},"resizePath":{"type":"string","nullable":true},"createdAt":{"type":"string"},"modifiedAt":{"type":"string"},"isFavorite":{"type":"boolean"},"mimeType":{"type":"string","nullable":true},"duration":{"type":"string"},"webpPath":{"type":"string","nullable":true},"encodedVideoPath":{"type":"string","nullable":true},"exifInfo":{"$ref":"#/components/schemas/ExifResponseDto"},"smartInfo":{"$ref":"#/components/schemas/SmartInfoResponseDto"}},"required":["type","id","deviceAssetId","ownerId","deviceId","originalPath","resizePath","createdAt","modifiedAt","isFavorite","mimeType","duration","webpPath","encodedVideoPath"]},"DeleteAssetDto":{"type":"object","properties":{"ids":{"title":"Array of asset IDs to delete","example":["bf973405-3f2a-48d2-a687-2ed4167164be","dd41870b-5d00-46d2-924e-1d8489a0aa0f","fad77c3f-deef-4e7e-9608-14c1aa4e559a"],"type":"array","items":{"type":"string"}}},"required":["ids"]},"DeleteAssetStatus":{"type":"string","enum":["SUCCESS","FAILED"]},"DeleteAssetResponseDto":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/DeleteAssetStatus"},"id":{"type":"string"}},"required":["status","id"]},"CheckDuplicateAssetDto":{"type":"object","properties":{"deviceAssetId":{"type":"string"},"deviceId":{"type":"string"}},"required":["deviceAssetId","deviceId"]},"CheckDuplicateAssetResponseDto":{"type":"object","properties":{"isExist":{"type":"boolean"}},"required":["isExist"]},"LoginCredentialDto":{"type":"object","properties":{"email":{"type":"string","example":"testuser@email.com"},"password":{"type":"string","example":"password"}},"required":["email","password"]},"LoginResponseDto":{"type":"object","properties":{"accessToken":{"type":"string","readOnly":true},"userId":{"type":"string","readOnly":true},"userEmail":{"type":"string","readOnly":true},"firstName":{"type":"string","readOnly":true},"lastName":{"type":"string","readOnly":true},"profileImagePath":{"type":"string","readOnly":true},"isAdmin":{"type":"boolean","readOnly":true},"shouldChangePassword":{"type":"boolean","readOnly":true}},"required":["accessToken","userId","userEmail","firstName","lastName","profileImagePath","isAdmin","shouldChangePassword"]},"SignUpDto":{"type":"object","properties":{"email":{"type":"string","example":"testuser@email.com"},"password":{"type":"string","example":"password"},"firstName":{"type":"string","example":"Admin"},"lastName":{"type":"string","example":"Doe"}},"required":["email","password","firstName","lastName"]},"AdminSignupResponseDto":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","email","firstName","lastName","createdAt"]},"ValidateAccessTokenResponseDto":{"type":"object","properties":{"authStatus":{"type":"boolean"}},"required":["authStatus"]},"DeviceTypeEnum":{"type":"string","enum":["IOS","ANDROID","WEB"]},"CreateDeviceInfoDto":{"type":"object","properties":{"deviceType":{"$ref":"#/components/schemas/DeviceTypeEnum"},"deviceId":{"type":"string"},"isAutoBackup":{"type":"boolean"}},"required":["deviceType","deviceId"]},"DeviceInfoResponseDto":{"type":"object","properties":{"id":{"type":"integer"},"deviceType":{"$ref":"#/components/schemas/DeviceTypeEnum"},"userId":{"type":"string"},"deviceId":{"type":"string"},"createdAt":{"type":"string"},"isAutoBackup":{"type":"boolean"}},"required":["id","deviceType","userId","deviceId","createdAt","isAutoBackup"]},"UpdateDeviceInfoDto":{"type":"object","properties":{"deviceType":{"$ref":"#/components/schemas/DeviceTypeEnum"},"deviceId":{"type":"string"},"isAutoBackup":{"type":"boolean"}},"required":["deviceType","deviceId"]},"ServerInfoResponseDto":{"type":"object","properties":{"diskSizeRaw":{"type":"integer"},"diskUseRaw":{"type":"integer"},"diskAvailableRaw":{"type":"integer"},"diskUsagePercentage":{"type":"number","format":"float"},"diskSize":{"type":"string"},"diskUse":{"type":"string"},"diskAvailable":{"type":"string"}},"required":["diskSizeRaw","diskUseRaw","diskAvailableRaw","diskUsagePercentage","diskSize","diskUse","diskAvailable"]},"ServerPingResponse":{"type":"object","properties":{"res":{"type":"string","readOnly":true,"example":"pong"}},"required":["res"]},"ServerVersionReponseDto":{"type":"object","properties":{"major":{"type":"integer"},"minor":{"type":"integer"},"patch":{"type":"integer"},"build":{"type":"integer"}},"required":["major","minor","patch","build"]},"CreateAlbumDto":{"type":"object","properties":{"albumName":{"type":"string"},"sharedWithUserIds":{"type":"array","items":{"type":"string"}},"assetIds":{"type":"array","items":{"type":"string"}}},"required":["albumName"]},"AlbumResponseDto":{"type":"object","properties":{"id":{"type":"string"},"ownerId":{"type":"string"},"albumName":{"type":"string"},"createdAt":{"type":"string"},"albumThumbnailAssetId":{"type":"string","nullable":true},"shared":{"type":"boolean"},"sharedUsers":{"type":"array","items":{"$ref":"#/components/schemas/UserResponseDto"}},"assets":{"type":"array","items":{"$ref":"#/components/schemas/AssetResponseDto"}}},"required":["id","ownerId","albumName","createdAt","albumThumbnailAssetId","shared","sharedUsers","assets"]},"AddUsersDto":{"type":"object","properties":{"sharedUserIds":{"type":"array","items":{"type":"string"}}},"required":["sharedUserIds"]},"AddAssetsDto":{"type":"object","properties":{"assetIds":{"type":"array","items":{"type":"string"}}},"required":["assetIds"]},"RemoveAssetsDto":{"type":"object","properties":{"assetIds":{"type":"array","items":{"type":"string"}}},"required":["assetIds"]},"UpdateAlbumDto":{"type":"object","properties":{"albumName":{"type":"string"},"ownerId":{"type":"string"}},"required":["albumName","ownerId"]}}}}
\ No newline at end of file
+{"openapi":"3.0.0","paths":{"/user":{"get":{"operationId":"getAllUsers","parameters":[{"name":"isAll","required":true,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UserResponseDto"}}}}}},"tags":["User"],"security":[{"bearer":[]}]},"post":{"operationId":"createUser","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]},"put":{"operationId":"updateUser","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]}},"/user/me":{"get":{"operationId":"getMyUserInfo","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]}},"/user/count":{"get":{"operationId":"getUserCount","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCountResponseDto"}}}}},"tags":["User"]}},"/user/profile-image":{"post":{"operationId":"createProfileImage","parameters":[],"requestBody":{"required":true,"description":"A new avatar for the user","content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CreateProfileImageDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProfileImageResponseDto"}}}}},"tags":["User"],"security":[{"bearer":[]}]}},"/user/profile-image/{userId}":{"get":{"operationId":"getProfileImage","parameters":[{"name":"userId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["User"]}},"/asset/upload":{"post":{"operationId":"uploadFile","parameters":[],"requestBody":{"required":true,"description":"Asset Upload Information","content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/AssetFileUploadDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetFileUploadResponseDto"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/download":{"get":{"operationId":"downloadFile","parameters":[{"name":"aid","required":true,"in":"query","schema":{"title":"Device Asset ID","type":"string"}},{"name":"did","required":true,"in":"query","schema":{"title":"Device ID","type":"string"}},{"name":"isThumb","required":false,"in":"query","schema":{"title":"Is serve thumbnail (resize) file","type":"boolean"}},{"name":"isWeb","required":false,"in":"query","schema":{"title":"Is request made from web","type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/file":{"get":{"operationId":"serveFile","parameters":[{"name":"aid","required":true,"in":"query","schema":{"title":"Device Asset ID","type":"string"}},{"name":"did","required":true,"in":"query","schema":{"title":"Device ID","type":"string"}},{"name":"isThumb","required":false,"in":"query","schema":{"title":"Is serve thumbnail (resize) file","type":"boolean"}},{"name":"isWeb","required":false,"in":"query","schema":{"title":"Is request made from web","type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/thumbnail/{assetId}":{"get":{"operationId":"getAssetThumbnail","parameters":[{"name":"assetId","required":true,"in":"path","schema":{"type":"string"}},{"name":"format","required":false,"in":"query","schema":{"$ref":"#/components/schemas/ThumbnailFormat"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/allObjects":{"get":{"operationId":"getCuratedObjects","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CuratedObjectsResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/allLocation":{"get":{"operationId":"getCuratedLocations","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CuratedLocationsResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/searchTerm":{"get":{"operationId":"getAssetSearchTerms","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/search":{"post":{"operationId":"searchAsset","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchAssetDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AssetResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset":{"get":{"operationId":"getAllAssets","summary":"","description":"Get all AssetEntity belong to the user","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AssetResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]},"delete":{"operationId":"deleteAsset","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteAssetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DeleteAssetResponseDto"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/{deviceId}":{"get":{"operationId":"getUserAssetsByDeviceId","summary":"","description":"Get all asset of a device that are in the database, ID only.","parameters":[{"name":"deviceId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/assetById/{assetId}":{"get":{"operationId":"getAssetById","summary":"","description":"Get a single asset's information","parameters":[{"name":"assetId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssetResponseDto"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/asset/check":{"post":{"operationId":"checkDuplicateAsset","summary":"","description":"Check duplicated asset before uploading - for Web upload used","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckDuplicateAssetDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckDuplicateAssetResponseDto"}}}}},"tags":["Asset"],"security":[{"bearer":[]}]}},"/auth/login":{"post":{"operationId":"login","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginCredentialDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponseDto"}}}}},"tags":["Authentication"]}},"/auth/admin-sign-up":{"post":{"operationId":"adminSignUp","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignUpDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSignupResponseDto"}}}},"400":{"description":"The server already has an admin"}},"tags":["Authentication"]}},"/auth/validateToken":{"post":{"operationId":"validateAccessToken","parameters":[],"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateAccessTokenResponseDto"}}}}},"tags":["Authentication"],"security":[{"bearer":[]}]}},"/device-info":{"post":{"operationId":"createDeviceInfo","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDeviceInfoDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceInfoResponseDto"}}}}},"tags":["Device Info"],"security":[{"bearer":[]}]},"patch":{"operationId":"updateDeviceInfo","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDeviceInfoDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceInfoResponseDto"}}}}},"tags":["Device Info"],"security":[{"bearer":[]}]}},"/server-info":{"get":{"operationId":"getServerInfo","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerInfoResponseDto"}}}}},"tags":["Server Info"]}},"/server-info/ping":{"get":{"operationId":"pingServer","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerPingResponse"}}}}},"tags":["Server Info"]}},"/server-info/version":{"get":{"operationId":"getServerVersion","parameters":[],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerVersionReponseDto"}}}}},"tags":["Server Info"]}},"/album":{"post":{"operationId":"createAlbum","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlbumDto"}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]},"get":{"operationId":"getAllAlbums","parameters":[{"name":"shared","required":false,"in":"query","schema":{"type":"boolean"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}/users":{"put":{"operationId":"addUsersToAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddUsersDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}/assets":{"put":{"operationId":"addAssetsToAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddAssetsDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]},"delete":{"operationId":"removeAssetFromAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveAssetsDto"}}}},"responses":{"200":{"description":""}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}":{"get":{"operationId":"getAlbumInfo","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]},"delete":{"operationId":"deleteAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Album"],"security":[{"bearer":[]}]},"patch":{"operationId":"updateAlbumInfo","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlbumDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlbumResponseDto"}}}}},"tags":["Album"],"security":[{"bearer":[]}]}},"/album/{albumId}/user/{userId}":{"delete":{"operationId":"removeUserFromAlbum","parameters":[{"name":"albumId","required":true,"in":"path","schema":{"type":"string"}},{"name":"userId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Album"],"security":[{"bearer":[]}]}}},"info":{"title":"Immich","description":"Immich API","version":"1.17.0","contact":{}},"tags":[],"servers":[{"url":"/api"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http","name":"JWT","description":"Enter JWT token","in":"header"}},"schemas":{"UserResponseDto":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"createdAt":{"type":"string"},"profileImagePath":{"type":"string"},"shouldChangePassword":{"type":"boolean"},"isAdmin":{"type":"boolean"}},"required":["id","email","firstName","lastName","createdAt","profileImagePath","shouldChangePassword","isAdmin"]},"CreateUserDto":{"type":"object","properties":{"email":{"type":"string","example":"testuser@email.com"},"password":{"type":"string","example":"password"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Doe"}},"required":["email","password","firstName","lastName"]},"UserCountResponseDto":{"type":"object","properties":{"userCount":{"type":"integer"}},"required":["userCount"]},"UpdateUserDto":{"type":"object","properties":{"id":{"type":"string"},"password":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"isAdmin":{"type":"boolean"},"shouldChangePassword":{"type":"boolean"},"profileImagePath":{"type":"string"}},"required":["id"]},"CreateProfileImageDto":{"type":"object","properties":{"file":{"type":"string","format":"binary"}},"required":["file"]},"CreateProfileImageResponseDto":{"type":"object","properties":{"userId":{"type":"string"},"profileImagePath":{"type":"string"}},"required":["userId","profileImagePath"]},"AssetFileUploadDto":{"type":"object","properties":{"assetData":{"type":"string","format":"binary"}},"required":["assetData"]},"AssetFileUploadResponseDto":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"ThumbnailFormat":{"type":"string","enum":["JPEG","WEBP"]},"CuratedObjectsResponseDto":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string"},"resizePath":{"type":"string"},"deviceAssetId":{"type":"string"},"deviceId":{"type":"string"}},"required":["id","object","resizePath","deviceAssetId","deviceId"]},"CuratedLocationsResponseDto":{"type":"object","properties":{"id":{"type":"string"},"city":{"type":"string"},"resizePath":{"type":"string"},"deviceAssetId":{"type":"string"},"deviceId":{"type":"string"}},"required":["id","city","resizePath","deviceAssetId","deviceId"]},"SearchAssetDto":{"type":"object","properties":{"searchTerm":{"type":"string"}},"required":["searchTerm"]},"AssetTypeEnum":{"type":"string","enum":["IMAGE","VIDEO","AUDIO","OTHER"]},"ExifResponseDto":{"type":"object","properties":{"id":{"type":"string","nullable":true,"default":null},"make":{"type":"string","nullable":true,"default":null},"model":{"type":"string","nullable":true,"default":null},"imageName":{"type":"string","nullable":true,"default":null},"exifImageWidth":{"type":"number","nullable":true,"default":null},"exifImageHeight":{"type":"number","nullable":true,"default":null},"fileSizeInByte":{"type":"number","nullable":true,"default":null},"orientation":{"type":"string","nullable":true,"default":null},"dateTimeOriginal":{"format":"date-time","type":"string","nullable":true,"default":null},"modifyDate":{"format":"date-time","type":"string","nullable":true,"default":null},"lensModel":{"type":"string","nullable":true,"default":null},"fNumber":{"type":"number","nullable":true,"default":null},"focalLength":{"type":"number","nullable":true,"default":null},"iso":{"type":"number","nullable":true,"default":null},"exposureTime":{"type":"number","nullable":true,"default":null},"latitude":{"type":"number","nullable":true,"default":null},"longitude":{"type":"number","nullable":true,"default":null},"city":{"type":"string","nullable":true,"default":null},"state":{"type":"string","nullable":true,"default":null},"country":{"type":"string","nullable":true,"default":null}}},"SmartInfoResponseDto":{"type":"object","properties":{"id":{"type":"string"},"tags":{"nullable":true,"type":"array","items":{"type":"string"}},"objects":{"nullable":true,"type":"array","items":{"type":"string"}}}},"AssetResponseDto":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/AssetTypeEnum"},"id":{"type":"string"},"deviceAssetId":{"type":"string"},"ownerId":{"type":"string"},"deviceId":{"type":"string"},"originalPath":{"type":"string"},"resizePath":{"type":"string","nullable":true},"createdAt":{"type":"string"},"modifiedAt":{"type":"string"},"isFavorite":{"type":"boolean"},"mimeType":{"type":"string","nullable":true},"duration":{"type":"string"},"webpPath":{"type":"string","nullable":true},"encodedVideoPath":{"type":"string","nullable":true},"exifInfo":{"$ref":"#/components/schemas/ExifResponseDto"},"smartInfo":{"$ref":"#/components/schemas/SmartInfoResponseDto"}},"required":["type","id","deviceAssetId","ownerId","deviceId","originalPath","resizePath","createdAt","modifiedAt","isFavorite","mimeType","duration","webpPath","encodedVideoPath"]},"DeleteAssetDto":{"type":"object","properties":{"ids":{"title":"Array of asset IDs to delete","example":["bf973405-3f2a-48d2-a687-2ed4167164be","dd41870b-5d00-46d2-924e-1d8489a0aa0f","fad77c3f-deef-4e7e-9608-14c1aa4e559a"],"type":"array","items":{"type":"string"}}},"required":["ids"]},"DeleteAssetStatus":{"type":"string","enum":["SUCCESS","FAILED"]},"DeleteAssetResponseDto":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/DeleteAssetStatus"},"id":{"type":"string"}},"required":["status","id"]},"CheckDuplicateAssetDto":{"type":"object","properties":{"deviceAssetId":{"type":"string"},"deviceId":{"type":"string"}},"required":["deviceAssetId","deviceId"]},"CheckDuplicateAssetResponseDto":{"type":"object","properties":{"isExist":{"type":"boolean"}},"required":["isExist"]},"LoginCredentialDto":{"type":"object","properties":{"email":{"type":"string","example":"testuser@email.com"},"password":{"type":"string","example":"password"}},"required":["email","password"]},"LoginResponseDto":{"type":"object","properties":{"accessToken":{"type":"string","readOnly":true},"userId":{"type":"string","readOnly":true},"userEmail":{"type":"string","readOnly":true},"firstName":{"type":"string","readOnly":true},"lastName":{"type":"string","readOnly":true},"profileImagePath":{"type":"string","readOnly":true},"isAdmin":{"type":"boolean","readOnly":true},"shouldChangePassword":{"type":"boolean","readOnly":true}},"required":["accessToken","userId","userEmail","firstName","lastName","profileImagePath","isAdmin","shouldChangePassword"]},"SignUpDto":{"type":"object","properties":{"email":{"type":"string","example":"testuser@email.com"},"password":{"type":"string","example":"password"},"firstName":{"type":"string","example":"Admin"},"lastName":{"type":"string","example":"Doe"}},"required":["email","password","firstName","lastName"]},"AdminSignupResponseDto":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"createdAt":{"type":"string"}},"required":["id","email","firstName","lastName","createdAt"]},"ValidateAccessTokenResponseDto":{"type":"object","properties":{"authStatus":{"type":"boolean"}},"required":["authStatus"]},"DeviceTypeEnum":{"type":"string","enum":["IOS","ANDROID","WEB"]},"CreateDeviceInfoDto":{"type":"object","properties":{"deviceType":{"$ref":"#/components/schemas/DeviceTypeEnum"},"deviceId":{"type":"string"},"isAutoBackup":{"type":"boolean"}},"required":["deviceType","deviceId"]},"DeviceInfoResponseDto":{"type":"object","properties":{"id":{"type":"integer"},"deviceType":{"$ref":"#/components/schemas/DeviceTypeEnum"},"userId":{"type":"string"},"deviceId":{"type":"string"},"createdAt":{"type":"string"},"isAutoBackup":{"type":"boolean"}},"required":["id","deviceType","userId","deviceId","createdAt","isAutoBackup"]},"UpdateDeviceInfoDto":{"type":"object","properties":{"deviceType":{"$ref":"#/components/schemas/DeviceTypeEnum"},"deviceId":{"type":"string"},"isAutoBackup":{"type":"boolean"}},"required":["deviceType","deviceId"]},"ServerInfoResponseDto":{"type":"object","properties":{"diskSizeRaw":{"type":"integer"},"diskUseRaw":{"type":"integer"},"diskAvailableRaw":{"type":"integer"},"diskUsagePercentage":{"type":"number","format":"float"},"diskSize":{"type":"string"},"diskUse":{"type":"string"},"diskAvailable":{"type":"string"}},"required":["diskSizeRaw","diskUseRaw","diskAvailableRaw","diskUsagePercentage","diskSize","diskUse","diskAvailable"]},"ServerPingResponse":{"type":"object","properties":{"res":{"type":"string","readOnly":true,"example":"pong"}},"required":["res"]},"ServerVersionReponseDto":{"type":"object","properties":{"major":{"type":"integer"},"minor":{"type":"integer"},"patch":{"type":"integer"},"build":{"type":"integer"}},"required":["major","minor","patch","build"]},"CreateAlbumDto":{"type":"object","properties":{"albumName":{"type":"string"},"sharedWithUserIds":{"type":"array","items":{"type":"string"}},"assetIds":{"type":"array","items":{"type":"string"}}},"required":["albumName"]},"AlbumResponseDto":{"type":"object","properties":{"id":{"type":"string"},"ownerId":{"type":"string"},"albumName":{"type":"string"},"createdAt":{"type":"string"},"albumThumbnailAssetId":{"type":"string","nullable":true},"shared":{"type":"boolean"},"sharedUsers":{"type":"array","items":{"$ref":"#/components/schemas/UserResponseDto"}},"assets":{"type":"array","items":{"$ref":"#/components/schemas/AssetResponseDto"}}},"required":["id","ownerId","albumName","createdAt","albumThumbnailAssetId","shared","sharedUsers","assets"]},"AddUsersDto":{"type":"object","properties":{"sharedUserIds":{"type":"array","items":{"type":"string"}}},"required":["sharedUserIds"]},"AddAssetsDto":{"type":"object","properties":{"assetIds":{"type":"array","items":{"type":"string"}}},"required":["assetIds"]},"RemoveAssetsDto":{"type":"object","properties":{"assetIds":{"type":"array","items":{"type":"string"}}},"required":["assetIds"]},"UpdateAlbumDto":{"type":"object","properties":{"albumName":{"type":"string"},"ownerId":{"type":"string"}},"required":["albumName","ownerId"]}}}}
\ No newline at end of file
diff --git a/web/.eslintignore b/web/.eslintignore
new file mode 100644
index 0000000000..38972655fa
--- /dev/null
+++ b/web/.eslintignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/web/.eslintrc.cjs b/web/.eslintrc.cjs
index 68be379b91..3ccf435f02 100644
--- a/web/.eslintrc.cjs
+++ b/web/.eslintrc.cjs
@@ -6,15 +6,15 @@ module.exports = {
 	ignorePatterns: ['*.cjs'],
 	overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
 	settings: {
-		'svelte3/typescript': () => require('typescript'),
+		'svelte3/typescript': () => require('typescript')
 	},
 	parserOptions: {
 		sourceType: 'module',
-		ecmaVersion: 2020,
+		ecmaVersion: 2020
 	},
 	env: {
 		browser: true,
 		es2017: true,
-		node: true,
-	},
+		node: true
+	}
 };
diff --git a/web/.gitignore b/web/.gitignore
index 64007bdd28..f4401a32d2 100644
--- a/web/.gitignore
+++ b/web/.gitignore
@@ -6,5 +6,3 @@ node_modules
 .env
 .env.*
 !.env.example
-.vercel
-.output
diff --git a/web/.prettierignore b/web/.prettierignore
new file mode 100644
index 0000000000..38972655fa
--- /dev/null
+++ b/web/.prettierignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/web/.prettierrc b/web/.prettierrc
index 1f9adb9b1f..ff2677efde 100644
--- a/web/.prettierrc
+++ b/web/.prettierrc
@@ -1,7 +1,6 @@
 {
 	"useTabs": true,
 	"singleQuote": true,
-	"trailingComma": "all",
-	"printWidth": 120,
-	"semi": true
+	"trailingComma": "none",
+	"printWidth": 100
 }
diff --git a/web/CHANGELOG.md b/web/CHANGELOG.md
deleted file mode 100644
index 352f3a89aa..0000000000
--- a/web/CHANGELOG.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# default-template
-
-## 0.0.2-next.0
-### Patch Changes
-
-
-
-- [chore] upgrade cookie library ([#4592](https://github.com/sveltejs/kit/pull/4592))
diff --git a/web/package-lock.json b/web/package-lock.json
index a6869a5bd9..84b3dc29fd 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -1,12 +1,12 @@
 {
-	"name": "web",
-	"version": "0.0.1",
+	"name": "immich-web",
+	"version": "1.0.0",
 	"lockfileVersion": 2,
 	"requires": true,
 	"packages": {
 		"": {
-			"name": "web",
-			"version": "0.0.1",
+			"name": "immich-web",
+			"version": "1.0.0",
 			"dependencies": {
 				"axios": "^0.27.2",
 				"cookie": "^0.4.2",
@@ -20,9 +20,8 @@
 			},
 			"devDependencies": {
 				"@sveltejs/adapter-auto": "next",
-				"@sveltejs/adapter-node": "^1.0.0-next.73",
+				"@sveltejs/adapter-node": "next",
 				"@sveltejs/kit": "next",
-				"@types/axios": "^0.14.0",
 				"@types/bcrypt": "^5.0.0",
 				"@types/cookie": "^0.4.1",
 				"@types/fluent-ffmpeg": "^2.1.20",
@@ -30,33 +29,40 @@
 				"@types/lodash": "^4.14.182",
 				"@types/lodash-es": "^4.17.6",
 				"@types/socket.io-client": "^3.0.0",
-				"@typescript-eslint/eslint-plugin": "^5.10.1",
-				"@typescript-eslint/parser": "^5.10.1",
+				"@typescript-eslint/eslint-plugin": "^5.27.0",
+				"@typescript-eslint/parser": "^5.27.0",
 				"autoprefixer": "^10.4.7",
-				"eslint": "^8.12.0",
+				"eslint": "^8.16.0",
 				"eslint-config-prettier": "^8.3.0",
 				"eslint-plugin-svelte3": "^4.0.0",
 				"postcss": "^8.4.13",
-				"prettier": "^2.5.1",
-				"prettier-plugin-svelte": "^2.5.0",
-				"svelte": "^3.46.0",
-				"svelte-check": "^2.2.6",
-				"svelte-preprocess": "^4.10.1",
+				"prettier": "^2.6.2",
+				"prettier-plugin-svelte": "^2.7.0",
+				"svelte": "^3.44.0",
+				"svelte-check": "^2.7.1",
+				"svelte-preprocess": "^4.10.6",
 				"tailwindcss": "^3.0.24",
 				"tslib": "^2.3.1",
-				"typescript": "~4.6.2"
+				"typescript": "^4.7.4",
+				"vite": "^3.0.0"
 			}
 		},
+		"node_modules/@cloudflare/workers-types": {
+			"version": "3.14.1",
+			"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-3.14.1.tgz",
+			"integrity": "sha512-B1/plF62pt+H2IJHvApK8fdOJAVsvojvacuac8x8s+JIyqbropMyqNqHTKLm3YD8ZFLGwYeFTudU+PQ7vGvBdA==",
+			"dev": true
+		},
 		"node_modules/@eslint/eslintrc": {
-			"version": "1.2.3",
-			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
-			"integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==",
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
+			"integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
 			"dev": true,
 			"dependencies": {
 				"ajv": "^6.12.4",
 				"debug": "^4.3.2",
 				"espree": "^9.3.2",
-				"globals": "^13.9.0",
+				"globals": "^13.15.0",
 				"ignore": "^5.2.0",
 				"import-fresh": "^3.2.1",
 				"js-yaml": "^4.1.0",
@@ -93,6 +99,51 @@
 			"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==",
 			"dev": true
 		},
+		"node_modules/@jridgewell/resolve-uri": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+			"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+			"dev": true,
+			"engines": {
+				"node": ">=6.0.0"
+			}
+		},
+		"node_modules/@jridgewell/sourcemap-codec": {
+			"version": "1.4.14",
+			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+			"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+			"dev": true
+		},
+		"node_modules/@jridgewell/trace-mapping": {
+			"version": "0.3.14",
+			"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
+			"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
+			"dev": true,
+			"dependencies": {
+				"@jridgewell/resolve-uri": "^3.0.3",
+				"@jridgewell/sourcemap-codec": "^1.4.10"
+			}
+		},
+		"node_modules/@mapbox/node-pre-gyp": {
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz",
+			"integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==",
+			"dev": true,
+			"dependencies": {
+				"detect-libc": "^2.0.0",
+				"https-proxy-agent": "^5.0.0",
+				"make-dir": "^3.1.0",
+				"node-fetch": "^2.6.7",
+				"nopt": "^5.0.0",
+				"npmlog": "^5.0.1",
+				"rimraf": "^3.0.2",
+				"semver": "^7.3.5",
+				"tar": "^6.1.11"
+			},
+			"bin": {
+				"node-pre-gyp": "bin/node-pre-gyp"
+			}
+		},
 		"node_modules/@nodelib/fs.scandir": {
 			"version": "2.1.5",
 			"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -147,96 +198,99 @@
 			"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
 		},
 		"node_modules/@sveltejs/adapter-auto": {
-			"version": "1.0.0-next.40",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-1.0.0-next.40.tgz",
-			"integrity": "sha512-TT6YJUF3asJ/2RbviEpcDJQ/TixPcvmH0L2266fGNT7+KfAf9wbbVdegPWRODk2E2hTN0X+h5YS9l+lap+BK9w==",
+			"version": "1.0.0-next.61",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-1.0.0-next.61.tgz",
+			"integrity": "sha512-0DwAx4BHhbY4irMx6GyT7cDhH22udUoWkeVHEIhmDtCAfjjzlqfWmyY9qt46Gjp8EApIBrXD2rJB6lJy4jYurQ==",
 			"dev": true,
 			"dependencies": {
-				"@sveltejs/adapter-cloudflare": "1.0.0-next.19",
-				"@sveltejs/adapter-netlify": "1.0.0-next.56",
-				"@sveltejs/adapter-vercel": "1.0.0-next.50"
+				"@sveltejs/adapter-cloudflare": "1.0.0-next.29",
+				"@sveltejs/adapter-netlify": "1.0.0-next.69",
+				"@sveltejs/adapter-vercel": "1.0.0-next.63"
 			}
 		},
 		"node_modules/@sveltejs/adapter-cloudflare": {
-			"version": "1.0.0-next.19",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-1.0.0-next.19.tgz",
-			"integrity": "sha512-LET3DUYpl+deoKhkWCzhHUT7iipYkgVkOcRIJX7qT4m23A+MAbzcAC3npgwEYSe9RokOSWMVBr3tVujeES5EeA==",
+			"version": "1.0.0-next.29",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-1.0.0-next.29.tgz",
+			"integrity": "sha512-bm95d2pDEExy1cSPqvWxvftHEJz57krLlW3DdGtxbXWLr8M+WZbCEe1AqsnGycaFXUsn0GZ77IWNrHqcGxwvRg==",
 			"dev": true,
 			"dependencies": {
-				"esbuild": "^0.14.21",
-				"worktop": "0.8.0-next.13"
+				"@cloudflare/workers-types": "^3.14.0",
+				"esbuild": "^0.14.48",
+				"worktop": "0.8.0-next.14"
 			}
 		},
 		"node_modules/@sveltejs/adapter-netlify": {
-			"version": "1.0.0-next.56",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-netlify/-/adapter-netlify-1.0.0-next.56.tgz",
-			"integrity": "sha512-fM3aBHsr7syCGfIJcuB1mEoZwynqyOxVijvmyrd9OWHi6MP3bXSP+GhKDMtDpQRwejJJiwuZNTx2PUbV3uirvA==",
+			"version": "1.0.0-next.69",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-netlify/-/adapter-netlify-1.0.0-next.69.tgz",
+			"integrity": "sha512-nIMtadrsnVemVDIuuqHSDxX/7xRypk+X2ewHY+JR/ONV853lUJ1r9AaXF9+XXPIqxGMKStsWm5GzgGNmM8ID2g==",
 			"dev": true,
 			"dependencies": {
 				"@iarna/toml": "^2.2.5",
-				"esbuild": "^0.14.21",
+				"esbuild": "^0.14.48",
+				"set-cookie-parser": "^2.4.8",
 				"tiny-glob": "^0.2.9"
 			}
 		},
 		"node_modules/@sveltejs/adapter-node": {
-			"version": "1.0.0-next.73",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.73.tgz",
-			"integrity": "sha512-eidd7u1dPHIaBKMjRePrxazUt+Mm/JpnaiKLzZJBdamhBiiYIb+epkPLLqfG5Oo346/0HLKwFRAM/FXn3u3BHQ==",
+			"version": "1.0.0-next.81",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.81.tgz",
+			"integrity": "sha512-OCYteMK4iNRR+sHMtpMBkNvJoo7lpfMiGF1TsvtE8wv7IjBA5pHwTETrvwZL9nGoQzhpDiDuUWYt7w0cLKCukw==",
 			"dev": true,
 			"dependencies": {
 				"tiny-glob": "^0.2.9"
 			}
 		},
 		"node_modules/@sveltejs/adapter-vercel": {
-			"version": "1.0.0-next.50",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.50.tgz",
-			"integrity": "sha512-yta0AkuWEr7qrm8LB34F4ZdCtMxj+cHD4huwrRYCgjv+PSJHLPwe7aH53+Mhrv6La0TgeyQ/f2lTyhBMXZXn9Q==",
+			"version": "1.0.0-next.63",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.63.tgz",
+			"integrity": "sha512-awb1zmT+hAAHv+x7gOY/8Ch64spxKX6H/DQb+S/VGYRQ6i1WvNgsBUF9vk88KR//7tUY8y/xiTLAb99hJ57WhA==",
 			"dev": true,
 			"dependencies": {
-				"esbuild": "^0.14.21"
+				"@vercel/nft": "^0.20.0",
+				"esbuild": "^0.14.48"
 			}
 		},
 		"node_modules/@sveltejs/kit": {
-			"version": "1.0.0-next.326",
-			"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.326.tgz",
-			"integrity": "sha512-prJqmXZ2H1wmFfnMw7wDujfbkcA8vuubuqUkpVVmXhfh2+SEzQscPTNwxoE5EJxb5sywtLWEvYx3hv1gPS4Lvg==",
+			"version": "1.0.0-next.377",
+			"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.377.tgz",
+			"integrity": "sha512-DH2v2yUBUuDZ7vzjPXUd/yt1AMR3BIkZN0ubLAvS2C+q5Wbvk7ZvAJhfPZ3OYc3ZpQXe4ZGEcptOjvEYvd1lLA==",
 			"dev": true,
 			"dependencies": {
-				"@sveltejs/vite-plugin-svelte": "^1.0.0-next.32",
+				"@sveltejs/vite-plugin-svelte": "^1.0.1",
 				"chokidar": "^3.5.3",
-				"sade": "^1.7.4",
-				"vite": "^2.9.0"
+				"sade": "^1.8.1"
 			},
 			"bin": {
 				"svelte-kit": "svelte-kit.js"
 			},
 			"engines": {
-				"node": ">=14.13"
+				"node": ">=16.9"
 			},
 			"peerDependencies": {
-				"svelte": "^3.44.0"
+				"svelte": "^3.44.0",
+				"vite": "^3.0.0"
 			}
 		},
 		"node_modules/@sveltejs/vite-plugin-svelte": {
-			"version": "1.0.0-next.43",
-			"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.43.tgz",
-			"integrity": "sha512-MzeczqGrnDmbAldw/LfXV/dhpLC2bdUzuMhcx0C2j79V2uNzQERHDinxXnG2AVTCTjSpbQxzQwMMmYflnI7W1g==",
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.1.tgz",
+			"integrity": "sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==",
 			"dev": true,
 			"dependencies": {
 				"@rollup/pluginutils": "^4.2.1",
 				"debug": "^4.3.4",
 				"deepmerge": "^4.2.2",
-				"kleur": "^4.1.4",
-				"magic-string": "^0.26.1",
-				"svelte-hmr": "^0.14.11"
+				"kleur": "^4.1.5",
+				"magic-string": "^0.26.2",
+				"svelte-hmr": "^0.14.12"
 			},
 			"engines": {
-				"node": "^14.13.1 || >= 16"
+				"node": "^14.18.0 || >= 16"
 			},
 			"peerDependencies": {
 				"diff-match-patch": "^1.0.5",
 				"svelte": "^3.44.0",
-				"vite": "^2.9.0"
+				"vite": "^3.0.0"
 			},
 			"peerDependenciesMeta": {
 				"diff-match-patch": {
@@ -244,16 +298,6 @@
 				}
 			}
 		},
-		"node_modules/@types/axios": {
-			"version": "0.14.0",
-			"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
-			"integrity": "sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ==",
-			"deprecated": "This is a stub types definition for axios (https://github.com/mzabriskie/axios). axios provides its own type definitions, so you don't need @types/axios installed!",
-			"dev": true,
-			"dependencies": {
-				"axios": "*"
-			}
-		},
 		"node_modules/@types/bcrypt": {
 			"version": "5.0.0",
 			"resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz",
@@ -279,9 +323,9 @@
 			}
 		},
 		"node_modules/@types/geojson": {
-			"version": "7946.0.8",
-			"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
-			"integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==",
+			"version": "7946.0.10",
+			"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
+			"integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==",
 			"dev": true
 		},
 		"node_modules/@types/json-schema": {
@@ -291,9 +335,9 @@
 			"dev": true
 		},
 		"node_modules/@types/leaflet": {
-			"version": "1.7.10",
-			"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.10.tgz",
-			"integrity": "sha512-RzK5BYwYboOXXxyF01tp8g1J8UbdRvoaf+F/jCnVaWC42+QITB6wKvUklcX7jCMRWkzTnGO9NLg7A6SzrlGALA==",
+			"version": "1.7.11",
+			"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.11.tgz",
+			"integrity": "sha512-VwAYom2pfIAf/pLj1VR5aLltd4tOtHyvfaJlNYCoejzP2nu52PrMi1ehsLRMUS+bgafmIIKBV1cMfKeS+uJ0Vg==",
 			"dev": true,
 			"dependencies": {
 				"@types/geojson": "*"
@@ -315,9 +359,9 @@
 			}
 		},
 		"node_modules/@types/node": {
-			"version": "17.0.32",
-			"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz",
-			"integrity": "sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw==",
+			"version": "18.0.5",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.5.tgz",
+			"integrity": "sha512-En7tneq+j0qAiVwysBD79y86MT3ModuoIJbe7JXp+sb5UAjInSShmK3nXXMioBzfF7rXC12hv12d4IyCVwN4dA==",
 			"dev": true
 		},
 		"node_modules/@types/pug": {
@@ -346,19 +390,19 @@
 			}
 		},
 		"node_modules/@typescript-eslint/eslint-plugin": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.23.0.tgz",
-			"integrity": "sha512-hEcSmG4XodSLiAp1uxv/OQSGsDY6QN3TcRU32gANp+19wGE1QQZLRS8/GV58VRUoXhnkuJ3ZxNQ3T6Z6zM59DA==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz",
+			"integrity": "sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/scope-manager": "5.23.0",
-				"@typescript-eslint/type-utils": "5.23.0",
-				"@typescript-eslint/utils": "5.23.0",
-				"debug": "^4.3.2",
+				"@typescript-eslint/scope-manager": "5.30.6",
+				"@typescript-eslint/type-utils": "5.30.6",
+				"@typescript-eslint/utils": "5.30.6",
+				"debug": "^4.3.4",
 				"functional-red-black-tree": "^1.0.1",
-				"ignore": "^5.1.8",
+				"ignore": "^5.2.0",
 				"regexpp": "^3.2.0",
-				"semver": "^7.3.5",
+				"semver": "^7.3.7",
 				"tsutils": "^3.21.0"
 			},
 			"engines": {
@@ -379,15 +423,15 @@
 			}
 		},
 		"node_modules/@typescript-eslint/parser": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.23.0.tgz",
-			"integrity": "sha512-V06cYUkqcGqpFjb8ttVgzNF53tgbB/KoQT/iB++DOIExKmzI9vBJKjZKt/6FuV9c+zrDsvJKbJ2DOCYwX91cbw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz",
+			"integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/scope-manager": "5.23.0",
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/typescript-estree": "5.23.0",
-				"debug": "^4.3.2"
+				"@typescript-eslint/scope-manager": "5.30.6",
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/typescript-estree": "5.30.6",
+				"debug": "^4.3.4"
 			},
 			"engines": {
 				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -406,13 +450,13 @@
 			}
 		},
 		"node_modules/@typescript-eslint/scope-manager": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.23.0.tgz",
-			"integrity": "sha512-EhjaFELQHCRb5wTwlGsNMvzK9b8Oco4aYNleeDlNuL6qXWDF47ch4EhVNPh8Rdhf9tmqbN4sWDk/8g+Z/J8JVw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz",
+			"integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/visitor-keys": "5.23.0"
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/visitor-keys": "5.30.6"
 			},
 			"engines": {
 				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -423,13 +467,13 @@
 			}
 		},
 		"node_modules/@typescript-eslint/type-utils": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.23.0.tgz",
-			"integrity": "sha512-iuI05JsJl/SUnOTXA9f4oI+/4qS/Zcgk+s2ir+lRmXI+80D8GaGwoUqs4p+X+4AxDolPpEpVUdlEH4ADxFy4gw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz",
+			"integrity": "sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/utils": "5.23.0",
-				"debug": "^4.3.2",
+				"@typescript-eslint/utils": "5.30.6",
+				"debug": "^4.3.4",
 				"tsutils": "^3.21.0"
 			},
 			"engines": {
@@ -449,9 +493,9 @@
 			}
 		},
 		"node_modules/@typescript-eslint/types": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.23.0.tgz",
-			"integrity": "sha512-NfBsV/h4dir/8mJwdZz7JFibaKC3E/QdeMEDJhiAE3/eMkoniZ7MjbEMCGXw6MZnZDMN3G9S0mH/6WUIj91dmw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz",
+			"integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==",
 			"dev": true,
 			"engines": {
 				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -462,17 +506,17 @@
 			}
 		},
 		"node_modules/@typescript-eslint/typescript-estree": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.23.0.tgz",
-			"integrity": "sha512-xE9e0lrHhI647SlGMl+m+3E3CKPF1wzvvOEWnuE3CCjjT7UiRnDGJxmAcVKJIlFgK6DY9RB98eLr1OPigPEOGg==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz",
+			"integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/visitor-keys": "5.23.0",
-				"debug": "^4.3.2",
-				"globby": "^11.0.4",
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/visitor-keys": "5.30.6",
+				"debug": "^4.3.4",
+				"globby": "^11.1.0",
 				"is-glob": "^4.0.3",
-				"semver": "^7.3.5",
+				"semver": "^7.3.7",
 				"tsutils": "^3.21.0"
 			},
 			"engines": {
@@ -489,15 +533,15 @@
 			}
 		},
 		"node_modules/@typescript-eslint/utils": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.23.0.tgz",
-			"integrity": "sha512-dbgaKN21drqpkbbedGMNPCtRPZo1IOUr5EI9Jrrh99r5UW5Q0dz46RKXeSBoPV+56R6dFKpbrdhgUNSJsDDRZA==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.6.tgz",
+			"integrity": "sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==",
 			"dev": true,
 			"dependencies": {
 				"@types/json-schema": "^7.0.9",
-				"@typescript-eslint/scope-manager": "5.23.0",
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/typescript-estree": "5.23.0",
+				"@typescript-eslint/scope-manager": "5.30.6",
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/typescript-estree": "5.30.6",
 				"eslint-scope": "^5.1.1",
 				"eslint-utils": "^3.0.0"
 			},
@@ -513,13 +557,13 @@
 			}
 		},
 		"node_modules/@typescript-eslint/visitor-keys": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.23.0.tgz",
-			"integrity": "sha512-Vd4mFNchU62sJB8pX19ZSPog05B0Y0CE2UxAZPT5k4iqhRYjPnqyY3woMxCd0++t9OTqkgjST+1ydLBi7e2Fvg==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz",
+			"integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==",
 			"dev": true,
 			"dependencies": {
-				"@typescript-eslint/types": "5.23.0",
-				"eslint-visitor-keys": "^3.0.0"
+				"@typescript-eslint/types": "5.30.6",
+				"eslint-visitor-keys": "^3.3.0"
 			},
 			"engines": {
 				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -529,6 +573,33 @@
 				"url": "https://opencollective.com/typescript-eslint"
 			}
 		},
+		"node_modules/@vercel/nft": {
+			"version": "0.20.1",
+			"resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.20.1.tgz",
+			"integrity": "sha512-hSLcr64KHOkcNiTAlv154K4p4faEFBwYIi2eIgu1QCDhB1qyQYvFuEhtw3eaapNjA4/7x/2jcclfCAjILua/ag==",
+			"dev": true,
+			"dependencies": {
+				"@mapbox/node-pre-gyp": "^1.0.5",
+				"acorn": "^8.6.0",
+				"bindings": "^1.4.0",
+				"estree-walker": "2.0.2",
+				"glob": "^7.1.3",
+				"graceful-fs": "^4.2.9",
+				"micromatch": "^4.0.2",
+				"node-gyp-build": "^4.2.2",
+				"resolve-from": "^5.0.0",
+				"rollup-pluginutils": "^2.8.2"
+			},
+			"bin": {
+				"nft": "out/cli.js"
+			}
+		},
+		"node_modules/abbrev": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+			"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+			"dev": true
+		},
 		"node_modules/acorn": {
 			"version": "8.7.1",
 			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
@@ -582,6 +653,18 @@
 				"node": ">=0.4.0"
 			}
 		},
+		"node_modules/agent-base": {
+			"version": "6.0.2",
+			"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+			"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+			"dev": true,
+			"dependencies": {
+				"debug": "4"
+			},
+			"engines": {
+				"node": ">= 6.0.0"
+			}
+		},
 		"node_modules/ajv": {
 			"version": "6.12.6",
 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -635,10 +718,29 @@
 				"node": ">= 8"
 			}
 		},
+		"node_modules/aproba": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+			"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+			"dev": true
+		},
+		"node_modules/are-we-there-yet": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+			"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
+			"dev": true,
+			"dependencies": {
+				"delegates": "^1.0.0",
+				"readable-stream": "^3.6.0"
+			},
+			"engines": {
+				"node": ">=10"
+			}
+		},
 		"node_modules/arg": {
-			"version": "5.0.1",
-			"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz",
-			"integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==",
+			"version": "5.0.2",
+			"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+			"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
 			"dev": true
 		},
 		"node_modules/argparse": {
@@ -718,6 +820,15 @@
 				"node": ">=8"
 			}
 		},
+		"node_modules/bindings": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+			"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+			"dev": true,
+			"dependencies": {
+				"file-uri-to-path": "1.0.0"
+			}
+		},
 		"node_modules/brace-expansion": {
 			"version": "1.1.11",
 			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -741,9 +852,9 @@
 			}
 		},
 		"node_modules/browserslist": {
-			"version": "4.20.3",
-			"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
-			"integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
+			"version": "4.21.2",
+			"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz",
+			"integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
 			"dev": true,
 			"funding": [
 				{
@@ -756,11 +867,10 @@
 				}
 			],
 			"dependencies": {
-				"caniuse-lite": "^1.0.30001332",
-				"electron-to-chromium": "^1.4.118",
-				"escalade": "^3.1.1",
-				"node-releases": "^2.0.3",
-				"picocolors": "^1.0.0"
+				"caniuse-lite": "^1.0.30001366",
+				"electron-to-chromium": "^1.4.188",
+				"node-releases": "^2.0.6",
+				"update-browserslist-db": "^1.0.4"
 			},
 			"bin": {
 				"browserslist": "cli.js"
@@ -772,7 +882,7 @@
 		"node_modules/buffer-crc32": {
 			"version": "0.2.13",
 			"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-			"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+			"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
 			"dev": true,
 			"engines": {
 				"node": "*"
@@ -797,9 +907,9 @@
 			}
 		},
 		"node_modules/caniuse-lite": {
-			"version": "1.0.30001339",
-			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001339.tgz",
-			"integrity": "sha512-Es8PiVqCe+uXdms0Gu5xP5PF2bxLR7OBp3wUzUnuO7OHzhOfCyg3hdiGWVPVxhiuniOzng+hTc1u3fEQ0TlkSQ==",
+			"version": "1.0.30001366",
+			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001366.tgz",
+			"integrity": "sha512-yy7XLWCubDobokgzudpkKux8e0UOOnLHE6mlNJBzT3lZJz6s5atSEzjoL+fsCPkI0G8MP5uVdDx1ur/fXEWkZA==",
 			"dev": true,
 			"funding": [
 				{
@@ -855,6 +965,15 @@
 				"fsevents": "~2.3.2"
 			}
 		},
+		"node_modules/chownr": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+			"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+			"dev": true,
+			"engines": {
+				"node": ">=10"
+			}
+		},
 		"node_modules/color-convert": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -873,6 +992,15 @@
 			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 			"dev": true
 		},
+		"node_modules/color-support": {
+			"version": "1.1.3",
+			"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+			"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+			"dev": true,
+			"bin": {
+				"color-support": "bin.js"
+			}
+		},
 		"node_modules/combined-stream": {
 			"version": "1.0.8",
 			"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -887,7 +1015,13 @@
 		"node_modules/concat-map": {
 			"version": "0.0.1",
 			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-			"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+			"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+			"dev": true
+		},
+		"node_modules/console-control-strings": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+			"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
 			"dev": true
 		},
 		"node_modules/cookie": {
@@ -958,7 +1092,7 @@
 		"node_modules/defined": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
-			"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
+			"integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==",
 			"dev": true
 		},
 		"node_modules/delayed-stream": {
@@ -969,6 +1103,12 @@
 				"node": ">=0.4.0"
 			}
 		},
+		"node_modules/delegates": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+			"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+			"dev": true
+		},
 		"node_modules/detect-indent": {
 			"version": "6.1.0",
 			"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
@@ -978,15 +1118,24 @@
 				"node": ">=8"
 			}
 		},
+		"node_modules/detect-libc": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+			"integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
 		"node_modules/detective": {
-			"version": "5.2.0",
-			"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz",
-			"integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==",
+			"version": "5.2.1",
+			"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
+			"integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==",
 			"dev": true,
 			"dependencies": {
-				"acorn-node": "^1.6.1",
+				"acorn-node": "^1.8.2",
 				"defined": "^1.0.0",
-				"minimist": "^1.1.1"
+				"minimist": "^1.2.6"
 			},
 			"bin": {
 				"detective": "bin/detective.js"
@@ -1032,9 +1181,15 @@
 			}
 		},
 		"node_modules/electron-to-chromium": {
-			"version": "1.4.137",
-			"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz",
-			"integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==",
+			"version": "1.4.191",
+			"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.191.tgz",
+			"integrity": "sha512-MeEaiuoSFh4G+rrN+Ilm1KJr8pTTZloeLurcZ+PRcthvdK1gWThje+E6baL7/7LoNctrzCncavAG/j/vpES9jg==",
+			"dev": true
+		},
+		"node_modules/emoji-regex": {
+			"version": "8.0.0",
+			"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+			"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
 			"dev": true
 		},
 		"node_modules/engine.io-client": {
@@ -1060,13 +1215,13 @@
 		"node_modules/es6-promise": {
 			"version": "3.3.1",
 			"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
-			"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
+			"integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==",
 			"dev": true
 		},
 		"node_modules/esbuild": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz",
-			"integrity": "sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz",
+			"integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==",
 			"dev": true,
 			"hasInstallScript": true,
 			"bin": {
@@ -1076,32 +1231,32 @@
 				"node": ">=12"
 			},
 			"optionalDependencies": {
-				"esbuild-android-64": "0.14.38",
-				"esbuild-android-arm64": "0.14.38",
-				"esbuild-darwin-64": "0.14.38",
-				"esbuild-darwin-arm64": "0.14.38",
-				"esbuild-freebsd-64": "0.14.38",
-				"esbuild-freebsd-arm64": "0.14.38",
-				"esbuild-linux-32": "0.14.38",
-				"esbuild-linux-64": "0.14.38",
-				"esbuild-linux-arm": "0.14.38",
-				"esbuild-linux-arm64": "0.14.38",
-				"esbuild-linux-mips64le": "0.14.38",
-				"esbuild-linux-ppc64le": "0.14.38",
-				"esbuild-linux-riscv64": "0.14.38",
-				"esbuild-linux-s390x": "0.14.38",
-				"esbuild-netbsd-64": "0.14.38",
-				"esbuild-openbsd-64": "0.14.38",
-				"esbuild-sunos-64": "0.14.38",
-				"esbuild-windows-32": "0.14.38",
-				"esbuild-windows-64": "0.14.38",
-				"esbuild-windows-arm64": "0.14.38"
+				"esbuild-android-64": "0.14.49",
+				"esbuild-android-arm64": "0.14.49",
+				"esbuild-darwin-64": "0.14.49",
+				"esbuild-darwin-arm64": "0.14.49",
+				"esbuild-freebsd-64": "0.14.49",
+				"esbuild-freebsd-arm64": "0.14.49",
+				"esbuild-linux-32": "0.14.49",
+				"esbuild-linux-64": "0.14.49",
+				"esbuild-linux-arm": "0.14.49",
+				"esbuild-linux-arm64": "0.14.49",
+				"esbuild-linux-mips64le": "0.14.49",
+				"esbuild-linux-ppc64le": "0.14.49",
+				"esbuild-linux-riscv64": "0.14.49",
+				"esbuild-linux-s390x": "0.14.49",
+				"esbuild-netbsd-64": "0.14.49",
+				"esbuild-openbsd-64": "0.14.49",
+				"esbuild-sunos-64": "0.14.49",
+				"esbuild-windows-32": "0.14.49",
+				"esbuild-windows-64": "0.14.49",
+				"esbuild-windows-arm64": "0.14.49"
 			}
 		},
 		"node_modules/esbuild-android-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz",
-			"integrity": "sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz",
+			"integrity": "sha512-vYsdOTD+yi+kquhBiFWl3tyxnj2qZJsl4tAqwhT90ktUdnyTizgle7TjNx6Ar1bN7wcwWqZ9QInfdk2WVagSww==",
 			"cpu": [
 				"x64"
 			],
@@ -1115,9 +1270,9 @@
 			}
 		},
 		"node_modules/esbuild-android-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz",
-			"integrity": "sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.49.tgz",
+			"integrity": "sha512-g2HGr/hjOXCgSsvQZ1nK4nW/ei8JUx04Li74qub9qWrStlysaVmadRyTVuW32FGIpLQyc5sUjjZopj49eGGM2g==",
 			"cpu": [
 				"arm64"
 			],
@@ -1131,9 +1286,9 @@
 			}
 		},
 		"node_modules/esbuild-darwin-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz",
-			"integrity": "sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.49.tgz",
+			"integrity": "sha512-3rvqnBCtX9ywso5fCHixt2GBCUsogNp9DjGmvbBohh31Ces34BVzFltMSxJpacNki96+WIcX5s/vum+ckXiLYg==",
 			"cpu": [
 				"x64"
 			],
@@ -1147,9 +1302,9 @@
 			}
 		},
 		"node_modules/esbuild-darwin-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz",
-			"integrity": "sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.49.tgz",
+			"integrity": "sha512-XMaqDxO846srnGlUSJnwbijV29MTKUATmOLyQSfswbK/2X5Uv28M9tTLUJcKKxzoo9lnkYPsx2o8EJcTYwCs/A==",
 			"cpu": [
 				"arm64"
 			],
@@ -1163,9 +1318,9 @@
 			}
 		},
 		"node_modules/esbuild-freebsd-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz",
-			"integrity": "sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.49.tgz",
+			"integrity": "sha512-NJ5Q6AjV879mOHFri+5lZLTp5XsO2hQ+KSJYLbfY9DgCu8s6/Zl2prWXVANYTeCDLlrIlNNYw8y34xqyLDKOmQ==",
 			"cpu": [
 				"x64"
 			],
@@ -1179,9 +1334,9 @@
 			}
 		},
 		"node_modules/esbuild-freebsd-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz",
-			"integrity": "sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.49.tgz",
+			"integrity": "sha512-lFLtgXnAc3eXYqj5koPlBZvEbBSOSUbWO3gyY/0+4lBdRqELyz4bAuamHvmvHW5swJYL7kngzIZw6kdu25KGOA==",
 			"cpu": [
 				"arm64"
 			],
@@ -1195,9 +1350,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-32": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz",
-			"integrity": "sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.49.tgz",
+			"integrity": "sha512-zTTH4gr2Kb8u4QcOpTDVn7Z8q7QEIvFl/+vHrI3cF6XOJS7iEI1FWslTo3uofB2+mn6sIJEQD9PrNZKoAAMDiA==",
 			"cpu": [
 				"ia32"
 			],
@@ -1211,9 +1366,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz",
-			"integrity": "sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz",
+			"integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==",
 			"cpu": [
 				"x64"
 			],
@@ -1227,9 +1382,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-arm": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz",
-			"integrity": "sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.49.tgz",
+			"integrity": "sha512-iE3e+ZVv1Qz1Sy0gifIsarJMQ89Rpm9mtLSRtG3AH0FPgAzQ5Z5oU6vYzhc/3gSPi2UxdCOfRhw2onXuFw/0lg==",
 			"cpu": [
 				"arm"
 			],
@@ -1243,9 +1398,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz",
-			"integrity": "sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.49.tgz",
+			"integrity": "sha512-KLQ+WpeuY+7bxukxLz5VgkAAVQxUv67Ft4DmHIPIW+2w3ObBPQhqNoeQUHxopoW/aiOn3m99NSmSV+bs4BSsdA==",
 			"cpu": [
 				"arm64"
 			],
@@ -1259,9 +1414,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-mips64le": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz",
-			"integrity": "sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.49.tgz",
+			"integrity": "sha512-n+rGODfm8RSum5pFIqFQVQpYBw+AztL8s6o9kfx7tjfK0yIGF6tm5HlG6aRjodiiKkH2xAiIM+U4xtQVZYU4rA==",
 			"cpu": [
 				"mips64el"
 			],
@@ -1275,9 +1430,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-ppc64le": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz",
-			"integrity": "sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.49.tgz",
+			"integrity": "sha512-WP9zR4HX6iCBmMFH+XHHng2LmdoIeUmBpL4aL2TR8ruzXyT4dWrJ5BSbT8iNo6THN8lod6GOmYDLq/dgZLalGw==",
 			"cpu": [
 				"ppc64"
 			],
@@ -1291,9 +1446,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-riscv64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz",
-			"integrity": "sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.49.tgz",
+			"integrity": "sha512-h66ORBz+Dg+1KgLvzTVQEA1LX4XBd1SK0Fgbhhw4akpG/YkN8pS6OzYI/7SGENiN6ao5hETRDSkVcvU9NRtkMQ==",
 			"cpu": [
 				"riscv64"
 			],
@@ -1307,9 +1462,9 @@
 			}
 		},
 		"node_modules/esbuild-linux-s390x": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz",
-			"integrity": "sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.49.tgz",
+			"integrity": "sha512-DhrUoFVWD+XmKO1y7e4kNCqQHPs6twz6VV6Uezl/XHYGzM60rBewBF5jlZjG0nCk5W/Xy6y1xWeopkrhFFM0sQ==",
 			"cpu": [
 				"s390x"
 			],
@@ -1323,9 +1478,9 @@
 			}
 		},
 		"node_modules/esbuild-netbsd-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz",
-			"integrity": "sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.49.tgz",
+			"integrity": "sha512-BXaUwFOfCy2T+hABtiPUIpWjAeWK9P8O41gR4Pg73hpzoygVGnj0nI3YK4SJhe52ELgtdgWP/ckIkbn2XaTxjQ==",
 			"cpu": [
 				"x64"
 			],
@@ -1339,9 +1494,9 @@
 			}
 		},
 		"node_modules/esbuild-openbsd-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz",
-			"integrity": "sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.49.tgz",
+			"integrity": "sha512-lP06UQeLDGmVPw9Rg437Btu6J9/BmyhdoefnQ4gDEJTtJvKtQaUcOQrhjTq455ouZN4EHFH1h28WOJVANK41kA==",
 			"cpu": [
 				"x64"
 			],
@@ -1355,9 +1510,9 @@
 			}
 		},
 		"node_modules/esbuild-sunos-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz",
-			"integrity": "sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.49.tgz",
+			"integrity": "sha512-4c8Zowp+V3zIWje329BeLbGh6XI9c/rqARNaj5yPHdC61pHI9UNdDxT3rePPJeWcEZVKjkiAS6AP6kiITp7FSw==",
 			"cpu": [
 				"x64"
 			],
@@ -1371,9 +1526,9 @@
 			}
 		},
 		"node_modules/esbuild-windows-32": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz",
-			"integrity": "sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.49.tgz",
+			"integrity": "sha512-q7Rb+J9yHTeKr9QTPDYkqfkEj8/kcKz9lOabDuvEXpXuIcosWCJgo5Z7h/L4r7rbtTH4a8U2FGKb6s1eeOHmJA==",
 			"cpu": [
 				"ia32"
 			],
@@ -1387,9 +1542,9 @@
 			}
 		},
 		"node_modules/esbuild-windows-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz",
-			"integrity": "sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.49.tgz",
+			"integrity": "sha512-+Cme7Ongv0UIUTniPqfTX6mJ8Deo7VXw9xN0yJEN1lQMHDppTNmKwAM3oGbD/Vqff+07K2gN0WfNkMohmG+dVw==",
 			"cpu": [
 				"x64"
 			],
@@ -1403,9 +1558,9 @@
 			}
 		},
 		"node_modules/esbuild-windows-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz",
-			"integrity": "sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.49.tgz",
+			"integrity": "sha512-v+HYNAXzuANrCbbLFJ5nmO3m5y2PGZWLe3uloAkLt87aXiO2mZr3BTmacZdjwNkNEHuH3bNtN8cak+mzVjVPfA==",
 			"cpu": [
 				"arm64"
 			],
@@ -1440,12 +1595,12 @@
 			}
 		},
 		"node_modules/eslint": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz",
-			"integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==",
+			"version": "8.19.0",
+			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz",
+			"integrity": "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==",
 			"dev": true,
 			"dependencies": {
-				"@eslint/eslintrc": "^1.2.3",
+				"@eslint/eslintrc": "^1.3.0",
 				"@humanwhocodes/config-array": "^0.9.2",
 				"ajv": "^6.10.0",
 				"chalk": "^4.0.0",
@@ -1463,7 +1618,7 @@
 				"file-entry-cache": "^6.0.1",
 				"functional-red-black-tree": "^1.0.1",
 				"glob-parent": "^6.0.1",
-				"globals": "^13.6.0",
+				"globals": "^13.15.0",
 				"ignore": "^5.2.0",
 				"import-fresh": "^3.0.0",
 				"imurmurhash": "^0.1.4",
@@ -1712,7 +1867,7 @@
 		"node_modules/fast-levenshtein": {
 			"version": "2.0.6",
 			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-			"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
 			"dev": true
 		},
 		"node_modules/fastq": {
@@ -1736,6 +1891,12 @@
 				"node": "^10.12.0 || >=12.0.0"
 			}
 		},
+		"node_modules/file-uri-to-path": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+			"dev": true
+		},
 		"node_modules/fill-range": {
 			"version": "7.0.1",
 			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -1762,9 +1923,9 @@
 			}
 		},
 		"node_modules/flatted": {
-			"version": "3.2.5",
-			"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
-			"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
+			"version": "3.2.6",
+			"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz",
+			"integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
 			"dev": true
 		},
 		"node_modules/follow-redirects": {
@@ -1812,10 +1973,22 @@
 				"url": "https://www.patreon.com/infusion"
 			}
 		},
+		"node_modules/fs-minipass": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+			"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+			"dev": true,
+			"dependencies": {
+				"minipass": "^3.0.0"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
 		"node_modules/fs.realpath": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-			"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+			"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
 			"dev": true
 		},
 		"node_modules/fsevents": {
@@ -1841,19 +2014,39 @@
 		"node_modules/functional-red-black-tree": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
-			"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+			"integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
 			"dev": true
 		},
+		"node_modules/gauge": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+			"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
+			"dev": true,
+			"dependencies": {
+				"aproba": "^1.0.3 || ^2.0.0",
+				"color-support": "^1.1.2",
+				"console-control-strings": "^1.0.0",
+				"has-unicode": "^2.0.1",
+				"object-assign": "^4.1.1",
+				"signal-exit": "^3.0.0",
+				"string-width": "^4.2.3",
+				"strip-ansi": "^6.0.1",
+				"wide-align": "^1.1.2"
+			},
+			"engines": {
+				"node": ">=10"
+			}
+		},
 		"node_modules/glob": {
-			"version": "7.2.0",
-			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
-			"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+			"version": "7.2.3",
+			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
 			"dev": true,
 			"dependencies": {
 				"fs.realpath": "^1.0.0",
 				"inflight": "^1.0.4",
 				"inherits": "2",
-				"minimatch": "^3.0.4",
+				"minimatch": "^3.1.1",
 				"once": "^1.3.0",
 				"path-is-absolute": "^1.0.0"
 			},
@@ -1877,9 +2070,9 @@
 			}
 		},
 		"node_modules/globals": {
-			"version": "13.14.0",
-			"resolved": "https://registry.npmjs.org/globals/-/globals-13.14.0.tgz",
-			"integrity": "sha512-ERO68sOYwm5UuLvSJTY7w7NP2c8S4UcXs3X1GBX8cwOr+ShOcDBbCY5mH4zxz0jsYCdJ8ve8Mv9n2YGJMB1aeg==",
+			"version": "13.16.0",
+			"resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz",
+			"integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==",
 			"dev": true,
 			"dependencies": {
 				"type-fest": "^0.20.2"
@@ -1950,6 +2143,25 @@
 				"node": ">=8"
 			}
 		},
+		"node_modules/has-unicode": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+			"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+			"dev": true
+		},
+		"node_modules/https-proxy-agent": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+			"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+			"dev": true,
+			"dependencies": {
+				"agent-base": "6",
+				"debug": "4"
+			},
+			"engines": {
+				"node": ">= 6"
+			}
+		},
 		"node_modules/ignore": {
 			"version": "5.2.0",
 			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@@ -1975,10 +2187,19 @@
 				"url": "https://github.com/sponsors/sindresorhus"
 			}
 		},
+		"node_modules/import-fresh/node_modules/resolve-from": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+			"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+			"dev": true,
+			"engines": {
+				"node": ">=4"
+			}
+		},
 		"node_modules/imurmurhash": {
 			"version": "0.1.4",
 			"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-			"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+			"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
 			"dev": true,
 			"engines": {
 				"node": ">=0.8.19"
@@ -1987,7 +2208,7 @@
 		"node_modules/inflight": {
 			"version": "1.0.6",
 			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-			"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+			"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
 			"dev": true,
 			"dependencies": {
 				"once": "^1.3.0",
@@ -2027,12 +2248,21 @@
 		"node_modules/is-extglob": {
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-			"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+			"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
 			"dev": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
 		},
+		"node_modules/is-fullwidth-code-point": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+			"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
 		"node_modules/is-glob": {
 			"version": "4.0.3",
 			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -2057,7 +2287,7 @@
 		"node_modules/isexe": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-			"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+			"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
 			"dev": true
 		},
 		"node_modules/js-yaml": {
@@ -2081,13 +2311,13 @@
 		"node_modules/json-stable-stringify-without-jsonify": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-			"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+			"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
 			"dev": true
 		},
 		"node_modules/kleur": {
-			"version": "4.1.4",
-			"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz",
-			"integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==",
+			"version": "4.1.5",
+			"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+			"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
 			"dev": true,
 			"engines": {
 				"node": ">=6"
@@ -2112,9 +2342,9 @@
 			}
 		},
 		"node_modules/lilconfig": {
-			"version": "2.0.5",
-			"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
-			"integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==",
+			"version": "2.0.6",
+			"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
+			"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
 			"dev": true,
 			"engines": {
 				"node": ">=10"
@@ -2149,9 +2379,9 @@
 			}
 		},
 		"node_modules/magic-string": {
-			"version": "0.26.1",
-			"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.1.tgz",
-			"integrity": "sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==",
+			"version": "0.26.2",
+			"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz",
+			"integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==",
 			"dev": true,
 			"dependencies": {
 				"sourcemap-codec": "^1.4.8"
@@ -2160,6 +2390,30 @@
 				"node": ">=12"
 			}
 		},
+		"node_modules/make-dir": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+			"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+			"dev": true,
+			"dependencies": {
+				"semver": "^6.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/make-dir/node_modules/semver": {
+			"version": "6.3.0",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+			"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+			"dev": true,
+			"bin": {
+				"semver": "bin/semver.js"
+			}
+		},
 		"node_modules/merge2": {
 			"version": "1.4.1",
 			"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -2228,6 +2482,31 @@
 			"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
 			"dev": true
 		},
+		"node_modules/minipass": {
+			"version": "3.3.4",
+			"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
+			"integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==",
+			"dev": true,
+			"dependencies": {
+				"yallist": "^4.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/minizlib": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+			"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+			"dev": true,
+			"dependencies": {
+				"minipass": "^3.0.0",
+				"yallist": "^4.0.0"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
 		"node_modules/mkdirp": {
 			"version": "0.5.6",
 			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
@@ -2241,9 +2520,9 @@
 			}
 		},
 		"node_modules/moment": {
-			"version": "2.29.3",
-			"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
-			"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==",
+			"version": "2.29.4",
+			"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+			"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
 			"engines": {
 				"node": "*"
 			}
@@ -2258,9 +2537,9 @@
 			}
 		},
 		"node_modules/mrmime": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz",
-			"integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==",
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
+			"integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==",
 			"dev": true,
 			"engines": {
 				"node": ">=10"
@@ -2286,15 +2565,61 @@
 		"node_modules/natural-compare": {
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-			"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+			"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
 			"dev": true
 		},
+		"node_modules/node-fetch": {
+			"version": "2.6.7",
+			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+			"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+			"dev": true,
+			"dependencies": {
+				"whatwg-url": "^5.0.0"
+			},
+			"engines": {
+				"node": "4.x || >=6.0.0"
+			},
+			"peerDependencies": {
+				"encoding": "^0.1.0"
+			},
+			"peerDependenciesMeta": {
+				"encoding": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/node-gyp-build": {
+			"version": "4.5.0",
+			"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
+			"integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==",
+			"dev": true,
+			"bin": {
+				"node-gyp-build": "bin.js",
+				"node-gyp-build-optional": "optional.js",
+				"node-gyp-build-test": "build-test.js"
+			}
+		},
 		"node_modules/node-releases": {
-			"version": "2.0.4",
-			"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz",
-			"integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==",
+			"version": "2.0.6",
+			"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+			"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
 			"dev": true
 		},
+		"node_modules/nopt": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+			"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+			"dev": true,
+			"dependencies": {
+				"abbrev": "1"
+			},
+			"bin": {
+				"nopt": "bin/nopt.js"
+			},
+			"engines": {
+				"node": ">=6"
+			}
+		},
 		"node_modules/normalize-path": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -2307,7 +2632,28 @@
 		"node_modules/normalize-range": {
 			"version": "0.1.2",
 			"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
-			"integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+			"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/npmlog": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+			"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
+			"dev": true,
+			"dependencies": {
+				"are-we-there-yet": "^2.0.0",
+				"console-control-strings": "^1.1.0",
+				"gauge": "^3.0.0",
+				"set-blocking": "^2.0.0"
+			}
+		},
+		"node_modules/object-assign": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+			"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
 			"dev": true,
 			"engines": {
 				"node": ">=0.10.0"
@@ -2325,7 +2671,7 @@
 		"node_modules/once": {
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-			"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+			"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
 			"dev": true,
 			"dependencies": {
 				"wrappy": "1"
@@ -2363,7 +2709,7 @@
 		"node_modules/path-is-absolute": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+			"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
 			"dev": true,
 			"engines": {
 				"node": ">=0.10.0"
@@ -2411,10 +2757,19 @@
 				"url": "https://github.com/sponsors/jonschlinkert"
 			}
 		},
+		"node_modules/pify": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+			"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
 		"node_modules/postcss": {
-			"version": "8.4.13",
-			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz",
-			"integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==",
+			"version": "8.4.14",
+			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
+			"integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
 			"dev": true,
 			"funding": [
 				{
@@ -2427,7 +2782,7 @@
 				}
 			],
 			"dependencies": {
-				"nanoid": "^3.3.3",
+				"nanoid": "^3.3.4",
 				"picocolors": "^1.0.0",
 				"source-map-js": "^1.0.2"
 			},
@@ -2435,6 +2790,23 @@
 				"node": "^10 || ^12 || >=14"
 			}
 		},
+		"node_modules/postcss-import": {
+			"version": "14.1.0",
+			"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz",
+			"integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==",
+			"dev": true,
+			"dependencies": {
+				"postcss-value-parser": "^4.0.0",
+				"read-cache": "^1.0.0",
+				"resolve": "^1.1.7"
+			},
+			"engines": {
+				"node": ">=10.0.0"
+			},
+			"peerDependencies": {
+				"postcss": "^8.0.0"
+			}
+		},
 		"node_modules/postcss-js": {
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz",
@@ -2531,9 +2903,9 @@
 			}
 		},
 		"node_modules/prettier": {
-			"version": "2.6.2",
-			"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz",
-			"integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==",
+			"version": "2.7.1",
+			"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+			"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
 			"dev": true,
 			"bin": {
 				"prettier": "bin-prettier.js"
@@ -2596,6 +2968,29 @@
 				"url": "https://github.com/sponsors/sindresorhus"
 			}
 		},
+		"node_modules/read-cache": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+			"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+			"dev": true,
+			"dependencies": {
+				"pify": "^2.3.0"
+			}
+		},
+		"node_modules/readable-stream": {
+			"version": "3.6.0",
+			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+			"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+			"dev": true,
+			"dependencies": {
+				"inherits": "^2.0.3",
+				"string_decoder": "^1.1.1",
+				"util-deprecate": "^1.0.1"
+			},
+			"engines": {
+				"node": ">= 6"
+			}
+		},
 		"node_modules/readdirp": {
 			"version": "3.6.0",
 			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -2609,9 +3004,9 @@
 			}
 		},
 		"node_modules/regexparam": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.0.tgz",
-			"integrity": "sha512-gJKwd2MVPWHAIFLsaYDZfyKzHNS4o7E/v8YmNf44vmeV2e4YfVoDToTOKTvE7ab68cRJ++kLuEXJBaEeJVt5ow==",
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.1.tgz",
+			"integrity": "sha512-zRgSaYemnNYxUv+/5SeoHI0eJIgTL/A2pUtXUPLHQxUldagouJ9p+K6IbIZ/JiQuCEv2E2B1O11SjVQy3aMCkw==",
 			"dev": true,
 			"engines": {
 				"node": ">=8"
@@ -2630,12 +3025,12 @@
 			}
 		},
 		"node_modules/resolve": {
-			"version": "1.22.0",
-			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
-			"integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+			"version": "1.22.1",
+			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+			"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
 			"dev": true,
 			"dependencies": {
-				"is-core-module": "^2.8.1",
+				"is-core-module": "^2.9.0",
 				"path-parse": "^1.0.7",
 				"supports-preserve-symlinks-flag": "^1.0.0"
 			},
@@ -2647,12 +3042,12 @@
 			}
 		},
 		"node_modules/resolve-from": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-			"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+			"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
 			"dev": true,
 			"engines": {
-				"node": ">=4"
+				"node": ">=8"
 			}
 		},
 		"node_modules/reusify": {
@@ -2681,9 +3076,9 @@
 			}
 		},
 		"node_modules/rollup": {
-			"version": "2.72.1",
-			"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.72.1.tgz",
-			"integrity": "sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA==",
+			"version": "2.77.0",
+			"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz",
+			"integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==",
 			"dev": true,
 			"bin": {
 				"rollup": "dist/bin/rollup"
@@ -2695,6 +3090,21 @@
 				"fsevents": "~2.3.2"
 			}
 		},
+		"node_modules/rollup-pluginutils": {
+			"version": "2.8.2",
+			"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
+			"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
+			"dev": true,
+			"dependencies": {
+				"estree-walker": "^0.6.1"
+			}
+		},
+		"node_modules/rollup-pluginutils/node_modules/estree-walker": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
+			"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
+			"dev": true
+		},
 		"node_modules/run-parallel": {
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -2730,10 +3140,30 @@
 				"node": ">=6"
 			}
 		},
+		"node_modules/safe-buffer": {
+			"version": "5.2.1",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+			"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+			"dev": true,
+			"funding": [
+				{
+					"type": "github",
+					"url": "https://github.com/sponsors/feross"
+				},
+				{
+					"type": "patreon",
+					"url": "https://www.patreon.com/feross"
+				},
+				{
+					"type": "consulting",
+					"url": "https://feross.org/support"
+				}
+			]
+		},
 		"node_modules/sander": {
 			"version": "0.5.1",
 			"resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz",
-			"integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=",
+			"integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==",
 			"dev": true,
 			"dependencies": {
 				"es6-promise": "^3.1.2",
@@ -2769,6 +3199,18 @@
 				"node": ">=10"
 			}
 		},
+		"node_modules/set-blocking": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+			"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+			"dev": true
+		},
+		"node_modules/set-cookie-parser": {
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.0.tgz",
+			"integrity": "sha512-cHMAtSXilfyBePduZEBVPTCftTQWz6ehWJD5YNUg4mqvRosrrjKbo4WS8JkB0/RxonMoohHm7cOGH60mDkRQ9w==",
+			"dev": true
+		},
 		"node_modules/shebang-command": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -2790,6 +3232,12 @@
 				"node": ">=8"
 			}
 		},
+		"node_modules/signal-exit": {
+			"version": "3.0.7",
+			"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+			"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+			"dev": true
+		},
 		"node_modules/slash": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -2814,9 +3262,9 @@
 			}
 		},
 		"node_modules/socket.io-parser": {
-			"version": "4.2.0",
-			"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz",
-			"integrity": "sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==",
+			"version": "4.2.1",
+			"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
+			"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
 			"dependencies": {
 				"@socket.io/component-emitter": "~3.1.0",
 				"debug": "~4.3.1"
@@ -2828,7 +3276,7 @@
 		"node_modules/sorcery": {
 			"version": "0.10.0",
 			"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
-			"integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=",
+			"integrity": "sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==",
 			"dev": true,
 			"dependencies": {
 				"buffer-crc32": "^0.2.5",
@@ -2840,15 +3288,6 @@
 				"sorcery": "bin/index.js"
 			}
 		},
-		"node_modules/source-map": {
-			"version": "0.7.3",
-			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
-			"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
-			"dev": true,
-			"engines": {
-				"node": ">= 8"
-			}
-		},
 		"node_modules/source-map-js": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
@@ -2864,6 +3303,29 @@
 			"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
 			"dev": true
 		},
+		"node_modules/string_decoder": {
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+			"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+			"dev": true,
+			"dependencies": {
+				"safe-buffer": "~5.2.0"
+			}
+		},
+		"node_modules/string-width": {
+			"version": "4.2.3",
+			"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+			"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+			"dev": true,
+			"dependencies": {
+				"emoji-regex": "^8.0.0",
+				"is-fullwidth-code-point": "^3.0.0",
+				"strip-ansi": "^6.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
 		"node_modules/strip-ansi": {
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -2925,25 +3387,25 @@
 			}
 		},
 		"node_modules/svelte": {
-			"version": "3.48.0",
-			"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.48.0.tgz",
-			"integrity": "sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==",
+			"version": "3.49.0",
+			"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz",
+			"integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA==",
 			"engines": {
 				"node": ">= 8"
 			}
 		},
 		"node_modules/svelte-check": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.7.0.tgz",
-			"integrity": "sha512-GrvG24j0+i8AOm0k0KyJ6Dqc+TAR2yzB7rtS4nljHStunVxCTr/1KYlv4EsOeoqtHLzeWMOd5D2O6nDdP/yw4A==",
+			"version": "2.8.0",
+			"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.8.0.tgz",
+			"integrity": "sha512-HRL66BxffMAZusqe5I5k26mRWQ+BobGd9Rxm3onh7ZVu0nTk8YTKJ9vu3LVPjUGLU9IX7zS+jmwPVhJYdXJ8vg==",
 			"dev": true,
 			"dependencies": {
+				"@jridgewell/trace-mapping": "^0.3.9",
 				"chokidar": "^3.4.1",
 				"fast-glob": "^3.2.7",
 				"import-fresh": "^3.2.1",
 				"picocolors": "^1.0.0",
 				"sade": "^1.7.4",
-				"source-map": "^0.7.3",
 				"svelte-preprocess": "^4.0.0",
 				"typescript": "*"
 			},
@@ -2955,9 +3417,9 @@
 			}
 		},
 		"node_modules/svelte-hmr": {
-			"version": "0.14.11",
-			"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.11.tgz",
-			"integrity": "sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==",
+			"version": "0.14.12",
+			"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz",
+			"integrity": "sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==",
 			"dev": true,
 			"engines": {
 				"node": "^12.20 || ^14.13.1 || >= 16"
@@ -2975,9 +3437,9 @@
 			}
 		},
 		"node_modules/svelte-preprocess": {
-			"version": "4.10.6",
-			"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.6.tgz",
-			"integrity": "sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ==",
+			"version": "4.10.7",
+			"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz",
+			"integrity": "sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==",
 			"dev": true,
 			"hasInstallScript": true,
 			"dependencies": {
@@ -2996,7 +3458,7 @@
 				"coffeescript": "^2.5.1",
 				"less": "^3.11.3 || ^4.0.0",
 				"postcss": "^7 || ^8",
-				"postcss-load-config": "^2.1.0 || ^3.0.0",
+				"postcss-load-config": "^2.1.0 || ^3.0.0 || ^4.0.0",
 				"pug": "^3.0.0",
 				"sass": "^1.26.8",
 				"stylus": "^0.55.0",
@@ -3050,15 +3512,15 @@
 			}
 		},
 		"node_modules/tailwindcss": {
-			"version": "3.0.24",
-			"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz",
-			"integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==",
+			"version": "3.1.6",
+			"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.6.tgz",
+			"integrity": "sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==",
 			"dev": true,
 			"dependencies": {
-				"arg": "^5.0.1",
+				"arg": "^5.0.2",
 				"chokidar": "^3.5.3",
 				"color-name": "^1.1.4",
-				"detective": "^5.2.0",
+				"detective": "^5.2.1",
 				"didyoumean": "^1.2.2",
 				"dlv": "^1.1.3",
 				"fast-glob": "^3.2.11",
@@ -3068,14 +3530,15 @@
 				"normalize-path": "^3.0.0",
 				"object-hash": "^3.0.0",
 				"picocolors": "^1.0.0",
-				"postcss": "^8.4.12",
+				"postcss": "^8.4.14",
+				"postcss-import": "^14.1.0",
 				"postcss-js": "^4.0.0",
 				"postcss-load-config": "^3.1.4",
 				"postcss-nested": "5.0.6",
 				"postcss-selector-parser": "^6.0.10",
 				"postcss-value-parser": "^4.2.0",
 				"quick-lru": "^5.1.1",
-				"resolve": "^1.22.0"
+				"resolve": "^1.22.1"
 			},
 			"bin": {
 				"tailwind": "lib/cli.js",
@@ -3100,10 +3563,39 @@
 				"node": ">=10.13.0"
 			}
 		},
+		"node_modules/tar": {
+			"version": "6.1.11",
+			"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+			"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+			"dev": true,
+			"dependencies": {
+				"chownr": "^2.0.0",
+				"fs-minipass": "^2.0.0",
+				"minipass": "^3.0.0",
+				"minizlib": "^2.1.1",
+				"mkdirp": "^1.0.3",
+				"yallist": "^4.0.0"
+			},
+			"engines": {
+				"node": ">= 10"
+			}
+		},
+		"node_modules/tar/node_modules/mkdirp": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+			"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+			"dev": true,
+			"bin": {
+				"mkdirp": "bin/cmd.js"
+			},
+			"engines": {
+				"node": ">=10"
+			}
+		},
 		"node_modules/text-table": {
 			"version": "0.2.0",
 			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-			"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+			"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
 			"dev": true
 		},
 		"node_modules/tiny-glob": {
@@ -3128,6 +3620,12 @@
 				"node": ">=8.0"
 			}
 		},
+		"node_modules/tr46": {
+			"version": "0.0.3",
+			"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+			"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+			"dev": true
+		},
 		"node_modules/tslib": {
 			"version": "2.4.0",
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
@@ -3180,9 +3678,9 @@
 			}
 		},
 		"node_modules/typescript": {
-			"version": "4.6.4",
-			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
-			"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
+			"version": "4.7.4",
+			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+			"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
 			"dev": true,
 			"bin": {
 				"tsc": "bin/tsc",
@@ -3192,6 +3690,32 @@
 				"node": ">=4.2.0"
 			}
 		},
+		"node_modules/update-browserslist-db": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz",
+			"integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==",
+			"dev": true,
+			"funding": [
+				{
+					"type": "opencollective",
+					"url": "https://opencollective.com/browserslist"
+				},
+				{
+					"type": "tidelift",
+					"url": "https://tidelift.com/funding/github/npm/browserslist"
+				}
+			],
+			"dependencies": {
+				"escalade": "^3.1.1",
+				"picocolors": "^1.0.0"
+			},
+			"bin": {
+				"browserslist-lint": "cli.js"
+			},
+			"peerDependencies": {
+				"browserslist": ">= 4.21.0"
+			}
+		},
 		"node_modules/uri-js": {
 			"version": "4.4.1",
 			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -3204,7 +3728,7 @@
 		"node_modules/util-deprecate": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-			"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+			"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
 			"dev": true
 		},
 		"node_modules/v8-compile-cache": {
@@ -3214,21 +3738,21 @@
 			"dev": true
 		},
 		"node_modules/vite": {
-			"version": "2.9.8",
-			"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.8.tgz",
-			"integrity": "sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==",
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/vite/-/vite-3.0.0.tgz",
+			"integrity": "sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==",
 			"dev": true,
 			"dependencies": {
-				"esbuild": "^0.14.27",
-				"postcss": "^8.4.13",
-				"resolve": "^1.22.0",
-				"rollup": "^2.59.0"
+				"esbuild": "^0.14.47",
+				"postcss": "^8.4.14",
+				"resolve": "^1.22.1",
+				"rollup": "^2.75.6"
 			},
 			"bin": {
 				"vite": "bin/vite.js"
 			},
 			"engines": {
-				"node": ">=12.2.0"
+				"node": ">=14.18.0"
 			},
 			"optionalDependencies": {
 				"fsevents": "~2.3.2"
@@ -3236,7 +3760,8 @@
 			"peerDependencies": {
 				"less": "*",
 				"sass": "*",
-				"stylus": "*"
+				"stylus": "*",
+				"terser": "^5.4.0"
 			},
 			"peerDependenciesMeta": {
 				"less": {
@@ -3247,9 +3772,28 @@
 				},
 				"stylus": {
 					"optional": true
+				},
+				"terser": {
+					"optional": true
 				}
 			}
 		},
+		"node_modules/webidl-conversions": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+			"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+			"dev": true
+		},
+		"node_modules/whatwg-url": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+			"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+			"dev": true,
+			"dependencies": {
+				"tr46": "~0.0.3",
+				"webidl-conversions": "^3.0.0"
+			}
+		},
 		"node_modules/which": {
 			"version": "2.0.2",
 			"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -3265,6 +3809,15 @@
 				"node": ">= 8"
 			}
 		},
+		"node_modules/wide-align": {
+			"version": "1.1.5",
+			"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+			"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+			"dev": true,
+			"dependencies": {
+				"string-width": "^1.0.2 || 2 || 3 || 4"
+			}
+		},
 		"node_modules/word-wrap": {
 			"version": "1.2.3",
 			"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -3275,9 +3828,9 @@
 			}
 		},
 		"node_modules/worktop": {
-			"version": "0.8.0-next.13",
-			"resolved": "https://registry.npmjs.org/worktop/-/worktop-0.8.0-next.13.tgz",
-			"integrity": "sha512-aLPWSneFtPJr3RAf841orF9GNlVdVkQd2Wj/BbcGHp3whBZoXx6dcwwClA9fezm7muNan4SuT+ZTyMWdoJSCAg==",
+			"version": "0.8.0-next.14",
+			"resolved": "https://registry.npmjs.org/worktop/-/worktop-0.8.0-next.14.tgz",
+			"integrity": "sha512-RZgqHu1w/JcUdWOE/BUEAzarrUUHh39eWkLdX8XpA6MfgLJF6X5Vl26CV7/wcm4O/UpZvHMGJUtB9eYTqDjc9g==",
 			"dev": true,
 			"dependencies": {
 				"mrmime": "^1.0.0",
@@ -3290,7 +3843,7 @@
 		"node_modules/wrappy": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-			"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+			"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
 			"dev": true
 		},
 		"node_modules/ws": {
@@ -3347,16 +3900,22 @@
 		}
 	},
 	"dependencies": {
+		"@cloudflare/workers-types": {
+			"version": "3.14.1",
+			"resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-3.14.1.tgz",
+			"integrity": "sha512-B1/plF62pt+H2IJHvApK8fdOJAVsvojvacuac8x8s+JIyqbropMyqNqHTKLm3YD8ZFLGwYeFTudU+PQ7vGvBdA==",
+			"dev": true
+		},
 		"@eslint/eslintrc": {
-			"version": "1.2.3",
-			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
-			"integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==",
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz",
+			"integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==",
 			"dev": true,
 			"requires": {
 				"ajv": "^6.12.4",
 				"debug": "^4.3.2",
 				"espree": "^9.3.2",
-				"globals": "^13.9.0",
+				"globals": "^13.15.0",
 				"ignore": "^5.2.0",
 				"import-fresh": "^3.2.1",
 				"js-yaml": "^4.1.0",
@@ -3387,6 +3946,45 @@
 			"integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==",
 			"dev": true
 		},
+		"@jridgewell/resolve-uri": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+			"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+			"dev": true
+		},
+		"@jridgewell/sourcemap-codec": {
+			"version": "1.4.14",
+			"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+			"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+			"dev": true
+		},
+		"@jridgewell/trace-mapping": {
+			"version": "0.3.14",
+			"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
+			"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
+			"dev": true,
+			"requires": {
+				"@jridgewell/resolve-uri": "^3.0.3",
+				"@jridgewell/sourcemap-codec": "^1.4.10"
+			}
+		},
+		"@mapbox/node-pre-gyp": {
+			"version": "1.0.9",
+			"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz",
+			"integrity": "sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==",
+			"dev": true,
+			"requires": {
+				"detect-libc": "^2.0.0",
+				"https-proxy-agent": "^5.0.0",
+				"make-dir": "^3.1.0",
+				"node-fetch": "^2.6.7",
+				"nopt": "^5.0.0",
+				"npmlog": "^5.0.1",
+				"rimraf": "^3.0.2",
+				"semver": "^7.3.5",
+				"tar": "^6.1.11"
+			}
+		},
 		"@nodelib/fs.scandir": {
 			"version": "2.1.5",
 			"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -3429,88 +4027,81 @@
 			"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
 		},
 		"@sveltejs/adapter-auto": {
-			"version": "1.0.0-next.40",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-1.0.0-next.40.tgz",
-			"integrity": "sha512-TT6YJUF3asJ/2RbviEpcDJQ/TixPcvmH0L2266fGNT7+KfAf9wbbVdegPWRODk2E2hTN0X+h5YS9l+lap+BK9w==",
+			"version": "1.0.0-next.61",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-1.0.0-next.61.tgz",
+			"integrity": "sha512-0DwAx4BHhbY4irMx6GyT7cDhH22udUoWkeVHEIhmDtCAfjjzlqfWmyY9qt46Gjp8EApIBrXD2rJB6lJy4jYurQ==",
 			"dev": true,
 			"requires": {
-				"@sveltejs/adapter-cloudflare": "1.0.0-next.19",
-				"@sveltejs/adapter-netlify": "1.0.0-next.56",
-				"@sveltejs/adapter-vercel": "1.0.0-next.50"
+				"@sveltejs/adapter-cloudflare": "1.0.0-next.29",
+				"@sveltejs/adapter-netlify": "1.0.0-next.69",
+				"@sveltejs/adapter-vercel": "1.0.0-next.63"
 			}
 		},
 		"@sveltejs/adapter-cloudflare": {
-			"version": "1.0.0-next.19",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-1.0.0-next.19.tgz",
-			"integrity": "sha512-LET3DUYpl+deoKhkWCzhHUT7iipYkgVkOcRIJX7qT4m23A+MAbzcAC3npgwEYSe9RokOSWMVBr3tVujeES5EeA==",
+			"version": "1.0.0-next.29",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-cloudflare/-/adapter-cloudflare-1.0.0-next.29.tgz",
+			"integrity": "sha512-bm95d2pDEExy1cSPqvWxvftHEJz57krLlW3DdGtxbXWLr8M+WZbCEe1AqsnGycaFXUsn0GZ77IWNrHqcGxwvRg==",
 			"dev": true,
 			"requires": {
-				"esbuild": "^0.14.21",
-				"worktop": "0.8.0-next.13"
+				"@cloudflare/workers-types": "^3.14.0",
+				"esbuild": "^0.14.48",
+				"worktop": "0.8.0-next.14"
 			}
 		},
 		"@sveltejs/adapter-netlify": {
-			"version": "1.0.0-next.56",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-netlify/-/adapter-netlify-1.0.0-next.56.tgz",
-			"integrity": "sha512-fM3aBHsr7syCGfIJcuB1mEoZwynqyOxVijvmyrd9OWHi6MP3bXSP+GhKDMtDpQRwejJJiwuZNTx2PUbV3uirvA==",
+			"version": "1.0.0-next.69",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-netlify/-/adapter-netlify-1.0.0-next.69.tgz",
+			"integrity": "sha512-nIMtadrsnVemVDIuuqHSDxX/7xRypk+X2ewHY+JR/ONV853lUJ1r9AaXF9+XXPIqxGMKStsWm5GzgGNmM8ID2g==",
 			"dev": true,
 			"requires": {
 				"@iarna/toml": "^2.2.5",
-				"esbuild": "^0.14.21",
+				"esbuild": "^0.14.48",
+				"set-cookie-parser": "^2.4.8",
 				"tiny-glob": "^0.2.9"
 			}
 		},
 		"@sveltejs/adapter-node": {
-			"version": "1.0.0-next.73",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.73.tgz",
-			"integrity": "sha512-eidd7u1dPHIaBKMjRePrxazUt+Mm/JpnaiKLzZJBdamhBiiYIb+epkPLLqfG5Oo346/0HLKwFRAM/FXn3u3BHQ==",
+			"version": "1.0.0-next.81",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.0.0-next.81.tgz",
+			"integrity": "sha512-OCYteMK4iNRR+sHMtpMBkNvJoo7lpfMiGF1TsvtE8wv7IjBA5pHwTETrvwZL9nGoQzhpDiDuUWYt7w0cLKCukw==",
 			"dev": true,
 			"requires": {
 				"tiny-glob": "^0.2.9"
 			}
 		},
 		"@sveltejs/adapter-vercel": {
-			"version": "1.0.0-next.50",
-			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.50.tgz",
-			"integrity": "sha512-yta0AkuWEr7qrm8LB34F4ZdCtMxj+cHD4huwrRYCgjv+PSJHLPwe7aH53+Mhrv6La0TgeyQ/f2lTyhBMXZXn9Q==",
+			"version": "1.0.0-next.63",
+			"resolved": "https://registry.npmjs.org/@sveltejs/adapter-vercel/-/adapter-vercel-1.0.0-next.63.tgz",
+			"integrity": "sha512-awb1zmT+hAAHv+x7gOY/8Ch64spxKX6H/DQb+S/VGYRQ6i1WvNgsBUF9vk88KR//7tUY8y/xiTLAb99hJ57WhA==",
 			"dev": true,
 			"requires": {
-				"esbuild": "^0.14.21"
+				"@vercel/nft": "^0.20.0",
+				"esbuild": "^0.14.48"
 			}
 		},
 		"@sveltejs/kit": {
-			"version": "1.0.0-next.326",
-			"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.326.tgz",
-			"integrity": "sha512-prJqmXZ2H1wmFfnMw7wDujfbkcA8vuubuqUkpVVmXhfh2+SEzQscPTNwxoE5EJxb5sywtLWEvYx3hv1gPS4Lvg==",
+			"version": "1.0.0-next.377",
+			"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-1.0.0-next.377.tgz",
+			"integrity": "sha512-DH2v2yUBUuDZ7vzjPXUd/yt1AMR3BIkZN0ubLAvS2C+q5Wbvk7ZvAJhfPZ3OYc3ZpQXe4ZGEcptOjvEYvd1lLA==",
 			"dev": true,
 			"requires": {
-				"@sveltejs/vite-plugin-svelte": "^1.0.0-next.32",
+				"@sveltejs/vite-plugin-svelte": "^1.0.1",
 				"chokidar": "^3.5.3",
-				"sade": "^1.7.4",
-				"vite": "^2.9.0"
+				"sade": "^1.8.1"
 			}
 		},
 		"@sveltejs/vite-plugin-svelte": {
-			"version": "1.0.0-next.43",
-			"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.0-next.43.tgz",
-			"integrity": "sha512-MzeczqGrnDmbAldw/LfXV/dhpLC2bdUzuMhcx0C2j79V2uNzQERHDinxXnG2AVTCTjSpbQxzQwMMmYflnI7W1g==",
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-1.0.1.tgz",
+			"integrity": "sha512-PorCgUounn0VXcpeJu+hOweZODKmGuLHsLomwqSj+p26IwjjGffmYQfVHtiTWq+NqaUuuHWWG7vPge6UFw4Aeg==",
 			"dev": true,
 			"requires": {
 				"@rollup/pluginutils": "^4.2.1",
 				"debug": "^4.3.4",
 				"deepmerge": "^4.2.2",
-				"kleur": "^4.1.4",
-				"magic-string": "^0.26.1",
-				"svelte-hmr": "^0.14.11"
-			}
-		},
-		"@types/axios": {
-			"version": "0.14.0",
-			"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
-			"integrity": "sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ==",
-			"dev": true,
-			"requires": {
-				"axios": "*"
+				"kleur": "^4.1.5",
+				"magic-string": "^0.26.2",
+				"svelte-hmr": "^0.14.12"
 			}
 		},
 		"@types/bcrypt": {
@@ -3538,9 +4129,9 @@
 			}
 		},
 		"@types/geojson": {
-			"version": "7946.0.8",
-			"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
-			"integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==",
+			"version": "7946.0.10",
+			"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
+			"integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==",
 			"dev": true
 		},
 		"@types/json-schema": {
@@ -3550,9 +4141,9 @@
 			"dev": true
 		},
 		"@types/leaflet": {
-			"version": "1.7.10",
-			"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.10.tgz",
-			"integrity": "sha512-RzK5BYwYboOXXxyF01tp8g1J8UbdRvoaf+F/jCnVaWC42+QITB6wKvUklcX7jCMRWkzTnGO9NLg7A6SzrlGALA==",
+			"version": "1.7.11",
+			"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.7.11.tgz",
+			"integrity": "sha512-VwAYom2pfIAf/pLj1VR5aLltd4tOtHyvfaJlNYCoejzP2nu52PrMi1ehsLRMUS+bgafmIIKBV1cMfKeS+uJ0Vg==",
 			"dev": true,
 			"requires": {
 				"@types/geojson": "*"
@@ -3574,9 +4165,9 @@
 			}
 		},
 		"@types/node": {
-			"version": "17.0.32",
-			"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz",
-			"integrity": "sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw==",
+			"version": "18.0.5",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.5.tgz",
+			"integrity": "sha512-En7tneq+j0qAiVwysBD79y86MT3ModuoIJbe7JXp+sb5UAjInSShmK3nXXMioBzfF7rXC12hv12d4IyCVwN4dA==",
 			"dev": true
 		},
 		"@types/pug": {
@@ -3604,100 +4195,124 @@
 			}
 		},
 		"@typescript-eslint/eslint-plugin": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.23.0.tgz",
-			"integrity": "sha512-hEcSmG4XodSLiAp1uxv/OQSGsDY6QN3TcRU32gANp+19wGE1QQZLRS8/GV58VRUoXhnkuJ3ZxNQ3T6Z6zM59DA==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz",
+			"integrity": "sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/scope-manager": "5.23.0",
-				"@typescript-eslint/type-utils": "5.23.0",
-				"@typescript-eslint/utils": "5.23.0",
-				"debug": "^4.3.2",
+				"@typescript-eslint/scope-manager": "5.30.6",
+				"@typescript-eslint/type-utils": "5.30.6",
+				"@typescript-eslint/utils": "5.30.6",
+				"debug": "^4.3.4",
 				"functional-red-black-tree": "^1.0.1",
-				"ignore": "^5.1.8",
+				"ignore": "^5.2.0",
 				"regexpp": "^3.2.0",
-				"semver": "^7.3.5",
+				"semver": "^7.3.7",
 				"tsutils": "^3.21.0"
 			}
 		},
 		"@typescript-eslint/parser": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.23.0.tgz",
-			"integrity": "sha512-V06cYUkqcGqpFjb8ttVgzNF53tgbB/KoQT/iB++DOIExKmzI9vBJKjZKt/6FuV9c+zrDsvJKbJ2DOCYwX91cbw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz",
+			"integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/scope-manager": "5.23.0",
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/typescript-estree": "5.23.0",
-				"debug": "^4.3.2"
+				"@typescript-eslint/scope-manager": "5.30.6",
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/typescript-estree": "5.30.6",
+				"debug": "^4.3.4"
 			}
 		},
 		"@typescript-eslint/scope-manager": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.23.0.tgz",
-			"integrity": "sha512-EhjaFELQHCRb5wTwlGsNMvzK9b8Oco4aYNleeDlNuL6qXWDF47ch4EhVNPh8Rdhf9tmqbN4sWDk/8g+Z/J8JVw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz",
+			"integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/visitor-keys": "5.23.0"
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/visitor-keys": "5.30.6"
 			}
 		},
 		"@typescript-eslint/type-utils": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.23.0.tgz",
-			"integrity": "sha512-iuI05JsJl/SUnOTXA9f4oI+/4qS/Zcgk+s2ir+lRmXI+80D8GaGwoUqs4p+X+4AxDolPpEpVUdlEH4ADxFy4gw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz",
+			"integrity": "sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/utils": "5.23.0",
-				"debug": "^4.3.2",
+				"@typescript-eslint/utils": "5.30.6",
+				"debug": "^4.3.4",
 				"tsutils": "^3.21.0"
 			}
 		},
 		"@typescript-eslint/types": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.23.0.tgz",
-			"integrity": "sha512-NfBsV/h4dir/8mJwdZz7JFibaKC3E/QdeMEDJhiAE3/eMkoniZ7MjbEMCGXw6MZnZDMN3G9S0mH/6WUIj91dmw==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz",
+			"integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==",
 			"dev": true
 		},
 		"@typescript-eslint/typescript-estree": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.23.0.tgz",
-			"integrity": "sha512-xE9e0lrHhI647SlGMl+m+3E3CKPF1wzvvOEWnuE3CCjjT7UiRnDGJxmAcVKJIlFgK6DY9RB98eLr1OPigPEOGg==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz",
+			"integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/visitor-keys": "5.23.0",
-				"debug": "^4.3.2",
-				"globby": "^11.0.4",
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/visitor-keys": "5.30.6",
+				"debug": "^4.3.4",
+				"globby": "^11.1.0",
 				"is-glob": "^4.0.3",
-				"semver": "^7.3.5",
+				"semver": "^7.3.7",
 				"tsutils": "^3.21.0"
 			}
 		},
 		"@typescript-eslint/utils": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.23.0.tgz",
-			"integrity": "sha512-dbgaKN21drqpkbbedGMNPCtRPZo1IOUr5EI9Jrrh99r5UW5Q0dz46RKXeSBoPV+56R6dFKpbrdhgUNSJsDDRZA==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.6.tgz",
+			"integrity": "sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==",
 			"dev": true,
 			"requires": {
 				"@types/json-schema": "^7.0.9",
-				"@typescript-eslint/scope-manager": "5.23.0",
-				"@typescript-eslint/types": "5.23.0",
-				"@typescript-eslint/typescript-estree": "5.23.0",
+				"@typescript-eslint/scope-manager": "5.30.6",
+				"@typescript-eslint/types": "5.30.6",
+				"@typescript-eslint/typescript-estree": "5.30.6",
 				"eslint-scope": "^5.1.1",
 				"eslint-utils": "^3.0.0"
 			}
 		},
 		"@typescript-eslint/visitor-keys": {
-			"version": "5.23.0",
-			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.23.0.tgz",
-			"integrity": "sha512-Vd4mFNchU62sJB8pX19ZSPog05B0Y0CE2UxAZPT5k4iqhRYjPnqyY3woMxCd0++t9OTqkgjST+1ydLBi7e2Fvg==",
+			"version": "5.30.6",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz",
+			"integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==",
 			"dev": true,
 			"requires": {
-				"@typescript-eslint/types": "5.23.0",
-				"eslint-visitor-keys": "^3.0.0"
+				"@typescript-eslint/types": "5.30.6",
+				"eslint-visitor-keys": "^3.3.0"
 			}
 		},
+		"@vercel/nft": {
+			"version": "0.20.1",
+			"resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.20.1.tgz",
+			"integrity": "sha512-hSLcr64KHOkcNiTAlv154K4p4faEFBwYIi2eIgu1QCDhB1qyQYvFuEhtw3eaapNjA4/7x/2jcclfCAjILua/ag==",
+			"dev": true,
+			"requires": {
+				"@mapbox/node-pre-gyp": "^1.0.5",
+				"acorn": "^8.6.0",
+				"bindings": "^1.4.0",
+				"estree-walker": "2.0.2",
+				"glob": "^7.1.3",
+				"graceful-fs": "^4.2.9",
+				"micromatch": "^4.0.2",
+				"node-gyp-build": "^4.2.2",
+				"resolve-from": "^5.0.0",
+				"rollup-pluginutils": "^2.8.2"
+			}
+		},
+		"abbrev": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+			"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+			"dev": true
+		},
 		"acorn": {
 			"version": "8.7.1",
 			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
@@ -3736,6 +4351,15 @@
 			"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
 			"dev": true
 		},
+		"agent-base": {
+			"version": "6.0.2",
+			"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+			"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+			"dev": true,
+			"requires": {
+				"debug": "4"
+			}
+		},
 		"ajv": {
 			"version": "6.12.6",
 			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -3773,10 +4397,26 @@
 				"picomatch": "^2.0.4"
 			}
 		},
+		"aproba": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+			"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+			"dev": true
+		},
+		"are-we-there-yet": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+			"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
+			"dev": true,
+			"requires": {
+				"delegates": "^1.0.0",
+				"readable-stream": "^3.6.0"
+			}
+		},
 		"arg": {
-			"version": "5.0.1",
-			"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz",
-			"integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==",
+			"version": "5.0.2",
+			"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+			"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
 			"dev": true
 		},
 		"argparse": {
@@ -3831,6 +4471,15 @@
 			"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
 			"dev": true
 		},
+		"bindings": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+			"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+			"dev": true,
+			"requires": {
+				"file-uri-to-path": "1.0.0"
+			}
+		},
 		"brace-expansion": {
 			"version": "1.1.11",
 			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -3851,22 +4500,21 @@
 			}
 		},
 		"browserslist": {
-			"version": "4.20.3",
-			"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz",
-			"integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==",
+			"version": "4.21.2",
+			"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz",
+			"integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
 			"dev": true,
 			"requires": {
-				"caniuse-lite": "^1.0.30001332",
-				"electron-to-chromium": "^1.4.118",
-				"escalade": "^3.1.1",
-				"node-releases": "^2.0.3",
-				"picocolors": "^1.0.0"
+				"caniuse-lite": "^1.0.30001366",
+				"electron-to-chromium": "^1.4.188",
+				"node-releases": "^2.0.6",
+				"update-browserslist-db": "^1.0.4"
 			}
 		},
 		"buffer-crc32": {
 			"version": "0.2.13",
 			"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-			"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
+			"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
 			"dev": true
 		},
 		"callsites": {
@@ -3882,9 +4530,9 @@
 			"dev": true
 		},
 		"caniuse-lite": {
-			"version": "1.0.30001339",
-			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001339.tgz",
-			"integrity": "sha512-Es8PiVqCe+uXdms0Gu5xP5PF2bxLR7OBp3wUzUnuO7OHzhOfCyg3hdiGWVPVxhiuniOzng+hTc1u3fEQ0TlkSQ==",
+			"version": "1.0.30001366",
+			"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001366.tgz",
+			"integrity": "sha512-yy7XLWCubDobokgzudpkKux8e0UOOnLHE6mlNJBzT3lZJz6s5atSEzjoL+fsCPkI0G8MP5uVdDx1ur/fXEWkZA==",
 			"dev": true
 		},
 		"chalk": {
@@ -3913,6 +4561,12 @@
 				"readdirp": "~3.6.0"
 			}
 		},
+		"chownr": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+			"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+			"dev": true
+		},
 		"color-convert": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -3928,6 +4582,12 @@
 			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 			"dev": true
 		},
+		"color-support": {
+			"version": "1.1.3",
+			"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+			"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+			"dev": true
+		},
 		"combined-stream": {
 			"version": "1.0.8",
 			"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -3939,7 +4599,13 @@
 		"concat-map": {
 			"version": "0.0.1",
 			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-			"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+			"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+			"dev": true
+		},
+		"console-control-strings": {
+			"version": "1.1.0",
+			"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+			"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
 			"dev": true
 		},
 		"cookie": {
@@ -3987,7 +4653,7 @@
 		"defined": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
-			"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
+			"integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==",
 			"dev": true
 		},
 		"delayed-stream": {
@@ -3995,21 +4661,33 @@
 			"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
 			"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
 		},
+		"delegates": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+			"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+			"dev": true
+		},
 		"detect-indent": {
 			"version": "6.1.0",
 			"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
 			"integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
 			"dev": true
 		},
+		"detect-libc": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+			"integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+			"dev": true
+		},
 		"detective": {
-			"version": "5.2.0",
-			"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz",
-			"integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==",
+			"version": "5.2.1",
+			"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
+			"integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==",
 			"dev": true,
 			"requires": {
-				"acorn-node": "^1.6.1",
+				"acorn-node": "^1.8.2",
 				"defined": "^1.0.0",
-				"minimist": "^1.1.1"
+				"minimist": "^1.2.6"
 			}
 		},
 		"didyoumean": {
@@ -4043,9 +4721,15 @@
 			}
 		},
 		"electron-to-chromium": {
-			"version": "1.4.137",
-			"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz",
-			"integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==",
+			"version": "1.4.191",
+			"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.191.tgz",
+			"integrity": "sha512-MeEaiuoSFh4G+rrN+Ilm1KJr8pTTZloeLurcZ+PRcthvdK1gWThje+E6baL7/7LoNctrzCncavAG/j/vpES9jg==",
+			"dev": true
+		},
+		"emoji-regex": {
+			"version": "8.0.0",
+			"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+			"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
 			"dev": true
 		},
 		"engine.io-client": {
@@ -4068,174 +4752,174 @@
 		"es6-promise": {
 			"version": "3.3.1",
 			"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
-			"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
+			"integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==",
 			"dev": true
 		},
 		"esbuild": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.38.tgz",
-			"integrity": "sha512-12fzJ0fsm7gVZX1YQ1InkOE5f9Tl7cgf6JPYXRJtPIoE0zkWAbHdPHVPPaLi9tYAcEBqheGzqLn/3RdTOyBfcA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.49.tgz",
+			"integrity": "sha512-/TlVHhOaq7Yz8N1OJrjqM3Auzo5wjvHFLk+T8pIue+fhnhIMpfAzsG6PLVMbFveVxqD2WOp3QHei+52IMUNmCw==",
 			"dev": true,
 			"requires": {
-				"esbuild-android-64": "0.14.38",
-				"esbuild-android-arm64": "0.14.38",
-				"esbuild-darwin-64": "0.14.38",
-				"esbuild-darwin-arm64": "0.14.38",
-				"esbuild-freebsd-64": "0.14.38",
-				"esbuild-freebsd-arm64": "0.14.38",
-				"esbuild-linux-32": "0.14.38",
-				"esbuild-linux-64": "0.14.38",
-				"esbuild-linux-arm": "0.14.38",
-				"esbuild-linux-arm64": "0.14.38",
-				"esbuild-linux-mips64le": "0.14.38",
-				"esbuild-linux-ppc64le": "0.14.38",
-				"esbuild-linux-riscv64": "0.14.38",
-				"esbuild-linux-s390x": "0.14.38",
-				"esbuild-netbsd-64": "0.14.38",
-				"esbuild-openbsd-64": "0.14.38",
-				"esbuild-sunos-64": "0.14.38",
-				"esbuild-windows-32": "0.14.38",
-				"esbuild-windows-64": "0.14.38",
-				"esbuild-windows-arm64": "0.14.38"
+				"esbuild-android-64": "0.14.49",
+				"esbuild-android-arm64": "0.14.49",
+				"esbuild-darwin-64": "0.14.49",
+				"esbuild-darwin-arm64": "0.14.49",
+				"esbuild-freebsd-64": "0.14.49",
+				"esbuild-freebsd-arm64": "0.14.49",
+				"esbuild-linux-32": "0.14.49",
+				"esbuild-linux-64": "0.14.49",
+				"esbuild-linux-arm": "0.14.49",
+				"esbuild-linux-arm64": "0.14.49",
+				"esbuild-linux-mips64le": "0.14.49",
+				"esbuild-linux-ppc64le": "0.14.49",
+				"esbuild-linux-riscv64": "0.14.49",
+				"esbuild-linux-s390x": "0.14.49",
+				"esbuild-netbsd-64": "0.14.49",
+				"esbuild-openbsd-64": "0.14.49",
+				"esbuild-sunos-64": "0.14.49",
+				"esbuild-windows-32": "0.14.49",
+				"esbuild-windows-64": "0.14.49",
+				"esbuild-windows-arm64": "0.14.49"
 			}
 		},
 		"esbuild-android-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.38.tgz",
-			"integrity": "sha512-aRFxR3scRKkbmNuGAK+Gee3+yFxkTJO/cx83Dkyzo4CnQl/2zVSurtG6+G86EQIZ+w+VYngVyK7P3HyTBKu3nw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz",
+			"integrity": "sha512-vYsdOTD+yi+kquhBiFWl3tyxnj2qZJsl4tAqwhT90ktUdnyTizgle7TjNx6Ar1bN7wcwWqZ9QInfdk2WVagSww==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-android-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.38.tgz",
-			"integrity": "sha512-L2NgQRWuHFI89IIZIlpAcINy9FvBk6xFVZ7xGdOwIm8VyhX1vNCEqUJO3DPSSy945Gzdg98cxtNt8Grv1CsyhA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.49.tgz",
+			"integrity": "sha512-g2HGr/hjOXCgSsvQZ1nK4nW/ei8JUx04Li74qub9qWrStlysaVmadRyTVuW32FGIpLQyc5sUjjZopj49eGGM2g==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-darwin-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.38.tgz",
-			"integrity": "sha512-5JJvgXkX87Pd1Og0u/NJuO7TSqAikAcQQ74gyJ87bqWRVeouky84ICoV4sN6VV53aTW+NE87qLdGY4QA2S7KNA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.49.tgz",
+			"integrity": "sha512-3rvqnBCtX9ywso5fCHixt2GBCUsogNp9DjGmvbBohh31Ces34BVzFltMSxJpacNki96+WIcX5s/vum+ckXiLYg==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-darwin-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.38.tgz",
-			"integrity": "sha512-eqF+OejMI3mC5Dlo9Kdq/Ilbki9sQBw3QlHW3wjLmsLh+quNfHmGMp3Ly1eWm981iGBMdbtSS9+LRvR2T8B3eQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.49.tgz",
+			"integrity": "sha512-XMaqDxO846srnGlUSJnwbijV29MTKUATmOLyQSfswbK/2X5Uv28M9tTLUJcKKxzoo9lnkYPsx2o8EJcTYwCs/A==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-freebsd-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.38.tgz",
-			"integrity": "sha512-epnPbhZUt93xV5cgeY36ZxPXDsQeO55DppzsIgWM8vgiG/Rz+qYDLmh5ts3e+Ln1wA9dQ+nZmVHw+RjaW3I5Ig==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.49.tgz",
+			"integrity": "sha512-NJ5Q6AjV879mOHFri+5lZLTp5XsO2hQ+KSJYLbfY9DgCu8s6/Zl2prWXVANYTeCDLlrIlNNYw8y34xqyLDKOmQ==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-freebsd-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.38.tgz",
-			"integrity": "sha512-/9icXUYJWherhk+y5fjPI5yNUdFPtXHQlwP7/K/zg8t8lQdHVj20SqU9/udQmeUo5pDFHMYzcEFfJqgOVeKNNQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.49.tgz",
+			"integrity": "sha512-lFLtgXnAc3eXYqj5koPlBZvEbBSOSUbWO3gyY/0+4lBdRqELyz4bAuamHvmvHW5swJYL7kngzIZw6kdu25KGOA==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-32": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.38.tgz",
-			"integrity": "sha512-QfgfeNHRFvr2XeHFzP8kOZVnal3QvST3A0cgq32ZrHjSMFTdgXhMhmWdKzRXP/PKcfv3e2OW9tT9PpcjNvaq6g==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.49.tgz",
+			"integrity": "sha512-zTTH4gr2Kb8u4QcOpTDVn7Z8q7QEIvFl/+vHrI3cF6XOJS7iEI1FWslTo3uofB2+mn6sIJEQD9PrNZKoAAMDiA==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.38.tgz",
-			"integrity": "sha512-uuZHNmqcs+Bj1qiW9k/HZU3FtIHmYiuxZ/6Aa+/KHb/pFKr7R3aVqvxlAudYI9Fw3St0VCPfv7QBpUITSmBR1Q==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.49.tgz",
+			"integrity": "sha512-hYmzRIDzFfLrB5c1SknkxzM8LdEUOusp6M2TnuQZJLRtxTgyPnZZVtyMeCLki0wKgYPXkFsAVhi8vzo2mBNeTg==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-arm": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.38.tgz",
-			"integrity": "sha512-FiFvQe8J3VKTDXG01JbvoVRXQ0x6UZwyrU4IaLBZeq39Bsbatd94Fuc3F1RGqPF5RbIWW7RvkVQjn79ejzysnA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.49.tgz",
+			"integrity": "sha512-iE3e+ZVv1Qz1Sy0gifIsarJMQ89Rpm9mtLSRtG3AH0FPgAzQ5Z5oU6vYzhc/3gSPi2UxdCOfRhw2onXuFw/0lg==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.38.tgz",
-			"integrity": "sha512-HlMGZTEsBrXrivr64eZ/EO0NQM8H8DuSENRok9d+Jtvq8hOLzrxfsAT9U94K3KOGk2XgCmkaI2KD8hX7F97lvA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.49.tgz",
+			"integrity": "sha512-KLQ+WpeuY+7bxukxLz5VgkAAVQxUv67Ft4DmHIPIW+2w3ObBPQhqNoeQUHxopoW/aiOn3m99NSmSV+bs4BSsdA==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-mips64le": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.38.tgz",
-			"integrity": "sha512-qd1dLf2v7QBiI5wwfil9j0HG/5YMFBAmMVmdeokbNAMbcg49p25t6IlJFXAeLzogv1AvgaXRXvgFNhScYEUXGQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.49.tgz",
+			"integrity": "sha512-n+rGODfm8RSum5pFIqFQVQpYBw+AztL8s6o9kfx7tjfK0yIGF6tm5HlG6aRjodiiKkH2xAiIM+U4xtQVZYU4rA==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-ppc64le": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.38.tgz",
-			"integrity": "sha512-mnbEm7o69gTl60jSuK+nn+pRsRHGtDPfzhrqEUXyCl7CTOCLtWN2bhK8bgsdp6J/2NyS/wHBjs1x8aBWwP2X9Q==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.49.tgz",
+			"integrity": "sha512-WP9zR4HX6iCBmMFH+XHHng2LmdoIeUmBpL4aL2TR8ruzXyT4dWrJ5BSbT8iNo6THN8lod6GOmYDLq/dgZLalGw==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-riscv64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.38.tgz",
-			"integrity": "sha512-+p6YKYbuV72uikChRk14FSyNJZ4WfYkffj6Af0/Tw63/6TJX6TnIKE+6D3xtEc7DeDth1fjUOEqm+ApKFXbbVQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.49.tgz",
+			"integrity": "sha512-h66ORBz+Dg+1KgLvzTVQEA1LX4XBd1SK0Fgbhhw4akpG/YkN8pS6OzYI/7SGENiN6ao5hETRDSkVcvU9NRtkMQ==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-linux-s390x": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.38.tgz",
-			"integrity": "sha512-0zUsiDkGJiMHxBQ7JDU8jbaanUY975CdOW1YDrurjrM0vWHfjv9tLQsW9GSyEb/heSK1L5gaweRjzfUVBFoybQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.49.tgz",
+			"integrity": "sha512-DhrUoFVWD+XmKO1y7e4kNCqQHPs6twz6VV6Uezl/XHYGzM60rBewBF5jlZjG0nCk5W/Xy6y1xWeopkrhFFM0sQ==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-netbsd-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.38.tgz",
-			"integrity": "sha512-cljBAApVwkpnJZfnRVThpRBGzCi+a+V9Ofb1fVkKhtrPLDYlHLrSYGtmnoTVWDQdU516qYI8+wOgcGZ4XIZh0Q==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.49.tgz",
+			"integrity": "sha512-BXaUwFOfCy2T+hABtiPUIpWjAeWK9P8O41gR4Pg73hpzoygVGnj0nI3YK4SJhe52ELgtdgWP/ckIkbn2XaTxjQ==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-openbsd-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.38.tgz",
-			"integrity": "sha512-CDswYr2PWPGEPpLDUO50mL3WO/07EMjnZDNKpmaxUPsrW+kVM3LoAqr/CE8UbzugpEiflYqJsGPLirThRB18IQ==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.49.tgz",
+			"integrity": "sha512-lP06UQeLDGmVPw9Rg437Btu6J9/BmyhdoefnQ4gDEJTtJvKtQaUcOQrhjTq455ouZN4EHFH1h28WOJVANK41kA==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-sunos-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.38.tgz",
-			"integrity": "sha512-2mfIoYW58gKcC3bck0j7lD3RZkqYA7MmujFYmSn9l6TiIcAMpuEvqksO+ntBgbLep/eyjpgdplF7b+4T9VJGOA==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.49.tgz",
+			"integrity": "sha512-4c8Zowp+V3zIWje329BeLbGh6XI9c/rqARNaj5yPHdC61pHI9UNdDxT3rePPJeWcEZVKjkiAS6AP6kiITp7FSw==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-windows-32": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.38.tgz",
-			"integrity": "sha512-L2BmEeFZATAvU+FJzJiRLFUP+d9RHN+QXpgaOrs2klshoAm1AE6Us4X6fS9k33Uy5SzScn2TpcgecbqJza1Hjw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.49.tgz",
+			"integrity": "sha512-q7Rb+J9yHTeKr9QTPDYkqfkEj8/kcKz9lOabDuvEXpXuIcosWCJgo5Z7h/L4r7rbtTH4a8U2FGKb6s1eeOHmJA==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-windows-64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.38.tgz",
-			"integrity": "sha512-Khy4wVmebnzue8aeSXLC+6clo/hRYeNIm0DyikoEqX+3w3rcvrhzpoix0S+MF9vzh6JFskkIGD7Zx47ODJNyCw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.49.tgz",
+			"integrity": "sha512-+Cme7Ongv0UIUTniPqfTX6mJ8Deo7VXw9xN0yJEN1lQMHDppTNmKwAM3oGbD/Vqff+07K2gN0WfNkMohmG+dVw==",
 			"dev": true,
 			"optional": true
 		},
 		"esbuild-windows-arm64": {
-			"version": "0.14.38",
-			"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.38.tgz",
-			"integrity": "sha512-k3FGCNmHBkqdJXuJszdWciAH77PukEyDsdIryEHn9cKLQFxzhT39dSumeTuggaQcXY57UlmLGIkklWZo2qzHpw==",
+			"version": "0.14.49",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.49.tgz",
+			"integrity": "sha512-v+HYNAXzuANrCbbLFJ5nmO3m5y2PGZWLe3uloAkLt87aXiO2mZr3BTmacZdjwNkNEHuH3bNtN8cak+mzVjVPfA==",
 			"dev": true,
 			"optional": true
 		},
@@ -4252,12 +4936,12 @@
 			"dev": true
 		},
 		"eslint": {
-			"version": "8.15.0",
-			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz",
-			"integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==",
+			"version": "8.19.0",
+			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.19.0.tgz",
+			"integrity": "sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw==",
 			"dev": true,
 			"requires": {
-				"@eslint/eslintrc": "^1.2.3",
+				"@eslint/eslintrc": "^1.3.0",
 				"@humanwhocodes/config-array": "^0.9.2",
 				"ajv": "^6.10.0",
 				"chalk": "^4.0.0",
@@ -4275,7 +4959,7 @@
 				"file-entry-cache": "^6.0.1",
 				"functional-red-black-tree": "^1.0.1",
 				"glob-parent": "^6.0.1",
-				"globals": "^13.6.0",
+				"globals": "^13.15.0",
 				"ignore": "^5.2.0",
 				"import-fresh": "^3.0.0",
 				"imurmurhash": "^0.1.4",
@@ -4464,7 +5148,7 @@
 		"fast-levenshtein": {
 			"version": "2.0.6",
 			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-			"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
 			"dev": true
 		},
 		"fastq": {
@@ -4485,6 +5169,12 @@
 				"flat-cache": "^3.0.4"
 			}
 		},
+		"file-uri-to-path": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+			"dev": true
+		},
 		"fill-range": {
 			"version": "7.0.1",
 			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -4505,9 +5195,9 @@
 			}
 		},
 		"flatted": {
-			"version": "3.2.5",
-			"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz",
-			"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
+			"version": "3.2.6",
+			"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz",
+			"integrity": "sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ==",
 			"dev": true
 		},
 		"follow-redirects": {
@@ -4531,10 +5221,19 @@
 			"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
 			"dev": true
 		},
+		"fs-minipass": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+			"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+			"dev": true,
+			"requires": {
+				"minipass": "^3.0.0"
+			}
+		},
 		"fs.realpath": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-			"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+			"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
 			"dev": true
 		},
 		"fsevents": {
@@ -4553,19 +5252,36 @@
 		"functional-red-black-tree": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
-			"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+			"integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
 			"dev": true
 		},
+		"gauge": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+			"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
+			"dev": true,
+			"requires": {
+				"aproba": "^1.0.3 || ^2.0.0",
+				"color-support": "^1.1.2",
+				"console-control-strings": "^1.0.0",
+				"has-unicode": "^2.0.1",
+				"object-assign": "^4.1.1",
+				"signal-exit": "^3.0.0",
+				"string-width": "^4.2.3",
+				"strip-ansi": "^6.0.1",
+				"wide-align": "^1.1.2"
+			}
+		},
 		"glob": {
-			"version": "7.2.0",
-			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
-			"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+			"version": "7.2.3",
+			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
 			"dev": true,
 			"requires": {
 				"fs.realpath": "^1.0.0",
 				"inflight": "^1.0.4",
 				"inherits": "2",
-				"minimatch": "^3.0.4",
+				"minimatch": "^3.1.1",
 				"once": "^1.3.0",
 				"path-is-absolute": "^1.0.0"
 			}
@@ -4580,9 +5296,9 @@
 			}
 		},
 		"globals": {
-			"version": "13.14.0",
-			"resolved": "https://registry.npmjs.org/globals/-/globals-13.14.0.tgz",
-			"integrity": "sha512-ERO68sOYwm5UuLvSJTY7w7NP2c8S4UcXs3X1GBX8cwOr+ShOcDBbCY5mH4zxz0jsYCdJ8ve8Mv9n2YGJMB1aeg==",
+			"version": "13.16.0",
+			"resolved": "https://registry.npmjs.org/globals/-/globals-13.16.0.tgz",
+			"integrity": "sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==",
 			"dev": true,
 			"requires": {
 				"type-fest": "^0.20.2"
@@ -4635,6 +5351,22 @@
 			"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
 			"dev": true
 		},
+		"has-unicode": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+			"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+			"dev": true
+		},
+		"https-proxy-agent": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+			"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+			"dev": true,
+			"requires": {
+				"agent-base": "6",
+				"debug": "4"
+			}
+		},
 		"ignore": {
 			"version": "5.2.0",
 			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
@@ -4649,18 +5381,26 @@
 			"requires": {
 				"parent-module": "^1.0.0",
 				"resolve-from": "^4.0.0"
+			},
+			"dependencies": {
+				"resolve-from": {
+					"version": "4.0.0",
+					"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+					"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+					"dev": true
+				}
 			}
 		},
 		"imurmurhash": {
 			"version": "0.1.4",
 			"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-			"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+			"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
 			"dev": true
 		},
 		"inflight": {
 			"version": "1.0.6",
 			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-			"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+			"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
 			"dev": true,
 			"requires": {
 				"once": "^1.3.0",
@@ -4694,7 +5434,13 @@
 		"is-extglob": {
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-			"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+			"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+			"dev": true
+		},
+		"is-fullwidth-code-point": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+			"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
 			"dev": true
 		},
 		"is-glob": {
@@ -4715,7 +5461,7 @@
 		"isexe": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-			"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+			"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
 			"dev": true
 		},
 		"js-yaml": {
@@ -4736,13 +5482,13 @@
 		"json-stable-stringify-without-jsonify": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-			"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
+			"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
 			"dev": true
 		},
 		"kleur": {
-			"version": "4.1.4",
-			"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz",
-			"integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==",
+			"version": "4.1.5",
+			"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+			"integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
 			"dev": true
 		},
 		"leaflet": {
@@ -4761,9 +5507,9 @@
 			}
 		},
 		"lilconfig": {
-			"version": "2.0.5",
-			"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
-			"integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==",
+			"version": "2.0.6",
+			"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
+			"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
 			"dev": true
 		},
 		"lodash": {
@@ -4792,14 +5538,31 @@
 			}
 		},
 		"magic-string": {
-			"version": "0.26.1",
-			"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.1.tgz",
-			"integrity": "sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==",
+			"version": "0.26.2",
+			"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz",
+			"integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==",
 			"dev": true,
 			"requires": {
 				"sourcemap-codec": "^1.4.8"
 			}
 		},
+		"make-dir": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+			"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+			"dev": true,
+			"requires": {
+				"semver": "^6.0.0"
+			},
+			"dependencies": {
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				}
+			}
+		},
 		"merge2": {
 			"version": "1.4.1",
 			"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -4850,6 +5613,25 @@
 			"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
 			"dev": true
 		},
+		"minipass": {
+			"version": "3.3.4",
+			"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
+			"integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==",
+			"dev": true,
+			"requires": {
+				"yallist": "^4.0.0"
+			}
+		},
+		"minizlib": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+			"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+			"dev": true,
+			"requires": {
+				"minipass": "^3.0.0",
+				"yallist": "^4.0.0"
+			}
+		},
 		"mkdirp": {
 			"version": "0.5.6",
 			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
@@ -4860,9 +5642,9 @@
 			}
 		},
 		"moment": {
-			"version": "2.29.3",
-			"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
-			"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw=="
+			"version": "2.29.4",
+			"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+			"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
 		},
 		"mri": {
 			"version": "1.2.0",
@@ -4871,9 +5653,9 @@
 			"dev": true
 		},
 		"mrmime": {
-			"version": "1.0.0",
-			"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz",
-			"integrity": "sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ==",
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz",
+			"integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==",
 			"dev": true
 		},
 		"ms": {
@@ -4890,15 +5672,39 @@
 		"natural-compare": {
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-			"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+			"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+			"dev": true
+		},
+		"node-fetch": {
+			"version": "2.6.7",
+			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+			"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+			"dev": true,
+			"requires": {
+				"whatwg-url": "^5.0.0"
+			}
+		},
+		"node-gyp-build": {
+			"version": "4.5.0",
+			"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz",
+			"integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==",
 			"dev": true
 		},
 		"node-releases": {
-			"version": "2.0.4",
-			"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz",
-			"integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==",
+			"version": "2.0.6",
+			"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+			"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
 			"dev": true
 		},
+		"nopt": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+			"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+			"dev": true,
+			"requires": {
+				"abbrev": "1"
+			}
+		},
 		"normalize-path": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -4908,7 +5714,25 @@
 		"normalize-range": {
 			"version": "0.1.2",
 			"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
-			"integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+			"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+			"dev": true
+		},
+		"npmlog": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+			"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
+			"dev": true,
+			"requires": {
+				"are-we-there-yet": "^2.0.0",
+				"console-control-strings": "^1.1.0",
+				"gauge": "^3.0.0",
+				"set-blocking": "^2.0.0"
+			}
+		},
+		"object-assign": {
+			"version": "4.1.1",
+			"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+			"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
 			"dev": true
 		},
 		"object-hash": {
@@ -4920,7 +5744,7 @@
 		"once": {
 			"version": "1.4.0",
 			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-			"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+			"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
 			"dev": true,
 			"requires": {
 				"wrappy": "1"
@@ -4952,7 +5776,7 @@
 		"path-is-absolute": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-			"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+			"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
 			"dev": true
 		},
 		"path-key": {
@@ -4985,17 +5809,34 @@
 			"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
 			"dev": true
 		},
+		"pify": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+			"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+			"dev": true
+		},
 		"postcss": {
-			"version": "8.4.13",
-			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz",
-			"integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==",
+			"version": "8.4.14",
+			"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
+			"integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
 			"dev": true,
 			"requires": {
-				"nanoid": "^3.3.3",
+				"nanoid": "^3.3.4",
 				"picocolors": "^1.0.0",
 				"source-map-js": "^1.0.2"
 			}
 		},
+		"postcss-import": {
+			"version": "14.1.0",
+			"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz",
+			"integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==",
+			"dev": true,
+			"requires": {
+				"postcss-value-parser": "^4.0.0",
+				"read-cache": "^1.0.0",
+				"resolve": "^1.1.7"
+			}
+		},
 		"postcss-js": {
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz",
@@ -5047,9 +5888,9 @@
 			"dev": true
 		},
 		"prettier": {
-			"version": "2.6.2",
-			"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz",
-			"integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==",
+			"version": "2.7.1",
+			"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+			"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
 			"dev": true
 		},
 		"prettier-plugin-svelte": {
@@ -5077,6 +5918,26 @@
 			"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
 			"dev": true
 		},
+		"read-cache": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+			"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+			"dev": true,
+			"requires": {
+				"pify": "^2.3.0"
+			}
+		},
+		"readable-stream": {
+			"version": "3.6.0",
+			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+			"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+			"dev": true,
+			"requires": {
+				"inherits": "^2.0.3",
+				"string_decoder": "^1.1.1",
+				"util-deprecate": "^1.0.1"
+			}
+		},
 		"readdirp": {
 			"version": "3.6.0",
 			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -5087,9 +5948,9 @@
 			}
 		},
 		"regexparam": {
-			"version": "2.0.0",
-			"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.0.tgz",
-			"integrity": "sha512-gJKwd2MVPWHAIFLsaYDZfyKzHNS4o7E/v8YmNf44vmeV2e4YfVoDToTOKTvE7ab68cRJ++kLuEXJBaEeJVt5ow==",
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/regexparam/-/regexparam-2.0.1.tgz",
+			"integrity": "sha512-zRgSaYemnNYxUv+/5SeoHI0eJIgTL/A2pUtXUPLHQxUldagouJ9p+K6IbIZ/JiQuCEv2E2B1O11SjVQy3aMCkw==",
 			"dev": true
 		},
 		"regexpp": {
@@ -5099,20 +5960,20 @@
 			"dev": true
 		},
 		"resolve": {
-			"version": "1.22.0",
-			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
-			"integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+			"version": "1.22.1",
+			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+			"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
 			"dev": true,
 			"requires": {
-				"is-core-module": "^2.8.1",
+				"is-core-module": "^2.9.0",
 				"path-parse": "^1.0.7",
 				"supports-preserve-symlinks-flag": "^1.0.0"
 			}
 		},
 		"resolve-from": {
-			"version": "4.0.0",
-			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-			"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+			"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
 			"dev": true
 		},
 		"reusify": {
@@ -5131,14 +5992,31 @@
 			}
 		},
 		"rollup": {
-			"version": "2.72.1",
-			"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.72.1.tgz",
-			"integrity": "sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA==",
+			"version": "2.77.0",
+			"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz",
+			"integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==",
 			"dev": true,
 			"requires": {
 				"fsevents": "~2.3.2"
 			}
 		},
+		"rollup-pluginutils": {
+			"version": "2.8.2",
+			"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
+			"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
+			"dev": true,
+			"requires": {
+				"estree-walker": "^0.6.1"
+			},
+			"dependencies": {
+				"estree-walker": {
+					"version": "0.6.1",
+					"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
+					"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
+					"dev": true
+				}
+			}
+		},
 		"run-parallel": {
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -5157,10 +6035,16 @@
 				"mri": "^1.1.0"
 			}
 		},
+		"safe-buffer": {
+			"version": "5.2.1",
+			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+			"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+			"dev": true
+		},
 		"sander": {
 			"version": "0.5.1",
 			"resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz",
-			"integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=",
+			"integrity": "sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==",
 			"dev": true,
 			"requires": {
 				"es6-promise": "^3.1.2",
@@ -5189,6 +6073,18 @@
 				"lru-cache": "^6.0.0"
 			}
 		},
+		"set-blocking": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+			"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+			"dev": true
+		},
+		"set-cookie-parser": {
+			"version": "2.5.0",
+			"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.0.tgz",
+			"integrity": "sha512-cHMAtSXilfyBePduZEBVPTCftTQWz6ehWJD5YNUg4mqvRosrrjKbo4WS8JkB0/RxonMoohHm7cOGH60mDkRQ9w==",
+			"dev": true
+		},
 		"shebang-command": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -5204,6 +6100,12 @@
 			"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
 			"dev": true
 		},
+		"signal-exit": {
+			"version": "3.0.7",
+			"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+			"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+			"dev": true
+		},
 		"slash": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -5222,9 +6124,9 @@
 			}
 		},
 		"socket.io-parser": {
-			"version": "4.2.0",
-			"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz",
-			"integrity": "sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==",
+			"version": "4.2.1",
+			"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
+			"integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
 			"requires": {
 				"@socket.io/component-emitter": "~3.1.0",
 				"debug": "~4.3.1"
@@ -5233,7 +6135,7 @@
 		"sorcery": {
 			"version": "0.10.0",
 			"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz",
-			"integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=",
+			"integrity": "sha512-R5ocFmKZQFfSTstfOtHjJuAwbpGyf9qjQa1egyhvXSbM7emjrtLXtGdZsDJDABC85YBfVvrOiGWKSYXPKdvP1g==",
 			"dev": true,
 			"requires": {
 				"buffer-crc32": "^0.2.5",
@@ -5242,12 +6144,6 @@
 				"sourcemap-codec": "^1.3.0"
 			}
 		},
-		"source-map": {
-			"version": "0.7.3",
-			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
-			"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
-			"dev": true
-		},
 		"source-map-js": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
@@ -5260,6 +6156,26 @@
 			"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
 			"dev": true
 		},
+		"string_decoder": {
+			"version": "1.3.0",
+			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+			"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+			"dev": true,
+			"requires": {
+				"safe-buffer": "~5.2.0"
+			}
+		},
+		"string-width": {
+			"version": "4.2.3",
+			"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+			"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+			"dev": true,
+			"requires": {
+				"emoji-regex": "^8.0.0",
+				"is-fullwidth-code-point": "^3.0.0",
+				"strip-ansi": "^6.0.1"
+			}
+		},
 		"strip-ansi": {
 			"version": "6.0.1",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -5300,30 +6216,30 @@
 			"dev": true
 		},
 		"svelte": {
-			"version": "3.48.0",
-			"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.48.0.tgz",
-			"integrity": "sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ=="
+			"version": "3.49.0",
+			"resolved": "https://registry.npmjs.org/svelte/-/svelte-3.49.0.tgz",
+			"integrity": "sha512-+lmjic1pApJWDfPCpUUTc1m8azDqYCG1JN9YEngrx/hUyIcFJo6VZhj0A1Ai0wqoHcEIuQy+e9tk+4uDgdtsFA=="
 		},
 		"svelte-check": {
-			"version": "2.7.0",
-			"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.7.0.tgz",
-			"integrity": "sha512-GrvG24j0+i8AOm0k0KyJ6Dqc+TAR2yzB7rtS4nljHStunVxCTr/1KYlv4EsOeoqtHLzeWMOd5D2O6nDdP/yw4A==",
+			"version": "2.8.0",
+			"resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.8.0.tgz",
+			"integrity": "sha512-HRL66BxffMAZusqe5I5k26mRWQ+BobGd9Rxm3onh7ZVu0nTk8YTKJ9vu3LVPjUGLU9IX7zS+jmwPVhJYdXJ8vg==",
 			"dev": true,
 			"requires": {
+				"@jridgewell/trace-mapping": "^0.3.9",
 				"chokidar": "^3.4.1",
 				"fast-glob": "^3.2.7",
 				"import-fresh": "^3.2.1",
 				"picocolors": "^1.0.0",
 				"sade": "^1.7.4",
-				"source-map": "^0.7.3",
 				"svelte-preprocess": "^4.0.0",
 				"typescript": "*"
 			}
 		},
 		"svelte-hmr": {
-			"version": "0.14.11",
-			"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.11.tgz",
-			"integrity": "sha512-R9CVfX6DXxW1Kn45Jtmx+yUe+sPhrbYSUp7TkzbW0jI5fVPn6lsNG9NEs5dFg5qRhFNAoVdRw5qQDLALNKhwbQ==",
+			"version": "0.14.12",
+			"resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.14.12.tgz",
+			"integrity": "sha512-4QSW/VvXuqVcFZ+RhxiR8/newmwOCTlbYIezvkeN6302YFRE8cXy0naamHcjz8Y9Ce3ITTZtrHrIL0AGfyo61w==",
 			"dev": true,
 			"requires": {}
 		},
@@ -5334,9 +6250,9 @@
 			"requires": {}
 		},
 		"svelte-preprocess": {
-			"version": "4.10.6",
-			"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.6.tgz",
-			"integrity": "sha512-I2SV1w/AveMvgIQlUF/ZOO3PYVnhxfcpNyGt8pxpUVhPfyfL/CZBkkw/KPfuFix5FJ9TnnNYMhACK3DtSaYVVQ==",
+			"version": "4.10.7",
+			"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz",
+			"integrity": "sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==",
 			"dev": true,
 			"requires": {
 				"@types/pug": "^2.0.4",
@@ -5359,15 +6275,15 @@
 			}
 		},
 		"tailwindcss": {
-			"version": "3.0.24",
-			"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz",
-			"integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==",
+			"version": "3.1.6",
+			"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.6.tgz",
+			"integrity": "sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==",
 			"dev": true,
 			"requires": {
-				"arg": "^5.0.1",
+				"arg": "^5.0.2",
 				"chokidar": "^3.5.3",
 				"color-name": "^1.1.4",
-				"detective": "^5.2.0",
+				"detective": "^5.2.1",
 				"didyoumean": "^1.2.2",
 				"dlv": "^1.1.3",
 				"fast-glob": "^3.2.11",
@@ -5377,14 +6293,15 @@
 				"normalize-path": "^3.0.0",
 				"object-hash": "^3.0.0",
 				"picocolors": "^1.0.0",
-				"postcss": "^8.4.12",
+				"postcss": "^8.4.14",
+				"postcss-import": "^14.1.0",
 				"postcss-js": "^4.0.0",
 				"postcss-load-config": "^3.1.4",
 				"postcss-nested": "5.0.6",
 				"postcss-selector-parser": "^6.0.10",
 				"postcss-value-parser": "^4.2.0",
 				"quick-lru": "^5.1.1",
-				"resolve": "^1.22.0"
+				"resolve": "^1.22.1"
 			},
 			"dependencies": {
 				"glob-parent": {
@@ -5398,10 +6315,32 @@
 				}
 			}
 		},
+		"tar": {
+			"version": "6.1.11",
+			"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+			"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+			"dev": true,
+			"requires": {
+				"chownr": "^2.0.0",
+				"fs-minipass": "^2.0.0",
+				"minipass": "^3.0.0",
+				"minizlib": "^2.1.1",
+				"mkdirp": "^1.0.3",
+				"yallist": "^4.0.0"
+			},
+			"dependencies": {
+				"mkdirp": {
+					"version": "1.0.4",
+					"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+					"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+					"dev": true
+				}
+			}
+		},
 		"text-table": {
 			"version": "0.2.0",
 			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-			"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+			"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
 			"dev": true
 		},
 		"tiny-glob": {
@@ -5423,6 +6362,12 @@
 				"is-number": "^7.0.0"
 			}
 		},
+		"tr46": {
+			"version": "0.0.3",
+			"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+			"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+			"dev": true
+		},
 		"tslib": {
 			"version": "2.4.0",
 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
@@ -5462,11 +6407,21 @@
 			"dev": true
 		},
 		"typescript": {
-			"version": "4.6.4",
-			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
-			"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
+			"version": "4.7.4",
+			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+			"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
 			"dev": true
 		},
+		"update-browserslist-db": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz",
+			"integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==",
+			"dev": true,
+			"requires": {
+				"escalade": "^3.1.1",
+				"picocolors": "^1.0.0"
+			}
+		},
 		"uri-js": {
 			"version": "4.4.1",
 			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -5479,7 +6434,7 @@
 		"util-deprecate": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-			"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+			"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
 			"dev": true
 		},
 		"v8-compile-cache": {
@@ -5489,16 +6444,32 @@
 			"dev": true
 		},
 		"vite": {
-			"version": "2.9.8",
-			"resolved": "https://registry.npmjs.org/vite/-/vite-2.9.8.tgz",
-			"integrity": "sha512-zsBGwn5UT3YS0NLSJ7hnR54+vUKfgzMUh/Z9CxF1YKEBVIe213+63jrFLmZphgGI5zXwQCSmqIdbPuE8NJywPw==",
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/vite/-/vite-3.0.0.tgz",
+			"integrity": "sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==",
 			"dev": true,
 			"requires": {
-				"esbuild": "^0.14.27",
+				"esbuild": "^0.14.47",
 				"fsevents": "~2.3.2",
-				"postcss": "^8.4.13",
-				"resolve": "^1.22.0",
-				"rollup": "^2.59.0"
+				"postcss": "^8.4.14",
+				"resolve": "^1.22.1",
+				"rollup": "^2.75.6"
+			}
+		},
+		"webidl-conversions": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+			"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+			"dev": true
+		},
+		"whatwg-url": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+			"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+			"dev": true,
+			"requires": {
+				"tr46": "~0.0.3",
+				"webidl-conversions": "^3.0.0"
 			}
 		},
 		"which": {
@@ -5510,6 +6481,15 @@
 				"isexe": "^2.0.0"
 			}
 		},
+		"wide-align": {
+			"version": "1.1.5",
+			"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+			"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+			"dev": true,
+			"requires": {
+				"string-width": "^1.0.2 || 2 || 3 || 4"
+			}
+		},
 		"word-wrap": {
 			"version": "1.2.3",
 			"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -5517,9 +6497,9 @@
 			"dev": true
 		},
 		"worktop": {
-			"version": "0.8.0-next.13",
-			"resolved": "https://registry.npmjs.org/worktop/-/worktop-0.8.0-next.13.tgz",
-			"integrity": "sha512-aLPWSneFtPJr3RAf841orF9GNlVdVkQd2Wj/BbcGHp3whBZoXx6dcwwClA9fezm7muNan4SuT+ZTyMWdoJSCAg==",
+			"version": "0.8.0-next.14",
+			"resolved": "https://registry.npmjs.org/worktop/-/worktop-0.8.0-next.14.tgz",
+			"integrity": "sha512-RZgqHu1w/JcUdWOE/BUEAzarrUUHh39eWkLdX8XpA6MfgLJF6X5Vl26CV7/wcm4O/UpZvHMGJUtB9eYTqDjc9g==",
 			"dev": true,
 			"requires": {
 				"mrmime": "^1.0.0",
@@ -5529,7 +6509,7 @@
 		"wrappy": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-			"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+			"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
 			"dev": true
 		},
 		"ws": {
diff --git a/web/package.json b/web/package.json
index c494c69118..705afe006d 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,22 +1,34 @@
 {
-	"name": "web",
-	"version": "0.0.1",
+	"name": "immich-web",
+	"version": "1.0.0",
 	"scripts": {
-		"dev": "svelte-kit dev --host 0.0.0.0",
-		"build": "svelte-kit build",
+		"dev": "vite dev --host 0.0.0.0 --port 3000",
+		"build": "vite build",
 		"package": "svelte-kit package",
-		"preview": "svelte-kit preview",
+		"preview": "vite preview",
 		"prepare": "svelte-kit sync",
 		"check": "svelte-check --tsconfig ./tsconfig.json",
 		"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
-		"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
-		"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
+		"lint": "prettier --check --plugin-search-dir=. . && eslint .",
+		"format": "prettier --write --plugin-search-dir=. ."
 	},
 	"devDependencies": {
 		"@sveltejs/adapter-auto": "next",
-		"@sveltejs/adapter-node": "^1.0.0-next.73",
 		"@sveltejs/kit": "next",
-		"@types/axios": "^0.14.0",
+		"@typescript-eslint/eslint-plugin": "^5.27.0",
+		"@typescript-eslint/parser": "^5.27.0",
+		"eslint": "^8.16.0",
+		"eslint-config-prettier": "^8.3.0",
+		"eslint-plugin-svelte3": "^4.0.0",
+		"prettier": "^2.6.2",
+		"prettier-plugin-svelte": "^2.7.0",
+		"svelte": "^3.44.0",
+		"svelte-check": "^2.7.1",
+		"svelte-preprocess": "^4.10.6",
+		"tslib": "^2.3.1",
+		"typescript": "^4.7.4",
+		"vite": "^3.0.0",
+		"@sveltejs/adapter-node": "next",
 		"@types/bcrypt": "^5.0.0",
 		"@types/cookie": "^0.4.1",
 		"@types/fluent-ffmpeg": "^2.1.20",
@@ -24,21 +36,9 @@
 		"@types/lodash": "^4.14.182",
 		"@types/lodash-es": "^4.17.6",
 		"@types/socket.io-client": "^3.0.0",
-		"@typescript-eslint/eslint-plugin": "^5.10.1",
-		"@typescript-eslint/parser": "^5.10.1",
 		"autoprefixer": "^10.4.7",
-		"eslint": "^8.12.0",
-		"eslint-config-prettier": "^8.3.0",
-		"eslint-plugin-svelte3": "^4.0.0",
 		"postcss": "^8.4.13",
-		"prettier": "^2.5.1",
-		"prettier-plugin-svelte": "^2.5.0",
-		"svelte": "^3.46.0",
-		"svelte-check": "^2.2.6",
-		"svelte-preprocess": "^4.10.1",
-		"tailwindcss": "^3.0.24",
-		"tslib": "^2.3.1",
-		"typescript": "~4.6.2"
+		"tailwindcss": "^3.0.24"
 	},
 	"type": "module",
 	"dependencies": {
diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts
index b61c24d1bc..8315367c53 100644
--- a/web/src/api/open-api/api.ts
+++ b/web/src/api/open-api/api.ts
@@ -957,6 +957,20 @@ export interface SmartInfoResponseDto {
      */
     'objects'?: Array<string> | null;
 }
+/**
+ * 
+ * @export
+ * @enum {string}
+ */
+
+export const ThumbnailFormat = {
+    Jpeg: 'JPEG',
+    Webp: 'WEBP'
+} as const;
+
+export type ThumbnailFormat = typeof ThumbnailFormat[keyof typeof ThumbnailFormat];
+
+
 /**
  * 
  * @export
@@ -2069,10 +2083,11 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
         /**
          * 
          * @param {string} assetId 
+         * @param {ThumbnailFormat} [format] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        getAssetThumbnail: async (assetId: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        getAssetThumbnail: async (assetId: string, format?: ThumbnailFormat, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             // verify required parameter 'assetId' is not null or undefined
             assertParamExists('getAssetThumbnail', 'assetId', assetId)
             const localVarPath = `/asset/thumbnail/{assetId}`
@@ -2092,6 +2107,10 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
             // http bearer authentication required
             await setBearerAuthToObject(localVarHeaderParameter, configuration)
 
+            if (format !== undefined) {
+                localVarQueryParameter['format'] = format;
+            }
+
 
     
             setSearchParams(localVarUrlObj, localVarQueryParameter);
@@ -2424,11 +2443,12 @@ export const AssetApiFp = function(configuration?: Configuration) {
         /**
          * 
          * @param {string} assetId 
+         * @param {ThumbnailFormat} [format] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async getAssetThumbnail(assetId: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
-            const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetThumbnail(assetId, options);
+        async getAssetThumbnail(assetId: string, format?: ThumbnailFormat, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
+            const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetThumbnail(assetId, format, options);
             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
         },
         /**
@@ -2564,11 +2584,12 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
         /**
          * 
          * @param {string} assetId 
+         * @param {ThumbnailFormat} [format] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        getAssetThumbnail(assetId: string, options?: any): AxiosPromise<object> {
-            return localVarFp.getAssetThumbnail(assetId, options).then((request) => request(axios, basePath));
+        getAssetThumbnail(assetId: string, format?: ThumbnailFormat, options?: any): AxiosPromise<object> {
+            return localVarFp.getAssetThumbnail(assetId, format, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -2709,12 +2730,13 @@ export class AssetApi extends BaseAPI {
     /**
      * 
      * @param {string} assetId 
+     * @param {ThumbnailFormat} [format] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof AssetApi
      */
-    public getAssetThumbnail(assetId: string, options?: AxiosRequestConfig) {
-        return AssetApiFp(this.configuration).getAssetThumbnail(assetId, options).then((request) => request(this.axios, this.basePath));
+    public getAssetThumbnail(assetId: string, format?: ThumbnailFormat, options?: AxiosRequestConfig) {
+        return AssetApiFp(this.configuration).getAssetThumbnail(assetId, format, options).then((request) => request(this.axios, this.basePath));
     }
 
     /**
diff --git a/web/src/app.html b/web/src/app.html
index 97027429e7..cde7fb6b6a 100644
--- a/web/src/app.html
+++ b/web/src/app.html
@@ -1,12 +1,15 @@
 <!DOCTYPE html>
 <html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<link rel="icon" href="%svelte.assets%/favicon.png" />
-		<meta name="viewport" content="width=device-width, initial-scale=1" />
-		%svelte.head%
-	</head>
-	<body>
-		<div>%svelte.body%</div>
-	</body>
-</html>
+
+<head>
+  <meta charset="utf-8" />
+  <link rel="icon" href="%sveltekit.assets%/favicon.png" />
+  <meta name="viewport" content="width=device-width, initial-scale=1" />
+  %sveltekit.head%
+</head>
+
+<body>
+  <div>%sveltekit.body%</div>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/web/src/lib/components/album/album-card.svelte b/web/src/lib/components/album/album-card.svelte
new file mode 100644
index 0000000000..bfc92d5f38
--- /dev/null
+++ b/web/src/lib/components/album/album-card.svelte
@@ -0,0 +1,57 @@
+<script lang="ts">
+	import { AlbumResponseDto, api, ThumbnailFormat } from '@api';
+	import { createEventDispatcher, onMount } from 'svelte';
+	import { fade } from 'svelte/transition';
+
+	export let album: AlbumResponseDto;
+
+	let imageData: string = '/no-thumbnail.png';
+	const dispatch = createEventDispatcher();
+
+	const loadImageData = async (thubmnailId: string | null) => {
+		if (thubmnailId == null) {
+			return '/no-thumbnail.png';
+		}
+
+		const { data } = await api.assetApi.getAssetThumbnail(thubmnailId!, ThumbnailFormat.Jpeg, { responseType: 'blob' });
+		if (data instanceof Blob) {
+			imageData = URL.createObjectURL(data);
+			return imageData;
+		}
+	};
+</script>
+
+<div class="h-[339px] w-[275px] hover:cursor-pointer mt-4" on:click={() => dispatch('click', album)}>
+	<div class={`h-[275px] w-[275px]`}>
+		{#await loadImageData(album.albumThumbnailAssetId)}
+			<div class={`bg-immich-primary/10 w-full h-full  flex place-items-center place-content-center rounded-xl`}>
+				...
+			</div>
+		{:then imageData}
+			<img
+				in:fade={{ duration: 250 }}
+				src={imageData}
+				alt={album.id}
+				class={`object-cover w-full h-full transition-all z-0 rounded-xl duration-300 hover:translate-x-2 hover:-translate-y-2 hover:shadow-[-8px_8px_0px_0_#FFB800]`}
+			/>
+		{/await}
+	</div>
+
+	<div class="mt-4">
+		<p class="text-sm font-medium text-gray-800">
+			{album.albumName}
+		</p>
+
+		<span class="text-xs flex gap-2">
+			<p>{album.assets.length} items</p>
+
+			{#if album.shared}
+				<p>ยท</p>
+				<p>Shared</p>
+			{/if}
+		</span>
+	</div>
+</div>
+
+<style>
+</style>
diff --git a/web/src/lib/components/album/album-viewer.svelte b/web/src/lib/components/album/album-viewer.svelte
new file mode 100644
index 0000000000..bc5df450e9
--- /dev/null
+++ b/web/src/lib/components/album/album-viewer.svelte
@@ -0,0 +1,101 @@
+<script lang="ts">
+	import { AlbumResponseDto, ThumbnailFormat } from '@api';
+	import { createEventDispatcher, onMount } from 'svelte';
+	import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
+	import FileImagePlusOutline from 'svelte-material-icons/FileImagePlusOutline.svelte';
+	import CircleAvatar from '../shared/circle-avatar.svelte';
+	import ImmichThumbnail from '../shared/immich-thumbnail.svelte';
+
+	const dispatch = createEventDispatcher();
+	export let album: AlbumResponseDto;
+	let viewWidth: number;
+	let thumbnailSize: number = 300;
+	let border = '';
+
+	$: {
+		if (album.assets.length < 6) {
+			thumbnailSize = Math.floor(viewWidth / album.assets.length - album.assets.length);
+		} else {
+			thumbnailSize = Math.floor(viewWidth / 6 - 6);
+		}
+	}
+
+	const getDateRange = () => {
+		const startDate = new Date(album.assets[0].createdAt);
+		const endDate = new Date(album.assets[album.assets.length - 1].createdAt);
+
+		const startDateString = startDate.toLocaleDateString('us-EN', {
+			month: 'short',
+			day: 'numeric',
+			year: 'numeric'
+		});
+		const endDateString = endDate.toLocaleDateString('us-EN', {
+			month: 'short',
+			day: 'numeric',
+			year: 'numeric'
+		});
+		return `${startDateString} - ${endDateString}`;
+	};
+
+	onMount(() => {
+		window.onscroll = (event: Event) => {
+			if (window.pageYOffset > 80) {
+				border = 'border border-gray-200 bg-gray-50';
+			} else {
+				border = '';
+			}
+		};
+	});
+</script>
+
+<section class="w-screen h-screen bg-immich-bg">
+	<div class="fixed top-0 w-full bg-immich-bg z-[100]">
+		<div class={`flex justify-between rounded-lg ${border} p-2 mx-2 mt-2 transition-all`}>
+			<a sveltekit:prefetch href="/albums" title="Go Back">
+				<button
+					id="immich-circle-icon-button"
+					class={`rounded-full p-3 flex place-items-center place-content-center text-gray-600 transition-all hover:bg-gray-200`}
+				>
+					<ArrowLeft size="24" />
+				</button>
+			</a>
+			<div class="right-button-group" title="Add Photos">
+				<button
+					id="immich-circle-icon-button"
+					class={`rounded-full p-3 flex place-items-center place-content-center text-gray-600 transition-all hover:bg-gray-200`}
+					on:click={() => dispatch('click')}
+				>
+					<FileImagePlusOutline size="24" />
+				</button>
+			</div>
+		</div>
+	</div>
+
+	<section class="m-6 py-[72px] px-[160px]">
+		<p class="text-6xl text-immich-primary">
+			{album.albumName}
+		</p>
+
+		<p class="my-4 text-sm text-gray-500">{getDateRange()}</p>
+
+		{#if album.sharedUsers.length > 0}
+			<div class="mb-4">
+				{#each album.sharedUsers as user}
+					<span class="mr-1">
+						<CircleAvatar {user} />
+					</span>
+				{/each}
+			</div>
+		{/if}
+
+		<div class="flex flex-wrap gap-1 w-full" bind:clientWidth={viewWidth}>
+			{#each album.assets as asset}
+				{#if album.assets.length < 7}
+					<ImmichThumbnail {asset} {thumbnailSize} format={ThumbnailFormat.Jpeg} />
+				{:else}
+					<ImmichThumbnail {asset} {thumbnailSize} />
+				{/if}
+			{/each}
+		</div>
+	</section>
+</section>
diff --git a/web/src/lib/components/asset-viewer/asser-viewer-nav-bar.svelte b/web/src/lib/components/asset-viewer/asser-viewer-nav-bar.svelte
index ac1ce747be..ee7bac26ef 100644
--- a/web/src/lib/components/asset-viewer/asser-viewer-nav-bar.svelte
+++ b/web/src/lib/components/asset-viewer/asser-viewer-nav-bar.svelte
@@ -6,7 +6,7 @@
 	import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte';
 	import TrashCanOutline from 'svelte-material-icons/TrashCanOutline.svelte';
 	import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
-	import CircleIconButton from '../shared/circle_icon_button.svelte';
+	import CircleIconButton from '../shared/circle-icon-button.svelte';
 	const dispatch = createEventDispatcher();
 </script>
 
diff --git a/web/src/lib/components/asset-viewer/asset-viewer.svelte b/web/src/lib/components/asset-viewer/asset-viewer.svelte
index 4306a7dbfd..1539b86751 100644
--- a/web/src/lib/components/asset-viewer/asset-viewer.svelte
+++ b/web/src/lib/components/asset-viewer/asset-viewer.svelte
@@ -5,13 +5,12 @@
 	import { flattenAssetGroupByDate } from '$lib/stores/assets';
 	import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
 	import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
-	import { AssetType } from '../../models/immich-asset';
 	import PhotoViewer from './photo-viewer.svelte';
 	import DetailPanel from './detail-panel.svelte';
 	import { session } from '$app/stores';
 	import { downloadAssets } from '$lib/stores/download';
 	import VideoViewer from './video-viewer.svelte';
-	import { api, AssetResponseDto } from '@api';
+	import { api, AssetResponseDto, AssetTypeEnum } from '@api';
 
 	const dispatch = createEventDispatcher();
 
@@ -191,7 +190,7 @@
 	<div class="row-start-1 row-span-full col-start-1 col-span-4">
 		{#key selectedIndex}
 			{#if viewAssetId && viewDeviceId}
-				{#if selectedAsset.type == AssetType.IMAGE}
+				{#if selectedAsset.type == AssetTypeEnum.Image}
 					<PhotoViewer assetId={viewAssetId} deviceId={viewDeviceId} on:close={closeViewer} />
 				{:else}
 					<VideoViewer assetId={viewAssetId} on:close={closeViewer} />
diff --git a/web/src/lib/components/shared/circle-avatar.svelte b/web/src/lib/components/shared/circle-avatar.svelte
new file mode 100644
index 0000000000..f4cf0694ba
--- /dev/null
+++ b/web/src/lib/components/shared/circle-avatar.svelte
@@ -0,0 +1,35 @@
+<script lang="ts">
+	import { api, UserResponseDto } from '@api';
+	import { onMount } from 'svelte';
+
+	export let user: UserResponseDto;
+
+	onMount(() => {
+		console.log(user);
+	});
+
+	const getUserAvatar = async () => {
+		try {
+			const { data } = await api.userApi.getProfileImage(user.id, {
+				responseType: 'blob'
+			});
+
+			if (data instanceof Blob) {
+				return URL.createObjectURL(data);
+			}
+		} catch (e) {
+			return '/favicon.png';
+		}
+	};
+</script>
+
+{#await getUserAvatar()}
+	<div class="w-12 h-12 rounded-full bg-immich-primary/25" />
+{:then data}
+	<img
+		src={data}
+		alt="profile-img"
+		class="inline rounded-full w-12 h-12 object-cover border shadow-md"
+		title={user.email}
+	/>
+{/await}
diff --git a/web/src/lib/components/shared/circle_icon_button.svelte b/web/src/lib/components/shared/circle-icon-button.svelte
similarity index 100%
rename from web/src/lib/components/shared/circle_icon_button.svelte
rename to web/src/lib/components/shared/circle-icon-button.svelte
diff --git a/web/src/lib/components/shared/click-outside.ts b/web/src/lib/components/shared/click-outside.ts
deleted file mode 100644
index 22f27b9f45..0000000000
--- a/web/src/lib/components/shared/click-outside.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-export function clickOutside(node: Node) {
-  const handleClick = (event: any) => {
-    if (!node.contains(event.target)) {
-      node.dispatchEvent(new CustomEvent("outclick"));
-    }
-  };
-
-  document.addEventListener("click", handleClick, true);
-
-  return {
-    destroy() {
-      document.removeEventListener("click", handleClick, true);
-    }
-  };
-}
diff --git a/web/src/lib/components/shared/full-screen-modal.svelte b/web/src/lib/components/shared/full-screen-modal.svelte
index 7a6866a3c3..dbde92320c 100644
--- a/web/src/lib/components/shared/full-screen-modal.svelte
+++ b/web/src/lib/components/shared/full-screen-modal.svelte
@@ -1,5 +1,5 @@
 <script lang="ts">
-	import { clickOutside } from './click-outside';
+	import { clickOutside } from '../../utils/click-outside';
 	import { createEventDispatcher } from 'svelte';
 	import { fade } from 'svelte/transition';
 
@@ -11,7 +11,7 @@
 	out:fade={{ duration: 100 }}
 	class="absolute w-full h-full bg-black/40 z-[100] flex place-items-center place-content-center "
 >
-	<div class="z-[9999]" use:clickOutside on:outclick={() => dispatch('clickOutside')}>
+	<div class="z-[9999]" use:clickOutside on:out-click={() => dispatch('clickOutside')}>
 		<slot />
 	</div>
 </section>
diff --git a/web/src/lib/components/asset-viewer/immich-thumbnail.svelte b/web/src/lib/components/shared/immich-thumbnail.svelte
similarity index 79%
rename from web/src/lib/components/asset-viewer/immich-thumbnail.svelte
rename to web/src/lib/components/shared/immich-thumbnail.svelte
index a07a6faa9d..9f13c3da70 100644
--- a/web/src/lib/components/asset-viewer/immich-thumbnail.svelte
+++ b/web/src/lib/components/shared/immich-thumbnail.svelte
@@ -1,5 +1,4 @@
 <script lang="ts">
-	import { AssetType } from '../../models/immich-asset';
 	import { session } from '$app/stores';
 	import { createEventDispatcher, onDestroy } from 'svelte';
 	import { fade, fly } from 'svelte/transition';
@@ -7,13 +6,15 @@
 	import CheckCircle from 'svelte-material-icons/CheckCircle.svelte';
 	import PlayCircleOutline from 'svelte-material-icons/PlayCircleOutline.svelte';
 	import PauseCircleOutline from 'svelte-material-icons/PauseCircleOutline.svelte';
-	import LoadingSpinner from '../shared/loading-spinner.svelte';
-	import { api, AssetResponseDto } from '@api';
+	import LoadingSpinner from './loading-spinner.svelte';
+	import { api, AssetResponseDto, AssetTypeEnum, ThumbnailFormat } from '@api';
 
 	const dispatch = createEventDispatcher();
 
 	export let asset: AssetResponseDto;
-	export let groupIndex: number;
+	export let groupIndex = 0;
+	export let thumbnailSize: number | undefined = undefined;
+	export let format: ThumbnailFormat = ThumbnailFormat.Webp;
 
 	let imageData: string;
 	let videoData: string;
@@ -29,7 +30,9 @@
 
 	const loadImageData = async () => {
 		if ($session.user) {
-			const { data } = await api.assetApi.getAssetThumbnail(asset.id, { responseType: 'blob' });
+			const { data } = await api.assetApi.getAssetThumbnail(asset.id, format, {
+				responseType: 'blob'
+			});
 			if (data instanceof Blob) {
 				imageData = URL.createObjectURL(data);
 				return imageData;
@@ -42,9 +45,15 @@
 
 		if ($session.user) {
 			try {
-				const { data } = await api.assetApi.serveFile(asset.deviceAssetId, asset.deviceId, false, true, {
-					responseType: 'blob',
-				});
+				const { data } = await api.assetApi.serveFile(
+					asset.deviceAssetId,
+					asset.deviceId,
+					false,
+					true,
+					{
+						responseType: 'blob'
+					}
+				);
 
 				if (!(data instanceof Blob)) {
 					return;
@@ -109,6 +118,10 @@
 	});
 
 	const getSize = () => {
+		if (thumbnailSize) {
+			return `w-[${thumbnailSize}px] h-[${thumbnailSize}px]`;
+		}
+
 		if (asset.exifInfo?.orientation === 'Rotate 90 CW') {
 			return 'w-[176px] h-[235px]';
 		} else if (asset.exifInfo?.orientation === 'Horizontal (normal)') {
@@ -135,6 +148,8 @@
 
 <IntersectionObserver once={true} let:intersecting>
 	<div
+		style:width={`${thumbnailSize}px`}
+		style:height={`${thumbnailSize}px`}
 		class={`bg-gray-100 relative hover:cursor-pointer ${getSize()}`}
 		on:mouseenter={handleMouseOverThumbnail}
 		on:mouseleave={handleMouseLeaveThumbnail}
@@ -156,8 +171,10 @@
 		{/if}
 
 		<!-- Playback and info -->
-		{#if asset.type === AssetType.VIDEO}
-			<div class="absolute right-2 top-2 text-white text-xs font-medium flex gap-1 place-items-center z-10">
+		{#if asset.type === AssetTypeEnum.Video}
+			<div
+				class="absolute right-2 top-2 text-white text-xs font-medium flex gap-1 place-items-center z-10"
+			>
 				{#if isThumbnailVideoPlaying}
 					<span in:fly={{ x: -25, duration: 500 }}>
 						{videoProgress}
@@ -189,9 +206,17 @@
 		<!-- Thumbnail -->
 		{#if intersecting}
 			{#await loadImageData()}
-				<div class={`bg-immich-primary/10 ${getSize()} flex place-items-center place-content-center`}>...</div>
+				<div
+					style:width={`${thumbnailSize}px`}
+					style:height={`${thumbnailSize}px`}
+					class={`bg-immich-primary/10 ${getSize()} flex place-items-center place-content-center`}
+				>
+					...
+				</div>
 			{:then imageData}
 				<img
+					style:width={`${thumbnailSize}px`}
+					style:height={`${thumbnailSize}px`}
 					in:fade={{ duration: 250 }}
 					src={imageData}
 					alt={asset.id}
@@ -201,9 +226,17 @@
 			{/await}
 		{/if}
 
-		{#if mouseOver && asset.type === AssetType.VIDEO}
+		{#if mouseOver && asset.type === AssetTypeEnum.Video}
 			<div class="absolute w-full h-full top-0" on:mouseenter={loadVideoData}>
-				<video muted autoplay preload="none" class="h-full object-cover" width="250px" bind:this={videoPlayerNode}>
+				<video
+					muted
+					autoplay
+					preload="none"
+					class="h-full object-cover"
+					width="250px"
+					style:width={`${thumbnailSize}px`}
+					bind:this={videoPlayerNode}
+				>
 					<track kind="captions" />
 				</video>
 			</div>
diff --git a/web/src/lib/components/shared/navigation-bar.svelte b/web/src/lib/components/shared/navigation-bar.svelte
index 1ebebf9085..31582efc44 100644
--- a/web/src/lib/components/shared/navigation-bar.svelte
+++ b/web/src/lib/components/shared/navigation-bar.svelte
@@ -7,7 +7,7 @@
 	import { fade, fly, slide } from 'svelte/transition';
 	import { serverEndpoint } from '../../constants';
 	import TrayArrowUp from 'svelte-material-icons/TrayArrowUp.svelte';
-	import { clickOutside } from './click-outside';
+	import { clickOutside } from '../../utils/click-outside';
 	import { api } from '@api';
 
 	export let user: ImmichUser;
@@ -56,7 +56,7 @@
 
 <section id="dashboard-navbar" class="fixed w-screen  z-[100] bg-immich-bg text-sm">
 	<div class="flex border-b place-items-center px-6 py-2 ">
-		<a class="flex gap-2 place-items-center hover:cursor-pointer" href="/photos">
+		<a sveltekit:prefetch class="flex gap-2 place-items-center hover:cursor-pointer" href="/photos">
 			<img src="/immich-logo.svg" alt="immich logo" height="35" width="35" />
 			<h1 class="font-immich-title text-2xl text-immich-primary">IMMICH</h1>
 		</a>
@@ -76,12 +76,13 @@
 			{/if}
 
 			{#if user.isAdmin}
-				<button
-					class={`flex place-items-center place-content-center gap-2 hover:bg-immich-primary/5 p-2 rounded-lg font-medium ${
-						$page.url.pathname == '/admin' && 'text-immich-primary underline'
-					}`}
-					on:click={navigateToAdmin}>Administration</button
-				>
+				<a sveltekit:prefetch href={`admin`}>
+					<button
+						class={`flex place-items-center place-content-center gap-2 hover:bg-immich-primary/5 p-2 rounded-lg font-medium ${
+							$page.url.pathname == '/admin' && 'text-immich-primary underline'
+						}`}>Administration</button
+					>
+				</a>
 			{/if}
 
 			<div
@@ -125,7 +126,7 @@
 			id="account-info-panel"
 			class="absolute right-[25px] top-[75px] bg-white shadow-lg rounded-2xl w-[360px] text-center"
 			use:clickOutside
-			on:outclick={() => (shouldShowAccountInfoPanel = false)}
+			on:out-click={() => (shouldShowAccountInfoPanel = false)}
 		>
 			<div class="flex place-items-center place-content-center mt-6">
 				<button
diff --git a/web/src/lib/components/shared/side-bar-button.svelte b/web/src/lib/components/shared/side-bar/side-bar-button.svelte
similarity index 84%
rename from web/src/lib/components/shared/side-bar-button.svelte
rename to web/src/lib/components/shared/side-bar/side-bar-button.svelte
index eeb02a2232..1139b713d3 100644
--- a/web/src/lib/components/shared/side-bar-button.svelte
+++ b/web/src/lib/components/shared/side-bar/side-bar-button.svelte
@@ -5,13 +5,16 @@
 	export let isSelected: boolean;
 
 	import { createEventDispatcher } from 'svelte';
-	import type { AdminSideBarSelection, AppSideBarSelection } from '../../models/admin-sidebar-selection';
+	import type {
+		AdminSideBarSelection,
+		AppSideBarSelection
+	} from '../../../models/admin-sidebar-selection';
 
 	const dispatch = createEventDispatcher();
 
 	const onButtonClicked = () => {
 		dispatch('selected', {
-			actionType,
+			actionType
 		});
 	};
 </script>
diff --git a/web/src/lib/components/shared/side-bar/side-bar.svelte b/web/src/lib/components/shared/side-bar/side-bar.svelte
new file mode 100644
index 0000000000..ce153760a6
--- /dev/null
+++ b/web/src/lib/components/shared/side-bar/side-bar.svelte
@@ -0,0 +1,65 @@
+<script lang="ts">
+	import { goto } from '$app/navigation';
+
+	import { AppSideBarSelection } from '$lib/models/admin-sidebar-selection';
+	import { onMount } from 'svelte';
+	import { page } from '$app/stores';
+	import ImageAlbum from 'svelte-material-icons/ImageAlbum.svelte';
+	import ImageOutline from 'svelte-material-icons/ImageOutline.svelte';
+	import SideBarButton from './side-bar-button.svelte';
+	import StatusBox from '../status-box.svelte';
+
+	let selectedAction: AppSideBarSelection;
+
+	const onSidebarButtonClicked = (buttonType: CustomEvent) => {
+		selectedAction = buttonType.detail['actionType'] as AppSideBarSelection;
+
+		if (selectedAction == AppSideBarSelection.PHOTOS) {
+			if ($page.routeId != 'photos') {
+				goto('/photos');
+			}
+		}
+
+		if (selectedAction == AppSideBarSelection.ALBUMS) {
+			if ($page.routeId != 'albums') {
+				goto('/albums');
+			}
+		}
+	};
+
+	onMount(async () => {
+		if ($page.routeId == 'albums') {
+			selectedAction = AppSideBarSelection.ALBUMS;
+		} else if ($page.routeId == 'photos') {
+			selectedAction = AppSideBarSelection.PHOTOS;
+		}
+	});
+</script>
+
+<section id="sidebar" class="flex flex-col gap-4 pt-8 pr-6">
+	<a sveltekit:prefetch href={$page.routeId != 'photos' ? `/photos` : null}>
+		<SideBarButton
+			title="Photos"
+			logo={ImageOutline}
+			actionType={AppSideBarSelection.PHOTOS}
+			isSelected={selectedAction === AppSideBarSelection.PHOTOS}
+		/></a
+	>
+
+	<div class="text-xs ml-5">
+		<p>LIBRARY</p>
+	</div>
+	<a sveltekit:prefetch href={$page.routeId != 'albums' ? `/albums` : null}>
+		<SideBarButton
+			title="Albums"
+			logo={ImageAlbum}
+			actionType={AppSideBarSelection.ALBUMS}
+			isSelected={selectedAction === AppSideBarSelection.ALBUMS}
+		/>
+	</a>
+	<!-- Status Box -->
+
+	<div class="mb-6 mt-auto">
+		<StatusBox />
+	</div>
+</section>
diff --git a/web/src/lib/models/admin-sidebar-selection.ts b/web/src/lib/models/admin-sidebar-selection.ts
index 3c1735f91c..8ceb46b889 100644
--- a/web/src/lib/models/admin-sidebar-selection.ts
+++ b/web/src/lib/models/admin-sidebar-selection.ts
@@ -1,9 +1,9 @@
 export enum AdminSideBarSelection {
-  USER_MANAGEMENT = "User management",
-
+	USER_MANAGEMENT = 'User management',
 }
 
 export enum AppSideBarSelection {
-  PHOTOS = "Photos",
-  EXPLORE = "Explore",
-}
\ No newline at end of file
+	PHOTOS = 'Photos',
+	EXPLORE = 'Explore',
+	ALBUMS = 'Albums',
+}
diff --git a/web/src/lib/models/immich-asset.ts b/web/src/lib/models/immich-asset.ts
deleted file mode 100644
index 8d8767b0e0..0000000000
--- a/web/src/lib/models/immich-asset.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-export enum AssetType {
-  IMAGE = 'IMAGE',
-  VIDEO = 'VIDEO',
-  AUDIO = 'AUDIO',
-  OTHER = 'OTHER',
-}
-
-export type ImmichExif = {
-  id: string;
-  assetId: string;
-  make: string;
-  model: string;
-  imageName: string;
-  exifImageWidth: number;
-  exifImageHeight: number;
-  fileSizeInByte: number;
-  orientation: string;
-  dateTimeOriginal: Date;
-  modifyDate: Date;
-  lensModel: string;
-  fNumber: number;
-  focalLength: number;
-  iso: number;
-  exposureTime: number;
-  latitude: number;
-  longitude: number;
-  city: string;
-  state: string;
-  country: string;
-}
-
-export type ImmichAssetSmartInfo = {
-  id: string;
-  assetId: string;
-  tags: string[];
-  objects: string[];
-}
-
-export type ImmichAsset = {
-  id: string;
-  deviceAssetId: string;
-  userId: string;
-  deviceId: string;
-  type: AssetType;
-  originalPath: string;
-  resizePath: string;
-  createdAt: string;
-  modifiedAt: string;
-  isFavorite: boolean;
-  mimeType: string;
-  duration: string;
-  exifInfo?: ImmichExif;
-  smartInfo?: ImmichAssetSmartInfo;
-}
\ No newline at end of file
diff --git a/web/src/lib/stores/websocket.ts b/web/src/lib/stores/websocket.ts
index f6bd6f9345..24e1b8ca8a 100644
--- a/web/src/lib/stores/websocket.ts
+++ b/web/src/lib/stores/websocket.ts
@@ -1,8 +1,6 @@
 import { Socket, io } from 'socket.io-client';
 import { writable } from 'svelte/store';
 import { serverEndpoint } from '../constants';
-import type { ImmichAsset } from '../models/immich-asset';
-import { assets } from './assets';
 
 let websocket: Socket;
 
@@ -28,10 +26,7 @@ export const openWebsocketConnection = (accessToken: string) => {
 };
 
 const listenToEvent = (socket: Socket) => {
-	socket.on('on_upload_success', (data) => {
-		const newUploadedAsset: ImmichAsset = JSON.parse(data);
-		// assets.update((assets) => [...assets, newUploadedAsset]);
-	});
+	socket.on('on_upload_success', (data) => {});
 
 	socket.on('error', (e) => {
 		console.log('Websocket Error', e);
diff --git a/web/src/lib/utils/click-outside.ts b/web/src/lib/utils/click-outside.ts
new file mode 100644
index 0000000000..9dddb056e9
--- /dev/null
+++ b/web/src/lib/utils/click-outside.ts
@@ -0,0 +1,15 @@
+export function clickOutside(node: Node) {
+	const handleClick = (event: any) => {
+		if (!node.contains(event.target)) {
+			node.dispatchEvent(new CustomEvent('out-click'));
+		}
+	};
+
+	document.addEventListener('click', handleClick, true);
+
+	return {
+		destroy() {
+			document.removeEventListener('click', handleClick, true);
+		},
+	};
+}
diff --git a/web/src/routes/__layout.svelte b/web/src/routes/__layout.svelte
index 98479b46d5..3e6f380ed5 100644
--- a/web/src/routes/__layout.svelte
+++ b/web/src/routes/__layout.svelte
@@ -16,7 +16,7 @@
 <script lang="ts">
 	import '../app.css';
 
-	import { blur } from 'svelte/transition';
+	import { blur, fade, slide } from 'svelte/transition';
 
 	import DownloadPanel from '$lib/components/asset-viewer/download-panel.svelte';
 	import AnnouncementBox from '$lib/components/shared/announcement-box.svelte';
@@ -40,7 +40,7 @@
 
 <main>
 	{#key url}
-		<div transition:blur={{ duration: 250 }}>
+		<div in:fade={{ duration: 100 }}>
 			<slot />
 			<DownloadPanel />
 			<UploadPanel />
diff --git a/web/src/routes/admin/api/create-user.ts b/web/src/routes/admin/api/create-user.ts
index 0af4872c00..436999ce89 100644
--- a/web/src/routes/admin/api/create-user.ts
+++ b/web/src/routes/admin/api/create-user.ts
@@ -1,7 +1,7 @@
 import type { RequestHandler } from '@sveltejs/kit';
 import { api } from '@api';
 
-export const post: RequestHandler = async ({ request }) => {
+export const POST: RequestHandler = async ({ request }) => {
 	const form = await request.formData();
 
 	const email = form.get('email');
@@ -13,22 +13,22 @@ export const post: RequestHandler = async ({ request }) => {
 		email: String(email),
 		password: String(password),
 		firstName: String(firstName),
-		lastName: String(lastName),
+		lastName: String(lastName)
 	});
 
 	if (status === 201) {
 		return {
 			status: 201,
 			body: {
-				success: 'Succesfully create user account',
-			},
+				success: 'Succesfully create user account'
+			}
 		};
 	} else {
 		return {
 			status: 400,
 			body: {
-				error: 'Error create user account',
-			},
+				error: 'Error create user account'
+			}
 		};
 	}
 };
diff --git a/web/src/routes/admin/index.svelte b/web/src/routes/admin/index.svelte
index cb577df2e2..1d5f8e8c77 100644
--- a/web/src/routes/admin/index.svelte
+++ b/web/src/routes/admin/index.svelte
@@ -27,7 +27,7 @@
 
 	import type { ImmichUser } from '$lib/models/immich-user';
 	import { AdminSideBarSelection } from '$lib/models/admin-sidebar-selection';
-	import SideBarButton from '$lib/components/shared/side-bar-button.svelte';
+	import SideBarButton from '$lib/components/shared/side-bar/side-bar-button.svelte';
 	import AccountMultipleOutline from 'svelte-material-icons/AccountMultipleOutline.svelte';
 	import NavigationBar from '$lib/components/shared/navigation-bar.svelte';
 	import UserManagement from '$lib/components/admin/user-management.svelte';
@@ -59,7 +59,7 @@
 </script>
 
 <svelte:head>
-	<title>Immich - Administration</title>
+	<title>Administration - Immich</title>
 </svelte:head>
 
 <NavigationBar {user} />
diff --git a/web/src/routes/albums/[albumId].svelte b/web/src/routes/albums/[albumId].svelte
new file mode 100644
index 0000000000..e88dd49ac1
--- /dev/null
+++ b/web/src/routes/albums/[albumId].svelte
@@ -0,0 +1,49 @@
+<script context="module" lang="ts">
+	export const prerender = false;
+
+	import type { Load } from '@sveltejs/kit';
+	import { AlbumResponseDto, api } from '@api';
+
+	export const load: Load = async ({ session, params }) => {
+		if (!session.user) {
+			return {
+				status: 302,
+				redirect: '/auth/login'
+			};
+		}
+		const albumId = params['albumId'];
+
+		let album: AlbumResponseDto;
+
+		try {
+			const { data } = await api.albumApi.getAlbumInfo(albumId);
+			album = data;
+		} catch (e) {
+			return {
+				status: 302,
+				redirect: '/albums'
+			};
+		}
+
+		return {
+			status: 200,
+			props: {
+				album: album
+			}
+		};
+	};
+</script>
+
+<script lang="ts">
+	import { goto } from '$app/navigation';
+
+	import AlbumViewer from '$lib/components/album/album-viewer.svelte';
+
+	export let album: AlbumResponseDto;
+</script>
+
+<svelte:head>
+	<title>{album.albumName} - Immich</title>
+</svelte:head>
+
+<AlbumViewer {album} />
diff --git a/web/src/routes/albums/index.svelte b/web/src/routes/albums/index.svelte
new file mode 100644
index 0000000000..263a2e9649
--- /dev/null
+++ b/web/src/routes/albums/index.svelte
@@ -0,0 +1,94 @@
+<script context="module" lang="ts">
+	export const prerender = false;
+
+	import PlusBoxOutline from 'svelte-material-icons/PlusBoxOutline.svelte';
+
+	import NavigationBar from '$lib/components/shared/navigation-bar.svelte';
+	import { ImmichUser } from '$lib/models/immich-user';
+	import type { Load } from '@sveltejs/kit';
+	import SideBar from '$lib/components/shared/side-bar/side-bar.svelte';
+	import { AlbumResponseDto, api } from '@api';
+
+	export const load: Load = async ({ session }) => {
+		if (!session.user) {
+			return {
+				status: 302,
+				redirect: '/auth/login'
+			};
+		}
+
+		let allAlbums: AlbumResponseDto[] = [];
+		try {
+			const { data } = await api.albumApi.getAllAlbums();
+			allAlbums = data;
+		} catch (e) {
+			console.log('Error [getAllAlbums] ', e);
+		}
+
+		return {
+			status: 200,
+			props: {
+				user: session.user,
+				allAlbums: allAlbums
+			}
+		};
+	};
+</script>
+
+<script lang="ts">
+	import AlbumCard from '$lib/components/album/album-card.svelte';
+	import { goto } from '$app/navigation';
+
+	export let user: ImmichUser;
+	export let allAlbums: AlbumResponseDto[];
+
+	const showAlbum = (event: CustomEvent) => {
+		goto('/albums/' + event.detail.id);
+	};
+</script>
+
+<svelte:head>
+	<title>Albums - Immich</title>
+</svelte:head>
+
+<section>
+	<NavigationBar {user} on:uploadClicked={() => {}} />
+</section>
+
+<section class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg">
+	<SideBar />
+
+	<!-- Main Section -->
+
+	<section class="overflow-y-auto relative">
+		<section id="album-content" class="relative pt-8 pl-4 mb-12 bg-immich-bg">
+			<div class="px-4 flex justify-between place-items-center">
+				<div>
+					<p>Albums</p>
+				</div>
+
+				<div>
+					<button
+						class="flex place-items-center gap-1 text-sm hover:bg-immich-primary/5 p-2 rounded-lg font-medium hover:text-gray-700"
+					>
+						<span>
+							<PlusBoxOutline size="18" />
+						</span>
+						<p>Create album</p>
+					</button>
+				</div>
+			</div>
+
+			<div class="my-4">
+				<hr />
+			</div>
+
+			<!-- Album Card -->
+			<div class="flex flex-wrap gap-8">
+				{#each allAlbums as album}
+					<a sveltekit:prefetch href={`albums/${album.id}`}> <AlbumCard {album} /></a>
+				{/each}
+			</div>
+		</section>
+	</section>
+</section>
diff --git a/web/src/routes/auth/change-password/index.svelte b/web/src/routes/auth/change-password/index.svelte
index 6782374df7..e3d1c32f2b 100644
--- a/web/src/routes/auth/change-password/index.svelte
+++ b/web/src/routes/auth/change-password/index.svelte
@@ -57,7 +57,7 @@
 </script>
 
 <svelte:head>
-	<title>Immich - Change Password</title>
+	<title>Change Password - Immich</title>
 </svelte:head>
 
 <section class="h-screen w-screen flex place-items-center place-content-center">
diff --git a/web/src/routes/auth/change-password/index.ts b/web/src/routes/auth/change-password/index.ts
index cdfb01675d..87a417284e 100644
--- a/web/src/routes/auth/change-password/index.ts
+++ b/web/src/routes/auth/change-password/index.ts
@@ -1,13 +1,13 @@
 import type { RequestHandler } from '@sveltejs/kit';
 import { api } from '@api';
 
-export const post: RequestHandler = async ({ request, locals }) => {
+export const POST: RequestHandler = async ({ request, locals }) => {
 	if (!locals.user) {
 		return {
 			status: 401,
 			body: {
-				error: 'Unauthorized',
-			},
+				error: 'Unauthorized'
+			}
 		};
 	}
 
@@ -17,22 +17,22 @@ export const post: RequestHandler = async ({ request, locals }) => {
 	const { status } = await api.userApi.updateUser({
 		id: locals.user.id,
 		password: String(password),
-		shouldChangePassword: false,
+		shouldChangePassword: false
 	});
 
 	if (status === 200) {
 		return {
 			status: 200,
 			body: {
-				success: 'Succesfully change password',
-			},
+				success: 'Succesfully change password'
+			}
 		};
 	} else {
 		return {
 			status: 400,
 			body: {
-				error: 'Error change password',
-			},
+				error: 'Error change password'
+			}
 		};
 	}
 };
diff --git a/web/src/routes/auth/login/index.svelte b/web/src/routes/auth/login/index.svelte
index 0e00cd31aa..37b09a5862 100644
--- a/web/src/routes/auth/login/index.svelte
+++ b/web/src/routes/auth/login/index.svelte
@@ -10,7 +10,7 @@
 </script>
 
 <svelte:head>
-	<title>Immich - Login</title>
+	<title>Login - Immich</title>
 </svelte:head>
 
 <section class="h-screen w-screen flex place-items-center place-content-center">
diff --git a/web/src/routes/auth/login/index.ts b/web/src/routes/auth/login/index.ts
index f2c05c170b..b94c6b40da 100644
--- a/web/src/routes/auth/login/index.ts
+++ b/web/src/routes/auth/login/index.ts
@@ -2,7 +2,7 @@ import type { RequestHandler } from '@sveltejs/kit';
 import * as cookie from 'cookie';
 import { api } from '@api';
 
-export const post: RequestHandler = async ({ request }) => {
+export const POST: RequestHandler = async ({ request }) => {
 	const form = await request.formData();
 
 	const email = form.get('email');
@@ -11,7 +11,7 @@ export const post: RequestHandler = async ({ request }) => {
 	try {
 		const { data: authUser } = await api.authenticationApi.login({
 			email: String(email),
-			password: String(password),
+			password: String(password)
 		});
 
 		return {
@@ -24,9 +24,9 @@ export const post: RequestHandler = async ({ request }) => {
 					lastName: authUser.lastName,
 					isAdmin: authUser.isAdmin,
 					email: authUser.userEmail,
-					shouldChangePassword: authUser.shouldChangePassword,
+					shouldChangePassword: authUser.shouldChangePassword
 				},
-				success: 'success',
+				success: 'success'
 			},
 			headers: {
 				'Set-Cookie': cookie.serialize(
@@ -37,23 +37,23 @@ export const post: RequestHandler = async ({ request }) => {
 						firstName: authUser.firstName,
 						lastName: authUser.lastName,
 						isAdmin: authUser.isAdmin,
-						email: authUser.userEmail,
+						email: authUser.userEmail
 					}),
 					{
 						path: '/',
 						httpOnly: true,
 						sameSite: 'strict',
-						maxAge: 60 * 60 * 24 * 30,
-					},
-				),
-			},
+						maxAge: 60 * 60 * 24 * 30
+					}
+				)
+			}
 		};
 	} catch (error) {
 		return {
 			status: 400,
 			body: {
-				error: 'Incorrect email or password',
-			},
+				error: 'Incorrect email or password'
+			}
 		};
 	}
 };
diff --git a/web/src/routes/auth/logout.ts b/web/src/routes/auth/logout.ts
index 8f9d669170..f59ee6d53b 100644
--- a/web/src/routes/auth/logout.ts
+++ b/web/src/routes/auth/logout.ts
@@ -1,12 +1,12 @@
 import type { RequestHandler } from '@sveltejs/kit';
 
-export const post: RequestHandler = async () => {
+export const POST: RequestHandler = async () => {
 	return {
 		headers: {
-			'Set-Cookie': 'session=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT',
+			'Set-Cookie': 'session=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
 		},
 		body: {
-			ok: true,
-		},
+			ok: true
+		}
 	};
 };
diff --git a/web/src/routes/auth/register/index.svelte b/web/src/routes/auth/register/index.svelte
index b7ce629072..77a1801f58 100644
--- a/web/src/routes/auth/register/index.svelte
+++ b/web/src/routes/auth/register/index.svelte
@@ -29,7 +29,7 @@
 </script>
 
 <svelte:head>
-	<title>Immich - Admin Registration</title>
+	<title>Admin Registration - Immich</title>
 </svelte:head>
 
 <section class="h-screen w-screen flex place-items-center place-content-center">
diff --git a/web/src/routes/auth/register/index.ts b/web/src/routes/auth/register/index.ts
index 8561b30622..8304e1f86d 100644
--- a/web/src/routes/auth/register/index.ts
+++ b/web/src/routes/auth/register/index.ts
@@ -1,7 +1,7 @@
 import type { RequestHandler } from '@sveltejs/kit';
 import { api } from '@api';
 
-export const post: RequestHandler = async ({ request }) => {
+export const POST: RequestHandler = async ({ request }) => {
 	const form = await request.formData();
 
 	const email = form.get('email');
@@ -13,22 +13,22 @@ export const post: RequestHandler = async ({ request }) => {
 		email: String(email),
 		password: String(password),
 		firstName: String(firstName),
-		lastName: String(lastName),
+		lastName: String(lastName)
 	});
 
 	if (status === 201) {
 		return {
 			status: 201,
 			body: {
-				success: 'Succesfully create admin account',
-			},
+				success: 'Succesfully create admin account'
+			}
 		};
 	} else {
 		return {
 			status: 400,
 			body: {
-				error: 'Error create admin account',
-			},
+				error: 'Error create admin account'
+			}
 		};
 	}
 };
diff --git a/web/src/routes/index.svelte b/web/src/routes/index.svelte
index edfeb06daf..dde30af716 100644
--- a/web/src/routes/index.svelte
+++ b/web/src/routes/index.svelte
@@ -33,7 +33,7 @@
 </script>
 
 <svelte:head>
-	<title>Immich - Welcome ๐ŸŽ‰</title>
+	<title>Welcome ๐ŸŽ‰ - Immich</title>
 	<meta name="description" content="Immich Web Interface" />
 </svelte:head>
 
diff --git a/web/src/routes/photos/index.svelte b/web/src/routes/photos/index.svelte
index ac48c9bdb0..368d207f52 100644
--- a/web/src/routes/photos/index.svelte
+++ b/web/src/routes/photos/index.svelte
@@ -8,7 +8,7 @@
 		if (!session.user) {
 			return {
 				status: 302,
-				redirect: '/auth/login',
+				redirect: '/auth/login'
 			};
 		}
 
@@ -17,8 +17,8 @@
 		return {
 			status: 200,
 			props: {
-				user: session.user,
-			},
+				user: session.user
+			}
 		};
 	};
 </script>
@@ -27,26 +27,19 @@
 	import type { ImmichUser } from '$lib/models/immich-user';
 
 	import NavigationBar from '$lib/components/shared/navigation-bar.svelte';
-	import SideBarButton from '$lib/components/shared/side-bar-button.svelte';
 	import CheckCircle from 'svelte-material-icons/CheckCircle.svelte';
-
-	import ImageOutline from 'svelte-material-icons/ImageOutline.svelte';
-	import { AppSideBarSelection } from '$lib/models/admin-sidebar-selection';
-	import { onMount } from 'svelte';
 	import { fly } from 'svelte/transition';
 	import { session } from '$app/stores';
 	import { assetsGroupByDate, flattenAssetGroupByDate } from '$lib/stores/assets';
-	import ImmichThumbnail from '$lib/components/asset-viewer/immich-thumbnail.svelte';
+	import ImmichThumbnail from '$lib/components/shared/immich-thumbnail.svelte';
 	import moment from 'moment';
 	import AssetViewer from '$lib/components/asset-viewer/asset-viewer.svelte';
-	import StatusBox from '$lib/components/shared/status-box.svelte';
 	import { fileUploader } from '$lib/utils/file-uploader';
 	import { AssetResponseDto } from '@api';
+	import SideBar from '$lib/components/shared/side-bar/side-bar.svelte';
 
 	export let user: ImmichUser;
 
-	let selectedAction: AppSideBarSelection;
-
 	let selectedGroupThumbnail: number | null;
 	let isMouseOverGroup: boolean;
 	$: if (isMouseOverGroup == false) {
@@ -57,14 +50,6 @@
 	let currentViewAssetIndex = 0;
 	let currentSelectedAsset: AssetResponseDto;
 
-	const onButtonClicked = (buttonType: CustomEvent) => {
-		selectedAction = buttonType.detail['actionType'] as AppSideBarSelection;
-	};
-
-	onMount(async () => {
-		selectedAction = AppSideBarSelection.PHOTOS;
-	});
-
 	const thumbnailMouseEventHandler = (event: CustomEvent) => {
 		const { selectedGroupIndex }: { selectedGroupIndex: number } = event.detail;
 
@@ -92,7 +77,7 @@
 					const files = Array.from<File>(e.target.files);
 
 					const acceptedFile = files.filter(
-						(e) => e.type.split('/')[0] === 'video' || e.type.split('/')[0] === 'image',
+						(e) => e.type.split('/')[0] === 'video' || e.type.split('/')[0] === 'image'
 					);
 
 					for (const asset of acceptedFile) {
@@ -109,7 +94,7 @@
 </script>
 
 <svelte:head>
-	<title>Immich - Photos</title>
+	<title>Photos - Immich</title>
 </svelte:head>
 
 <section>
@@ -117,22 +102,7 @@
 </section>
 
 <section class="grid grid-cols-[250px_auto] relative pt-[72px] h-screen bg-immich-bg">
-	<!-- Sidebar -->
-	<section id="sidebar" class="flex flex-col gap-4 pt-8 pr-6">
-		<SideBarButton
-			title="Photos"
-			logo={ImageOutline}
-			actionType={AppSideBarSelection.PHOTOS}
-			isSelected={selectedAction === AppSideBarSelection.PHOTOS}
-			on:selected={onButtonClicked}
-		/>
-
-		<!-- Status Box -->
-
-		<div class="mb-6 mt-auto">
-			<StatusBox />
-		</div>
-	</section>
+	<SideBar />
 
 	<!-- Main Section -->
 	<section class="overflow-y-auto relative">
diff --git a/web/static/no-thumbnail.png b/web/static/no-thumbnail.png
new file mode 100644
index 0000000000..6aa2c69990
Binary files /dev/null and b/web/static/no-thumbnail.png differ
diff --git a/web/svelte.config.js b/web/svelte.config.js
index 76b65e346d..dee9c3f0ec 100644
--- a/web/svelte.config.js
+++ b/web/svelte.config.js
@@ -8,17 +8,9 @@ const config = {
 	kit: {
 		adapter: adapter({ out: 'build' }),
 		methodOverride: {
-			allowed: ['PATCH', 'DELETE'],
-		},
-		vite: {
-			resolve: {
-				alias: {
-					'xmlhttprequest-ssl': './node_modules/engine.io-client/lib/xmlhttprequest.js',
-					'@api': path.resolve('./src/api'),
-				},
-			},
-		},
-	},
+			allowed: ['PATCH', 'DELETE']
+		}
+	}
 };
 
 export default config;
diff --git a/web/tsconfig.json b/web/tsconfig.json
index 8145e4c575..1ab3c81f2e 100644
--- a/web/tsconfig.json
+++ b/web/tsconfig.json
@@ -19,9 +19,15 @@
     "importsNotUsedAsValues": "preserve",
     "preserveValueImports": false,
     "paths": {
-      "$lib": ["src/lib"],
-      "$lib/*": ["src/lib/*"],
-      "@api": ["src/api"]
+      "$lib": [
+        "src/lib"
+      ],
+      "$lib/*": [
+        "src/lib/*"
+      ],
+      "@api": [
+        "src/api"
+      ]
     }
   },
 }
\ No newline at end of file
diff --git a/web/vite.config.js b/web/vite.config.js
new file mode 100644
index 0000000000..8446d5a80e
--- /dev/null
+++ b/web/vite.config.js
@@ -0,0 +1,15 @@
+import { sveltekit } from '@sveltejs/kit/vite';
+import path from 'path';
+
+/** @type {import('vite').UserConfig} */
+const config = {
+	resolve: {
+		alias: {
+			'xmlhttprequest-ssl': './node_modules/engine.io-client/lib/xmlhttprequest.js',
+			'@api': path.resolve('./src/api')
+		}
+	},
+	plugins: [sveltekit()]
+};
+
+export default config;