@voyantjs/customer-portal 0.2.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.
@@ -0,0 +1,128 @@
1
+ import { Hono } from "hono";
2
+ import { publicCustomerPortalService } from "./service-public.js";
3
+ import { bootstrapCustomerPortalSchema, createCustomerPortalCompanionSchema, updateCustomerPortalCompanionSchema, updateCustomerPortalProfileSchema, } from "./validation-public.js";
4
+ function unauthorized(c) {
5
+ return c.json({ error: "Unauthorized" }, 401);
6
+ }
7
+ function notFound(c, error) {
8
+ return c.json({ error }, 404);
9
+ }
10
+ function hasErrorResult(value) {
11
+ return "error" in value;
12
+ }
13
+ function hasBootstrapErrorResult(value) {
14
+ return "error" in value;
15
+ }
16
+ export const publicCustomerPortalRoutes = new Hono()
17
+ .get("/me", async (c) => {
18
+ const userId = c.get("userId");
19
+ if (!userId) {
20
+ return unauthorized(c);
21
+ }
22
+ const profile = await publicCustomerPortalService.getProfile(c.get("db"), userId);
23
+ return profile ? c.json({ data: profile }) : notFound(c, "Customer profile not found");
24
+ })
25
+ .patch("/me", async (c) => {
26
+ const userId = c.get("userId");
27
+ if (!userId) {
28
+ return unauthorized(c);
29
+ }
30
+ const result = await publicCustomerPortalService.updateProfile(c.get("db"), userId, updateCustomerPortalProfileSchema.parse(await c.req.json()));
31
+ if (hasErrorResult(result)) {
32
+ if (result.error === "not_found") {
33
+ return notFound(c, "Customer profile not found");
34
+ }
35
+ return c.json({ error: "Customer record is not linked to this account" }, 409);
36
+ }
37
+ return c.json({ data: result.profile });
38
+ })
39
+ .post("/bootstrap", async (c) => {
40
+ const userId = c.get("userId");
41
+ if (!userId) {
42
+ return unauthorized(c);
43
+ }
44
+ const result = await publicCustomerPortalService.bootstrap(c.get("db"), userId, bootstrapCustomerPortalSchema.parse(await c.req.json()));
45
+ if (hasBootstrapErrorResult(result)) {
46
+ if (result.error === "not_found") {
47
+ return notFound(c, "Customer profile not found");
48
+ }
49
+ if (result.error === "customer_record_not_found") {
50
+ return notFound(c, "Customer record not found");
51
+ }
52
+ return c.json({ error: "Customer record is already linked to another account" }, 409);
53
+ }
54
+ if (result.status === "customer_selection_required") {
55
+ return c.json({ data: result }, 409);
56
+ }
57
+ return c.json({ data: result });
58
+ })
59
+ .get("/companions", async (c) => {
60
+ const userId = c.get("userId");
61
+ if (!userId) {
62
+ return unauthorized(c);
63
+ }
64
+ return c.json({ data: await publicCustomerPortalService.listCompanions(c.get("db"), userId) });
65
+ })
66
+ .post("/companions", async (c) => {
67
+ const userId = c.get("userId");
68
+ if (!userId) {
69
+ return unauthorized(c);
70
+ }
71
+ const companion = await publicCustomerPortalService.createCompanion(c.get("db"), userId, createCustomerPortalCompanionSchema.parse(await c.req.json()));
72
+ if (!companion) {
73
+ return c.json({ error: "Customer record is not linked to this account" }, 409);
74
+ }
75
+ return c.json({ data: companion }, 201);
76
+ })
77
+ .patch("/companions/:companionId", async (c) => {
78
+ const userId = c.get("userId");
79
+ if (!userId) {
80
+ return unauthorized(c);
81
+ }
82
+ const companion = await publicCustomerPortalService.updateCompanion(c.get("db"), userId, c.req.param("companionId"), updateCustomerPortalCompanionSchema.parse(await c.req.json()));
83
+ if (companion === "forbidden") {
84
+ return c.json({ error: "Companion does not belong to this customer" }, 403);
85
+ }
86
+ if (!companion) {
87
+ return notFound(c, "Companion not found");
88
+ }
89
+ return c.json({ data: companion });
90
+ })
91
+ .delete("/companions/:companionId", async (c) => {
92
+ const userId = c.get("userId");
93
+ if (!userId) {
94
+ return unauthorized(c);
95
+ }
96
+ const result = await publicCustomerPortalService.deleteCompanion(c.get("db"), userId, c.req.param("companionId"));
97
+ if (result === "forbidden") {
98
+ return c.json({ error: "Companion does not belong to this customer" }, 403);
99
+ }
100
+ if (result === "not_found") {
101
+ return notFound(c, "Companion not found");
102
+ }
103
+ return c.json({ success: true });
104
+ })
105
+ .get("/bookings", async (c) => {
106
+ const userId = c.get("userId");
107
+ if (!userId) {
108
+ return unauthorized(c);
109
+ }
110
+ const bookings = await publicCustomerPortalService.listBookings(c.get("db"), userId);
111
+ return bookings ? c.json({ data: bookings }) : notFound(c, "Customer profile not found");
112
+ })
113
+ .get("/bookings/:bookingId", async (c) => {
114
+ const userId = c.get("userId");
115
+ if (!userId) {
116
+ return unauthorized(c);
117
+ }
118
+ const booking = await publicCustomerPortalService.getBooking(c.get("db"), userId, c.req.param("bookingId"));
119
+ return booking ? c.json({ data: booking }) : notFound(c, "Booking not found");
120
+ })
121
+ .get("/bookings/:bookingId/documents", async (c) => {
122
+ const userId = c.get("userId");
123
+ if (!userId) {
124
+ return unauthorized(c);
125
+ }
126
+ const documents = await publicCustomerPortalService.listBookingDocuments(c.get("db"), userId, c.req.param("bookingId"));
127
+ return documents ? c.json({ data: documents }) : notFound(c, "Booking not found");
128
+ });
@@ -0,0 +1,26 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ type Env = {
3
+ Variables: {
4
+ db: PostgresJsDatabase;
5
+ };
6
+ };
7
+ export declare const customerPortalRoutes: import("hono/hono-base").HonoBase<Env, {
8
+ "/contact-exists": {
9
+ $get: {
10
+ input: {};
11
+ output: {
12
+ data: {
13
+ email: string;
14
+ authAccountExists: boolean;
15
+ customerRecordExists: boolean;
16
+ linkedCustomerRecordExists: boolean;
17
+ };
18
+ };
19
+ outputFormat: "json";
20
+ status: import("hono/utils/http-status").ContentfulStatusCode;
21
+ };
22
+ };
23
+ }, "/", "/contact-exists">;
24
+ export type CustomerPortalRoutes = typeof customerPortalRoutes;
25
+ export {};
26
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAMjE,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,kBAAkB,CAAA;KACvB,CAAA;CACF,CAAA;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;0BAQ/B,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,OAAO,oBAAoB,CAAA"}
package/dist/routes.js ADDED
@@ -0,0 +1,9 @@
1
+ import { Hono } from "hono";
2
+ import { publicCustomerPortalService } from "./service-public.js";
3
+ import { customerPortalContactExistsQuerySchema } from "./validation-public.js";
4
+ export const customerPortalRoutes = new Hono().get("/contact-exists", async (c) => {
5
+ const query = customerPortalContactExistsQuerySchema.parse(Object.fromEntries(new URL(c.req.url).searchParams));
6
+ return c.json({
7
+ data: await publicCustomerPortalService.contactExists(c.get("db"), query.email),
8
+ });
9
+ });
@@ -0,0 +1,28 @@
1
+ import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
2
+ import type { BootstrapCustomerPortalInput, BootstrapCustomerPortalResult, CreateCustomerPortalCompanionInput, CustomerPortalBookingDetail, CustomerPortalBookingSummary, CustomerPortalCompanion, CustomerPortalContactExistsResult, CustomerPortalProfile, UpdateCustomerPortalCompanionInput, UpdateCustomerPortalProfileInput } from "./validation-public.js";
3
+ export declare const publicCustomerPortalService: {
4
+ contactExists(db: PostgresJsDatabase, email: string): Promise<CustomerPortalContactExistsResult>;
5
+ getProfile(db: PostgresJsDatabase, userId: string): Promise<CustomerPortalProfile | null>;
6
+ updateProfile(db: PostgresJsDatabase, userId: string, input: UpdateCustomerPortalProfileInput): Promise<{
7
+ profile: CustomerPortalProfile;
8
+ } | {
9
+ error: "not_found" | "customer_record_required";
10
+ }>;
11
+ bootstrap(db: PostgresJsDatabase, userId: string, input: BootstrapCustomerPortalInput): Promise<BootstrapCustomerPortalResult | {
12
+ error: "not_found" | "customer_record_not_found" | "customer_record_claimed";
13
+ }>;
14
+ listCompanions(db: PostgresJsDatabase, userId: string): Promise<CustomerPortalCompanion[]>;
15
+ createCompanion(db: PostgresJsDatabase, userId: string, input: CreateCustomerPortalCompanionInput): Promise<CustomerPortalCompanion | null>;
16
+ updateCompanion(db: PostgresJsDatabase, userId: string, companionId: string, input: UpdateCustomerPortalCompanionInput): Promise<CustomerPortalCompanion | null | "forbidden">;
17
+ deleteCompanion(db: PostgresJsDatabase, userId: string, companionId: string): Promise<"deleted" | "not_found" | "forbidden">;
18
+ listBookings(db: PostgresJsDatabase, userId: string): Promise<CustomerPortalBookingSummary[] | null>;
19
+ getBooking(db: PostgresJsDatabase, userId: string, bookingId: string): Promise<CustomerPortalBookingDetail | null>;
20
+ listBookingDocuments(db: PostgresJsDatabase, userId: string, bookingId: string): Promise<{
21
+ id: string;
22
+ participantId: string | null;
23
+ type: "visa" | "insurance" | "health" | "passport_copy" | "other";
24
+ fileName: string;
25
+ fileUrl: string;
26
+ }[] | null>;
27
+ };
28
+ //# sourceMappingURL=service-public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-public.d.ts","sourceRoot":"","sources":["../src/service-public.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,kCAAkC,EAClC,2BAA2B,EAC3B,4BAA4B,EAE5B,uBAAuB,EACvB,iCAAiC,EACjC,qBAAqB,EACrB,kCAAkC,EAClC,gCAAgC,EACjC,MAAM,wBAAwB,CAAA;AA+U/B,eAAO,MAAM,2BAA2B;sBAEhC,kBAAkB,SACf,MAAM,GACZ,OAAO,CAAC,iCAAiC,CAAC;mBAsBxB,kBAAkB,UAAU,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;sBA8BzF,kBAAkB,UACd,MAAM,SACP,gCAAgC,GACtC,OAAO,CACR;QAAE,OAAO,EAAE,qBAAqB,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,WAAW,GAAG,0BAA0B,CAAA;KAAE,CACzF;kBAmIK,kBAAkB,UACd,MAAM,SACP,4BAA4B,GAClC,OAAO,CACN,6BAA6B,GAC7B;QAAE,KAAK,EAAE,WAAW,GAAG,2BAA2B,GAAG,yBAAyB,CAAA;KAAE,CACnF;uBA8IwB,kBAAkB,UAAU,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC;wBAiB1F,kBAAkB,UACd,MAAM,SACP,kCAAkC,GACxC,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;wBA0BpC,kBAAkB,UACd,MAAM,eACD,MAAM,SACZ,kCAAkC,GACxC,OAAO,CAAC,uBAAuB,GAAG,IAAI,GAAG,WAAW,CAAC;wBAuClD,kBAAkB,UACd,MAAM,eACD,MAAM,GAClB,OAAO,CAAC,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;qBAyB3C,kBAAkB,UACd,MAAM,GACb,OAAO,CAAC,4BAA4B,EAAE,GAAG,IAAI,CAAC;mBAwD3C,kBAAkB,UACd,MAAM,aACH,MAAM,GAChB,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC;6BAoCf,kBAAkB,UAAU,MAAM,aAAa,MAAM;;;;;;;CAIrF,CAAA"}