From 32c16ff6638dcd2813b778218ea9eadcdb106562 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 09:53:46 +0100 Subject: [PATCH 001/124] #1 Create Endpoint added Signed-off-by: Benny Samir Hierl --- examples.http | 33 +++++++++++++++++++ src/api/config/errors/index.ts | 15 +++++++++ src/api/models/wishlist/index.ts | 6 ++++ src/api/routes/wishlist/create.ts | 55 +++++++++++++++++++++++++++++++ src/api/routes/wishlist/index.ts | 2 ++ src/api/services/prisma/index.ts | 4 ++- src/types.ts | 2 +- 7 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 examples.http create mode 100644 src/api/config/errors/index.ts create mode 100644 src/api/routes/wishlist/create.ts diff --git a/examples.http b/examples.http new file mode 100644 index 0000000..966382e --- /dev/null +++ b/examples.http @@ -0,0 +1,33 @@ +@BASE_URL=http://localhost:5000/api + + +### +# @name createWishlistFirst +POST {{BASE_URL}}/wishlist +Content-Type: application/json + +{ + "title": "Junior", + "imageSrc": "https://unsplash.com/photos/JZ51o_-UOY8/download?force=true&w=200", + "slugUrlText": "junior" +} + +### +# @name createWishlistSecond +POST {{BASE_URL}}/wishlist +Content-Type: application/json + +{ + "title": "Wedding", + "imageSrc": "https://unsplash.com/photos/8vaQKYnawHw/download?ixid=MnwxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjQ0MDQ4MTIy&force=true&w=200", + "description": "We are getting married", + "slugUrlText": "wedding" +} + +### +# @name getWishlists +GET {{BASE_URL}}/wishlist + +### +# @name getFirstWishlist +GET {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.slugUrlText}} diff --git a/src/api/config/errors/index.ts b/src/api/config/errors/index.ts new file mode 100644 index 0000000..a3d14a2 --- /dev/null +++ b/src/api/config/errors/index.ts @@ -0,0 +1,15 @@ +class httpError extends Error { + code: string + statusCode: number + constructor(message: string, statusCode: number, code: string) { + super(message) + this.name = this.constructor.name + Error.captureStackTrace(this, this.constructor) + this.statusCode = statusCode + this.code = code + } +} + +export const uniqueKeyError = (msg: string, code = '4001') => { + return new httpError(msg, 400, code) +} diff --git a/src/api/models/wishlist/index.ts b/src/api/models/wishlist/index.ts index 35b5ddc..fe7cbcc 100644 --- a/src/api/models/wishlist/index.ts +++ b/src/api/models/wishlist/index.ts @@ -1,4 +1,5 @@ import { prisma } from '../../services' +import { Wishlist } from '@/types' export default { getAll: async (): Promise => { @@ -17,6 +18,11 @@ export default { include: { items: includeItems }, }) }, + create: async (payload: Wishlist) => { + return await prisma.client.wishlist.create({ + data: payload, + }) + }, // eslint-disable-next-line @typescript-eslint/no-explicit-any updateItem: async (itemId: number, payload: any) => { return await prisma.client.item.update({ diff --git a/src/api/routes/wishlist/create.ts b/src/api/routes/wishlist/create.ts new file mode 100644 index 0000000..f6bbc50 --- /dev/null +++ b/src/api/routes/wishlist/create.ts @@ -0,0 +1,55 @@ +import { Wishlist } from '@/types' +import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' +import { wishlist } from '../../models' +import { prisma } from '../../services' +import { uniqueKeyError } from '../../config/errors' + +interface GetBySlugUrlTextRequest extends FastifyRequest { + params: { + wishlistId: string + itemId: number + } +} + +export const createList = { + method: 'POST', + url: '/', + schema: { + body: { + type: 'object', + additionalProperties: false, + required: ['title', 'imageSrc', 'slugUrlText'], + properties: { + title: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + slugUrlText: { type: 'string' }, + }, + }, + response: { + 201: { + type: 'object', + properties: { + id: { type: 'string' }, + title: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + slugUrlText: { type: 'string' }, + }, + }, + }, + }, + handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => { + request.log.debug(request.body) + try { + const item = await wishlist.create(request.body as Wishlist) + return item + } catch (error) { + if (error instanceof prisma.errorType && error.code === 'P2002') { + return reply.send(uniqueKeyError('Slugtext has to be unique')) + } + request.log.error(error) + throw new Error('Unexptected Error') + } + }, +} diff --git a/src/api/routes/wishlist/index.ts b/src/api/routes/wishlist/index.ts index 32fd362..1c9e7ee 100644 --- a/src/api/routes/wishlist/index.ts +++ b/src/api/routes/wishlist/index.ts @@ -1,9 +1,11 @@ import { FastifyInstance } from 'fastify' import { getAll, getBySlugUrl } from './read' import { updateItem } from './update' +import { createList } from './create' export default async (app: FastifyInstance) => { await app.route(getAll) await app.route(getBySlugUrl) + await app.route(createList) await app.route(updateItem) } diff --git a/src/api/services/prisma/index.ts b/src/api/services/prisma/index.ts index 3134896..9716a39 100644 --- a/src/api/services/prisma/index.ts +++ b/src/api/services/prisma/index.ts @@ -1,7 +1,9 @@ -import { PrismaClient } from '@prisma/client' +import { PrismaClient, Prisma } from '@prisma/client' const client = new PrismaClient() +const errorType = Prisma.PrismaClientKnownRequestError export default { client, + errorType, } diff --git a/src/types.ts b/src/types.ts index de90a26..5898f69 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,7 +9,7 @@ export interface WishlistItem { wishlistId: boolean } export interface Wishlist { - id: string + id?: string title: string description: string imageSrc: string From abf6addb704421e9f9aec09691e69bc9f9dd413f Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 09:56:15 +0100 Subject: [PATCH 002/124] #1 http status changed for case not unique slug text Signed-off-by: Benny Samir Hierl --- src/api/config/errors/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/config/errors/index.ts b/src/api/config/errors/index.ts index a3d14a2..99bacf3 100644 --- a/src/api/config/errors/index.ts +++ b/src/api/config/errors/index.ts @@ -11,5 +11,5 @@ class httpError extends Error { } export const uniqueKeyError = (msg: string, code = '4001') => { - return new httpError(msg, 400, code) + return new httpError(msg, 422, code) } From ff4a891b3500c9670a356c35a500f595a7da09c8 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 10:16:23 +0100 Subject: [PATCH 003/124] #1 not found handling improved Signed-off-by: Benny Samir Hierl --- src/api/config/errors/index.ts | 4 ++++ src/api/routes/index.ts | 4 ++++ src/api/routes/wishlist/read.ts | 5 +---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/api/config/errors/index.ts b/src/api/config/errors/index.ts index 99bacf3..992af1b 100644 --- a/src/api/config/errors/index.ts +++ b/src/api/config/errors/index.ts @@ -10,6 +10,10 @@ class httpError extends Error { } } +export const notFoundError = () => { + return new httpError('Not Found', 404, '404') +} + export const uniqueKeyError = (msg: string, code = '4001') => { return new httpError(msg, 422, code) } diff --git a/src/api/routes/index.ts b/src/api/routes/index.ts index 222f45c..a4dbf16 100644 --- a/src/api/routes/index.ts +++ b/src/api/routes/index.ts @@ -1,10 +1,14 @@ import { FastifyInstance } from 'fastify' import { default as wishlistRoute } from './wishlist/' +import { notFoundError } from '../config/errors' export default { register: (app: FastifyInstance) => { return app.register( async (app) => { + app.setNotFoundHandler((request, reply) => { + reply.send(notFoundError()) + }) await app.register(wishlistRoute, { prefix: '/wishlist' }) }, { prefix: '/api' } diff --git a/src/api/routes/wishlist/read.ts b/src/api/routes/wishlist/read.ts index 389ad37..04fd5c9 100644 --- a/src/api/routes/wishlist/read.ts +++ b/src/api/routes/wishlist/read.ts @@ -68,10 +68,7 @@ export const getBySlugUrl = { if (list) { return list } else { - return reply.code(404).send({ - error: 'notFound', - http: 404, - }) + return reply.callNotFound() } }, } From 4b553830b02d0d7dd63341304da0c95ab0d425e1 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 13:14:12 +0100 Subject: [PATCH 004/124] #1 error handling improved Signed-off-by: Benny Samir Hierl --- src/api/routes/wishlist/create.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/api/routes/wishlist/create.ts b/src/api/routes/wishlist/create.ts index f6bbc50..f945bc0 100644 --- a/src/api/routes/wishlist/create.ts +++ b/src/api/routes/wishlist/create.ts @@ -39,17 +39,16 @@ export const createList = { }, }, }, + errorHandler: (error, request, reply) => { + if (error instanceof prisma.errorType && error.code === 'P2002') { + return reply.send(uniqueKeyError('Slugtext has to be unique')) + } + request.log.error(error) + reply.send(new Error('Unexptected Error')) + }, handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => { request.log.debug(request.body) - try { - const item = await wishlist.create(request.body as Wishlist) - return item - } catch (error) { - if (error instanceof prisma.errorType && error.code === 'P2002') { - return reply.send(uniqueKeyError('Slugtext has to be unique')) - } - request.log.error(error) - throw new Error('Unexptected Error') - } + const item = await wishlist.create(request.body as Wishlist) + return item }, } From 8b0d8d27e38a000b843ca2b5eb6cc0b7726fd391 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 13:20:44 +0100 Subject: [PATCH 005/124] #1 response code changed Signed-off-by: Benny Samir Hierl --- src/api/routes/wishlist/create.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/routes/wishlist/create.ts b/src/api/routes/wishlist/create.ts index f945bc0..cc33fe0 100644 --- a/src/api/routes/wishlist/create.ts +++ b/src/api/routes/wishlist/create.ts @@ -49,6 +49,6 @@ export const createList = { handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => { request.log.debug(request.body) const item = await wishlist.create(request.body as Wishlist) - return item + reply.code(201).send(item) }, } From 5626fabdcee96f27aced48c138714aaea9f8707c Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 13:21:06 +0100 Subject: [PATCH 006/124] seed data adjusted Signed-off-by: Benny Samir Hierl --- .gitignore | 1 - prisma/seed.ts | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 prisma/seed.ts diff --git a/.gitignore b/.gitignore index b48fca3..e28467e 100644 --- a/.gitignore +++ b/.gitignore @@ -30,5 +30,4 @@ dist/ coverage .env data -prisma/seed.ts public/*.jpeg diff --git a/prisma/seed.ts b/prisma/seed.ts new file mode 100644 index 0000000..c369da5 --- /dev/null +++ b/prisma/seed.ts @@ -0,0 +1,78 @@ +import { PrismaClient, Prisma } from '@prisma/client' + +const prisma = new PrismaClient() + +const wishlistData: Prisma.WishlistCreateInput[] = [ + { + title: 'Junior', + imageSrc: + 'https://unsplash.com/photos/JZ51o_-UOY8/download?force=true&w=200', + description: '', + slugUrlText: 'junior', + items: { + create: [ + { + title: 'Mr Maria Lion "First Light" Lampe', + url: 'https://babykochs.de/mr-maria-lion-first-light-lampe/', + imageSrc: + 'https://babykochs.de/wp-content/uploads/2021/01/First-Light-Lion1.jpg', + description: + 'Lion ist Teil der Serie "First Light - Miffy und Freunde" Kollektion, eine Nachtlampe, die als "kleiner Freund für ein kleines Wunder" entworfen wurde.', + comment: '', + }, + { + title: 'Liewood Nachtlicht Winston Bär dove blue', + url: 'https://babykochs.de/liewood-nachtlicht-baer/', + imageSrc: + 'https://babykochs.de/wp-content/uploads/2021/01/Liewood-Nachtlicht-Winston-bear-dove-blue.jpg', + description: + 'Mit dem Licht dieses süßen Bären fühlen sich Eure Kleinen in der Nacht ganz sicher und haben’s schön gemütlich.', + comment: '', + }, + { + title: 'Baby- und Kleinkindbett', + url: 'https://www.tchibo.de/baby-und-kleinkindbett-p400114225.html#modal-productimagegallery-modalGalleryImage-400886394', + imageSrc: + 'https://www.tchibo.de/newmedia/art_img/MAIN-IMPORTED/f045f71ebabea9e4/baby-und-kleinkindbett.jpg', + description: + 'Ein Bett, das mitwächst Zu einem erholsamen Schlaf und einer schönen Nacht gehört natürlich auch ein gutes Bett – das gilt auch für die Kleinsten.', + comment: '', + }, + ], + }, + }, + { + title: 'Wedding', + imageSrc: + 'https://unsplash.com/photos/8vaQKYnawHw/download?ixid=MnwxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjQ0MDQ4MTIy&force=true&w=200', + description: 'We are getting married', + slugUrlText: 'wedding', + }, + { + title: '40th birthday', + imageSrc: + 'https://unsplash.com/photos/poH6OvcEeXE/download?ixid=MnwxMjA3fDB8MXxzZWFyY2h8NHx8YmlydGhkYXl8fDB8fHx8MTY0NDA1NDEzNA&force=true&w=200', + description: 'We are getting married', + slugUrlText: '40th-birthday', + }, +] + +async function main() { + console.log(`Start seeding ...`) + for (const u of wishlistData) { + const wishlist = await prisma.wishlist.create({ + data: u, + }) + console.log(`Created wishlist with id: ${wishlist.id}`) + } + console.log(`Seeding finished.`) +} + +main() + .catch((e) => { + console.error(e) + process.exit(1) + }) + .finally(async () => { + await prisma.$disconnect() + }) From 520ddfe653f3f87869c0dd02da5f920c4f387faa Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 13:22:19 +0100 Subject: [PATCH 007/124] small adjustment Signed-off-by: Benny Samir Hierl --- src/api/routes/wishlist/create.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/api/routes/wishlist/create.ts b/src/api/routes/wishlist/create.ts index cc33fe0..198d400 100644 --- a/src/api/routes/wishlist/create.ts +++ b/src/api/routes/wishlist/create.ts @@ -4,13 +4,6 @@ import { wishlist } from '../../models' import { prisma } from '../../services' import { uniqueKeyError } from '../../config/errors' -interface GetBySlugUrlTextRequest extends FastifyRequest { - params: { - wishlistId: string - itemId: number - } -} - export const createList = { method: 'POST', url: '/', @@ -46,7 +39,7 @@ export const createList = { request.log.error(error) reply.send(new Error('Unexptected Error')) }, - handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => { + handler: async (request: FastifyRequest, reply: FastifyReply) => { request.log.debug(request.body) const item = await wishlist.create(request.body as Wishlist) reply.code(201).send(item) From 2b5f4a9fd63398717046bd26e291a8cbcebc128c Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 13:43:55 +0100 Subject: [PATCH 008/124] #1 update api added Signed-off-by: Benny Samir Hierl --- examples.http | 12 +++++++ src/api/models/wishlist/index.ts | 10 ++++++ src/api/routes/wishlist/index.ts | 3 +- src/api/routes/wishlist/read.ts | 2 +- src/api/routes/wishlist/update.ts | 60 +++++++++++++++++++++++++++++-- 5 files changed, 83 insertions(+), 4 deletions(-) diff --git a/examples.http b/examples.http index 966382e..700d9a6 100644 --- a/examples.http +++ b/examples.http @@ -31,3 +31,15 @@ GET {{BASE_URL}}/wishlist ### # @name getFirstWishlist GET {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.slugUrlText}} + +### +# @name updateFirstWishlist +PUT {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}} +Content-Type: application/json + +{ + "title": "Junior", + "imageSrc": "https://unsplash.com/photos/JZ51o_-UOY8/download?force=true&w=200", + "description": "Juniors Wishlist", + "slugUrlText": "junior" +} diff --git a/src/api/models/wishlist/index.ts b/src/api/models/wishlist/index.ts index fe7cbcc..15245e1 100644 --- a/src/api/models/wishlist/index.ts +++ b/src/api/models/wishlist/index.ts @@ -23,6 +23,16 @@ export default { data: payload, }) }, + update: async (id: string, payload: Wishlist) => { + return await prisma.client.wishlist.update({ + where: { + id: id, + }, + data: { + ...payload, + }, + }) + }, // eslint-disable-next-line @typescript-eslint/no-explicit-any updateItem: async (itemId: number, payload: any) => { return await prisma.client.item.update({ diff --git a/src/api/routes/wishlist/index.ts b/src/api/routes/wishlist/index.ts index 1c9e7ee..33f34fb 100644 --- a/src/api/routes/wishlist/index.ts +++ b/src/api/routes/wishlist/index.ts @@ -1,11 +1,12 @@ import { FastifyInstance } from 'fastify' import { getAll, getBySlugUrl } from './read' -import { updateItem } from './update' +import { updateList, updateItem } from './update' import { createList } from './create' export default async (app: FastifyInstance) => { await app.route(getAll) await app.route(getBySlugUrl) await app.route(createList) + await app.route(updateList) await app.route(updateItem) } diff --git a/src/api/routes/wishlist/read.ts b/src/api/routes/wishlist/read.ts index 04fd5c9..03e5928 100644 --- a/src/api/routes/wishlist/read.ts +++ b/src/api/routes/wishlist/read.ts @@ -1,7 +1,7 @@ import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' -export const getAll = { +export const getAll = { method: 'GET', url: '/', schema: { diff --git a/src/api/routes/wishlist/update.ts b/src/api/routes/wishlist/update.ts index a8775fe..bdc6952 100644 --- a/src/api/routes/wishlist/update.ts +++ b/src/api/routes/wishlist/update.ts @@ -1,13 +1,69 @@ +import { uniqueKeyError } from '../../config/errors' +import { prisma } from '../../services' +import { Wishlist } from '@/types' import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' -interface GetBySlugUrlTextRequest extends FastifyRequest { +interface updateRequest extends FastifyRequest { + params: { + wishlistId: string + } +} +interface updateItemRequest extends FastifyRequest { params: { wishlistId: string itemId: number } } +export const updateList = { + method: 'PUT', + url: '/:wishlistId', + schema: { + body: { + type: 'object', + additionalProperties: false, + required: ['title', 'imageSrc', 'slugUrlText'], + properties: { + title: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + slugUrlText: { type: 'string' }, + }, + }, + response: { + 200: { + type: 'object', + properties: { + id: { type: 'string' }, + title: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + slugUrlText: { type: 'string' }, + }, + }, + }, + }, + errorHandler: (error, request, reply) => { + if (error instanceof prisma.errorType && error.code === 'P2002') { + return reply.send(uniqueKeyError('Slugtext has to be unique')) + } + if (error instanceof prisma.errorType && error.code === 'P2025') { + return reply.callNotFound() + } + request.log.error(error) + reply.send(new Error('Unexptected Error')) + }, + handler: async (request: updateRequest, reply: FastifyReply) => { + request.log.debug(request.body) + const item = await wishlist.update( + request.params.wishlistId, + request.body as Wishlist + ) + reply.code(201).send(item) + }, +} + export const updateItem = { method: 'PUT', url: '/:wishlistId/item/:itemId', @@ -40,7 +96,7 @@ export const updateItem = { }, }, }, - handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => { + handler: async (request: updateItemRequest, reply: FastifyReply) => { request.log.debug(request.body) const item = await wishlist.updateItem( Number(request.params.itemId), From 82ac242d9649168828a0c3e6740e47eba6ed5424 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 14:03:29 +0100 Subject: [PATCH 009/124] #1 JSON Schemas centralized Signed-off-by: Benny Samir Hierl --- src/api/config/schemas/index.ts | 1 + src/api/config/schemas/wishlist.ts | 53 ++++++++++++++++++++++++++++ src/api/routes/wishlist/create.ts | 27 ++++---------- src/api/routes/wishlist/read.ts | 37 ++------------------ src/api/routes/wishlist/update.ts | 56 ++++++------------------------ 5 files changed, 73 insertions(+), 101 deletions(-) create mode 100644 src/api/config/schemas/index.ts create mode 100644 src/api/config/schemas/wishlist.ts diff --git a/src/api/config/schemas/index.ts b/src/api/config/schemas/index.ts new file mode 100644 index 0000000..5284f07 --- /dev/null +++ b/src/api/config/schemas/index.ts @@ -0,0 +1 @@ +export * from './wishlist' diff --git a/src/api/config/schemas/wishlist.ts b/src/api/config/schemas/wishlist.ts new file mode 100644 index 0000000..897bf25 --- /dev/null +++ b/src/api/config/schemas/wishlist.ts @@ -0,0 +1,53 @@ +export const wishlistItemRequestSchema = { + type: 'object', + additionalProperties: false, + required: ['title', 'imageSrc'], + properties: { + title: { type: 'string' }, + url: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + comment: { type: 'string' }, + bought: { type: 'boolean' }, + }, +} + +export const wishlistItemResponseSchema = { + type: 'object', + properties: { + id: { type: 'number' }, + title: { type: 'string' }, + url: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + comment: { type: 'string' }, + bought: { type: 'boolean' }, + wishlistId: { type: 'string' }, + }, +} + +export const wishlistRequestSchema = { + type: 'object', + additionalProperties: false, + required: ['title', 'imageSrc', 'slugUrlText'], + properties: { + title: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + slugUrlText: { type: 'string' }, + }, +} +export const wishlistResponseSchema = { + type: 'object', + properties: { + id: { type: 'string' }, + title: { type: 'string' }, + imageSrc: { type: 'string' }, + description: { type: 'string' }, + slugUrlText: { type: 'string' }, + items: { + type: 'array', + items: wishlistItemResponseSchema, + }, + }, +} diff --git a/src/api/routes/wishlist/create.ts b/src/api/routes/wishlist/create.ts index 198d400..9ee934a 100644 --- a/src/api/routes/wishlist/create.ts +++ b/src/api/routes/wishlist/create.ts @@ -3,33 +3,18 @@ import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' import { prisma } from '../../services' import { uniqueKeyError } from '../../config/errors' +import { + wishlistRequestSchema, + wishlistResponseSchema, +} from '../../config/schemas' export const createList = { method: 'POST', url: '/', schema: { - body: { - type: 'object', - additionalProperties: false, - required: ['title', 'imageSrc', 'slugUrlText'], - properties: { - title: { type: 'string' }, - imageSrc: { type: 'string' }, - description: { type: 'string' }, - slugUrlText: { type: 'string' }, - }, - }, + body: wishlistRequestSchema, response: { - 201: { - type: 'object', - properties: { - id: { type: 'string' }, - title: { type: 'string' }, - imageSrc: { type: 'string' }, - description: { type: 'string' }, - slugUrlText: { type: 'string' }, - }, - }, + 201: wishlistResponseSchema, }, }, errorHandler: (error, request, reply) => { diff --git a/src/api/routes/wishlist/read.ts b/src/api/routes/wishlist/read.ts index 03e5928..3bc6e80 100644 --- a/src/api/routes/wishlist/read.ts +++ b/src/api/routes/wishlist/read.ts @@ -1,5 +1,6 @@ import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' +import { wishlistResponseSchema } from '../../config/schemas' export const getAll = { method: 'GET', @@ -8,15 +9,7 @@ export const getAll = { response: { 200: { type: 'array', - items: { - properties: { - id: { type: 'string' }, - title: { type: 'string' }, - imageSrc: { type: 'string' }, - description: { type: 'string' }, - slugUrlText: { type: 'string' }, - }, - }, + items: wishlistResponseSchema, }, }, }, @@ -36,31 +29,7 @@ export const getBySlugUrl = { url: '/:slugText', schema: { response: { - 200: { - type: 'object', - properties: { - id: { type: 'string' }, - title: { type: 'string' }, - imageSrc: { type: 'string' }, - description: { type: 'string' }, - slugUrlText: { type: 'string' }, - items: { - type: 'array', - items: { - properties: { - id: { type: 'number' }, - title: { type: 'string' }, - url: { type: 'string' }, - imageSrc: { type: 'string' }, - description: { type: 'string' }, - comment: { type: 'string' }, - bought: { type: 'boolean' }, - wishlistId: { type: 'string' }, - }, - }, - }, - }, - }, + 200: wishlistResponseSchema, }, }, handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => { diff --git a/src/api/routes/wishlist/update.ts b/src/api/routes/wishlist/update.ts index bdc6952..b6f9a4d 100644 --- a/src/api/routes/wishlist/update.ts +++ b/src/api/routes/wishlist/update.ts @@ -3,6 +3,12 @@ import { prisma } from '../../services' import { Wishlist } from '@/types' import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' +import { + wishlistRequestSchema, + wishlistResponseSchema, + wishlistItemRequestSchema, + wishlistItemResponseSchema, +} from '../../config/schemas' interface updateRequest extends FastifyRequest { params: { @@ -20,28 +26,9 @@ export const updateList = { method: 'PUT', url: '/:wishlistId', schema: { - body: { - type: 'object', - additionalProperties: false, - required: ['title', 'imageSrc', 'slugUrlText'], - properties: { - title: { type: 'string' }, - imageSrc: { type: 'string' }, - description: { type: 'string' }, - slugUrlText: { type: 'string' }, - }, - }, + body: wishlistRequestSchema, response: { - 200: { - type: 'object', - properties: { - id: { type: 'string' }, - title: { type: 'string' }, - imageSrc: { type: 'string' }, - description: { type: 'string' }, - slugUrlText: { type: 'string' }, - }, - }, + 200: wishlistResponseSchema, }, }, errorHandler: (error, request, reply) => { @@ -68,32 +55,9 @@ export const updateItem = { method: 'PUT', url: '/:wishlistId/item/:itemId', schema: { - body: { - type: 'object', - additionalProperties: false, - properties: { - title: { type: 'string' }, - url: { type: 'string' }, - image: { type: 'string' }, - description: { type: 'string' }, - comment: { type: 'string' }, - bought: { type: 'boolean' }, - }, - }, + body: wishlistItemRequestSchema, response: { - 204: { - type: 'object', - properties: { - id: { type: 'number' }, - title: { type: 'string' }, - url: { type: 'string' }, - image: { type: 'string' }, - description: { type: 'string' }, - comment: { type: 'string' }, - bought: { type: 'boolean' }, - wishlistId: { type: 'string' }, - }, - }, + 200: wishlistItemResponseSchema, }, }, handler: async (request: updateItemRequest, reply: FastifyReply) => { From 56db8ba65a2afeb5f5c994fc59207659fea4b45d Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 14:45:56 +0100 Subject: [PATCH 010/124] #1 Schema adjusted Signed-off-by: Benny Samir Hierl --- .../migration.sql | 8 ++++---- prisma/schema.prisma | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) rename prisma/migrations/{20220129174151_first_migration => 20220205134511_first_migration}/migration.sql (79%) diff --git a/prisma/migrations/20220129174151_first_migration/migration.sql b/prisma/migrations/20220205134511_first_migration/migration.sql similarity index 79% rename from prisma/migrations/20220129174151_first_migration/migration.sql rename to prisma/migrations/20220205134511_first_migration/migration.sql index f84bb69..d37838a 100644 --- a/prisma/migrations/20220129174151_first_migration/migration.sql +++ b/prisma/migrations/20220205134511_first_migration/migration.sql @@ -4,17 +4,17 @@ CREATE TABLE "Wishlist" ( "title" TEXT NOT NULL, "imageSrc" TEXT NOT NULL, "slugUrlText" TEXT NOT NULL, - "description" TEXT + "description" TEXT NOT NULL DEFAULT '' ); -- CreateTable CREATE TABLE "Item" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "title" TEXT NOT NULL, - "url" TEXT, - "imageSrc" TEXT, + "url" TEXT NOT NULL DEFAULT '', + "imageSrc" TEXT NOT NULL DEFAULT '', "description" TEXT NOT NULL, - "comment" TEXT, + "comment" TEXT NOT NULL DEFAULT '', "bought" BOOLEAN NOT NULL DEFAULT false, "wishlistId" TEXT NOT NULL, CONSTRAINT "Item_wishlistId_fkey" FOREIGN KEY ("wishlistId") REFERENCES "Wishlist" ("id") ON DELETE RESTRICT ON UPDATE CASCADE diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7616486..492ab53 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,18 +15,18 @@ model Wishlist { title String imageSrc String slugUrlText String @unique - description String? + description String @default("") items Item[] } model Item { - id Int @id @default(autoincrement()) + id Int @id @default(autoincrement()) title String - url String? - imageSrc String? + url String @default("") + imageSrc String @default("") description String - comment String? + comment String @default("") bought Boolean @default(false) - wishlist Wishlist @relation(fields: [wishlistId], references: [id]) + wishlist Wishlist @relation(fields: [wishlistId], references: [id]) wishlistId String } From dea3aaf477983a75772cd13dede5ad2a4c752ac5 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 14:47:37 +0100 Subject: [PATCH 011/124] #1 Add item API Endpoint added Signed-off-by: Benny Samir Hierl --- examples.http | 12 ++++++++++ prisma/seed.ts | 26 ++++----------------- src/api/config/schemas/wishlist.ts | 2 +- src/api/models/wishlist/index.ts | 18 ++++++++++++++- src/api/routes/wishlist/create.ts | 36 +++++++++++++++++++++++++++++- src/api/routes/wishlist/index.ts | 3 ++- src/api/routes/wishlist/update.ts | 8 +++---- 7 files changed, 74 insertions(+), 31 deletions(-) diff --git a/examples.http b/examples.http index 700d9a6..eefce8d 100644 --- a/examples.http +++ b/examples.http @@ -43,3 +43,15 @@ Content-Type: application/json "description": "Juniors Wishlist", "slugUrlText": "junior" } + +### +# @name addItemToFirstWishlist +POST {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}}/item +Content-Type: application/json + +{ + "title": "Goldfish 40442 | BrickHeadz", + "url": "https://www.lego.com/en-de/product/goldfish-40442", + "imageSrc": "https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1", + "description": "Cute goldfish and fry, build-and-display BrickHeadz™ model" +} diff --git a/prisma/seed.ts b/prisma/seed.ts index c369da5..b404659 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -12,30 +12,12 @@ const wishlistData: Prisma.WishlistCreateInput[] = [ items: { create: [ { - title: 'Mr Maria Lion "First Light" Lampe', - url: 'https://babykochs.de/mr-maria-lion-first-light-lampe/', + title: 'Goldfish 40442 | BrickHeadz', + url: 'https://www.lego.com/en-de/product/goldfish-40442', imageSrc: - 'https://babykochs.de/wp-content/uploads/2021/01/First-Light-Lion1.jpg', + 'https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1', description: - 'Lion ist Teil der Serie "First Light - Miffy und Freunde" Kollektion, eine Nachtlampe, die als "kleiner Freund für ein kleines Wunder" entworfen wurde.', - comment: '', - }, - { - title: 'Liewood Nachtlicht Winston Bär dove blue', - url: 'https://babykochs.de/liewood-nachtlicht-baer/', - imageSrc: - 'https://babykochs.de/wp-content/uploads/2021/01/Liewood-Nachtlicht-Winston-bear-dove-blue.jpg', - description: - 'Mit dem Licht dieses süßen Bären fühlen sich Eure Kleinen in der Nacht ganz sicher und haben’s schön gemütlich.', - comment: '', - }, - { - title: 'Baby- und Kleinkindbett', - url: 'https://www.tchibo.de/baby-und-kleinkindbett-p400114225.html#modal-productimagegallery-modalGalleryImage-400886394', - imageSrc: - 'https://www.tchibo.de/newmedia/art_img/MAIN-IMPORTED/f045f71ebabea9e4/baby-und-kleinkindbett.jpg', - description: - 'Ein Bett, das mitwächst Zu einem erholsamen Schlaf und einer schönen Nacht gehört natürlich auch ein gutes Bett – das gilt auch für die Kleinsten.', + 'Cute goldfish and fry, build-and-display BrickHeadz™ model', comment: '', }, ], diff --git a/src/api/config/schemas/wishlist.ts b/src/api/config/schemas/wishlist.ts index 897bf25..3e575fc 100644 --- a/src/api/config/schemas/wishlist.ts +++ b/src/api/config/schemas/wishlist.ts @@ -1,7 +1,7 @@ export const wishlistItemRequestSchema = { type: 'object', additionalProperties: false, - required: ['title', 'imageSrc'], + required: ['title', 'description'], properties: { title: { type: 'string' }, url: { type: 'string' }, diff --git a/src/api/models/wishlist/index.ts b/src/api/models/wishlist/index.ts index 15245e1..e140f3d 100644 --- a/src/api/models/wishlist/index.ts +++ b/src/api/models/wishlist/index.ts @@ -1,5 +1,5 @@ import { prisma } from '../../services' -import { Wishlist } from '@/types' +import { Wishlist, WishlistItem } from '@/types' export default { getAll: async (): Promise => { @@ -33,6 +33,22 @@ export default { }, }) }, + createItem: async (wishlistId: string, payload: WishlistItem) => { + const wishlist = await prisma.client.wishlist.update({ + where: { + id: wishlistId, + }, + data: { + items: { + create: { + ...payload, + }, + }, + }, + include: { items: true }, + }) + return wishlist.items.pop() + }, // eslint-disable-next-line @typescript-eslint/no-explicit-any updateItem: async (itemId: number, payload: any) => { return await prisma.client.item.update({ diff --git a/src/api/routes/wishlist/create.ts b/src/api/routes/wishlist/create.ts index 9ee934a..55a5087 100644 --- a/src/api/routes/wishlist/create.ts +++ b/src/api/routes/wishlist/create.ts @@ -1,13 +1,21 @@ -import { Wishlist } from '@/types' +import { Wishlist, WishlistItem } from '@/types' import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' import { prisma } from '../../services' import { uniqueKeyError } from '../../config/errors' import { + wishlistItemRequestSchema, + wishlistItemResponseSchema, wishlistRequestSchema, wishlistResponseSchema, } from '../../config/schemas' +interface createItemRequest extends FastifyRequest { + params: { + wishlistId: string + } +} + export const createList = { method: 'POST', url: '/', @@ -30,3 +38,29 @@ export const createList = { reply.code(201).send(item) }, } + +export const createItem = { + method: 'POST', + url: '/:wishlistId/item', + schema: { + body: wishlistItemRequestSchema, + response: { + 201: wishlistItemResponseSchema, + }, + }, + errorHandler: (error, request, reply) => { + if (error instanceof prisma.errorType && error.code === 'P2025') { + return reply.callNotFound() + } + request.log.error(error) + reply.send(new Error('Unexptected Error')) + }, + handler: async (request: createItemRequest, reply: FastifyReply) => { + request.log.debug(request.body) + const item = await wishlist.createItem( + request.params.wishlistId, + request.body as WishlistItem + ) + reply.code(201).send(item) + }, +} diff --git a/src/api/routes/wishlist/index.ts b/src/api/routes/wishlist/index.ts index 33f34fb..ec37853 100644 --- a/src/api/routes/wishlist/index.ts +++ b/src/api/routes/wishlist/index.ts @@ -1,12 +1,13 @@ import { FastifyInstance } from 'fastify' import { getAll, getBySlugUrl } from './read' import { updateList, updateItem } from './update' -import { createList } from './create' +import { createList, createItem } from './create' export default async (app: FastifyInstance) => { await app.route(getAll) await app.route(getBySlugUrl) await app.route(createList) + await app.route(createItem) await app.route(updateList) await app.route(updateItem) } diff --git a/src/api/routes/wishlist/update.ts b/src/api/routes/wishlist/update.ts index b6f9a4d..be8224c 100644 --- a/src/api/routes/wishlist/update.ts +++ b/src/api/routes/wishlist/update.ts @@ -15,6 +15,7 @@ interface updateRequest extends FastifyRequest { wishlistId: string } } + interface updateItemRequest extends FastifyRequest { params: { wishlistId: string @@ -67,12 +68,9 @@ export const updateItem = { request.body ) if (item) { - return item + reply.send(item) } else { - return reply.code(404).send({ - error: 'notFound', - http: 404, - }) + reply.callNotFound() } }, } From 9534bc270ffab0a3d3c41d56188734ddba548054 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sat, 5 Feb 2022 14:58:20 +0100 Subject: [PATCH 012/124] small typescript adjustments Signed-off-by: Benny Samir Hierl --- src/api/models/wishlist/index.ts | 11 ++++------- src/types.ts | 2 +- src/views/DetailView.vue | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/api/models/wishlist/index.ts b/src/api/models/wishlist/index.ts index e140f3d..570f159 100644 --- a/src/api/models/wishlist/index.ts +++ b/src/api/models/wishlist/index.ts @@ -2,15 +2,12 @@ import { prisma } from '../../services' import { Wishlist, WishlistItem } from '@/types' export default { - getAll: async (): Promise => { - return await prisma.client.wishlist.findMany({ + getAll: async (): Promise => { + return (await prisma.client.wishlist.findMany({ include: { items: false }, - }) + })) as Wishlist[] }, - getBySlugUrlText: async ( - value: string, - includeItems = false - ): Promise => { + getBySlugUrlText: async (value: string, includeItems = false) => { return await prisma.client.wishlist.findUnique({ where: { slugUrlText: value, diff --git a/src/types.ts b/src/types.ts index 5898f69..9962ef6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -14,7 +14,7 @@ export interface Wishlist { description: string imageSrc: string slugUrlText: string - items: WishlistItem[] + items?: WishlistItem[] } export interface TileProp { title: string diff --git a/src/views/DetailView.vue b/src/views/DetailView.vue index fe89828..73cf606 100644 --- a/src/views/DetailView.vue +++ b/src/views/DetailView.vue @@ -16,7 +16,7 @@ const { list, fetch, updateItem } = useWishlistStore() await fetch(route.params.slug as string) const notBoughtItems = computed(() => { - return list.value?.items.filter( + return list.value?.items?.filter( (item: WishlistItemType) => item.bought === false ) }) From 14cded061f3de4d28d92c39fe032a5cf730dbc2e Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 11:23:47 +0100 Subject: [PATCH 013/124] #1 error handling improved Signed-off-by: Benny Samir Hierl --- src/api/config/errors/index.ts | 41 +++++++++++++++++++++++++++++-- src/api/routes/index.ts | 7 +++--- src/api/routes/wishlist/create.ts | 22 +++++------------ src/api/routes/wishlist/update.ts | 35 +++++++++++--------------- src/api/services/prisma/index.ts | 4 +-- 5 files changed, 64 insertions(+), 45 deletions(-) diff --git a/src/api/config/errors/index.ts b/src/api/config/errors/index.ts index 992af1b..9d91200 100644 --- a/src/api/config/errors/index.ts +++ b/src/api/config/errors/index.ts @@ -1,3 +1,40 @@ +import { FastifyRequest, FastifyReply, FastifyError } from 'fastify' +import { Prisma } from '@prisma/client' + +const errorIs = (e: unknown, c: string) => + e instanceof Prisma.PrismaClientKnownRequestError && e.code === c + +export const defaultErrorHandler = ( + error: FastifyError, + request: FastifyRequest, + reply: FastifyReply +) => { + if (error.validation) { + error.code = '400' + reply.send(error) + } else if (errorIs(error, 'P2002')) { + reply.send( + uniqueKeyError( + // @ts-expect-error: Object is possibly 'undefined' + `${error.meta.target[0] || 'One of the fields'} has to be unique` + ) + ) + } else if (errorIs(error, 'P2025')) { + reply.callNotFound() + } else { + request.log.error(error) + const e = new httpError('unexpected error', 500, '500') + reply.send(e) + } +} + +export const notFoundHandler = ( + request: FastifyRequest, + reply: FastifyReply +) => { + reply.send(notFoundError()) +} + class httpError extends Error { code: string statusCode: number @@ -10,10 +47,10 @@ class httpError extends Error { } } -export const notFoundError = () => { +const notFoundError = () => { return new httpError('Not Found', 404, '404') } -export const uniqueKeyError = (msg: string, code = '4001') => { +const uniqueKeyError = (msg: string, code = '4001') => { return new httpError(msg, 422, code) } diff --git a/src/api/routes/index.ts b/src/api/routes/index.ts index a4dbf16..d88f405 100644 --- a/src/api/routes/index.ts +++ b/src/api/routes/index.ts @@ -1,14 +1,13 @@ import { FastifyInstance } from 'fastify' import { default as wishlistRoute } from './wishlist/' -import { notFoundError } from '../config/errors' +import { defaultErrorHandler, notFoundHandler } from '../config/errors' export default { register: (app: FastifyInstance) => { return app.register( async (app) => { - app.setNotFoundHandler((request, reply) => { - reply.send(notFoundError()) - }) + await app.setNotFoundHandler(notFoundHandler) + await app.setErrorHandler(defaultErrorHandler) await app.register(wishlistRoute, { prefix: '/wishlist' }) }, { prefix: '/api' } diff --git a/src/api/routes/wishlist/create.ts b/src/api/routes/wishlist/create.ts index 55a5087..cf8117b 100644 --- a/src/api/routes/wishlist/create.ts +++ b/src/api/routes/wishlist/create.ts @@ -1,8 +1,6 @@ import { Wishlist, WishlistItem } from '@/types' import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' -import { prisma } from '../../services' -import { uniqueKeyError } from '../../config/errors' import { wishlistItemRequestSchema, wishlistItemResponseSchema, @@ -25,13 +23,6 @@ export const createList = { 201: wishlistResponseSchema, }, }, - errorHandler: (error, request, reply) => { - if (error instanceof prisma.errorType && error.code === 'P2002') { - return reply.send(uniqueKeyError('Slugtext has to be unique')) - } - request.log.error(error) - reply.send(new Error('Unexptected Error')) - }, handler: async (request: FastifyRequest, reply: FastifyReply) => { request.log.debug(request.body) const item = await wishlist.create(request.body as Wishlist) @@ -44,17 +35,16 @@ export const createItem = { url: '/:wishlistId/item', schema: { body: wishlistItemRequestSchema, + params: { + type: 'object', + properties: { + wishlistId: { type: 'string' }, + }, + }, response: { 201: wishlistItemResponseSchema, }, }, - errorHandler: (error, request, reply) => { - if (error instanceof prisma.errorType && error.code === 'P2025') { - return reply.callNotFound() - } - request.log.error(error) - reply.send(new Error('Unexptected Error')) - }, handler: async (request: createItemRequest, reply: FastifyReply) => { request.log.debug(request.body) const item = await wishlist.createItem( diff --git a/src/api/routes/wishlist/update.ts b/src/api/routes/wishlist/update.ts index be8224c..78d78fb 100644 --- a/src/api/routes/wishlist/update.ts +++ b/src/api/routes/wishlist/update.ts @@ -1,5 +1,3 @@ -import { uniqueKeyError } from '../../config/errors' -import { prisma } from '../../services' import { Wishlist } from '@/types' import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' import { wishlist } from '../../models' @@ -28,20 +26,16 @@ export const updateList = { url: '/:wishlistId', schema: { body: wishlistRequestSchema, + params: { + type: 'object', + properties: { + wishlistId: { type: 'string' }, + }, + }, response: { 200: wishlistResponseSchema, }, }, - errorHandler: (error, request, reply) => { - if (error instanceof prisma.errorType && error.code === 'P2002') { - return reply.send(uniqueKeyError('Slugtext has to be unique')) - } - if (error instanceof prisma.errorType && error.code === 'P2025') { - return reply.callNotFound() - } - request.log.error(error) - reply.send(new Error('Unexptected Error')) - }, handler: async (request: updateRequest, reply: FastifyReply) => { request.log.debug(request.body) const item = await wishlist.update( @@ -57,20 +51,21 @@ export const updateItem = { url: '/:wishlistId/item/:itemId', schema: { body: wishlistItemRequestSchema, + params: { + type: 'object', + properties: { + wishlistId: { type: 'string' }, + itemId: { type: 'number' }, + }, + }, response: { 200: wishlistItemResponseSchema, }, }, handler: async (request: updateItemRequest, reply: FastifyReply) => { request.log.debug(request.body) - const item = await wishlist.updateItem( - Number(request.params.itemId), - request.body + reply.send( + await wishlist.updateItem(Number(request.params.itemId), request.body) ) - if (item) { - reply.send(item) - } else { - reply.callNotFound() - } }, } diff --git a/src/api/services/prisma/index.ts b/src/api/services/prisma/index.ts index 9716a39..3134896 100644 --- a/src/api/services/prisma/index.ts +++ b/src/api/services/prisma/index.ts @@ -1,9 +1,7 @@ -import { PrismaClient, Prisma } from '@prisma/client' +import { PrismaClient } from '@prisma/client' const client = new PrismaClient() -const errorType = Prisma.PrismaClientKnownRequestError export default { client, - errorType, } From 16df584334b3945038096a646ef5578be349a6f6 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 11:44:50 +0100 Subject: [PATCH 014/124] #1 delete endpoint added --- examples.http | 16 ++++++++++ src/api/models/wishlist/index.ts | 14 +++++++++ src/api/routes/wishlist/delete.ts | 50 +++++++++++++++++++++++++++++++ src/api/routes/wishlist/index.ts | 3 ++ src/api/routes/wishlist/update.ts | 4 +-- 5 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 src/api/routes/wishlist/delete.ts diff --git a/examples.http b/examples.http index eefce8d..9ff63c8 100644 --- a/examples.http +++ b/examples.http @@ -55,3 +55,19 @@ Content-Type: application/json "imageSrc": "https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1", "description": "Cute goldfish and fry, build-and-display BrickHeadz™ model" } + +### +# @name updateItemOnFirstWishlist +PUT {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}}/item/1 +Content-Type: application/json + +{ + "title": "Goldfish | BrickHeadz", + "url": "https://www.lego.com/en-de/product/goldfish-40442", + "imageSrc": "https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1", + "description": "Cute goldfish and fry, build-and-display BrickHeadz™ model" +} + +### +# @name deleteItemToFirstWishlist +DELETE {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}}/item/2 diff --git a/src/api/models/wishlist/index.ts b/src/api/models/wishlist/index.ts index 570f159..183f227 100644 --- a/src/api/models/wishlist/index.ts +++ b/src/api/models/wishlist/index.ts @@ -30,6 +30,13 @@ export default { }, }) }, + delete: async (id: string) => { + return await prisma.client.wishlist.delete({ + where: { + id: id, + }, + }) + }, createItem: async (wishlistId: string, payload: WishlistItem) => { const wishlist = await prisma.client.wishlist.update({ where: { @@ -57,4 +64,11 @@ export default { }, }) }, + deleteItem: async (itemId: number) => { + return await prisma.client.item.delete({ + where: { + id: itemId, + }, + }) + }, } diff --git a/src/api/routes/wishlist/delete.ts b/src/api/routes/wishlist/delete.ts new file mode 100644 index 0000000..ebeb9e9 --- /dev/null +++ b/src/api/routes/wishlist/delete.ts @@ -0,0 +1,50 @@ +import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' +import { wishlist } from '../../models' + +interface deleteRequest extends FastifyRequest { + params: { + wishlistId: string + } +} + +interface deleteItemRequest extends FastifyRequest { + params: { + wishlistId: string + itemId: number + } +} + +export const deleteList = { + method: 'DELETE', + url: '/:wishlistId', + schema: { + params: { + type: 'object', + properties: { + wishlistId: { type: 'string' }, + }, + }, + }, + handler: async (request: deleteRequest, reply: FastifyReply) => { + await wishlist.delete(request.params.wishlistId) + reply.code(204).send() + }, +} + +export const deleteItem = { + method: 'DELETE', + url: '/:wishlistId/item/:itemId', + schema: { + params: { + type: 'object', + properties: { + wishlistId: { type: 'string' }, + itemId: { type: 'number' }, + }, + }, + }, + handler: async (request: deleteItemRequest, reply: FastifyReply) => { + await wishlist.deleteItem(request.params.itemId) + reply.code(204).send() + }, +} diff --git a/src/api/routes/wishlist/index.ts b/src/api/routes/wishlist/index.ts index ec37853..13ad069 100644 --- a/src/api/routes/wishlist/index.ts +++ b/src/api/routes/wishlist/index.ts @@ -2,6 +2,7 @@ import { FastifyInstance } from 'fastify' import { getAll, getBySlugUrl } from './read' import { updateList, updateItem } from './update' import { createList, createItem } from './create' +import { deleteList, deleteItem } from './delete' export default async (app: FastifyInstance) => { await app.route(getAll) @@ -10,4 +11,6 @@ export default async (app: FastifyInstance) => { await app.route(createItem) await app.route(updateList) await app.route(updateItem) + await app.route(deleteList) + await app.route(deleteItem) } diff --git a/src/api/routes/wishlist/update.ts b/src/api/routes/wishlist/update.ts index 78d78fb..2f64817 100644 --- a/src/api/routes/wishlist/update.ts +++ b/src/api/routes/wishlist/update.ts @@ -64,8 +64,6 @@ export const updateItem = { }, handler: async (request: updateItemRequest, reply: FastifyReply) => { request.log.debug(request.body) - reply.send( - await wishlist.updateItem(Number(request.params.itemId), request.body) - ) + reply.send(await wishlist.updateItem(request.params.itemId, request.body)) }, } From ac160b58f976672f83f228b0635a4025a3a602fe Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 13:30:31 +0100 Subject: [PATCH 015/124] 1.0.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 632c211..a5c4611 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "wishlist", - "version": "0.1.2", + "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.1.2", + "version": "1.0.0", "dependencies": { "@prisma/client": "^3.8.1", "axios": "^0.25.0", diff --git a/package.json b/package.json index 65b88f7..7e452ee 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "0.1.2", + "version": "1.0.0", "scripts": { "dev": "concurrently --kill-others \"npm run dev:frontend\" \"npm run dev:backend\"", "dev:frontend": "vite", From ea60f2b6ebe1008d1efc3e5985fd422bf5ac11bf Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 13:31:57 +0100 Subject: [PATCH 016/124] fix not found issue Signed-off-by: Benny Samir Hierl --- src/composables/useAxios.ts | 12 +++++++++--- src/composables/useWishlistStore.ts | 11 +++++++++-- src/router/index.ts | 6 +++--- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/composables/useAxios.ts b/src/composables/useAxios.ts index 38ae217..1c872c2 100644 --- a/src/composables/useAxios.ts +++ b/src/composables/useAxios.ts @@ -1,6 +1,7 @@ import axios, { AxiosInstance, AxiosRequestConfig } from 'axios' import { apiConfig } from '@/config' import { ref } from 'vue' +import router from '../router' const isLoading = ref(false) const error = ref(null) @@ -11,7 +12,7 @@ const config: AxiosRequestConfig = { const client: AxiosInstance = axios.create(config) -client.interceptors.request.use( +export const requestInterceptor = client.interceptors.request.use( function (config) { isLoading.value = true error.value = null @@ -24,14 +25,19 @@ client.interceptors.request.use( } ) -client.interceptors.response.use( +export const responseInterceptor = client.interceptors.response.use( function (response) { isLoading.value = false return response }, function (err) { isLoading.value = false - error.value = err + if (err.response?.status === 404) { + router.push({ name: 'notFound' }) + err.ignore = true + } else { + error.value = err + } return Promise.reject(err) } ) diff --git a/src/composables/useWishlistStore.ts b/src/composables/useWishlistStore.ts index 9177509..caac117 100644 --- a/src/composables/useWishlistStore.ts +++ b/src/composables/useWishlistStore.ts @@ -1,13 +1,20 @@ import useAxios from '@/composables/useAxios' import { Wishlist, WishlistItem } from '@/types' +import { AxiosError } from 'axios' import { ref } from 'vue' const { client } = useAxios() const list = ref(null) const fetch = async (slugText: string): Promise => { - const { data } = await client.get(`/wishlist/${slugText}`) - list.value = data + try { + const { data } = await client.get(`/wishlist/${slugText}`) + list.value = data + } catch (e: any) { + if (e.isAxiosError && !(e.ignore)) { + throw e + } + } } const updateItem = async (item: WishlistItem): Promise => { diff --git a/src/router/index.ts b/src/router/index.ts index bacec4d..ca65550 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,6 +1,6 @@ import { createRouter, createWebHistory } from 'vue-router' -import HomeView from '../views/HomeView.vue' -import DetailView from '../views/DetailView.vue' +import HomeView from '@/views/HomeView.vue' +import DetailView from '@/views/DetailView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -18,7 +18,7 @@ const router = createRouter({ { name: 'notFound', path: '/:pathMatch(.*)*', - component: () => import('../views/NotFound.vue'), + component: () => import('@/views/NotFound.vue'), }, ], }) From ea0be6fe69ac77a88adff0023263616d40a8184a Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 14:40:37 +0100 Subject: [PATCH 017/124] #4 api to load open graph metadata added Signed-off-by: Benny Samir Hierl --- package-lock.json | 698 ++++++++++++++++++++++++++++-- package.json | 6 +- src/api/routes/index.ts | 2 + src/api/routes/utils/index.ts | 6 + src/api/routes/utils/opengraph.ts | 48 ++ 5 files changed, 720 insertions(+), 40 deletions(-) create mode 100644 src/api/routes/utils/index.ts create mode 100644 src/api/routes/utils/opengraph.ts diff --git a/package-lock.json b/package-lock.json index 632c211..69bc788 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "fastify-cors": "^6.0.2", "fastify-helmet": "^7.0.1", "fastify-static": "^4.5.0", + "open-graph-scraper": "^4.11.0", "vue": "^3.2.27", "vue-i18n": "^9.2.0-beta.30", "vue-router": "^4.0.12" @@ -21,6 +22,7 @@ "devDependencies": { "@rushstack/eslint-patch": "^1.1.0", "@types/node": "^16.11.21", + "@types/open-graph-scraper": "^4.8.1", "@vitejs/plugin-vue": "^2.0.1", "@vue/eslint-config-prettier": "^7.0.0", "@vue/eslint-config-typescript": "^10.0.0", @@ -481,6 +483,17 @@ "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", "dev": true }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, "node_modules/@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -496,6 +509,11 @@ "@types/chai": "*" } }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -510,11 +528,27 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "node_modules/@types/keyv": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", + "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "16.11.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.21.tgz", - "integrity": "sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A==", - "dev": true + "integrity": "sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A==" + }, + "node_modules/@types/open-graph-scraper": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@types/open-graph-scraper/-/open-graph-scraper-4.8.1.tgz", + "integrity": "sha512-YtDUxwWiqD0urgCrhGfIeuy84J5TfnrtkM/5a5JXAXGLfi1uMHtZGpDT4ZVwlo9jBNemvXHya6cH28bZS1To1g==", + "dev": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/parse-json": { "version": "4.0.0", @@ -522,6 +556,14 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.0.tgz", @@ -1347,6 +1389,11 @@ "node": ">=8" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, "node_modules/boxen": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", @@ -1452,6 +1499,14 @@ "node": ">=10.12.0" } }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, "node_modules/cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -1589,6 +1644,11 @@ "is-regex": "^1.0.3" } }, + "node_modules/chardet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.4.0.tgz", + "integrity": "sha512-NpwMDdSIprbYx1CLnfbxEIarI0Z+s9MssEgggMNheGM+WD68yOhV7IEA/3r6tr0yTRgQD0HuZJDw32s99i6L+A==" + }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -1598,6 +1658,72 @@ "node": "*" } }, + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dependencies": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", + "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "dependencies": { + "css-select": "^4.1.3", + "css-what": "^5.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0", + "domutils": "^2.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/cheerio/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/cheerio/node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1670,7 +1796,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "dependencies": { "mimic-response": "^1.0.0" } @@ -1879,6 +2004,32 @@ "node": ">=8" } }, + "node_modules/css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -2131,7 +2282,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -2145,7 +2295,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -2154,7 +2303,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true, "funding": [ { "type": "github", @@ -2178,7 +2326,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", - "dev": true, "dependencies": { "domelementtype": "^2.2.0" }, @@ -2193,7 +2340,6 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -3615,8 +3761,7 @@ "node_modules/http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "node_modules/http-errors": { "version": "1.8.1", @@ -3647,6 +3792,18 @@ "node": ">= 6" } }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -3679,7 +3836,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -4419,7 +4575,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "engines": { "node": ">=4" } @@ -4599,6 +4754,17 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", @@ -4642,6 +4808,179 @@ "wrappy": "1" } }, + "node_modules/open-graph-scraper": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/open-graph-scraper/-/open-graph-scraper-4.11.0.tgz", + "integrity": "sha512-APlovc5JOWXXUIyNc/1o340ik5d7RA/0TBTRMxpOMvsUXX4/uyjpHQijBUU7NxhjJpDHpc3d/lg7KcHBaSpKEw==", + "dependencies": { + "chardet": "^1.4.0", + "cheerio": "^1.0.0-rc.10", + "got": "^11.8.2", + "iconv-lite": "^0.6.3", + "validator": "^13.7.0" + }, + "engines": { + "node": ">=12.x.x" + } + }, + "node_modules/open-graph-scraper/node_modules/@sindresorhus/is": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/open-graph-scraper/node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/open-graph-scraper/node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/open-graph-scraper/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open-graph-scraper/node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/open-graph-scraper/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open-graph-scraper/node_modules/got": { + "version": "11.8.3", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", + "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/open-graph-scraper/node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/open-graph-scraper/node_modules/keyv": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.0.tgz", + "integrity": "sha512-YsY3wr6HabE11/sscee+3nZ03XjvkrPWGouAmJFBdZoK92wiOlJCzI5/sDEIKdJhdhHO144ei45U9gXfbu14Uw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/open-graph-scraper/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/open-graph-scraper/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open-graph-scraper/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open-graph-scraper/node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/open-graph-scraper/node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -4764,8 +5103,15 @@ "node_modules/parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } }, "node_modules/path-exists": { "version": "4.0.0", @@ -5310,7 +5656,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "engines": { "node": ">=10" }, @@ -5457,6 +5802,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -5578,8 +5928,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/saxes": { "version": "5.0.1", @@ -6380,6 +6729,14 @@ "node": ">= 8" } }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -7354,6 +7711,17 @@ "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", "dev": true }, + "@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, "@types/chai": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.0.tgz", @@ -7369,6 +7737,11 @@ "@types/chai": "*" } }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, "@types/istanbul-lib-coverage": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", @@ -7383,11 +7756,27 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "@types/keyv": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz", + "integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==", + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "16.11.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.21.tgz", - "integrity": "sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A==", - "dev": true + "integrity": "sha512-Pf8M1XD9i1ksZEcCP8vuSNwooJ/bZapNmIzpmsMaL+jMI+8mEYU3PKvs+xDNuQcJWF/x24WzY4qxLtB0zNow9A==" + }, + "@types/open-graph-scraper": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@types/open-graph-scraper/-/open-graph-scraper-4.8.1.tgz", + "integrity": "sha512-YtDUxwWiqD0urgCrhGfIeuy84J5TfnrtkM/5a5JXAXGLfi1uMHtZGpDT4ZVwlo9jBNemvXHya6cH28bZS1To1g==", + "dev": true, + "requires": { + "@types/node": "*" + } }, "@types/parse-json": { "version": "4.0.0", @@ -7395,6 +7784,14 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "requires": { + "@types/node": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.0.tgz", @@ -8026,6 +8423,11 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, "boxen": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", @@ -8106,6 +8508,11 @@ "yargs-parser": "^20.2.7" } }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" + }, "cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -8205,12 +8612,66 @@ "is-regex": "^1.0.3" } }, + "chardet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.4.0.tgz", + "integrity": "sha512-NpwMDdSIprbYx1CLnfbxEIarI0Z+s9MssEgggMNheGM+WD68yOhV7IEA/3r6tr0yTRgQD0HuZJDw32s99i6L+A==" + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "requires": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "dependencies": { + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + } + } + }, + "cheerio-select": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", + "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "requires": { + "css-select": "^4.1.3", + "css-what": "^5.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0", + "domutils": "^2.7.0" + } + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -8265,7 +8726,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -8428,6 +8888,23 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, + "css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -8619,7 +9096,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", - "dev": true, "requires": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -8629,16 +9105,14 @@ "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" } } }, "domelementtype": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", - "dev": true + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" }, "domexception": { "version": "4.0.0", @@ -8653,7 +9127,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", - "dev": true, "requires": { "domelementtype": "^2.2.0" } @@ -8662,7 +9135,6 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, "requires": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -9699,8 +10171,7 @@ "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "http-errors": { "version": "1.8.1", @@ -9725,6 +10196,15 @@ "debug": "4" } }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -9745,7 +10225,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -10310,8 +10789,7 @@ "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", @@ -10440,6 +10918,14 @@ "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "requires": { + "boolbase": "^1.0.0" + } + }, "nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", @@ -10474,6 +10960,127 @@ "wrappy": "1" } }, + "open-graph-scraper": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/open-graph-scraper/-/open-graph-scraper-4.11.0.tgz", + "integrity": "sha512-APlovc5JOWXXUIyNc/1o340ik5d7RA/0TBTRMxpOMvsUXX4/uyjpHQijBUU7NxhjJpDHpc3d/lg7KcHBaSpKEw==", + "requires": { + "chardet": "^1.4.0", + "cheerio": "^1.0.0-rc.10", + "got": "^11.8.2", + "iconv-lite": "^0.6.3", + "validator": "^13.7.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", + "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==" + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "11.8.3", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz", + "integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==", + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "keyv": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.1.0.tgz", + "integrity": "sha512-YsY3wr6HabE11/sscee+3nZ03XjvkrPWGouAmJFBdZoK92wiOlJCzI5/sDEIKdJhdhHO144ei45U9gXfbu14Uw==", + "requires": { + "json-buffer": "3.0.1" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "requires": { + "lowercase-keys": "^2.0.0" + } + } + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -10562,8 +11169,15 @@ "parse5": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "requires": { + "parse5": "^6.0.1" + } }, "path-exists": { "version": "4.0.0", @@ -11008,8 +11622,7 @@ "quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" }, "range-parser": { "version": "1.2.1", @@ -11113,6 +11726,11 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -11195,8 +11813,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "saxes": { "version": "5.0.1", @@ -11803,6 +12420,11 @@ } } }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 65b88f7..34e66ae 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "fastify-cors": "^6.0.2", "fastify-helmet": "^7.0.1", "fastify-static": "^4.5.0", + "open-graph-scraper": "^4.11.0", "vue": "^3.2.27", "vue-i18n": "^9.2.0-beta.30", "vue-router": "^4.0.12" @@ -32,6 +33,7 @@ "devDependencies": { "@rushstack/eslint-patch": "^1.1.0", "@types/node": "^16.11.21", + "@types/open-graph-scraper": "^4.8.1", "@vitejs/plugin-vue": "^2.0.1", "@vue/eslint-config-prettier": "^7.0.0", "@vue/eslint-config-typescript": "^10.0.0", @@ -42,6 +44,7 @@ "eslint": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-vue": "^8.2.0", + "husky": "^7.0.0", "jsdom": "^19.0.0", "nodemon": "^2.0.15", "pino-pretty": "^7.5.1", @@ -53,7 +56,6 @@ "typescript": "~4.5.4", "vite": "^2.7.13", "vitest": "^0.1.23", - "vue-tsc": "^0.29.8", - "husky": "^7.0.0" + "vue-tsc": "^0.29.8" } } diff --git a/src/api/routes/index.ts b/src/api/routes/index.ts index 222f45c..42b8442 100644 --- a/src/api/routes/index.ts +++ b/src/api/routes/index.ts @@ -1,11 +1,13 @@ import { FastifyInstance } from 'fastify' import { default as wishlistRoute } from './wishlist/' +import { default as utilsRoute } from './utils/' export default { register: (app: FastifyInstance) => { return app.register( async (app) => { await app.register(wishlistRoute, { prefix: '/wishlist' }) + await app.register(utilsRoute, { prefix: '/utils' }) }, { prefix: '/api' } ) diff --git a/src/api/routes/utils/index.ts b/src/api/routes/utils/index.ts new file mode 100644 index 0000000..df5609d --- /dev/null +++ b/src/api/routes/utils/index.ts @@ -0,0 +1,6 @@ +import { FastifyInstance } from 'fastify' +import { fetchOpenGraph } from './opengraph' + +export default async (app: FastifyInstance) => { + await app.route(fetchOpenGraph) +} diff --git a/src/api/routes/utils/opengraph.ts b/src/api/routes/utils/opengraph.ts new file mode 100644 index 0000000..36f3519 --- /dev/null +++ b/src/api/routes/utils/opengraph.ts @@ -0,0 +1,48 @@ +import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify' +import ogs from 'open-graph-scraper' + +interface fetchOpenGraphRequest extends FastifyRequest { + query: { + url: string + } +} + +export const fetchOpenGraph = { + method: 'GET', + url: '/fetch-open-graph', + schema: { + querystring: { + type: 'object', + required: ['url'], + properties: { + url: { type: 'string', format: 'uri' }, + }, + }, + response: { + 200: { + type: 'object', + properties: { + title: { type: 'string' }, + description: { type: 'string' }, + image: { type: 'string' }, + }, + }, + }, + }, + handler: async (request: fetchOpenGraphRequest, reply: FastifyReply) => { + const { result } = await ogs({ + url: request.query.url, + }) + request.log.debug(result) + if (result.success) { + const image = + //@ts-expect-error: url not defined + result.ogImage && result.ogImage.url ? result.ogImage.url : '' + reply.send({ + title: result.ogTitle || '', + description: result.ogDescription || '', + image, + }) + } + }, +} From aa623f8bee3ac5b775100b7defa8dc6adf98e57e Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 15:46:17 +0100 Subject: [PATCH 018/124] generate prelease docker image Signed-off-by: Benny Samir Hierl --- .github/workflows/ci-pre-release.yml | 85 ++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 .github/workflows/ci-pre-release.yml diff --git a/.github/workflows/ci-pre-release.yml b/.github/workflows/ci-pre-release.yml new file mode 100644 index 0000000..5c79e33 --- /dev/null +++ b/.github/workflows/ci-pre-release.yml @@ -0,0 +1,85 @@ +name: 'CI' + +on: + push: + branches: + - 'release/**' + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up NodeJs + uses: actions/setup-node@v2 + with: + node-version: 16 + - name: Install dependencies + run: npm ci + - name: Linter + run: npm run lint + - name: Typecheck + run: npm run typecheck + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up NodeJs + uses: actions/setup-node@v2 + with: + node-version: 16 + - name: Install dependencies + run: npm ci + - name: Unit tests + run: npm run test:unit:ci + docker: + runs-on: ubuntu-latest + needs: + - lint + - test + steps: + - name: Checkout + uses: actions/checkout@v2 + + - uses: actions/setup-node@v2 + with: + node-version: 16 + - name: Prepare + id: prep + run: | + DOCKER_IMAGE=${{ secrets.DOCKER_USERNAME }}/${GITHUB_REPOSITORY#*/} + VERSION=$(node -e "console.log(require('./package.json').version);") + + TAGS="${DOCKER_IMAGE}:${VERSION}-pre" + + echo ::set-output name=tags::${TAGS} + echo ::set-output name=docker_image::${DOCKER_IMAGE} + + - name: Set up QEMU + uses: docker/setup-qemu-action@master + with: + platforms: all + + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@master + + - name: Available platforms + run: echo ${{ steps.buildx.outputs.platforms }} + + - name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build + uses: docker/build-push-action@v2 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + file: ./Dockerfile + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.prep.outputs.tags }} From f997045b48149134058c7277dbaa24e07405c5d2 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 16:16:37 +0100 Subject: [PATCH 019/124] fix docker build issue Signed-off-by: Benny Samir Hierl --- Dockerfile | 2 +- src/api/app.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 60934eb..0b912ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,4 +32,4 @@ COPY --from=builder /app/dist /app EXPOSE 5000 -ENTRYPOINT npx prisma migrate deploy && node server.js +ENTRYPOINT npx prisma migrate deploy && node api/server.js diff --git a/src/api/app.ts b/src/api/app.ts index 52ab408..703ccd4 100644 --- a/src/api/app.ts +++ b/src/api/app.ts @@ -7,9 +7,8 @@ const build = async (opts = {}) => { const app = await initApp(opts) routes.register(app) - app.register(staticFiles, { - root: path.join(__dirname, 'static'), + root: path.join(__dirname, '..', 'static'), }) app.setNotFoundHandler((req, res) => { res.sendFile('index.html') From b653faceac00c7743f11d3426117f170e6dbeb77 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 18:08:52 +0100 Subject: [PATCH 020/124] fix overlapping description issue Signed-off-by: Benny Samir Hierl --- package-lock.json | 369 ++++++++--------------------- package.json | 1 + src/api/config/schemas/wishlist.ts | 2 +- src/components/WishlistItem.vue | 18 +- tailwind.config.js | 4 +- 5 files changed, 120 insertions(+), 274 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9f6c72b..3b5d796 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "version": "1.0.0", "dependencies": { "@prisma/client": "^3.8.1", + "@tailwindcss/line-clamp": "^0.3.1", "axios": "^0.25.0", "fastify": "^3.27.0", "fastify-compress": "^4.0.1", @@ -52,7 +53,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, "dependencies": { "@babel/highlight": "^7.16.7" }, @@ -64,7 +64,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -73,7 +72,6 @@ "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -87,7 +85,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -99,7 +96,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -113,7 +109,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -121,14 +116,12 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -137,7 +130,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, "engines": { "node": ">=4" } @@ -146,7 +138,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -190,7 +181,7 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 12" } @@ -199,7 +190,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-consumer": "0.8.0" }, @@ -360,7 +351,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -373,7 +363,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "engines": { "node": ">= 8" } @@ -382,7 +371,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -450,6 +438,14 @@ "node": ">=6" } }, + "node_modules/@tailwindcss/line-clamp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz", + "integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==", + "peerDependencies": { + "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -463,25 +459,25 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "devOptional": true }, "node_modules/@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "devOptional": true }, "node_modules/@types/cacheable-request": { "version": "6.0.2", @@ -553,8 +549,7 @@ "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "node_modules/@types/responselike": { "version": "1.0.0", @@ -1017,7 +1012,7 @@ "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -1060,7 +1055,6 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, "dependencies": { "acorn": "^7.0.0", "acorn-walk": "^7.0.0", @@ -1071,7 +1065,6 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -1083,7 +1076,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -1137,7 +1129,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -1152,7 +1143,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1169,8 +1159,7 @@ "node_modules/arg": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" }, "node_modules/argparse": { "version": "2.0.1", @@ -1321,7 +1310,6 @@ "version": "10.4.2", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", - "dev": true, "dependencies": { "browserslist": "^4.19.1", "caniuse-lite": "^1.0.30001297", @@ -1384,7 +1372,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, "engines": { "node": ">=8" } @@ -1429,7 +1416,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -1447,7 +1433,6 @@ "version": "4.19.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", - "dev": true, "dependencies": { "caniuse-lite": "^1.0.30001286", "electron-to-chromium": "^1.4.17", @@ -1566,7 +1551,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -1587,7 +1571,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "engines": { "node": ">= 6" } @@ -1596,7 +1579,6 @@ "version": "1.0.30001301", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz", "integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==", - "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/browserslist" @@ -1623,7 +1605,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1728,7 +1709,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -1755,7 +1735,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -1804,7 +1783,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -1815,8 +1793,7 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/colorette": { "version": "2.0.16", @@ -1963,7 +1940,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -1979,7 +1955,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -2034,7 +2010,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -2185,8 +2160,7 @@ "node_modules/defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, "node_modules/delayed-stream": { "version": "1.0.0", @@ -2214,7 +2188,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, "dependencies": { "acorn-node": "^1.6.1", "defined": "^1.0.0", @@ -2230,14 +2203,13 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.3.1" } @@ -2257,8 +2229,7 @@ "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/doctrine": { "version": "3.0.0", @@ -2395,8 +2366,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.51", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.51.tgz", - "integrity": "sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==", - "dev": true + "integrity": "sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==" }, "node_modules/emmet": { "version": "2.3.5", @@ -2454,7 +2424,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -2713,7 +2682,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -3120,7 +3088,6 @@ "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3136,7 +3103,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -3298,7 +3264,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3422,7 +3387,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", - "dev": true, "engines": { "node": "*" }, @@ -3479,7 +3443,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -3492,8 +3455,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/functional-red-black-tree": { "version": "1.0.1", @@ -3568,7 +3530,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -3658,7 +3619,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -3670,7 +3630,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -3862,7 +3821,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -3941,14 +3899,12 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -3972,7 +3928,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -4011,7 +3966,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4029,7 +3983,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -4077,7 +4030,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -4230,8 +4182,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -4300,8 +4251,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -4408,7 +4358,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", - "dev": true, "engines": { "node": ">=10" } @@ -4416,8 +4365,7 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/local-pkg": { "version": "0.4.1", @@ -4516,13 +4464,12 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "engines": { "node": ">= 8" } @@ -4531,7 +4478,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, "dependencies": { "braces": "^3.0.1", "picomatch": "^2.2.3" @@ -4593,8 +4539,7 @@ "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "node_modules/minipass": { "version": "3.1.6", @@ -4641,8 +4586,7 @@ "node_modules/node-releases": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, "node_modules/nodemon": { "version": "2.0.15", @@ -4731,7 +4675,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4740,7 +4683,6 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4784,7 +4726,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "dev": true, "engines": { "node": ">= 6" } @@ -5074,7 +5015,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -5086,7 +5026,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -5144,14 +5083,12 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -5217,7 +5154,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -5310,7 +5246,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, "dependencies": { "camelcase-css": "^2.0.1" }, @@ -5329,7 +5264,6 @@ "version": "5.0.6", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", - "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.6" }, @@ -5348,7 +5282,6 @@ "version": "6.0.9", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -5360,8 +5293,7 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/prelude-ls": { "version": "1.2.1", @@ -5718,7 +5650,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -5789,7 +5720,6 @@ "version": "1.21.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.1.tgz", "integrity": "sha512-lfEImVbnolPuaSZuLQ52cAxPBHeI77sPwCOWRdy12UG/CNa8an7oBHH1R+Fp1/mUqSJi4c8TIP6FOIPSZAUrEQ==", - "dev": true, "dependencies": { "is-core-module": "^2.8.0", "path-parse": "^1.0.7", @@ -5811,7 +5741,6 @@ "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" } @@ -5881,7 +5810,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -6214,7 +6142,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6226,7 +6153,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -6244,7 +6170,6 @@ "version": "3.0.15", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.15.tgz", "integrity": "sha512-bT2iy7FtjwgsXik4ZoJnHXR+SRCiGR1W95fVqpLZebr64m4ahwUwRbIAc5w5+2fzr1YF4Ct2eI7dojMRRl8sVQ==", - "dev": true, "dependencies": { "arg": "^5.0.1", "chalk": "^4.1.2", @@ -6283,7 +6208,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.1.tgz", "integrity": "sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg==", - "dev": true, "dependencies": { "lilconfig": "^2.0.4", "yaml": "^1.10.2" @@ -6405,7 +6329,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -6478,7 +6401,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", - "dev": true, + "devOptional": true, "dependencies": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", @@ -6519,7 +6442,7 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.0" } @@ -6528,7 +6451,7 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true }, "node_modules/tslib": { "version": "1.14.1", @@ -6597,7 +6520,7 @@ "version": "4.5.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7315,7 +7238,6 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, "engines": { "node": ">= 6" } @@ -7351,7 +7273,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -7373,7 +7295,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, "requires": { "@babel/highlight": "^7.16.7" } @@ -7381,14 +7302,12 @@ "@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" }, "@babel/highlight": { "version": "7.16.10", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -7399,7 +7318,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -7408,7 +7326,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -7419,7 +7336,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -7427,26 +7343,22 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -7480,13 +7392,13 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", - "dev": true + "devOptional": true }, "@cspotcode/source-map-support": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", - "dev": true, + "devOptional": true, "requires": { "@cspotcode/source-map-consumer": "0.8.0" } @@ -7619,7 +7531,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -7628,14 +7539,12 @@ "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" }, "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -7681,6 +7590,12 @@ "defer-to-connect": "^1.0.1" } }, + "@tailwindcss/line-clamp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz", + "integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==", + "requires": {} + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -7691,25 +7606,25 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", - "dev": true + "devOptional": true }, "@tsconfig/node12": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", - "dev": true + "devOptional": true }, "@tsconfig/node14": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", - "dev": true + "devOptional": true }, "@tsconfig/node16": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", - "dev": true + "devOptional": true }, "@types/cacheable-request": { "version": "6.0.2", @@ -7781,8 +7696,7 @@ "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "@types/responselike": { "version": "1.0.0", @@ -8136,7 +8050,7 @@ "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true + "devOptional": true }, "acorn-globals": { "version": "6.0.0", @@ -8167,7 +8081,6 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, "requires": { "acorn": "^7.0.0", "acorn-walk": "^7.0.0", @@ -8177,16 +8090,14 @@ "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" } } }, "acorn-walk": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" }, "agent-base": { "version": "6.0.2", @@ -8227,7 +8138,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -8236,7 +8146,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -8250,8 +8159,7 @@ "arg": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", - "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", - "dev": true + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" }, "argparse": { "version": "2.0.1", @@ -8374,7 +8282,6 @@ "version": "10.4.2", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", - "dev": true, "requires": { "browserslist": "^4.19.1", "caniuse-lite": "^1.0.30001297", @@ -8420,8 +8327,7 @@ "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, "boolbase": { "version": "1.0.0", @@ -8457,7 +8363,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -8472,7 +8377,6 @@ "version": "4.19.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001286", "electron-to-chromium": "^1.4.17", @@ -8558,8 +8462,7 @@ "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "camelcase": { "version": "6.3.0", @@ -8570,14 +8473,12 @@ "camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" }, "caniuse-lite": { "version": "1.0.30001301", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz", - "integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==", - "dev": true + "integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==" }, "chai": { "version": "4.3.4", @@ -8597,7 +8498,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -8676,7 +8576,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -8692,7 +8591,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -8734,7 +8632,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -8742,8 +8639,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "colorette": { "version": "2.0.16", @@ -8856,7 +8752,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, "requires": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -8869,7 +8764,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "devOptional": true }, "cross-spawn": { "version": "7.0.3", @@ -8908,8 +8803,7 @@ "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" }, "cssom": { "version": "0.5.0", @@ -9020,8 +8914,7 @@ "defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, "delayed-stream": { "version": "1.0.0", @@ -9043,7 +8936,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, "requires": { "acorn-node": "^1.6.1", "defined": "^1.0.0", @@ -9053,14 +8945,13 @@ "didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "devOptional": true }, "dir-glob": { "version": "3.0.1", @@ -9074,8 +8965,7 @@ "dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "doctrine": { "version": "3.0.0", @@ -9181,8 +9071,7 @@ "electron-to-chromium": { "version": "1.4.51", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.51.tgz", - "integrity": "sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==", - "dev": true + "integrity": "sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==" }, "emmet": { "version": "2.3.5", @@ -9228,7 +9117,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } @@ -9380,8 +9268,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-goat": { "version": "2.1.1", @@ -9675,7 +9562,6 @@ "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -9688,7 +9574,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -9837,7 +9722,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -9922,8 +9806,7 @@ "fraction.js": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", - "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==", - "dev": true + "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==" }, "fresh": { "version": "0.5.2", @@ -9972,14 +9855,12 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -10036,7 +9917,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "requires": { "is-glob": "^4.0.3" } @@ -10102,7 +9982,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -10110,8 +9989,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-symbols": { "version": "1.0.2", @@ -10245,7 +10123,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -10300,14 +10177,12 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "requires": { "binary-extensions": "^2.0.0" } @@ -10325,7 +10200,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -10356,8 +10230,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -10369,7 +10242,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -10398,8 +10270,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-obj": { "version": "2.0.0", @@ -10516,8 +10387,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "4.1.0", @@ -10572,8 +10442,7 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema-traverse": { "version": "0.4.1", @@ -10668,14 +10537,12 @@ "lilconfig": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", - "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", - "dev": true + "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==" }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "local-pkg": { "version": "0.4.1", @@ -10749,19 +10616,17 @@ "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "devOptional": true }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.2.3" @@ -10802,8 +10667,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minipass": { "version": "3.1.6", @@ -10838,8 +10702,7 @@ "node-releases": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, "nodemon": { "version": "2.0.15", @@ -10903,14 +10766,12 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-range": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" }, "normalize-url": { "version": "4.5.1", @@ -10941,8 +10802,7 @@ "object-hash": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "dev": true + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" }, "on-finished": { "version": "2.3.0", @@ -11149,7 +11009,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "requires": { "callsites": "^3.0.0" } @@ -11158,7 +11017,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -11201,14 +11059,12 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "pathval": { "version": "1.1.1", @@ -11269,8 +11125,7 @@ "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pino": { "version": "6.13.4", @@ -11346,7 +11201,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", - "dev": true, "requires": { "camelcase-css": "^2.0.1" } @@ -11355,7 +11209,6 @@ "version": "5.0.6", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", - "dev": true, "requires": { "postcss-selector-parser": "^6.0.6" } @@ -11364,7 +11217,6 @@ "version": "6.0.9", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", - "dev": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -11373,8 +11225,7 @@ "postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "prelude-ls": { "version": "1.2.1", @@ -11669,7 +11520,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -11719,7 +11569,6 @@ "version": "1.21.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.1.tgz", "integrity": "sha512-lfEImVbnolPuaSZuLQ52cAxPBHeI77sPwCOWRdy12UG/CNa8an7oBHH1R+Fp1/mUqSJi4c8TIP6FOIPSZAUrEQ==", - "dev": true, "requires": { "is-core-module": "^2.8.0", "path-parse": "^1.0.7", @@ -11734,8 +11583,7 @@ "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 + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, "responselike": { "version": "1.0.2", @@ -11783,7 +11631,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "requires": { "queue-microtask": "^1.2.2" } @@ -12042,7 +11889,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -12050,8 +11896,7 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "symbol-tree": { "version": "3.2.4", @@ -12063,7 +11908,6 @@ "version": "3.0.15", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.15.tgz", "integrity": "sha512-bT2iy7FtjwgsXik4ZoJnHXR+SRCiGR1W95fVqpLZebr64m4ahwUwRbIAc5w5+2fzr1YF4Ct2eI7dojMRRl8sVQ==", - "dev": true, "requires": { "arg": "^5.0.1", "chalk": "^4.1.2", @@ -12091,7 +11935,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.1.tgz", "integrity": "sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg==", - "dev": true, "requires": { "lilconfig": "^2.0.4", "yaml": "^1.10.2" @@ -12184,7 +12027,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -12239,7 +12081,7 @@ "version": "10.4.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", - "dev": true, + "devOptional": true, "requires": { "@cspotcode/source-map-support": "0.7.0", "@tsconfig/node10": "^1.0.7", @@ -12259,13 +12101,13 @@ "version": "8.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true + "devOptional": true }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "devOptional": true } } }, @@ -12318,7 +12160,7 @@ "version": "4.5.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", - "dev": true + "devOptional": true }, "undefsafe": { "version": "2.0.5", @@ -12851,8 +12693,7 @@ "yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" }, "yargs": { "version": "16.2.0", @@ -12879,7 +12720,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "devOptional": true }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index 260bbf5..3820d0c 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ }, "dependencies": { "@prisma/client": "^3.8.1", + "@tailwindcss/line-clamp": "^0.3.1", "axios": "^0.25.0", "fastify": "^3.27.0", "fastify-compress": "^4.0.1", diff --git a/src/api/config/schemas/wishlist.ts b/src/api/config/schemas/wishlist.ts index 3e575fc..2bbdea3 100644 --- a/src/api/config/schemas/wishlist.ts +++ b/src/api/config/schemas/wishlist.ts @@ -19,7 +19,7 @@ export const wishlistItemResponseSchema = { title: { type: 'string' }, url: { type: 'string' }, imageSrc: { type: 'string' }, - description: { type: 'string' }, + description: { type: 'string', maxLength: 300 }, comment: { type: 'string' }, bought: { type: 'boolean' }, wishlistId: { type: 'string' }, diff --git a/src/components/WishlistItem.vue b/src/components/WishlistItem.vue index f2fd274..0f0421d 100644 --- a/src/components/WishlistItem.vue +++ b/src/components/WishlistItem.vue @@ -34,7 +34,17 @@ const { t } = useI18n()

{{ title }}

-

{{ description }}

+

+ {{ description }} +

+
+
+ {{ t('components.wishlist-item.bought-button.text') }}
- {{ t('components.wishlist-item.bought-button.text') }}
diff --git a/tailwind.config.js b/tailwind.config.js index 5f06cac..164990f 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,8 +1,8 @@ -// eslint-disable-next-line no-undef +/* eslint-disable no-undef */ module.exports = { content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], theme: { extend: {}, }, - plugins: [], + plugins: [require('@tailwindcss/line-clamp')], } From fb4842d007c7b451b2bbd67bba1f9333d7b5a65e Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Sun, 6 Feb 2022 18:11:50 +0100 Subject: [PATCH 021/124] comment field removed from wishlist items Signed-off-by: Benny Samir Hierl --- .../migration.sql | 23 +++++++++++++++++++ prisma/schema.prisma | 1 - prisma/seed.ts | 1 - src/api/config/schemas/wishlist.ts | 2 -- src/components/WishlistItem.vue | 1 - src/types.ts | 1 - src/views/DetailView.vue | 1 - 7 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 prisma/migrations/20220206171013_comment_field_removed/migration.sql diff --git a/prisma/migrations/20220206171013_comment_field_removed/migration.sql b/prisma/migrations/20220206171013_comment_field_removed/migration.sql new file mode 100644 index 0000000..2d75752 --- /dev/null +++ b/prisma/migrations/20220206171013_comment_field_removed/migration.sql @@ -0,0 +1,23 @@ +/* + Warnings: + + - You are about to drop the column `comment` on the `Item` table. All the data in the column will be lost. + +*/ +-- RedefineTables +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Item" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "title" TEXT NOT NULL, + "url" TEXT NOT NULL DEFAULT '', + "imageSrc" TEXT NOT NULL DEFAULT '', + "description" TEXT NOT NULL, + "bought" BOOLEAN NOT NULL DEFAULT false, + "wishlistId" TEXT NOT NULL, + CONSTRAINT "Item_wishlistId_fkey" FOREIGN KEY ("wishlistId") REFERENCES "Wishlist" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); +INSERT INTO "new_Item" ("bought", "description", "id", "imageSrc", "title", "url", "wishlistId") SELECT "bought", "description", "id", "imageSrc", "title", "url", "wishlistId" FROM "Item"; +DROP TABLE "Item"; +ALTER TABLE "new_Item" RENAME TO "Item"; +PRAGMA foreign_key_check; +PRAGMA foreign_keys=ON; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 492ab53..adb8d25 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -25,7 +25,6 @@ model Item { url String @default("") imageSrc String @default("") description String - comment String @default("") bought Boolean @default(false) wishlist Wishlist @relation(fields: [wishlistId], references: [id]) wishlistId String diff --git a/prisma/seed.ts b/prisma/seed.ts index b404659..b03b616 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -18,7 +18,6 @@ const wishlistData: Prisma.WishlistCreateInput[] = [ 'https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1', description: 'Cute goldfish and fry, build-and-display BrickHeadz™ model', - comment: '', }, ], }, diff --git a/src/api/config/schemas/wishlist.ts b/src/api/config/schemas/wishlist.ts index 2bbdea3..06d7b63 100644 --- a/src/api/config/schemas/wishlist.ts +++ b/src/api/config/schemas/wishlist.ts @@ -7,7 +7,6 @@ export const wishlistItemRequestSchema = { url: { type: 'string' }, imageSrc: { type: 'string' }, description: { type: 'string' }, - comment: { type: 'string' }, bought: { type: 'boolean' }, }, } @@ -20,7 +19,6 @@ export const wishlistItemResponseSchema = { url: { type: 'string' }, imageSrc: { type: 'string' }, description: { type: 'string', maxLength: 300 }, - comment: { type: 'string' }, bought: { type: 'boolean' }, wishlistId: { type: 'string' }, }, diff --git a/src/components/WishlistItem.vue b/src/components/WishlistItem.vue index 0f0421d..c270197 100644 --- a/src/components/WishlistItem.vue +++ b/src/components/WishlistItem.vue @@ -9,7 +9,6 @@ defineProps<{ image: string url?: string description: string - comment?: string }>() const { t } = useI18n() diff --git a/src/types.ts b/src/types.ts index 9962ef6..7b0df49 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,7 +4,6 @@ export interface WishlistItem { url: string imageSrc: string description: string - comment: string bought: boolean wishlistId: boolean } diff --git a/src/views/DetailView.vue b/src/views/DetailView.vue index 73cf606..7429148 100644 --- a/src/views/DetailView.vue +++ b/src/views/DetailView.vue @@ -58,7 +58,6 @@ const bought = async (item: WishlistItemType): Promise => { :url="item.url" :image="item.imageSrc" :description="item.description" - :comment="item.comment" @bought="bought(item)" /> From 1c18ddfcc31245ccf6419ffbdcca6be65263a698 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Mon, 7 Feb 2022 15:40:09 +0100 Subject: [PATCH 022/124] small change for tile Signed-off-by: Benny Samir Hierl --- src/components/Tile.vue | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/Tile.vue b/src/components/Tile.vue index 067d1be..fd84731 100644 --- a/src/components/Tile.vue +++ b/src/components/Tile.vue @@ -10,9 +10,14 @@ defineProps<{
{{ title }}
+ From 56f8ccc13cf6c9be5d85c9d79f9cf60b60ca7b8b Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Mon, 7 Feb 2022 19:19:12 +0100 Subject: [PATCH 023/124] small ui/ux improvments --- src/App.vue | 56 ++++++++++++++--------------- src/components/icons/IconNoGift.vue | 8 +++++ src/config/locales/de-DE.json | 5 +++ src/config/locales/en-US.json | 5 +++ src/views/DetailView.vue | 16 +++++++-- 5 files changed, 59 insertions(+), 31 deletions(-) create mode 100644 src/components/icons/IconNoGift.vue diff --git a/src/App.vue b/src/App.vue index 186e5fb..7254361 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,33 +1,31 @@ From 1a2cc6dfeb50e4e6c05c7e2f86a1470a79274f9c Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Mon, 7 Feb 2022 19:20:13 +0100 Subject: [PATCH 024/124] margin on wishlist overview changed to 4 --- src/views/HomeView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index ccc490d..17e5477 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -19,7 +19,7 @@ await fetch() From e0abc98b19437ad320947f4e97a36f32c9d919d1 Mon Sep 17 00:00:00 2001 From: Benny Samir Hierl Date: Mon, 7 Feb 2022 20:14:55 +0100 Subject: [PATCH 025/124] feature: dark-mode --- index.html | 5 +- package-lock.json | 98 ++++++++++++++++++++++++++ package.json | 1 + src/App.vue | 58 ++++++++------- src/components/BaseButton.vue | 2 +- src/components/Header.vue | 15 ++++ src/components/Tile.vue | 2 +- src/components/WishlistItem.vue | 4 +- src/components/icons/IconLightDark.vue | 8 +++ src/components/icons/index.ts | 2 + src/views/DetailView.vue | 4 +- src/views/HomeView.vue | 10 ++- tailwind.config.js | 1 + 13 files changed, 170 insertions(+), 40 deletions(-) create mode 100644 src/components/Header.vue create mode 100644 src/components/icons/IconLightDark.vue diff --git a/index.html b/index.html index f05e3fb..d7a8b6c 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,10 @@ Wunschlisten -
+
diff --git a/package-lock.json b/package-lock.json index 3b5d796..78d1c88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "dependencies": { "@prisma/client": "^3.8.1", "@tailwindcss/line-clamp": "^0.3.1", + "@vueuse/core": "^7.5.5", "axios": "^0.25.0", "fastify": "^3.27.0", "fastify-compress": "^4.0.1", @@ -991,6 +992,78 @@ "vue": "^3.0.1" } }, + "node_modules/@vueuse/core": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-7.5.5.tgz", + "integrity": "sha512-RBDqmIoGfak4h3xdXa/Av+ibkb8NY044wEy6+PG2FAWNaID8/FkqmSFjbxogrbmpSX1yZ1PBHrM8DUp/FrIpbg==", + "dependencies": { + "@vueuse/shared": "7.5.5", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.1.0", + "vue": "^2.6.0 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core/node_modules/@vueuse/shared": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-7.5.5.tgz", + "integrity": "sha512-mzzTsotHQRPnPAChy8iCv6ek/90CKYhAFyMRgNsMxpT0afZJkbMO/X0OaOu/1NuGbgb8UVjlsWKmCUgKTOF5hA==", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.1.0", + "vue": "^2.6.0 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.1.tgz", + "integrity": "sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", @@ -8029,6 +8102,31 @@ "dev": true, "requires": {} }, + "@vueuse/core": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-7.5.5.tgz", + "integrity": "sha512-RBDqmIoGfak4h3xdXa/Av+ibkb8NY044wEy6+PG2FAWNaID8/FkqmSFjbxogrbmpSX1yZ1PBHrM8DUp/FrIpbg==", + "requires": { + "@vueuse/shared": "7.5.5", + "vue-demi": "*" + }, + "dependencies": { + "@vueuse/shared": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-7.5.5.tgz", + "integrity": "sha512-mzzTsotHQRPnPAChy8iCv6ek/90CKYhAFyMRgNsMxpT0afZJkbMO/X0OaOu/1NuGbgb8UVjlsWKmCUgKTOF5hA==", + "requires": { + "vue-demi": "*" + } + }, + "vue-demi": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.1.tgz", + "integrity": "sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw==", + "requires": {} + } + } + }, "abab": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", diff --git a/package.json b/package.json index 3820d0c..c37f671 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dependencies": { "@prisma/client": "^3.8.1", "@tailwindcss/line-clamp": "^0.3.1", + "@vueuse/core": "^7.5.5", "axios": "^0.25.0", "fastify": "^3.27.0", "fastify-compress": "^4.0.1", diff --git a/src/App.vue b/src/App.vue index 7254361..bfce685 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,34 +1,38 @@