diff --git a/03_source/cms_backend/package.json b/03_source/cms_backend/package.json index dafd392..045663a 100644 --- a/03_source/cms_backend/package.json +++ b/03_source/cms_backend/package.json @@ -5,6 +5,7 @@ "description": "Mock server & assets", "private": true, "scripts": { + "dev:check": "yarn tsc:w", "dev": "next dev -p 7272 -H 0.0.0.0", "start": "next start -p 7272 -H 0.0.0.0", "build": "next build", @@ -31,7 +32,9 @@ "db:push": "prisma db push --force-reset", "db:push:w": "npx nodemon --delay 1 --watch prisma --ext \"ts,tsx,prisma\" --exec \"yarn db:push && yarn seed\"", "db:studio": "prisma studio", - "db:studio:w": "npx nodemon --delay 1 --watch prisma --ext \"prisma\" --exec \"yarn db:studio\"" + "db:studio:w": "npx nodemon --delay 1 --watch prisma --ext \"prisma\" --exec \"yarn db:studio\"", + "db:dev": "yarn db:push && yarn seed && yarn dev", + "db:dev:w": "npx nodemon --delay 1 --ext \"ts,tsx,prisma\" --exec \"yarn db:dev\"" }, "engines": { "node": ">=20" @@ -68,6 +71,7 @@ "@types/react": "^18.3.20", "@types/react-dom": "^18.3.5", "@typescript-eslint/parser": "^8.28.0", + "concurrently": "^9.1.2", "eslint": "^9.23.0", "eslint-import-resolver-typescript": "^4.2.2", "eslint-plugin-import": "^2.31.0", diff --git a/03_source/cms_backend/prisma/schema.prisma b/03_source/cms_backend/prisma/schema.prisma index f8d57f5..741a4f1 100644 --- a/03_source/cms_backend/prisma/schema.prisma +++ b/03_source/cms_backend/prisma/schema.prisma @@ -1148,47 +1148,58 @@ model EventReview { // mapped to IEventItem // a.k.a. PartyEvent party-event model EventItem { - id String @id @default(uuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt + id String @id @default(uuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt // - available Int - category String - code String - colors String[] - coverUrl String - description String - gender String[] - images String[] - inventoryType String - name String - newLabel Json - price Float - priceSale Float? - publish String - quantity Int - ratings Json[] - saleLabel Json - sizes String[] - sku String - subDescription String - tags String[] - taxes Float - totalRatings Float - totalReviews Int - totalSold Int + available Int @default(99) + category String + code String @default("") + colors String[] + coverUrl String + description String + gender String[] + images String[] + inventoryType String @default("") + name String @default("") + newLabel Json @default("{}") + price Float @default(999.9) + priceSale Float? @default(111.1) + publish String @default("") + quantity Int @default(99) + ratings Json[] + saleLabel Json @default("{}") + sizes String[] @default([""]) + sku String @default("") + subDescription String @default("") + tags String[] @default([""]) + taxes Float @default(5.0) + totalRatings Float @default(5.0) + totalReviews Int @default(10) + totalSold Int @default(10) // - ageBottom Float - ageTop Float - avatar String[] - currency String - duration_m Float - eventDate DateTime @default(now()) - joinMembers Json[] - location String - title String + ageBottom Float @default(-1) + ageTop Float @default(-1) + avatar String[] @default([""]) + currency String @default("HKD") + capacity Int @default(10) + duration_m Float @default(180) + endDate String? @default("") + eventDate DateTime @default(now()) + isFeatured Boolean @default(false) + joinMembers Json[] @default([]) + location String @default("HK") + organizer String @default("") + registrationDeadline String @default("") + requirements String @default("") + schedule String @default("") + speakers String[] @default([]) + sponsors String[] @default([]) + startDate String? @default("") + status String? @default("") + title String @default("") // - reviews EventReview[] + reviews EventReview[] } model AppLog { diff --git a/03_source/cms_backend/scripts/00_dev.sh b/03_source/cms_backend/scripts/00_dev.sh index f7153d7..60cb2d2 100755 --- a/03_source/cms_backend/scripts/00_dev.sh +++ b/03_source/cms_backend/scripts/00_dev.sh @@ -5,13 +5,13 @@ yarn --dev clear while true; do - yarn db:push - - yarn seed + # yarn db:push + # yarn seed yarn db:studio & - yarn dev + npx nodemon --ext ts,tsx,prisma --exec "yarn dev" + # yarn dev echo "restarting..." sleep 1 diff --git a/03_source/cms_backend/scripts/01_db_push.sh b/03_source/cms_backend/scripts/01_db_push.sh new file mode 100755 index 0000000..317f711 --- /dev/null +++ b/03_source/cms_backend/scripts/01_db_push.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +yarn --dev + +clear + +while true; do + npx nodemon --ext prisma --exec "yarn db:push && yarn seed" + echo "restarting..." + sleep 1 +done diff --git a/03_source/cms_backend/src/app/api/party-event/create/route.ts b/03_source/cms_backend/src/app/api/party-event/create/route.ts new file mode 100644 index 0000000..7a193df --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/create/route.ts @@ -0,0 +1,40 @@ +// src/app/api/party-event/create/route.ts +// +// PURPOSE: +// Create new party event in db +// +// RULES: +// T.B.A. + +import type { NextRequest } from 'next/server'; + +import { STATUS, response, handleError } from 'src/utils/response'; + +import { isDev } from 'src/constants'; +import { createEvent } from 'src/app/services/party-event.service'; + +// ---------------------------------------------------------------------- + +/** ************************************** + * POST - Create PartyEvent + *************************************** */ +export async function POST(req: NextRequest) { + const { partyEventData } = await req.json(); + + try { + if (isDev) { + console.log({ partyEventData }); + } + + const created = await createEvent(partyEventData); + + if (isDev) { + console.log('Event created successfully'); + } + + return response(created, STATUS.OK); + } catch (error) { + console.error('Error creating event:', { partyEventData }); + return handleError('PartyEvent - Create', error); + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/create/test.http b/03_source/cms_backend/src/app/api/party-event/create/test.http new file mode 100644 index 0000000..3b3669f --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/create/test.http @@ -0,0 +1,34 @@ +### + +POST http://localhost:7272/api/party-event/create +Content-Type: application/json + +{ + "partyEventData": { + "title": "Summer Music Festival", + "description": "Annual summer music festival featuring local bands and artists", + "startDate": "2024-07-15T18:00:00Z", + "endDate": "2024-07-15T23:00:00Z", + "location": "Central Park, Hong Kong", + "coverUrl": "", + "images": [ + "data:image/png;base64,C", + "data:image/png;base64,C" + ], + "tags": [ + "Music", + "Festival" + ], + "status": "upcoming", + "capacity": 500, + "price": 150.00, + "organizer": "HK Music Society", + "category": "Music", + "isFeatured": true, + "registrationDeadline": "2024-07-10T00:00:00Z", + "requirements": "Age 18+", + "schedule": "18:00 Doors open\n19:00 First performance\n21:00 Main act", + "speakers": ["DJ Lee", "Band XYZ"], + "sponsors": ["HK Radio", "Music Magazine"] + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/delete/route.ts b/03_source/cms_backend/src/app/api/party-event/delete/route.ts new file mode 100644 index 0000000..5c356d6 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/delete/route.ts @@ -0,0 +1,22 @@ +import type { NextRequest } from 'next/server'; + +import { STATUS, response, handleError } from 'src/utils/response'; + +import { deleteEvent } from 'src/app/services/party-event.service'; + +/** ************************************** + * PATCH - Delete PartyEvent + *************************************** */ +export async function PATCH(req: NextRequest) { + try { + const { eventId } = await req.json(); + + if (!eventId) throw new Error('eventId cannot be null'); + + await deleteEvent(eventId); + + return response({ eventId }, STATUS.OK); + } catch (error) { + return handleError('PartyEvent - Delete', error); + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/delete/test.http b/03_source/cms_backend/src/app/api/party-event/delete/test.http new file mode 100644 index 0000000..a0ca061 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/delete/test.http @@ -0,0 +1,8 @@ +### + +PATCH http://localhost:7272/api/party-event/delete +Content-Type: application/json + +{ + "eventId": "e99f09a7-dd88-49d5-b1c8-1daf80c2d7b01" +} diff --git a/03_source/cms_backend/src/app/api/party-event/details/route.ts b/03_source/cms_backend/src/app/api/party-event/details/route.ts new file mode 100644 index 0000000..590acf6 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/details/route.ts @@ -0,0 +1,56 @@ +// src/app/api/party-event/details/route.ts +// +// PURPOSE: +// Get party event from db by id +// +// RULES: +// T.B.A. + +import type { NextRequest } from 'next/server'; + +import { logger } from 'src/utils/logger'; +import { STATUS, response, handleError } from 'src/utils/response'; + +import { L_INFO, L_ERROR } from 'src/constants'; +import { getEvent } from 'src/app/services/party-event.service'; +import { createAppLog } from 'src/app/services/app-log.service'; + +import { flattenNextjsRequest } from '../../auth/sign-in/flattenNextjsRequest'; + +// ---------------------------------------------------------------------- + +/** + ************************************** + * GET PartyEvent detail + *************************************** + */ +export async function GET(req: NextRequest) { + const debug = { 'req.headers': flattenNextjsRequest(req) }; + + try { + const { searchParams } = req.nextUrl; + + // RULES: eventId must exist + const eventId = searchParams.get('eventId'); + if (!eventId) { + return response({ message: 'Event ID is required!' }, STATUS.BAD_REQUEST); + } + + // NOTE: eventId confirmed exist, run below + const event = await getEvent(eventId); + + if (!event) { + return response({ message: 'Event not found!' }, STATUS.NOT_FOUND); + } + + logger('[PartyEvent] details', event.id); + + createAppLog(L_INFO, 'Get event detail OK', debug); + + return response({ event }, STATUS.OK); + } catch (error) { + createAppLog(L_ERROR, 'event detail error', debug); + + return handleError('PartyEvent - Get details', error); + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/details/test.http b/03_source/cms_backend/src/app/api/party-event/details/test.http new file mode 100644 index 0000000..414b66f --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/details/test.http @@ -0,0 +1,9 @@ +### + +# Get details for a specific party event +GET http://localhost:7272/api/party-event/details?eventId=e99f09a7-dd88-49d5-b1c8-1daf80c2d7b01 + +### + +# Alternative format with different ID +GET http://localhost:7272/api/party-event/details?eventId=evt_987654321 diff --git a/03_source/cms_backend/src/app/api/party-event/helloworld/route.ts b/03_source/cms_backend/src/app/api/party-event/helloworld/route.ts new file mode 100644 index 0000000..d11982a --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/helloworld/route.ts @@ -0,0 +1,16 @@ +import type { NextRequest, NextResponse } from 'next/server'; + +import { STATUS, response, handleError } from 'src/utils/response'; + +/** + *************************************** + * GET - helloworld + *************************************** + */ +export async function GET(req: NextRequest, res: NextResponse) { + try { + return response({ helloworld: 'party-event' }, STATUS.OK); + } catch (error) { + return handleError('Helloworld - Get all', error); + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/helloworld/test.http b/03_source/cms_backend/src/app/api/party-event/helloworld/test.http new file mode 100644 index 0000000..d29b86d --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/helloworld/test.http @@ -0,0 +1,4 @@ +### +GET /api/party-event/helloworld HTTP/1.1 +Host: localhost:7272 + diff --git a/03_source/cms_backend/src/app/api/party-event/list/route.ts b/03_source/cms_backend/src/app/api/party-event/list/route.ts new file mode 100644 index 0000000..c5b7802 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/list/route.ts @@ -0,0 +1,38 @@ +// src/app/api/party-event/list/route.ts +// +// PURPOSE: +// List all party events from db +// +// RULES: +// T.B.A. + +import type { NextRequest } from 'next/server'; + +import { STATUS, response, handleError } from 'src/utils/response'; + +import { L_INFO, L_ERROR } from 'src/constants'; +import { createAppLog } from 'src/app/services/app-log.service'; +import { listEvents } from 'src/app/services/party-event.service'; + +import { flattenNextjsRequest } from '../../auth/sign-in/flattenNextjsRequest'; + +// ---------------------------------------------------------------------- + +/** ************************************** + * GET - PartyEvents list + *************************************** */ +export async function GET(req: NextRequest) { + const debug = { 'req.headers': flattenNextjsRequest(req) }; + + try { + const events = await listEvents(); + + createAppLog(L_INFO, 'party-event list ok', {}); + + return response({ events }, STATUS.OK); + } catch (error) { + createAppLog(L_ERROR, 'party-event list error', debug); + + return handleError('PartyEvent - Get list', error); + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/list/test.http b/03_source/cms_backend/src/app/api/party-event/list/test.http new file mode 100644 index 0000000..788b577 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/list/test.http @@ -0,0 +1,14 @@ +### + +# Basic list all party events +GET http://localhost:7272/api/party-event/list + +### + +# List upcoming party events +GET http://localhost:7272/api/party-event/list?status=upcoming + +### + +# List featured party events +GET http://localhost:7272/api/party-event/list?isFeatured=true diff --git a/03_source/cms_backend/src/app/api/party-event/route.ts b/03_source/cms_backend/src/app/api/party-event/route.ts new file mode 100644 index 0000000..b8feb93 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/route.ts @@ -0,0 +1,75 @@ +import type { NextRequest, NextResponse } from 'next/server'; + +import { STATUS, response, handleError } from 'src/utils/response'; + +import { listEvents, deleteEvent, updateEvent, createEvent } from 'src/app/services/party-event.service'; + +/** + ************************************** + * GET - PartyEvent + *************************************** + */ +export async function GET(req: NextRequest, res: NextResponse) { + try { + const events = await listEvents(); + return response(events, STATUS.OK); + } catch (error) { + return handleError('PartyEvent - Get list', error); + } +} + +/** + *************************************** + * POST - Create PartyEvent + *************************************** + */ +export async function POST(req: NextRequest) { + const OPERATION = 'PartyEvent - Create'; + const { data } = await req.json(); + + try { + const event = await createEvent(data); + return response(OPERATION, STATUS.OK); + } catch (error) { + return handleError(OPERATION, error); + } +} + +/** + *************************************** + * PUT - Update PartyEvent + *************************************** + */ +export async function PUT(req: NextRequest) { + const { searchParams } = req.nextUrl; + const eventId = searchParams.get('eventId'); + const { data } = await req.json(); + + try { + if (!eventId) throw new Error('eventId cannot be null'); + + const result = await updateEvent(eventId, data); + return response(result, STATUS.OK); + } catch (error) { + return handleError('PartyEvent - Update', error); + } +} + +/** + *************************************** + * DELETE - Delete PartyEvent + *************************************** + */ +export async function DELETE(req: NextRequest) { + const { searchParams } = req.nextUrl; + const eventId = searchParams.get('eventId'); + + try { + if (!eventId) throw new Error('eventId cannot be null'); + + await deleteEvent(eventId); + return response({ success: true }, STATUS.OK); + } catch (error) { + return handleError('PartyEvent - Delete', error); + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/search/route.ts b/03_source/cms_backend/src/app/api/party-event/search/route.ts new file mode 100644 index 0000000..710362c --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/search/route.ts @@ -0,0 +1,34 @@ +import type { NextRequest } from 'next/server'; + +import { logger } from 'src/utils/logger'; +import { STATUS, response, handleError } from 'src/utils/response'; +import { IEventItem } from '../update/route'; + +// import { searchEvents } from 'src/app/services/party-event.service'; + +// ---------------------------------------------------------------------- + +/** ************************************** + * GET - Search PartyEvents + *************************************** */ +export async function GET(req: NextRequest) { + try { + const { searchParams } = req.nextUrl; + const query = searchParams.get('query')?.trim().toLowerCase(); + + if (!query) { + return response({ results: [] }, STATUS.OK); + } + + const results: IEventItem[] = []; + // TODO: search party event not implemented + console.log('search party event not implemented'); + // const results = await searchEvents(query); + + logger('[PartyEvent] search-results', results?.length); + + return response({ results }, STATUS.OK); + } catch (error) { + return handleError('PartyEvent - Get search', error); + } +} diff --git a/03_source/cms_backend/src/app/api/party-event/search/test.http b/03_source/cms_backend/src/app/api/party-event/search/test.http new file mode 100644 index 0000000..0fe1196 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/search/test.http @@ -0,0 +1,24 @@ +### + +# Search party events by title +GET http://localhost:7272/api/party-event/search?query=Music + +### + +# Search party events by location +GET http://localhost:7272/api/party-event/search?query=Central+Park + +### + +# Search party events by tag +GET http://localhost:7272/api/party-event/search?query=Festival + +### + +# Combined search with multiple parameters +GET http://localhost:7272/api/party-event/search?query=Summer&location=Hong+Kong&category=Music + +### + +# No results expected +GET http://localhost:7272/api/party-event/search?query=zzzzzz diff --git a/03_source/cms_backend/src/app/api/party-event/update/route.ts b/03_source/cms_backend/src/app/api/party-event/update/route.ts new file mode 100644 index 0000000..9046c37 --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/update/route.ts @@ -0,0 +1,57 @@ +// src/app/api/party-event/update/route.ts +// +// PURPOSE: +// Update party event in db by id +// +// RULES: +// T.B.A. + +import type { NextRequest } from 'next/server'; + +import { STATUS, response, handleError } from 'src/utils/response'; + +import { updateEvent } from 'src/app/services/party-event.service'; + +// ---------------------------------------------------------------------- + +/** ************************************** + * PUT - Update PartyEvent + *************************************** */ +export async function PUT(req: NextRequest) { + const { partyEventData } = await req.json(); + const { id } = partyEventData; + + if (!id) return response({ message: 'id not found' }, STATUS.ERROR); + + try { + const result = await updateEvent(id, partyEventData); + + return response({ result }, STATUS.OK); + } catch (error) { + console.error('Error updating event:', { partyEventData }); + return handleError('PartyEvent - Update', error); + } +} + +export type IEventItem = { + id: string; + title: string; + description: string; + startDate: Date; + endDate: Date; + location: string; + coverUrl: string; + images: string[]; + tags: string[]; + status: string; + capacity: number; + price: number; + organizer: string; + category: string; + isFeatured: boolean; + registrationDeadline: Date; + requirements: string[]; + schedule: string; + speakers: string[]; + sponsors: string[]; +}; diff --git a/03_source/cms_backend/src/app/api/party-event/update/test.http b/03_source/cms_backend/src/app/api/party-event/update/test.http new file mode 100644 index 0000000..a64355c --- /dev/null +++ b/03_source/cms_backend/src/app/api/party-event/update/test.http @@ -0,0 +1,35 @@ +### + +PUT http://localhost:7272/api/party-event/update +Content-Type: application/json + +{ + "partyEventData": { + "id":"e99f09a7-dd88-49d5-b1c8-1daf80c2d7b01", + "title": "Summer Music Festival", + "description": "Annual summer music festival featuring local bands and artists", + "startDate": "2024-07-15T18:00:00Z", + "endDate": "2024-07-15T23:00:00Z", + "location": "Central Park, Hong Kong", + "coverUrl": "", + "images": [ + "data:image/png;base64,C", + "data:image/png;base64,C" + ], + "tags": [ + "Music", + "Festival" + ], + "status": "upcoming", + "capacity": 500, + "price": 150.00, + "organizer": "HK Music Society", + "category": "Music", + "isFeatured": true, + "registrationDeadline": "2024-07-10T00:00:00Z", + "requirements": "Age 18+", + "schedule": "18:00 Doors open\n19:00 First performance\n21:00 Main act", + "speakers": ["DJ Lee", "Band XYZ"], + "sponsors": ["HK Radio", "Music Magazine"] + } +} diff --git a/03_source/cms_backend/src/app/services/party-event.service.ts b/03_source/cms_backend/src/app/services/party-event.service.ts new file mode 100644 index 0000000..5b6111b --- /dev/null +++ b/03_source/cms_backend/src/app/services/party-event.service.ts @@ -0,0 +1,92 @@ +// src/app/services/party-event.service.ts +// +// PURPOSE: +// - Service for handling EventItem (PartyEvent) Record +// + +import type { EventItem } from '@prisma/client'; + +import prisma from '../lib/prisma'; + +type CreateEvent = { + name: string; + title: string; + eventDate: Date; + location: string; + duration_m: number; + ageBottom?: number; + ageTop?: number; + currency?: string; + price?: number; + priceSale?: number; + coverUrl?: string; + images?: string[]; + description?: string; + subDescription?: string; + publish?: string; + category?: string; + tags?: string[]; + joinMembers?: any[]; +}; + +type UpdateEvent = { + name?: string; + title?: string; + eventDate?: Date; + location?: string; + duration_m?: number; + ageBottom?: number; + ageTop?: number; + currency?: string; + price?: number; + priceSale?: number; + coverUrl?: string; + images?: string[]; + description?: string; + subDescription?: string; + publish?: string; + category?: string; + tags?: string[]; + joinMembers?: any[]; +}; + +async function listEvents(): Promise { + return prisma.eventItem.findMany({ + include: { reviews: true }, + }); +} + +async function getEvent(eventId: string): Promise { + return prisma.eventItem.findUnique({ + where: { id: eventId }, + include: { reviews: true }, + }); +} + +async function getEventByNameOrTitle(searchText: string): Promise { + return prisma.eventItem.findMany({ + where: { + OR: [{ name: { contains: searchText, mode: 'insensitive' } }, { title: { contains: searchText, mode: 'insensitive' } }], + }, + include: { reviews: true }, + }); +} + +async function createEvent(eventData: any) { + return await prisma.eventItem.create({ data: eventData }); +} + +async function updateEvent(eventId: string, updateForm: UpdateEvent) { + return prisma.eventItem.update({ + where: { id: eventId }, + data: updateForm, + }); +} + +async function deleteEvent(eventId: string) { + return prisma.eventItem.delete({ + where: { id: eventId }, + }); +} + +export { getEvent, listEvents, createEvent, updateEvent, deleteEvent, getEventByNameOrTitle, type CreateEvent, type UpdateEvent }; diff --git a/03_source/cms_backend/yarn.lock b/03_source/cms_backend/yarn.lock index c4f2302..90277e3 100644 --- a/03_source/cms_backend/yarn.lock +++ b/03_source/cms_backend/yarn.lock @@ -1021,7 +1021,7 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1239,7 +1239,7 @@ caniuse-lite@^1.0.30001579: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz" integrity sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw== -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1257,6 +1257,15 @@ client-only@0.0.1: resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + clsx@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" @@ -1284,6 +1293,19 @@ concat-map@0.0.1: resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +concurrently@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-9.1.2.tgz#22d9109296961eaee773e12bfb1ce9a66bc9836c" + integrity sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ== + dependencies: + chalk "^4.1.2" + lodash "^4.17.21" + rxjs "^7.8.1" + shell-quote "^1.8.1" + supports-color "^8.1.1" + tree-kill "^1.2.2" + yargs "^17.7.2" + console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -1614,6 +1636,11 @@ esbuild@~0.25.0: "@esbuild/win32-ia32" "0.25.5" "@esbuild/win32-x64" "0.25.5" +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" @@ -1945,6 +1972,11 @@ gauge@^3.0.0: strip-ansi "^6.0.1" wide-align "^1.1.2" +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" @@ -2985,6 +3017,11 @@ regexp.prototype.flags@^1.5.3: gopd "^1.2.0" set-function-name "^2.0.2" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" @@ -3049,6 +3086,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@^7.8.1: + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz" @@ -3152,6 +3196,11 @@ shebang-regex@^3.0.0: resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shell-quote@^1.8.1: + version "1.8.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.3.tgz#55e40ef33cf5c689902353a3d8cd1a6725f08b4b" + integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw== + side-channel-list@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz" @@ -3222,7 +3271,7 @@ streamsearch@^1.1.0: resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz" integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -3297,7 +3346,7 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -3333,6 +3382,13 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" @@ -3370,6 +3426,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + ts-api-utils@^2.0.1: version "2.1.0" resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz" @@ -3404,7 +3465,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.4.0: +tslib@^2.1.0, tslib@^2.4.0: version "2.8.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -3612,6 +3673,15 @@ word-wrap@^1.2.5: resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -3622,6 +3692,11 @@ xtend@^4.0.0: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" @@ -3632,6 +3707,24 @@ yaml@^1.10.0: resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yn@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" diff --git a/03_source/frontend/package.json b/03_source/frontend/package.json index 960f62c..2455db5 100644 --- a/03_source/frontend/package.json +++ b/03_source/frontend/package.json @@ -6,6 +6,7 @@ "private": true, "type": "module", "scripts": { + "dev:check": "yarn tsc:w", "dev": "vite", "start": "vite preview", "build": "tsc && vite build", diff --git a/03_source/mobile/package.json b/03_source/mobile/package.json index 5adf421..cc3906a 100644 --- a/03_source/mobile/package.json +++ b/03_source/mobile/package.json @@ -79,6 +79,7 @@ "name": "ionic-react-conference-app", "private": true, "scripts": { + "dev:check": "yarn tsc:w", "build": "tsc && vite build --force", "build:w": "npx nodemon --ext \"ts,tsx\" --exec \"npm run tsc && npm run build\"", "dev": "vite --force --host 0.0.0.0 --cors", @@ -94,4 +95,4 @@ "tsc": "tsc --noEmit" }, "version": "0.0.1" -} +} \ No newline at end of file