@voyant-travel/storefront 0.120.1
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/LICENSE +201 -0
- package/README.md +231 -0
- package/dist/booking-intents.d.ts +42 -0
- package/dist/booking-intents.d.ts.map +1 -0
- package/dist/booking-intents.js +83 -0
- package/dist/customer-portal/index.d.ts +16 -0
- package/dist/customer-portal/index.d.ts.map +1 -0
- package/dist/customer-portal/index.js +23 -0
- package/dist/customer-portal/route-runtime.d.ts +16 -0
- package/dist/customer-portal/route-runtime.d.ts.map +1 -0
- package/dist/customer-portal/route-runtime.js +27 -0
- package/dist/customer-portal/routes-public.d.ts +1936 -0
- package/dist/customer-portal/routes-public.d.ts.map +1 -0
- package/dist/customer-portal/routes-public.js +165 -0
- package/dist/customer-portal/routes.d.ts +43 -0
- package/dist/customer-portal/routes.d.ts.map +1 -0
- package/dist/customer-portal/routes.js +17 -0
- package/dist/customer-portal/service-public-impl.d.ts +138 -0
- package/dist/customer-portal/service-public-impl.d.ts.map +1 -0
- package/dist/customer-portal/service-public-impl.js +1808 -0
- package/dist/customer-portal/service-public.d.ts +2 -0
- package/dist/customer-portal/service-public.d.ts.map +1 -0
- package/dist/customer-portal/service-public.js +1 -0
- package/dist/customer-portal/validation-public/bookings.d.ts +551 -0
- package/dist/customer-portal/validation-public/bookings.d.ts.map +1 -0
- package/dist/customer-portal/validation-public/bookings.js +132 -0
- package/dist/customer-portal/validation-public/common.d.ts +162 -0
- package/dist/customer-portal/validation-public/common.d.ts.map +1 -0
- package/dist/customer-portal/validation-public/common.js +139 -0
- package/dist/customer-portal/validation-public/profile.d.ts +749 -0
- package/dist/customer-portal/validation-public/profile.d.ts.map +1 -0
- package/dist/customer-portal/validation-public/profile.js +308 -0
- package/dist/customer-portal/validation-public.d.ts +3 -0
- package/dist/customer-portal/validation-public.d.ts.map +1 -0
- package/dist/customer-portal/validation-public.js +2 -0
- package/dist/guest-booking-guard.d.ts +24 -0
- package/dist/guest-booking-guard.d.ts.map +1 -0
- package/dist/guest-booking-guard.js +55 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/product-extra-ref.d.ts +238 -0
- package/dist/product-extra-ref.d.ts.map +1 -0
- package/dist/product-extra-ref.js +22 -0
- package/dist/routes-admin.d.ts +220 -0
- package/dist/routes-admin.d.ts.map +1 -0
- package/dist/routes-admin.js +28 -0
- package/dist/routes-public.d.ts +1475 -0
- package/dist/routes-public.d.ts.map +1 -0
- package/dist/routes-public.js +362 -0
- package/dist/service-booking-session-bootstrap.d.ts +227 -0
- package/dist/service-booking-session-bootstrap.d.ts.map +1 -0
- package/dist/service-booking-session-bootstrap.js +287 -0
- package/dist/service-boundary-resource-sql.d.ts +18 -0
- package/dist/service-boundary-resource-sql.d.ts.map +1 -0
- package/dist/service-boundary-resource-sql.js +73 -0
- package/dist/service-boundary-sql.d.ts +103 -0
- package/dist/service-boundary-sql.d.ts.map +1 -0
- package/dist/service-boundary-sql.js +307 -0
- package/dist/service-departures-core.d.ts +41 -0
- package/dist/service-departures-core.d.ts.map +1 -0
- package/dist/service-departures-core.js +92 -0
- package/dist/service-departures-extensions.d.ts +46 -0
- package/dist/service-departures-extensions.d.ts.map +1 -0
- package/dist/service-departures-extensions.js +81 -0
- package/dist/service-departures-offers.d.ts +220 -0
- package/dist/service-departures-offers.d.ts.map +1 -0
- package/dist/service-departures-offers.js +177 -0
- package/dist/service-departures-price-preview.d.ts +306 -0
- package/dist/service-departures-price-preview.d.ts.map +1 -0
- package/dist/service-departures-price-preview.js +383 -0
- package/dist/service-departures-pricing-context.d.ts +115 -0
- package/dist/service-departures-pricing-context.d.ts.map +1 -0
- package/dist/service-departures-pricing-context.js +237 -0
- package/dist/service-departures-pricing.d.ts +5 -0
- package/dist/service-departures-pricing.d.ts.map +1 -0
- package/dist/service-departures-pricing.js +4 -0
- package/dist/service-departures.d.ts +192 -0
- package/dist/service-departures.d.ts.map +1 -0
- package/dist/service-departures.js +213 -0
- package/dist/service-intake.d.ts +130 -0
- package/dist/service-intake.d.ts.map +1 -0
- package/dist/service-intake.js +274 -0
- package/dist/service-transport-eligibility.d.ts +10 -0
- package/dist/service-transport-eligibility.d.ts.map +1 -0
- package/dist/service-transport-eligibility.js +198 -0
- package/dist/service.d.ts +1062 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +332 -0
- package/dist/transport-eligibility.d.ts +4 -0
- package/dist/transport-eligibility.d.ts.map +1 -0
- package/dist/transport-eligibility.js +2 -0
- package/dist/validation/departures.d.ts +1669 -0
- package/dist/validation/departures.d.ts.map +1 -0
- package/dist/validation/departures.js +397 -0
- package/dist/validation/intake.d.ts +147 -0
- package/dist/validation/intake.d.ts.map +1 -0
- package/dist/validation/intake.js +69 -0
- package/dist/validation/offers.d.ts +340 -0
- package/dist/validation/offers.d.ts.map +1 -0
- package/dist/validation/offers.js +117 -0
- package/dist/validation-settings.d.ts +609 -0
- package/dist/validation-settings.d.ts.map +1 -0
- package/dist/validation-settings.js +235 -0
- package/dist/validation-transport-eligibility.d.ts +314 -0
- package/dist/validation-transport-eligibility.d.ts.map +1 -0
- package/dist/validation-transport-eligibility.js +97 -0
- package/dist/validation.d.ts +6 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +4 -0
- package/dist/verification/index.d.ts +12 -0
- package/dist/verification/index.d.ts.map +1 -0
- package/dist/verification/index.js +18 -0
- package/dist/verification/routes-public.d.ts +121 -0
- package/dist/verification/routes-public.d.ts.map +1 -0
- package/dist/verification/routes-public.js +125 -0
- package/dist/verification/schema.d.ts +273 -0
- package/dist/verification/schema.d.ts.map +1 -0
- package/dist/verification/schema.js +50 -0
- package/dist/verification/service.d.ts +114 -0
- package/dist/verification/service.d.ts.map +1 -0
- package/dist/verification/service.js +283 -0
- package/dist/verification/validation.d.ts +98 -0
- package/dist/verification/validation.d.ts.map +1 -0
- package/dist/verification/validation.js +54 -0
- package/package.json +148 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HonoModule } from "@voyant-travel/hono/module";
|
|
2
|
+
import { type StorefrontVerificationRoutesOptions } from "./routes-public.js";
|
|
3
|
+
export type { StorefrontVerificationPublicRoutes, StorefrontVerificationRoutesOptions, } from "./routes-public.js";
|
|
4
|
+
export { buildStorefrontVerificationSenders, createStorefrontVerificationPublicRoutes, STOREFRONT_VERIFICATION_SENDERS_CONTAINER_KEY, } from "./routes-public.js";
|
|
5
|
+
export type { NewStorefrontVerificationChallenge, StorefrontVerificationChallenge, } from "./schema.js";
|
|
6
|
+
export { storefrontVerificationChallenges, storefrontVerificationChannelEnum, storefrontVerificationLinkable, storefrontVerificationModule, storefrontVerificationStatusEnum, } from "./schema.js";
|
|
7
|
+
export type { StorefrontVerificationDeliveryResult, StorefrontVerificationEmailSendInput, StorefrontVerificationNotificationChannel, StorefrontVerificationNotificationPayload, StorefrontVerificationNotificationProvider, StorefrontVerificationNotificationResult, StorefrontVerificationProviderOptions, StorefrontVerificationSenders, StorefrontVerificationServiceOptions, StorefrontVerificationSmsSendInput, } from "./service.js";
|
|
8
|
+
export { createStorefrontVerificationSendersFromProviders, createStorefrontVerificationService, StorefrontVerificationError, } from "./service.js";
|
|
9
|
+
export type { ConfirmEmailVerificationChallengeInput, ConfirmSmsVerificationChallengeInput, StartEmailVerificationChallengeInput, StartSmsVerificationChallengeInput, StorefrontVerificationChallengeRecord, StorefrontVerificationChannel, StorefrontVerificationConfirmResult, StorefrontVerificationStartResult, StorefrontVerificationStatus, } from "./validation.js";
|
|
10
|
+
export { confirmEmailVerificationChallengeSchema, confirmSmsVerificationChallengeSchema, startEmailVerificationChallengeSchema, startSmsVerificationChallengeSchema, storefrontVerificationChallengeRecordSchema, storefrontVerificationChannelSchema, storefrontVerificationConfirmResultSchema, storefrontVerificationStartResultSchema, storefrontVerificationStatusSchema, } from "./validation.js";
|
|
11
|
+
export declare function createStorefrontVerificationHonoModule(options?: StorefrontVerificationRoutesOptions): HonoModule;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAC5D,OAAO,EAIL,KAAK,mCAAmC,EACzC,MAAM,oBAAoB,CAAA;AAG3B,YAAY,EACV,kCAAkC,EAClC,mCAAmC,GACpC,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,kCAAkC,EAClC,wCAAwC,EACxC,6CAA6C,GAC9C,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,kCAAkC,EAClC,+BAA+B,GAChC,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,gCAAgC,EAChC,iCAAiC,EACjC,8BAA8B,EAC9B,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,aAAa,CAAA;AACpB,YAAY,EACV,oCAAoC,EACpC,oCAAoC,EACpC,yCAAyC,EACzC,yCAAyC,EACzC,0CAA0C,EAC1C,wCAAwC,EACxC,qCAAqC,EACrC,6BAA6B,EAC7B,oCAAoC,EACpC,kCAAkC,GACnC,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,gDAAgD,EAChD,mCAAmC,EACnC,2BAA2B,GAC5B,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,sCAAsC,EACtC,oCAAoC,EACpC,oCAAoC,EACpC,kCAAkC,EAClC,qCAAqC,EACrC,6BAA6B,EAC7B,mCAAmC,EACnC,iCAAiC,EACjC,4BAA4B,GAC7B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,uCAAuC,EACvC,qCAAqC,EACrC,qCAAqC,EACrC,mCAAmC,EACnC,2CAA2C,EAC3C,mCAAmC,EACnC,yCAAyC,EACzC,uCAAuC,EACvC,kCAAkC,GACnC,MAAM,iBAAiB,CAAA;AAExB,wBAAgB,sCAAsC,CACpD,OAAO,CAAC,EAAE,mCAAmC,GAC5C,UAAU,CAeZ"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { buildStorefrontVerificationSenders, createStorefrontVerificationPublicRoutes, STOREFRONT_VERIFICATION_SENDERS_CONTAINER_KEY, } from "./routes-public.js";
|
|
2
|
+
import { storefrontVerificationModule } from "./schema.js";
|
|
3
|
+
export { buildStorefrontVerificationSenders, createStorefrontVerificationPublicRoutes, STOREFRONT_VERIFICATION_SENDERS_CONTAINER_KEY, } from "./routes-public.js";
|
|
4
|
+
export { storefrontVerificationChallenges, storefrontVerificationChannelEnum, storefrontVerificationLinkable, storefrontVerificationModule, storefrontVerificationStatusEnum, } from "./schema.js";
|
|
5
|
+
export { createStorefrontVerificationSendersFromProviders, createStorefrontVerificationService, StorefrontVerificationError, } from "./service.js";
|
|
6
|
+
export { confirmEmailVerificationChallengeSchema, confirmSmsVerificationChallengeSchema, startEmailVerificationChallengeSchema, startSmsVerificationChallengeSchema, storefrontVerificationChallengeRecordSchema, storefrontVerificationChannelSchema, storefrontVerificationConfirmResultSchema, storefrontVerificationStartResultSchema, storefrontVerificationStatusSchema, } from "./validation.js";
|
|
7
|
+
export function createStorefrontVerificationHonoModule(options) {
|
|
8
|
+
const module = {
|
|
9
|
+
...storefrontVerificationModule,
|
|
10
|
+
bootstrap: ({ bindings, container }) => {
|
|
11
|
+
container.register(STOREFRONT_VERIFICATION_SENDERS_CONTAINER_KEY, buildStorefrontVerificationSenders(bindings, options));
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
module,
|
|
16
|
+
publicRoutes: createStorefrontVerificationPublicRoutes(options),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { ModuleContainer } from "@voyant-travel/core";
|
|
2
|
+
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
3
|
+
import { type StorefrontVerificationNotificationProvider, type StorefrontVerificationProviderOptions, type StorefrontVerificationSenders, type StorefrontVerificationServiceOptions } from "./service.js";
|
|
4
|
+
type Env = {
|
|
5
|
+
Bindings: Record<string, unknown>;
|
|
6
|
+
Variables: {
|
|
7
|
+
container: ModuleContainer;
|
|
8
|
+
db: PostgresJsDatabase;
|
|
9
|
+
userId?: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export interface StorefrontVerificationRoutesOptions extends StorefrontVerificationServiceOptions, StorefrontVerificationProviderOptions {
|
|
13
|
+
sendEmailChallenge?: StorefrontVerificationSenders["sendEmailChallenge"];
|
|
14
|
+
sendSmsChallenge?: StorefrontVerificationSenders["sendSmsChallenge"];
|
|
15
|
+
providers?: ReadonlyArray<StorefrontVerificationNotificationProvider>;
|
|
16
|
+
resolveProviders?: (bindings: Record<string, unknown>) => ReadonlyArray<StorefrontVerificationNotificationProvider>;
|
|
17
|
+
}
|
|
18
|
+
export declare const STOREFRONT_VERIFICATION_SENDERS_CONTAINER_KEY = "providers.storefrontVerification.senders";
|
|
19
|
+
export declare function buildStorefrontVerificationSenders(bindings: Record<string, unknown>, options?: StorefrontVerificationRoutesOptions): StorefrontVerificationSenders;
|
|
20
|
+
export declare function createStorefrontVerificationPublicRoutes(options?: StorefrontVerificationRoutesOptions): import("hono/hono-base").HonoBase<Env, {
|
|
21
|
+
"/email/start": {
|
|
22
|
+
$post: {
|
|
23
|
+
input: {};
|
|
24
|
+
output: {};
|
|
25
|
+
outputFormat: string;
|
|
26
|
+
status: import("hono/utils/http-status").StatusCode;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
} & {
|
|
30
|
+
"/email/confirm": {
|
|
31
|
+
$post: {
|
|
32
|
+
input: {};
|
|
33
|
+
output: {
|
|
34
|
+
error: string;
|
|
35
|
+
code: "sender_not_configured";
|
|
36
|
+
} | {
|
|
37
|
+
error: string;
|
|
38
|
+
code: "challenge_not_found";
|
|
39
|
+
} | {
|
|
40
|
+
error: string;
|
|
41
|
+
code: "challenge_expired";
|
|
42
|
+
} | {
|
|
43
|
+
error: string;
|
|
44
|
+
code: "challenge_invalid" | "challenge_failed";
|
|
45
|
+
} | {
|
|
46
|
+
error: string;
|
|
47
|
+
};
|
|
48
|
+
outputFormat: "json";
|
|
49
|
+
status: 404 | 400 | 409 | 410 | 501;
|
|
50
|
+
} | {
|
|
51
|
+
input: {};
|
|
52
|
+
output: {
|
|
53
|
+
data: {
|
|
54
|
+
id: string;
|
|
55
|
+
channel: "email" | "sms";
|
|
56
|
+
destination: string;
|
|
57
|
+
purpose: string;
|
|
58
|
+
status: "failed" | "pending" | "cancelled" | "expired" | "verified";
|
|
59
|
+
expiresAt: string;
|
|
60
|
+
verifiedAt: string | null;
|
|
61
|
+
createdAt: string;
|
|
62
|
+
updatedAt: string;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
outputFormat: "json";
|
|
66
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
} & {
|
|
70
|
+
"/sms/start": {
|
|
71
|
+
$post: {
|
|
72
|
+
input: {};
|
|
73
|
+
output: {};
|
|
74
|
+
outputFormat: string;
|
|
75
|
+
status: import("hono/utils/http-status").StatusCode;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
} & {
|
|
79
|
+
"/sms/confirm": {
|
|
80
|
+
$post: {
|
|
81
|
+
input: {};
|
|
82
|
+
output: {
|
|
83
|
+
error: string;
|
|
84
|
+
code: "sender_not_configured";
|
|
85
|
+
} | {
|
|
86
|
+
error: string;
|
|
87
|
+
code: "challenge_not_found";
|
|
88
|
+
} | {
|
|
89
|
+
error: string;
|
|
90
|
+
code: "challenge_expired";
|
|
91
|
+
} | {
|
|
92
|
+
error: string;
|
|
93
|
+
code: "challenge_invalid" | "challenge_failed";
|
|
94
|
+
} | {
|
|
95
|
+
error: string;
|
|
96
|
+
};
|
|
97
|
+
outputFormat: "json";
|
|
98
|
+
status: 404 | 400 | 409 | 410 | 501;
|
|
99
|
+
} | {
|
|
100
|
+
input: {};
|
|
101
|
+
output: {
|
|
102
|
+
data: {
|
|
103
|
+
id: string;
|
|
104
|
+
channel: "email" | "sms";
|
|
105
|
+
destination: string;
|
|
106
|
+
purpose: string;
|
|
107
|
+
status: "failed" | "pending" | "cancelled" | "expired" | "verified";
|
|
108
|
+
expiresAt: string;
|
|
109
|
+
verifiedAt: string | null;
|
|
110
|
+
createdAt: string;
|
|
111
|
+
updatedAt: string;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
outputFormat: "json";
|
|
115
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
}, "/", "/sms/confirm">;
|
|
119
|
+
export type StorefrontVerificationPublicRoutes = ReturnType<typeof createStorefrontVerificationPublicRoutes>;
|
|
120
|
+
export {};
|
|
121
|
+
//# sourceMappingURL=routes-public.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../../src/verification/routes-public.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAE1D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,EAIL,KAAK,0CAA0C,EAC/C,KAAK,qCAAqC,EAC1C,KAAK,6BAA6B,EAClC,KAAK,oCAAoC,EAC1C,MAAM,cAAc,CAAA;AAQrB,KAAK,GAAG,GAAG;IACT,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,SAAS,EAAE;QACT,SAAS,EAAE,eAAe,CAAA;QAC1B,EAAE,EAAE,kBAAkB,CAAA;QACtB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED,MAAM,WAAW,mCACf,SAAQ,oCAAoC,EAC1C,qCAAqC;IACvC,kBAAkB,CAAC,EAAE,6BAA6B,CAAC,oBAAoB,CAAC,CAAA;IACxE,gBAAgB,CAAC,EAAE,6BAA6B,CAAC,kBAAkB,CAAC,CAAA;IACpE,SAAS,CAAC,EAAE,aAAa,CAAC,0CAA0C,CAAC,CAAA;IACrE,gBAAgB,CAAC,EAAE,CACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,aAAa,CAAC,0CAA0C,CAAC,CAAA;CAC/D;AAED,eAAO,MAAM,6CAA6C,6CACd,CAAA;AAE5C,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,OAAO,CAAC,EAAE,mCAAmC,GAC5C,6BAA6B,CAgB/B;AA2ED,wBAAgB,wCAAwC,CACtD,OAAO,CAAC,EAAE,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA6D9C;AAED,MAAM,MAAM,kCAAkC,GAAG,UAAU,CACzD,OAAO,wCAAwC,CAChD,CAAA"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { clientIpKey, enforceRateLimit, parseJsonBody } from "@voyant-travel/hono";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
import { createStorefrontVerificationSendersFromProviders, createStorefrontVerificationService, StorefrontVerificationError, } from "./service.js";
|
|
4
|
+
import { confirmEmailVerificationChallengeSchema, confirmSmsVerificationChallengeSchema, startEmailVerificationChallengeSchema, startSmsVerificationChallengeSchema, } from "./validation.js";
|
|
5
|
+
export const STOREFRONT_VERIFICATION_SENDERS_CONTAINER_KEY = "providers.storefrontVerification.senders";
|
|
6
|
+
export function buildStorefrontVerificationSenders(bindings, options) {
|
|
7
|
+
const senders = {
|
|
8
|
+
sendEmailChallenge: options?.sendEmailChallenge,
|
|
9
|
+
sendSmsChallenge: options?.sendSmsChallenge,
|
|
10
|
+
};
|
|
11
|
+
if (!senders.sendEmailChallenge || !senders.sendSmsChallenge) {
|
|
12
|
+
const providers = options?.resolveProviders?.(bindings) ?? options?.providers;
|
|
13
|
+
if (providers?.length) {
|
|
14
|
+
const providerSenders = createStorefrontVerificationSendersFromProviders(providers, options);
|
|
15
|
+
senders.sendEmailChallenge ??= providerSenders.sendEmailChallenge;
|
|
16
|
+
senders.sendSmsChallenge ??= providerSenders.sendSmsChallenge;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return senders;
|
|
20
|
+
}
|
|
21
|
+
function getSenders(bindings, options, resolveFromContainer) {
|
|
22
|
+
if (resolveFromContainer) {
|
|
23
|
+
try {
|
|
24
|
+
return resolveFromContainer(STOREFRONT_VERIFICATION_SENDERS_CONTAINER_KEY);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Fall back to per-request sender construction when bootstrap has not run.
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return buildStorefrontVerificationSenders(bindings, options);
|
|
31
|
+
}
|
|
32
|
+
function errorResponse(error) {
|
|
33
|
+
if (error instanceof StorefrontVerificationError) {
|
|
34
|
+
if (error.code === "sender_not_configured") {
|
|
35
|
+
return { status: 501, body: { error: error.message, code: error.code } };
|
|
36
|
+
}
|
|
37
|
+
if (error.code === "challenge_not_found") {
|
|
38
|
+
return { status: 404, body: { error: error.message, code: error.code } };
|
|
39
|
+
}
|
|
40
|
+
if (error.code === "challenge_expired") {
|
|
41
|
+
return { status: 410, body: { error: error.message, code: error.code } };
|
|
42
|
+
}
|
|
43
|
+
if (error.code === "challenge_invalid" || error.code === "challenge_failed") {
|
|
44
|
+
return { status: 409, body: { error: error.message, code: error.code } };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const message = error instanceof Error ? error.message : "Verification request failed";
|
|
48
|
+
return { status: 400, body: { error: message } };
|
|
49
|
+
}
|
|
50
|
+
function normalizeDestination(channel, destination) {
|
|
51
|
+
return channel === "email" ? destination.trim().toLowerCase() : destination.trim();
|
|
52
|
+
}
|
|
53
|
+
async function enforceVerificationStartLimits(c, channel, destination) {
|
|
54
|
+
const normalized = normalizeDestination(channel, destination);
|
|
55
|
+
return ((await enforceRateLimit(c, {
|
|
56
|
+
bucket: `storefront-verification:${channel}:destination-cooldown`,
|
|
57
|
+
max: 1,
|
|
58
|
+
windowSeconds: 30,
|
|
59
|
+
clientKey: () => normalized,
|
|
60
|
+
})) ??
|
|
61
|
+
(await enforceRateLimit(c, {
|
|
62
|
+
bucket: `storefront-verification:${channel}:destination-hour`,
|
|
63
|
+
max: channel === "sms" ? 5 : 10,
|
|
64
|
+
windowSeconds: 60 * 60,
|
|
65
|
+
clientKey: () => normalized,
|
|
66
|
+
})) ??
|
|
67
|
+
(await enforceRateLimit(c, {
|
|
68
|
+
bucket: `storefront-verification:${channel}:ip-hour`,
|
|
69
|
+
max: channel === "sms" ? 20 : 40,
|
|
70
|
+
windowSeconds: 60 * 60,
|
|
71
|
+
clientKey: clientIpKey,
|
|
72
|
+
})));
|
|
73
|
+
}
|
|
74
|
+
export function createStorefrontVerificationPublicRoutes(options) {
|
|
75
|
+
const service = createStorefrontVerificationService(options);
|
|
76
|
+
return new Hono()
|
|
77
|
+
.post("/email/start", async (c) => {
|
|
78
|
+
try {
|
|
79
|
+
const body = await parseJsonBody(c, startEmailVerificationChallengeSchema);
|
|
80
|
+
const limited = await enforceVerificationStartLimits(c, "email", body.email);
|
|
81
|
+
if (limited)
|
|
82
|
+
return limited;
|
|
83
|
+
const result = await service.startEmailChallenge(c.get("db"), body, getSenders(c.env, options, (key) => c.var.container.resolve(key)));
|
|
84
|
+
return c.json({ data: result }, 201);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const response = errorResponse(error);
|
|
88
|
+
return c.json(response.body, response.status);
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
.post("/email/confirm", async (c) => {
|
|
92
|
+
try {
|
|
93
|
+
const result = await service.confirmEmailChallenge(c.get("db"), await parseJsonBody(c, confirmEmailVerificationChallengeSchema));
|
|
94
|
+
return c.json({ data: result });
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const response = errorResponse(error);
|
|
98
|
+
return c.json(response.body, response.status);
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
.post("/sms/start", async (c) => {
|
|
102
|
+
try {
|
|
103
|
+
const body = await parseJsonBody(c, startSmsVerificationChallengeSchema);
|
|
104
|
+
const limited = await enforceVerificationStartLimits(c, "sms", body.phone);
|
|
105
|
+
if (limited)
|
|
106
|
+
return limited;
|
|
107
|
+
const result = await service.startSmsChallenge(c.get("db"), body, getSenders(c.env, options, (key) => c.var.container.resolve(key)));
|
|
108
|
+
return c.json({ data: result }, 201);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
const response = errorResponse(error);
|
|
112
|
+
return c.json(response.body, response.status);
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
.post("/sms/confirm", async (c) => {
|
|
116
|
+
try {
|
|
117
|
+
const result = await service.confirmSmsChallenge(c.get("db"), await parseJsonBody(c, confirmSmsVerificationChallengeSchema));
|
|
118
|
+
return c.json({ data: result });
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
const response = errorResponse(error);
|
|
122
|
+
return c.json(response.body, response.status);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import type { LinkableDefinition, Module } from "@voyant-travel/core";
|
|
2
|
+
export declare const storefrontVerificationChannelEnum: import("drizzle-orm/pg-core").PgEnum<["email", "sms"]>;
|
|
3
|
+
export declare const storefrontVerificationStatusEnum: import("drizzle-orm/pg-core").PgEnum<["pending", "verified", "expired", "failed", "cancelled"]>;
|
|
4
|
+
export declare const storefrontVerificationChallenges: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
5
|
+
name: "storefront_verification_challenges";
|
|
6
|
+
schema: undefined;
|
|
7
|
+
columns: {
|
|
8
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
9
|
+
name: string;
|
|
10
|
+
tableName: "storefront_verification_challenges";
|
|
11
|
+
dataType: "string";
|
|
12
|
+
columnType: "PgText";
|
|
13
|
+
data: string;
|
|
14
|
+
driverParam: string;
|
|
15
|
+
notNull: true;
|
|
16
|
+
hasDefault: true;
|
|
17
|
+
isPrimaryKey: true;
|
|
18
|
+
isAutoincrement: false;
|
|
19
|
+
hasRuntimeDefault: true;
|
|
20
|
+
enumValues: [string, ...string[]];
|
|
21
|
+
baseColumn: never;
|
|
22
|
+
identity: undefined;
|
|
23
|
+
generated: undefined;
|
|
24
|
+
}, {}, {}>;
|
|
25
|
+
channel: import("drizzle-orm/pg-core").PgColumn<{
|
|
26
|
+
name: "channel";
|
|
27
|
+
tableName: "storefront_verification_challenges";
|
|
28
|
+
dataType: "string";
|
|
29
|
+
columnType: "PgEnumColumn";
|
|
30
|
+
data: "email" | "sms";
|
|
31
|
+
driverParam: string;
|
|
32
|
+
notNull: true;
|
|
33
|
+
hasDefault: false;
|
|
34
|
+
isPrimaryKey: false;
|
|
35
|
+
isAutoincrement: false;
|
|
36
|
+
hasRuntimeDefault: false;
|
|
37
|
+
enumValues: ["email", "sms"];
|
|
38
|
+
baseColumn: never;
|
|
39
|
+
identity: undefined;
|
|
40
|
+
generated: undefined;
|
|
41
|
+
}, {}, {}>;
|
|
42
|
+
destination: import("drizzle-orm/pg-core").PgColumn<{
|
|
43
|
+
name: "destination";
|
|
44
|
+
tableName: "storefront_verification_challenges";
|
|
45
|
+
dataType: "string";
|
|
46
|
+
columnType: "PgText";
|
|
47
|
+
data: string;
|
|
48
|
+
driverParam: string;
|
|
49
|
+
notNull: true;
|
|
50
|
+
hasDefault: false;
|
|
51
|
+
isPrimaryKey: false;
|
|
52
|
+
isAutoincrement: false;
|
|
53
|
+
hasRuntimeDefault: false;
|
|
54
|
+
enumValues: [string, ...string[]];
|
|
55
|
+
baseColumn: never;
|
|
56
|
+
identity: undefined;
|
|
57
|
+
generated: undefined;
|
|
58
|
+
}, {}, {}>;
|
|
59
|
+
purpose: import("drizzle-orm/pg-core").PgColumn<{
|
|
60
|
+
name: "purpose";
|
|
61
|
+
tableName: "storefront_verification_challenges";
|
|
62
|
+
dataType: "string";
|
|
63
|
+
columnType: "PgText";
|
|
64
|
+
data: string;
|
|
65
|
+
driverParam: string;
|
|
66
|
+
notNull: true;
|
|
67
|
+
hasDefault: true;
|
|
68
|
+
isPrimaryKey: false;
|
|
69
|
+
isAutoincrement: false;
|
|
70
|
+
hasRuntimeDefault: false;
|
|
71
|
+
enumValues: [string, ...string[]];
|
|
72
|
+
baseColumn: never;
|
|
73
|
+
identity: undefined;
|
|
74
|
+
generated: undefined;
|
|
75
|
+
}, {}, {}>;
|
|
76
|
+
codeHash: import("drizzle-orm/pg-core").PgColumn<{
|
|
77
|
+
name: "code_hash";
|
|
78
|
+
tableName: "storefront_verification_challenges";
|
|
79
|
+
dataType: "string";
|
|
80
|
+
columnType: "PgText";
|
|
81
|
+
data: string;
|
|
82
|
+
driverParam: string;
|
|
83
|
+
notNull: true;
|
|
84
|
+
hasDefault: false;
|
|
85
|
+
isPrimaryKey: false;
|
|
86
|
+
isAutoincrement: false;
|
|
87
|
+
hasRuntimeDefault: false;
|
|
88
|
+
enumValues: [string, ...string[]];
|
|
89
|
+
baseColumn: never;
|
|
90
|
+
identity: undefined;
|
|
91
|
+
generated: undefined;
|
|
92
|
+
}, {}, {}>;
|
|
93
|
+
status: import("drizzle-orm/pg-core").PgColumn<{
|
|
94
|
+
name: "status";
|
|
95
|
+
tableName: "storefront_verification_challenges";
|
|
96
|
+
dataType: "string";
|
|
97
|
+
columnType: "PgEnumColumn";
|
|
98
|
+
data: "failed" | "pending" | "cancelled" | "expired" | "verified";
|
|
99
|
+
driverParam: string;
|
|
100
|
+
notNull: true;
|
|
101
|
+
hasDefault: true;
|
|
102
|
+
isPrimaryKey: false;
|
|
103
|
+
isAutoincrement: false;
|
|
104
|
+
hasRuntimeDefault: false;
|
|
105
|
+
enumValues: ["pending", "verified", "expired", "failed", "cancelled"];
|
|
106
|
+
baseColumn: never;
|
|
107
|
+
identity: undefined;
|
|
108
|
+
generated: undefined;
|
|
109
|
+
}, {}, {}>;
|
|
110
|
+
attemptCount: import("drizzle-orm/pg-core").PgColumn<{
|
|
111
|
+
name: "attempt_count";
|
|
112
|
+
tableName: "storefront_verification_challenges";
|
|
113
|
+
dataType: "number";
|
|
114
|
+
columnType: "PgInteger";
|
|
115
|
+
data: number;
|
|
116
|
+
driverParam: string | number;
|
|
117
|
+
notNull: true;
|
|
118
|
+
hasDefault: true;
|
|
119
|
+
isPrimaryKey: false;
|
|
120
|
+
isAutoincrement: false;
|
|
121
|
+
hasRuntimeDefault: false;
|
|
122
|
+
enumValues: undefined;
|
|
123
|
+
baseColumn: never;
|
|
124
|
+
identity: undefined;
|
|
125
|
+
generated: undefined;
|
|
126
|
+
}, {}, {}>;
|
|
127
|
+
maxAttempts: import("drizzle-orm/pg-core").PgColumn<{
|
|
128
|
+
name: "max_attempts";
|
|
129
|
+
tableName: "storefront_verification_challenges";
|
|
130
|
+
dataType: "number";
|
|
131
|
+
columnType: "PgInteger";
|
|
132
|
+
data: number;
|
|
133
|
+
driverParam: string | number;
|
|
134
|
+
notNull: true;
|
|
135
|
+
hasDefault: true;
|
|
136
|
+
isPrimaryKey: false;
|
|
137
|
+
isAutoincrement: false;
|
|
138
|
+
hasRuntimeDefault: false;
|
|
139
|
+
enumValues: undefined;
|
|
140
|
+
baseColumn: never;
|
|
141
|
+
identity: undefined;
|
|
142
|
+
generated: undefined;
|
|
143
|
+
}, {}, {}>;
|
|
144
|
+
expiresAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
145
|
+
name: "expires_at";
|
|
146
|
+
tableName: "storefront_verification_challenges";
|
|
147
|
+
dataType: "date";
|
|
148
|
+
columnType: "PgTimestamp";
|
|
149
|
+
data: Date;
|
|
150
|
+
driverParam: string;
|
|
151
|
+
notNull: true;
|
|
152
|
+
hasDefault: false;
|
|
153
|
+
isPrimaryKey: false;
|
|
154
|
+
isAutoincrement: false;
|
|
155
|
+
hasRuntimeDefault: false;
|
|
156
|
+
enumValues: undefined;
|
|
157
|
+
baseColumn: never;
|
|
158
|
+
identity: undefined;
|
|
159
|
+
generated: undefined;
|
|
160
|
+
}, {}, {}>;
|
|
161
|
+
lastSentAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
162
|
+
name: "last_sent_at";
|
|
163
|
+
tableName: "storefront_verification_challenges";
|
|
164
|
+
dataType: "date";
|
|
165
|
+
columnType: "PgTimestamp";
|
|
166
|
+
data: Date;
|
|
167
|
+
driverParam: string;
|
|
168
|
+
notNull: true;
|
|
169
|
+
hasDefault: true;
|
|
170
|
+
isPrimaryKey: false;
|
|
171
|
+
isAutoincrement: false;
|
|
172
|
+
hasRuntimeDefault: false;
|
|
173
|
+
enumValues: undefined;
|
|
174
|
+
baseColumn: never;
|
|
175
|
+
identity: undefined;
|
|
176
|
+
generated: undefined;
|
|
177
|
+
}, {}, {}>;
|
|
178
|
+
verifiedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
179
|
+
name: "verified_at";
|
|
180
|
+
tableName: "storefront_verification_challenges";
|
|
181
|
+
dataType: "date";
|
|
182
|
+
columnType: "PgTimestamp";
|
|
183
|
+
data: Date;
|
|
184
|
+
driverParam: string;
|
|
185
|
+
notNull: false;
|
|
186
|
+
hasDefault: false;
|
|
187
|
+
isPrimaryKey: false;
|
|
188
|
+
isAutoincrement: false;
|
|
189
|
+
hasRuntimeDefault: false;
|
|
190
|
+
enumValues: undefined;
|
|
191
|
+
baseColumn: never;
|
|
192
|
+
identity: undefined;
|
|
193
|
+
generated: undefined;
|
|
194
|
+
}, {}, {}>;
|
|
195
|
+
failedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
196
|
+
name: "failed_at";
|
|
197
|
+
tableName: "storefront_verification_challenges";
|
|
198
|
+
dataType: "date";
|
|
199
|
+
columnType: "PgTimestamp";
|
|
200
|
+
data: Date;
|
|
201
|
+
driverParam: string;
|
|
202
|
+
notNull: false;
|
|
203
|
+
hasDefault: false;
|
|
204
|
+
isPrimaryKey: false;
|
|
205
|
+
isAutoincrement: false;
|
|
206
|
+
hasRuntimeDefault: false;
|
|
207
|
+
enumValues: undefined;
|
|
208
|
+
baseColumn: never;
|
|
209
|
+
identity: undefined;
|
|
210
|
+
generated: undefined;
|
|
211
|
+
}, {}, {}>;
|
|
212
|
+
metadata: import("drizzle-orm/pg-core").PgColumn<{
|
|
213
|
+
name: "metadata";
|
|
214
|
+
tableName: "storefront_verification_challenges";
|
|
215
|
+
dataType: "json";
|
|
216
|
+
columnType: "PgJsonb";
|
|
217
|
+
data: Record<string, unknown>;
|
|
218
|
+
driverParam: unknown;
|
|
219
|
+
notNull: false;
|
|
220
|
+
hasDefault: false;
|
|
221
|
+
isPrimaryKey: false;
|
|
222
|
+
isAutoincrement: false;
|
|
223
|
+
hasRuntimeDefault: false;
|
|
224
|
+
enumValues: undefined;
|
|
225
|
+
baseColumn: never;
|
|
226
|
+
identity: undefined;
|
|
227
|
+
generated: undefined;
|
|
228
|
+
}, {}, {
|
|
229
|
+
$type: Record<string, unknown>;
|
|
230
|
+
}>;
|
|
231
|
+
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
232
|
+
name: "created_at";
|
|
233
|
+
tableName: "storefront_verification_challenges";
|
|
234
|
+
dataType: "date";
|
|
235
|
+
columnType: "PgTimestamp";
|
|
236
|
+
data: Date;
|
|
237
|
+
driverParam: string;
|
|
238
|
+
notNull: true;
|
|
239
|
+
hasDefault: true;
|
|
240
|
+
isPrimaryKey: false;
|
|
241
|
+
isAutoincrement: false;
|
|
242
|
+
hasRuntimeDefault: false;
|
|
243
|
+
enumValues: undefined;
|
|
244
|
+
baseColumn: never;
|
|
245
|
+
identity: undefined;
|
|
246
|
+
generated: undefined;
|
|
247
|
+
}, {}, {}>;
|
|
248
|
+
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
249
|
+
name: "updated_at";
|
|
250
|
+
tableName: "storefront_verification_challenges";
|
|
251
|
+
dataType: "date";
|
|
252
|
+
columnType: "PgTimestamp";
|
|
253
|
+
data: Date;
|
|
254
|
+
driverParam: string;
|
|
255
|
+
notNull: true;
|
|
256
|
+
hasDefault: true;
|
|
257
|
+
isPrimaryKey: false;
|
|
258
|
+
isAutoincrement: false;
|
|
259
|
+
hasRuntimeDefault: false;
|
|
260
|
+
enumValues: undefined;
|
|
261
|
+
baseColumn: never;
|
|
262
|
+
identity: undefined;
|
|
263
|
+
generated: undefined;
|
|
264
|
+
}, {}, {}>;
|
|
265
|
+
};
|
|
266
|
+
dialect: "pg";
|
|
267
|
+
}>;
|
|
268
|
+
export declare const storefrontVerificationChallengesRelations: import("drizzle-orm").Relations<"storefront_verification_challenges", {}>;
|
|
269
|
+
export type StorefrontVerificationChallenge = typeof storefrontVerificationChallenges.$inferSelect;
|
|
270
|
+
export type NewStorefrontVerificationChallenge = typeof storefrontVerificationChallenges.$inferInsert;
|
|
271
|
+
export declare const storefrontVerificationLinkable: LinkableDefinition;
|
|
272
|
+
export declare const storefrontVerificationModule: Module;
|
|
273
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/verification/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAKrE,eAAO,MAAM,iCAAiC,wDAG5C,CAAA;AAEF,eAAO,MAAM,gCAAgC,iGAM3C,CAAA;AAEF,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgC5C,CAAA;AAED,eAAO,MAAM,yCAAyC,2EAGrD,CAAA;AAED,MAAM,MAAM,+BAA+B,GAAG,OAAO,gCAAgC,CAAC,YAAY,CAAA;AAClG,MAAM,MAAM,kCAAkC,GAC5C,OAAO,gCAAgC,CAAC,YAAY,CAAA;AAEtD,eAAO,MAAM,8BAA8B,EAAE,kBAK5C,CAAA;AAED,eAAO,MAAM,4BAA4B,EAAE,MAK1C,CAAA"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { typeId } from "@voyant-travel/db/lib/typeid-column";
|
|
2
|
+
import { relations } from "drizzle-orm";
|
|
3
|
+
import { index, integer, jsonb, pgEnum, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
|
4
|
+
export const storefrontVerificationChannelEnum = pgEnum("storefront_verification_channel", [
|
|
5
|
+
"email",
|
|
6
|
+
"sms",
|
|
7
|
+
]);
|
|
8
|
+
export const storefrontVerificationStatusEnum = pgEnum("storefront_verification_status", [
|
|
9
|
+
"pending",
|
|
10
|
+
"verified",
|
|
11
|
+
"expired",
|
|
12
|
+
"failed",
|
|
13
|
+
"cancelled",
|
|
14
|
+
]);
|
|
15
|
+
export const storefrontVerificationChallenges = pgTable("storefront_verification_challenges", {
|
|
16
|
+
id: typeId("storefront_verification_challenges"),
|
|
17
|
+
channel: storefrontVerificationChannelEnum("channel").notNull(),
|
|
18
|
+
destination: text("destination").notNull(),
|
|
19
|
+
purpose: text("purpose").notNull().default("contact_confirmation"),
|
|
20
|
+
codeHash: text("code_hash").notNull(),
|
|
21
|
+
status: storefrontVerificationStatusEnum("status").notNull().default("pending"),
|
|
22
|
+
attemptCount: integer("attempt_count").notNull().default(0),
|
|
23
|
+
maxAttempts: integer("max_attempts").notNull().default(5),
|
|
24
|
+
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
|
|
25
|
+
lastSentAt: timestamp("last_sent_at", { withTimezone: true }).notNull().defaultNow(),
|
|
26
|
+
verifiedAt: timestamp("verified_at", { withTimezone: true }),
|
|
27
|
+
failedAt: timestamp("failed_at", { withTimezone: true }),
|
|
28
|
+
metadata: jsonb("metadata").$type(),
|
|
29
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
30
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
31
|
+
}, (table) => [
|
|
32
|
+
index("idx_storefront_verification_channel").on(table.channel),
|
|
33
|
+
index("idx_storefront_verification_destination").on(table.destination),
|
|
34
|
+
index("idx_storefront_verification_purpose").on(table.purpose),
|
|
35
|
+
index("idx_storefront_verification_status").on(table.status),
|
|
36
|
+
index("idx_storefront_verification_lookup").on(table.channel, table.destination, table.purpose, table.updatedAt, table.createdAt),
|
|
37
|
+
]);
|
|
38
|
+
export const storefrontVerificationChallengesRelations = relations(storefrontVerificationChallenges, () => ({}));
|
|
39
|
+
export const storefrontVerificationLinkable = {
|
|
40
|
+
module: "storefront-verification",
|
|
41
|
+
entity: "storefrontVerificationChallenge",
|
|
42
|
+
table: "storefront_verification_challenges",
|
|
43
|
+
idPrefix: "svch",
|
|
44
|
+
};
|
|
45
|
+
export const storefrontVerificationModule = {
|
|
46
|
+
name: "storefront-verification",
|
|
47
|
+
linkable: {
|
|
48
|
+
storefrontVerificationChallenge: storefrontVerificationLinkable,
|
|
49
|
+
},
|
|
50
|
+
};
|