@bash-app/bash-common 30.33.0 → 30.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bash-app/bash-common",
3
- "version": "30.33.0",
3
+ "version": "30.34.0",
4
4
  "description": "Common data and scripts to use on the frontend and backend",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -38,6 +38,7 @@
38
38
  "devDependencies": {
39
39
  "@types/jest": "^29.5.5",
40
40
  "@types/luxon": "^3.4.2",
41
+ "@types/luxon": "^3.4.2",
41
42
  "@types/node": "^20.11.1",
42
43
  "@types/react": "^18.3.2",
43
44
  "@types/shelljs": "^0.8.15",
@@ -297,6 +297,69 @@ export interface DeletedAndHiddenTiers {
297
297
  errorType?: ApiErrorType;
298
298
  }
299
299
 
300
+ export interface ServiceNextGooglePhotoArgs {
301
+ photoIndex: string;
302
+ useBusinessPhotos: boolean;
303
+ }
304
+
305
+ export interface GooglePeopleApiResponse {
306
+ emailAddresses?: Array<{
307
+ value: string;
308
+ type?: string;
309
+ formattedType?: string;
310
+ }>;
311
+ names?: Array<{
312
+ displayName?: string;
313
+ givenName?: string;
314
+ familyName?: string;
315
+ metadata?: any;
316
+ }>;
317
+ phoneNumbers?: Array<{
318
+ value: string;
319
+ canonicalForm?: string;
320
+ type?: string;
321
+ formattedType?: string;
322
+ }>;
323
+ addresses?: Array<{
324
+ streetAddress?: string;
325
+ city?: string;
326
+ region?: string;
327
+ postalCode?: string;
328
+ country?: string;
329
+ formattedValue?: string;
330
+ type?: string;
331
+ }>;
332
+ photos?: Array<{
333
+ url: string;
334
+ default?: boolean;
335
+ }>;
336
+ birthdays?: Array<{
337
+ date?: {
338
+ year?: number;
339
+ month?: number;
340
+ day?: number;
341
+ };
342
+ text?: string; // Optional, sometimes present for display
343
+ metadata?: {
344
+ primary?: boolean;
345
+ source?: {
346
+ type?: string;
347
+ id?: string;
348
+ };
349
+ };
350
+ }>;
351
+ }
352
+
353
+ export interface GoogleSignInData {
354
+ accessToken: string;
355
+ // data: GooglePeopleApiResponse;
356
+ }
357
+
358
+ export interface LoginSession {
359
+ user: PublicUser;
360
+ token: string;
361
+ }
362
+
300
363
  export interface AttendeeOfBashEvent {
301
364
  user: PublicUser;
302
365
  tickets: Ticket[];
@@ -524,6 +587,15 @@ export interface GenericTitle {
524
587
  title: string;
525
588
  }
526
589
 
590
+ export interface ServiceGenerateCoverPhotoArgs {
591
+ searchTerm: string;
592
+ }
593
+
594
+ export interface ServiceNextGooglePhotoArgs {
595
+ photoIndex: string;
596
+ useBusinessPhotos: boolean;
597
+ }
598
+
527
599
  export type StripeSessionRedirect = {
528
600
  stripeAccountIdDB: string;
529
601
  redirectUrl: string;
@@ -344,12 +344,6 @@ export const SERVICE_DATA_TO_INCLUDE = {
344
344
  // },
345
345
  } satisfies Prisma.ServiceInclude;
346
346
 
347
- //full service data to include, includes specific service data
348
- export const SERVICE_FULL_DATA_TO_INCLUDE = {
349
- ...SERVICE_DATA_TO_INCLUDE,
350
- ...createAllTrueObject(serviceKeysArray),
351
- } satisfies Prisma.ServiceInclude;
352
-
353
347
  export const SERVICE_FULL_DATA_TO_CLONE = [
354
348
  "media",
355
349
  "targetAudience",
@@ -542,6 +536,50 @@ export interface ServiceExt extends Service {
542
536
  // bookedCheckouts: ServiceBookingCheckoutExt[]; //not necessary to include
543
537
  // bookings?: ServiceBookingExt[];
544
538
  }
539
+
540
+ export type ServiceExtNonSpecific = Exclude<
541
+ ServiceExt,
542
+ | "id"
543
+ | "venue"
544
+ | "venueId"
545
+ | "entertainmentService"
546
+ | "entertainmentServiceId"
547
+ | "eventService"
548
+ | "eventServiceId"
549
+ | "vendor"
550
+ | "vendorId"
551
+ | "organization"
552
+ | "organizationId"
553
+ | "sponsor"
554
+ | "sponsorId"
555
+ | "exhibitor"
556
+ | "exhibitorId"
557
+ | "volunteerService"
558
+ | "volunteerServiceId"
559
+ | "bashEvent"
560
+ | "bashEventId"
561
+ >;
562
+
563
+ export type ServiceExtNoIds = Exclude<
564
+ ServiceExt,
565
+ | "id"
566
+ | "venueId"
567
+ | "entertainmentServiceId"
568
+ | "eventServiceId"
569
+ | "vendorId"
570
+ | "organizationId"
571
+ | "sponsorId"
572
+ | "exhibitor"
573
+ | "exhibitorId"
574
+ | "volunteerServiceId"
575
+ | "bashEventId"
576
+ | "targetAudienceId"
577
+ | "creatorId"
578
+ | "ownerId"
579
+ | "stripeAccountId"
580
+ | "serviceRatesAssociationId"
581
+ | "serviceId"
582
+ >;
545
583
  export interface EventServiceExt extends EventService {
546
584
  crowdSize?: AmountOfGuests;
547
585
  serviceRange?: ServiceRange;
package/src/index.ts CHANGED
@@ -16,7 +16,7 @@ export * from "./utils/promoCodesUtils";
16
16
  export * from "./utils/userPromoCodeUtils";
17
17
  export * from "./utils/userSubscriptionUtils";
18
18
  export * from "./utils/service/regexUtils";
19
- export * from "./utils/objUtils"
19
+ export * from "./utils/objUtils";
20
20
  export * from "./utils/service/serviceUtils";
21
21
  export * from "./utils/service/venueUtils";
22
22
  export * from "./utils/service/attendeeOptionUtils";
@@ -4,7 +4,11 @@ import {
4
4
  ServiceSubscriptionStatus,
5
5
  ServiceTypes,
6
6
  } from "@prisma/client";
7
- import { ServiceExt } from "../../extendedSchemas";
7
+ import {
8
+ ServiceExt,
9
+ ServiceExtNoIds,
10
+ ServiceExtNonSpecific,
11
+ } from "../../extendedSchemas";
8
12
 
9
13
  export type ServiceCancellationRefundPolicy = {
10
14
  days?: number;
@@ -215,55 +219,286 @@ export const serviceTypeToField = (
215
219
  return specificServiceMap[serviceType];
216
220
  };
217
221
 
218
- // export type SpecificServiceMap = {
219
- // [P in keyof T]: ServiceSpecificInfo;
220
- // };
221
-
222
- // type ServiceExtKeyMap = {
223
- // EventServices: "eventService";
224
- // EntertainmentServices: "entertainmentService";
225
- // Vendors: "vendor";
226
- // Exhibitors: "exhibitor";
227
- // Sponsors: "sponsor";
228
- // Venues: "venue";
229
- // Organizations: "organization";
230
- // };
231
- // export type ServiceExtKey<T extends ServiceTypes> = ServiceExtKeyMap[T];
232
- // export type ServiceSpecificInfo = {
233
- // description: string;
234
- // };
235
-
236
- // export type ServiceSpecificInfoMap<T> = {
237
- // [P in keyof T]: ServiceSpecificInfo;
238
- // };
239
- // export type SpecificServiceInfoMap = {
240
- // [K in ServiceTypes]: ServiceSpecificInfoMap<
241
- // ServiceExt[ServiceExtKey<K>]
242
- // >;
243
- // };
244
-
245
- // export const serviceSpecificInfo = {
246
- // EventServices:{
247
-
248
- // },
249
- // EntertainmentServices: {
250
-
251
- // },
252
- // Vendors:{
253
-
254
- // },
255
- // Exhibitors:{
256
-
257
- // };
258
- // Sponsors:{
259
-
260
- // },
261
- // Venues:{
262
- // venueTypes: {
263
- // description: `venueTypes (array of primary venue types)`
264
- // }
265
- // },
266
- // Organizations: {
267
-
268
- // },
269
- // } as SpecificServiceInfoMap;
222
+ type ServiceExtKeyMap = {
223
+ EventServices: "eventService";
224
+ EntertainmentServices: "entertainmentService";
225
+ Vendors: "vendor";
226
+ Exhibitors: "exhibitor";
227
+ Sponsors: "sponsor";
228
+ Venues: "venue";
229
+ Organizations: "organization";
230
+ };
231
+
232
+ export type ServiceFieldType =
233
+ | "string"
234
+ | "integer"
235
+ | "float"
236
+ | "boolean"
237
+ | "date";
238
+ export type ServiceExtKey<T extends ServiceTypes> = ServiceExtKeyMap[T];
239
+ export type ServiceAIInfo = {
240
+ description: string;
241
+ example: string;
242
+
243
+ type: ServiceFieldType;
244
+ isArray: boolean;
245
+ };
246
+
247
+ export type ServiceSpecificInfoAIMap<T> = {
248
+ [P in keyof T]: ServiceAIInfo;
249
+ };
250
+ export type SpecificServiceInfoAIMap = {
251
+ [K in ServiceTypes]: ServiceSpecificInfoAIMap<
252
+ Partial<ServiceExt[ServiceExtKey<K>]>
253
+ >;
254
+ };
255
+ export type ServiceInfoAIMap = {
256
+ [key in keyof ServiceExtNonSpecific]: ServiceAIInfo;
257
+ };
258
+
259
+ export function aiServiceInfoToInfoString(
260
+ field: string,
261
+ info: ServiceAIInfo
262
+ ): string {
263
+ return `${field}: ${info.description} - ${info.type}${
264
+ info.isArray ? "[]" : ""
265
+ }`;
266
+ }
267
+
268
+ export function aiServiceInfoToExampleString(
269
+ field: string,
270
+ info: ServiceAIInfo
271
+ ): string {
272
+ return `${field}: ${info.example} - ${info.type}${info.isArray ? "[]" : ""}`;
273
+ }
274
+
275
+ export const serviceGetInfoAI = (serviceType: ServiceTypes) => {
276
+ const res: Partial<ServiceInfoAIMap> = {
277
+ serviceName: {
278
+ description: `serviceName (a catchy, descriptive name for the ${serviceType})`,
279
+ example: `The Grand Atrium`,
280
+ type: "string",
281
+ isArray: false,
282
+ },
283
+ description: {
284
+ description: `description for the ${serviceType}`,
285
+ example: `The Grand Atrium provides a fantastic dining experience with great prices and supports local farmers and reduces environmental impact.`,
286
+ type: "string",
287
+ isArray: false,
288
+ },
289
+ mission: {
290
+ description: `if the ${serviceType} has a mission to make a positive impact, describe it`,
291
+ example: `We strive to provide a sustainable dining experience that supports local farmers and reduces environmental impact.`,
292
+ type: "string",
293
+ isArray: false,
294
+ },
295
+ communityInvolvement: {
296
+ description: `describe how the ${serviceType} is involved in the community, if applicable`,
297
+ example: `We host monthly charity events and donate 10% of profits to local education initiatives.`,
298
+ type: "string",
299
+ isArray: false,
300
+ },
301
+ };
302
+
303
+ return res;
304
+ };
305
+
306
+ export const serviceSpecificInfoAI = {
307
+ EventServices: {},
308
+ EntertainmentServices: {},
309
+ Vendors: {},
310
+ Exhibitors: {},
311
+ Sponsors: {},
312
+ Venues: {
313
+ venueTypes: {
314
+ description: `venueTypes (array of primary venue types)`,
315
+ example: `["Restaurant", "Bar"]`,
316
+ type: "string",
317
+ isArray: true,
318
+ },
319
+ secondaryVenueTypes: {
320
+ description: `secondaryVenueTypes (array of secondary venue types)`,
321
+ example: `["Event Venue", "Private Dining"]`,
322
+ type: "string",
323
+ isArray: true,
324
+ },
325
+ vibe: {
326
+ description: `describe the atmosphere/mood - this will be used as the main description`,
327
+ example: `Upscale and sophisticated with a warm, inviting atmosphere`,
328
+ type: "string",
329
+ isArray: false,
330
+ },
331
+ dress: {
332
+ description: `specify dress code`,
333
+ example: `Smart casual`,
334
+ type: "string",
335
+ isArray: false,
336
+ },
337
+ allowed: {
338
+ description: `what guests can bring or do`,
339
+ example: `Outside food for special occasions with prior approval`,
340
+ type: "string",
341
+ isArray: false,
342
+ },
343
+ notAllowed: {
344
+ description: `what guests cannot bring or do`,
345
+ example: `Smoking, outside alcohol, disruptive behavior`,
346
+ type: "string",
347
+ isArray: false,
348
+ },
349
+ capacity: {
350
+ description: `number of people the venue can accommodate`,
351
+ example: `150`,
352
+ type: "integer",
353
+ isArray: false,
354
+ },
355
+ amenities: {
356
+ description: `array of amenities like "WiFi", "Parking", etc.`,
357
+ example: `["WiFi", "Parking", "Wheelchair Access", "Restrooms"]`,
358
+ type: "string",
359
+ isArray: false,
360
+ },
361
+ features: {
362
+ description: `array of features like "Stage", "Dance Floor", etc.`,
363
+ example: `["Private Dining Area", "Full Bar", "Audio System", "Projector"]`,
364
+ type: "string",
365
+ isArray: false,
366
+ },
367
+ yearsInBusiness: {
368
+ description: `how long the venue has been in business as a string: "LessThanOneYear", "OneToThreeYears", "ThreeToFiveYears", "FivePlusYears"`,
369
+ example: `"ThreeToFiveYears"`,
370
+ type: "string",
371
+ isArray: false,
372
+ },
373
+ },
374
+ Organizations: {},
375
+ } as SpecificServiceInfoAIMap;
376
+
377
+ /**
378
+ * Builds a formatted string of AI context fields, handling optional schemas and types.
379
+ */
380
+ export function buildAIFieldsString<T extends Record<string, unknown>>(
381
+ data: Partial<T>,
382
+ info: Partial<Record<keyof T, ServiceAIInfo>>
383
+ ): string {
384
+ return (Object.entries(info) as Array<[keyof T, ServiceAIInfo]>)
385
+ .map(([key, cfg]) => {
386
+ const { type, isArray } = cfg;
387
+ const raw = data[key];
388
+
389
+ const formatSingle = (val: unknown): string => {
390
+ if (val == null) return "";
391
+ switch (type) {
392
+ case "integer":
393
+ return Number(val).toFixed(0);
394
+ case "float":
395
+ return Number(val).toString();
396
+ case "boolean":
397
+ return Boolean(val).toString();
398
+ case "date": {
399
+ const d = new Date(val as string);
400
+ return isNaN(d.getTime()) ? String(val) : d.toISOString();
401
+ }
402
+ case "string":
403
+ default:
404
+ return String(val);
405
+ }
406
+ };
407
+
408
+ let display: string;
409
+ if (isArray) {
410
+ if (Array.isArray(raw)) {
411
+ display = (raw as unknown[]).map(formatSingle).join(", ");
412
+ } else {
413
+ display = formatSingle(raw);
414
+ }
415
+ } else {
416
+ display = formatSingle(raw);
417
+ }
418
+
419
+ return `${String(key)}: ${
420
+ raw != null ? display : `No ${String(key)} provided`
421
+ }`;
422
+ })
423
+ .join(",\n ");
424
+ }
425
+
426
+ export function serviceExcludeIds(
427
+ service: Partial<ServiceExt>
428
+ ): Partial<ServiceExtNoIds> {
429
+ const {
430
+ id,
431
+ venueId,
432
+ entertainmentServiceId,
433
+ eventServiceId,
434
+ organizationId,
435
+ volunteerServiceId,
436
+ sponsorId,
437
+ vendorId,
438
+ exhibitorId,
439
+ googlePlaceId,
440
+ stripeAccountId,
441
+ targetAudienceId,
442
+ creatorId,
443
+ ownerId,
444
+ ...rest
445
+ } = service;
446
+
447
+ return rest;
448
+ }
449
+
450
+ export function serviceExcludeOwners(
451
+ service: Partial<ServiceExt>
452
+ ): Partial<ServiceExtNoIds> {
453
+ const { owner, creator, ...rest } = service;
454
+
455
+ return rest;
456
+ }
457
+
458
+ export function serviceExcludeRates(
459
+ service: Partial<ServiceExt>
460
+ ): Partial<ServiceExtNoIds> {
461
+ const { serviceRatesAssociation, ...rest } = service;
462
+
463
+ return rest;
464
+ }
465
+
466
+ export function serviceExcludeDates(
467
+ service: Partial<ServiceExt>
468
+ ): Partial<ServiceExtNoIds> {
469
+ const { createdAt, updatedAt, ...rest } = service;
470
+
471
+ return rest;
472
+ }
473
+
474
+ export function serviceExcludeMiscData(
475
+ service: Partial<ServiceExt>
476
+ ): Partial<ServiceExtNoIds> {
477
+ const {
478
+ serviceName,
479
+ isApproved,
480
+ serviceType,
481
+ cancellationPolicy,
482
+ instantBookingLeadTimeHours,
483
+ allowsInstantBooking,
484
+ displayBashReviewsOnDetailPage,
485
+ displayGoogleReviewsOnDetailPage,
486
+ subscriptionStatus,
487
+ serviceCondition,
488
+ serviceStatus,
489
+ visibility,
490
+ ...rest
491
+ } = service;
492
+
493
+ return rest;
494
+ }
495
+
496
+ export function serviceRelevantData(
497
+ service: Partial<ServiceExt>
498
+ ): Partial<ServiceExtNoIds> {
499
+ return serviceExcludeOwners(
500
+ serviceExcludeDates(
501
+ serviceExcludeRates(serviceExcludeIds(serviceExcludeMiscData(service)))
502
+ )
503
+ );
504
+ }