@voyantjs/storefront 0.47.0 → 0.49.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/README.md +39 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/routes-public.d.ts +55 -2
- package/dist/routes-public.d.ts.map +1 -1
- package/dist/routes-public.js +37 -1
- package/dist/service-intake.d.ts +40 -0
- package/dist/service-intake.d.ts.map +1 -0
- package/dist/service-intake.js +231 -0
- package/dist/service.d.ts +40 -3
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +14 -0
- package/dist/validation.d.ts +152 -7
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +67 -0
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -3,6 +3,45 @@
|
|
|
3
3
|
Public storefront routes and service helpers for checkout-adjacent product, departure,
|
|
4
4
|
offer, and eligibility flows.
|
|
5
5
|
|
|
6
|
+
## Public Intake
|
|
7
|
+
|
|
8
|
+
Storefront can accept public CRM intake at the public root:
|
|
9
|
+
|
|
10
|
+
- `POST /leads`
|
|
11
|
+
- `POST /newsletter/subscribe`
|
|
12
|
+
|
|
13
|
+
When mounted through `createStorefrontHonoModule`, these become
|
|
14
|
+
`/v1/public/leads` and `/v1/public/newsletter/subscribe`.
|
|
15
|
+
|
|
16
|
+
Both routes create a CRM person and a CRM customer signal. Lead intake accepts
|
|
17
|
+
the CRM signal `kind`, `source`, product/option references, bounded payload
|
|
18
|
+
metadata, and consent metadata. Newsletter intake records a `notify` signal and
|
|
19
|
+
uses `sourceSubmissionId` for idempotency; when omitted, the email address is
|
|
20
|
+
used to derive a stable newsletter submission key.
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { createStorefrontHonoModule } from "@voyantjs/storefront"
|
|
24
|
+
|
|
25
|
+
createStorefrontHonoModule({
|
|
26
|
+
intake: {
|
|
27
|
+
guard({ body, context }) {
|
|
28
|
+
// Install host-owned rate-limit, captcha, signature, or abuse checks.
|
|
29
|
+
if (!isCaptchaValid(body, context)) {
|
|
30
|
+
return { allowed: false, status: 429, error: "Captcha required" }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
async requestNewsletterDoubleOptIn({ email, signalId }) {
|
|
34
|
+
await sendDoubleOptInEmail(email, { signalId })
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Accepted intake emits `customer.signal.created` on the app event bus with
|
|
41
|
+
`metadata.category: "domain"` and an `intake` payload describing whether the
|
|
42
|
+
signal came from `lead` or `newsletter` intake. Notification adapters can
|
|
43
|
+
subscribe to that event to send CRM email, Slack, or other operator alerts.
|
|
44
|
+
|
|
6
45
|
## Transport Eligibility
|
|
7
46
|
|
|
8
47
|
Storefronts can check whether traveler document facts satisfy departure-level
|
package/dist/index.d.ts
CHANGED
|
@@ -5,9 +5,11 @@ export type { StorefrontPublicRoutes } from "./routes-public.js";
|
|
|
5
5
|
export { createStorefrontPublicRoutes } from "./routes-public.js";
|
|
6
6
|
export type { StorefrontOfferResolvers, StorefrontRequestContext, StorefrontServiceOptions, } from "./service.js";
|
|
7
7
|
export { createStorefrontService, resolveStorefrontSettings } from "./service.js";
|
|
8
|
+
export type { StorefrontIntakeGuard, StorefrontIntakeGuardDecision, StorefrontIntakeOptions, StorefrontNewsletterDoubleOptInHook, } from "./service-intake.js";
|
|
9
|
+
export { CUSTOMER_SIGNAL_CREATED_EVENT } from "./service-intake.js";
|
|
8
10
|
export { evaluateStorefrontTransportEligibility } from "./service-transport-eligibility.js";
|
|
9
|
-
export type { StorefrontAppliedOffer, StorefrontDepartureListQuery, StorefrontFormField, StorefrontFormFieldInput, StorefrontOfferApplyInput, StorefrontOfferMutationResult, StorefrontOfferRedeemInput, StorefrontPaymentMethod, StorefrontPaymentMethodCode, StorefrontPaymentMethodInput, StorefrontProductAvailabilitySummaryQuery, StorefrontPromotionalOffer, StorefrontSettings, StorefrontSettingsInput, } from "./validation.js";
|
|
10
|
-
export { storefrontAppliedOfferSchema, storefrontDepartureItinerarySchema, storefrontDepartureListQuerySchema, storefrontDepartureListResponseSchema, storefrontDeparturePricePreviewInputSchema, storefrontDeparturePricePreviewSchema, storefrontDepartureSchema, storefrontFormFieldInputSchema, storefrontFormFieldOptionSchema, storefrontFormFieldSchema, storefrontFormFieldTypeSchema, storefrontOfferApplyInputSchema, storefrontOfferAudienceSchema, storefrontOfferConflictSchema, storefrontOfferMutationReasonSchema, storefrontOfferMutationResponseSchema, storefrontOfferMutationResultSchema, storefrontOfferMutationStatusSchema, storefrontOfferRedeemInputSchema, storefrontPaymentMethodCodeSchema, storefrontPaymentMethodInputSchema, storefrontPaymentMethodSchema, storefrontProductAvailabilitySlotSchema, storefrontProductAvailabilityStateSchema, storefrontProductAvailabilitySummaryQuerySchema, storefrontProductAvailabilitySummaryResponseSchema, storefrontProductAvailabilitySummarySchema, storefrontProductExtensionsQuerySchema, storefrontProductExtensionsResponseSchema, storefrontPromotionalOfferListQuerySchema, storefrontPromotionalOfferListResponseSchema, storefrontPromotionalOfferResponseSchema, storefrontPromotionalOfferSchema, storefrontSettingsInputSchema, storefrontSettingsSchema, } from "./validation.js";
|
|
11
|
+
export type { StorefrontAppliedOffer, StorefrontDepartureListQuery, StorefrontFormField, StorefrontFormFieldInput, StorefrontIntakeConsent, StorefrontIntakeResponse, StorefrontLeadContact, StorefrontLeadIntakeInput, StorefrontNewsletterSubscribeInput, StorefrontNewsletterSubscribeResponse, StorefrontOfferApplyInput, StorefrontOfferMutationResult, StorefrontOfferRedeemInput, StorefrontPaymentMethod, StorefrontPaymentMethodCode, StorefrontPaymentMethodInput, StorefrontProductAvailabilitySummaryQuery, StorefrontPromotionalOffer, StorefrontSettings, StorefrontSettingsInput, } from "./validation.js";
|
|
12
|
+
export { storefrontAppliedOfferSchema, storefrontDepartureItinerarySchema, storefrontDepartureListQuerySchema, storefrontDepartureListResponseSchema, storefrontDeparturePricePreviewInputSchema, storefrontDeparturePricePreviewSchema, storefrontDepartureSchema, storefrontFormFieldInputSchema, storefrontFormFieldOptionSchema, storefrontFormFieldSchema, storefrontFormFieldTypeSchema, storefrontIntakeConsentSchema, storefrontIntakeResponseSchema, storefrontLeadContactSchema, storefrontLeadIntakeInputSchema, storefrontNewsletterSubscribeInputSchema, storefrontNewsletterSubscribeResponseSchema, storefrontOfferApplyInputSchema, storefrontOfferAudienceSchema, storefrontOfferConflictSchema, storefrontOfferMutationReasonSchema, storefrontOfferMutationResponseSchema, storefrontOfferMutationResultSchema, storefrontOfferMutationStatusSchema, storefrontOfferRedeemInputSchema, storefrontPaymentMethodCodeSchema, storefrontPaymentMethodInputSchema, storefrontPaymentMethodSchema, storefrontProductAvailabilitySlotSchema, storefrontProductAvailabilityStateSchema, storefrontProductAvailabilitySummaryQuerySchema, storefrontProductAvailabilitySummaryResponseSchema, storefrontProductAvailabilitySummarySchema, storefrontProductExtensionsQuerySchema, storefrontProductExtensionsResponseSchema, storefrontPromotionalOfferListQuerySchema, storefrontPromotionalOfferListResponseSchema, storefrontPromotionalOfferResponseSchema, storefrontPromotionalOfferSchema, storefrontSettingsInputSchema, storefrontSettingsSchema, } from "./validation.js";
|
|
11
13
|
export type { StorefrontTransportEligibilityInput, StorefrontTransportEligibilityIssue, StorefrontTransportEligibilityResult, StorefrontTransportEligibilityRule, StorefrontTransportEligibilityRuleInput, } from "./validation-transport-eligibility.js";
|
|
12
14
|
export { storefrontRequiredDocumentTypeSchema, storefrontTransportEligibilityDocumentInputSchema, storefrontTransportEligibilityInputSchema, storefrontTransportEligibilityIssueCodeSchema, storefrontTransportEligibilityIssueSchema, storefrontTransportEligibilityResultSchema, storefrontTransportEligibilityRuleSchema, storefrontTransportEligibilitySeveritySchema, storefrontTransportEligibilityTravelerInputSchema, storefrontTransportEligibilityTravelerResultSchema, storefrontTravelDocumentTypeSchema, } from "./validation-transport-eligibility.js";
|
|
13
15
|
export declare const storefrontModule: Module;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AAEjE,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AACjE,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACjF,OAAO,EAAE,sCAAsC,EAAE,MAAM,oCAAoC,CAAA;AAC3F,YAAY,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,EACvB,2BAA2B,EAC3B,4BAA4B,EAC5B,yCAAyC,EACzC,0BAA0B,EAC1B,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,4BAA4B,EAC5B,kCAAkC,EAClC,kCAAkC,EAClC,qCAAqC,EACrC,0CAA0C,EAC1C,qCAAqC,EACrC,yBAAyB,EACzB,8BAA8B,EAC9B,+BAA+B,EAC/B,yBAAyB,EACzB,6BAA6B,EAC7B,+BAA+B,EAC/B,6BAA6B,EAC7B,6BAA6B,EAC7B,mCAAmC,EACnC,qCAAqC,EACrC,mCAAmC,EACnC,mCAAmC,EACnC,gCAAgC,EAChC,iCAAiC,EACjC,kCAAkC,EAClC,6BAA6B,EAC7B,uCAAuC,EACvC,wCAAwC,EACxC,+CAA+C,EAC/C,kDAAkD,EAClD,0CAA0C,EAC1C,sCAAsC,EACtC,yCAAyC,EACzC,yCAAyC,EACzC,4CAA4C,EAC5C,wCAAwC,EACxC,gCAAgC,EAChC,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,mCAAmC,EACnC,mCAAmC,EACnC,oCAAoC,EACpC,kCAAkC,EAClC,uCAAuC,GACxC,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EACL,oCAAoC,EACpC,iDAAiD,EACjD,yCAAyC,EACzC,6CAA6C,EAC7C,yCAAyC,EACzC,0CAA0C,EAC1C,wCAAwC,EACxC,4CAA4C,EAC5C,iDAAiD,EACjD,kDAAkD,EAClD,kCAAkC,GACnC,MAAM,uCAAuC,CAAA;AAE9C,eAAO,MAAM,gBAAgB,EAAE,MAE9B,CAAA;AAED,wBAAgB,0BAA0B,CACxC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAC,CAAC,CAAC,GAC3D,UAAU,CAMZ"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAEvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AAEjE,YAAY,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAA;AACjE,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACjF,YAAY,EACV,qBAAqB,EACrB,6BAA6B,EAC7B,uBAAuB,EACvB,mCAAmC,GACpC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,6BAA6B,EAAE,MAAM,qBAAqB,CAAA;AACnE,OAAO,EAAE,sCAAsC,EAAE,MAAM,oCAAoC,CAAA;AAC3F,YAAY,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,EACzB,kCAAkC,EAClC,qCAAqC,EACrC,yBAAyB,EACzB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,EACvB,2BAA2B,EAC3B,4BAA4B,EAC5B,yCAAyC,EACzC,0BAA0B,EAC1B,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,4BAA4B,EAC5B,kCAAkC,EAClC,kCAAkC,EAClC,qCAAqC,EACrC,0CAA0C,EAC1C,qCAAqC,EACrC,yBAAyB,EACzB,8BAA8B,EAC9B,+BAA+B,EAC/B,yBAAyB,EACzB,6BAA6B,EAC7B,6BAA6B,EAC7B,8BAA8B,EAC9B,2BAA2B,EAC3B,+BAA+B,EAC/B,wCAAwC,EACxC,2CAA2C,EAC3C,+BAA+B,EAC/B,6BAA6B,EAC7B,6BAA6B,EAC7B,mCAAmC,EACnC,qCAAqC,EACrC,mCAAmC,EACnC,mCAAmC,EACnC,gCAAgC,EAChC,iCAAiC,EACjC,kCAAkC,EAClC,6BAA6B,EAC7B,uCAAuC,EACvC,wCAAwC,EACxC,+CAA+C,EAC/C,kDAAkD,EAClD,0CAA0C,EAC1C,sCAAsC,EACtC,yCAAyC,EACzC,yCAAyC,EACzC,4CAA4C,EAC5C,wCAAwC,EACxC,gCAAgC,EAChC,6BAA6B,EAC7B,wBAAwB,GACzB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EACV,mCAAmC,EACnC,mCAAmC,EACnC,oCAAoC,EACpC,kCAAkC,EAClC,uCAAuC,GACxC,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EACL,oCAAoC,EACpC,iDAAiD,EACjD,yCAAyC,EACzC,6CAA6C,EAC7C,yCAAyC,EACzC,0CAA0C,EAC1C,wCAAwC,EACxC,4CAA4C,EAC5C,iDAAiD,EACjD,kDAAkD,EAClD,kCAAkC,GACnC,MAAM,uCAAuC,CAAA;AAE9C,eAAO,MAAM,gBAAgB,EAAE,MAE9B,CAAA;AAED,wBAAgB,0BAA0B,CACxC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAC,CAAC,CAAC,GAC3D,UAAU,CAMZ"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createStorefrontPublicRoutes } from "./routes-public.js";
|
|
2
2
|
export { createStorefrontPublicRoutes } from "./routes-public.js";
|
|
3
3
|
export { createStorefrontService, resolveStorefrontSettings } from "./service.js";
|
|
4
|
+
export { CUSTOMER_SIGNAL_CREATED_EVENT } from "./service-intake.js";
|
|
4
5
|
export { evaluateStorefrontTransportEligibility } from "./service-transport-eligibility.js";
|
|
5
|
-
export { storefrontAppliedOfferSchema, storefrontDepartureItinerarySchema, storefrontDepartureListQuerySchema, storefrontDepartureListResponseSchema, storefrontDeparturePricePreviewInputSchema, storefrontDeparturePricePreviewSchema, storefrontDepartureSchema, storefrontFormFieldInputSchema, storefrontFormFieldOptionSchema, storefrontFormFieldSchema, storefrontFormFieldTypeSchema, storefrontOfferApplyInputSchema, storefrontOfferAudienceSchema, storefrontOfferConflictSchema, storefrontOfferMutationReasonSchema, storefrontOfferMutationResponseSchema, storefrontOfferMutationResultSchema, storefrontOfferMutationStatusSchema, storefrontOfferRedeemInputSchema, storefrontPaymentMethodCodeSchema, storefrontPaymentMethodInputSchema, storefrontPaymentMethodSchema, storefrontProductAvailabilitySlotSchema, storefrontProductAvailabilityStateSchema, storefrontProductAvailabilitySummaryQuerySchema, storefrontProductAvailabilitySummaryResponseSchema, storefrontProductAvailabilitySummarySchema, storefrontProductExtensionsQuerySchema, storefrontProductExtensionsResponseSchema, storefrontPromotionalOfferListQuerySchema, storefrontPromotionalOfferListResponseSchema, storefrontPromotionalOfferResponseSchema, storefrontPromotionalOfferSchema, storefrontSettingsInputSchema, storefrontSettingsSchema, } from "./validation.js";
|
|
6
|
+
export { storefrontAppliedOfferSchema, storefrontDepartureItinerarySchema, storefrontDepartureListQuerySchema, storefrontDepartureListResponseSchema, storefrontDeparturePricePreviewInputSchema, storefrontDeparturePricePreviewSchema, storefrontDepartureSchema, storefrontFormFieldInputSchema, storefrontFormFieldOptionSchema, storefrontFormFieldSchema, storefrontFormFieldTypeSchema, storefrontIntakeConsentSchema, storefrontIntakeResponseSchema, storefrontLeadContactSchema, storefrontLeadIntakeInputSchema, storefrontNewsletterSubscribeInputSchema, storefrontNewsletterSubscribeResponseSchema, storefrontOfferApplyInputSchema, storefrontOfferAudienceSchema, storefrontOfferConflictSchema, storefrontOfferMutationReasonSchema, storefrontOfferMutationResponseSchema, storefrontOfferMutationResultSchema, storefrontOfferMutationStatusSchema, storefrontOfferRedeemInputSchema, storefrontPaymentMethodCodeSchema, storefrontPaymentMethodInputSchema, storefrontPaymentMethodSchema, storefrontProductAvailabilitySlotSchema, storefrontProductAvailabilityStateSchema, storefrontProductAvailabilitySummaryQuerySchema, storefrontProductAvailabilitySummaryResponseSchema, storefrontProductAvailabilitySummarySchema, storefrontProductExtensionsQuerySchema, storefrontProductExtensionsResponseSchema, storefrontPromotionalOfferListQuerySchema, storefrontPromotionalOfferListResponseSchema, storefrontPromotionalOfferResponseSchema, storefrontPromotionalOfferSchema, storefrontSettingsInputSchema, storefrontSettingsSchema, } from "./validation.js";
|
|
6
7
|
export { storefrontRequiredDocumentTypeSchema, storefrontTransportEligibilityDocumentInputSchema, storefrontTransportEligibilityInputSchema, storefrontTransportEligibilityIssueCodeSchema, storefrontTransportEligibilityIssueSchema, storefrontTransportEligibilityResultSchema, storefrontTransportEligibilityRuleSchema, storefrontTransportEligibilitySeveritySchema, storefrontTransportEligibilityTravelerInputSchema, storefrontTransportEligibilityTravelerResultSchema, storefrontTravelDocumentTypeSchema, } from "./validation-transport-eligibility.js";
|
|
7
8
|
export const storefrontModule = {
|
|
8
9
|
name: "storefront",
|
package/dist/routes-public.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { EventBus } from "@voyantjs/core";
|
|
1
2
|
import { type StorefrontServiceOptions } from "./service.js";
|
|
2
3
|
type Env = {
|
|
3
4
|
Variables: {
|
|
4
5
|
db: unknown;
|
|
6
|
+
eventBus?: EventBus;
|
|
5
7
|
};
|
|
6
8
|
};
|
|
7
9
|
export declare function createStorefrontPublicRoutes(options?: StorefrontServiceOptions): import("hono/hono-base").HonoBase<Env, {
|
|
@@ -56,9 +58,9 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
56
58
|
};
|
|
57
59
|
};
|
|
58
60
|
payment: {
|
|
59
|
-
defaultMethod: "voucher" | "
|
|
61
|
+
defaultMethod: "voucher" | "bank_transfer" | "card" | "cash" | "invoice" | null;
|
|
60
62
|
methods: {
|
|
61
|
-
code: "voucher" | "
|
|
63
|
+
code: "voucher" | "bank_transfer" | "card" | "cash" | "invoice";
|
|
62
64
|
label: string;
|
|
63
65
|
description: string | null;
|
|
64
66
|
enabled: boolean;
|
|
@@ -70,6 +72,57 @@ export declare function createStorefrontPublicRoutes(options?: StorefrontService
|
|
|
70
72
|
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
71
73
|
};
|
|
72
74
|
};
|
|
75
|
+
} & {
|
|
76
|
+
"/leads": {
|
|
77
|
+
$post: {
|
|
78
|
+
input: {};
|
|
79
|
+
output: {
|
|
80
|
+
error: string;
|
|
81
|
+
};
|
|
82
|
+
outputFormat: "json";
|
|
83
|
+
status: 400 | 403 | 429;
|
|
84
|
+
} | {
|
|
85
|
+
input: {};
|
|
86
|
+
output: {
|
|
87
|
+
data: {
|
|
88
|
+
id: string;
|
|
89
|
+
personId: string;
|
|
90
|
+
kind: "wishlist" | "notify" | "inquiry" | "request_offer" | "referral";
|
|
91
|
+
source: "admin" | "form" | "phone" | "website" | "booking" | "abandoned_cart";
|
|
92
|
+
status: "expired" | "converted" | "lost" | "new" | "contacted" | "qualified";
|
|
93
|
+
duplicate: boolean;
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
outputFormat: "json";
|
|
97
|
+
status: 201;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
} & {
|
|
101
|
+
"/newsletter/subscribe": {
|
|
102
|
+
$post: {
|
|
103
|
+
input: {};
|
|
104
|
+
output: {
|
|
105
|
+
error: string;
|
|
106
|
+
};
|
|
107
|
+
outputFormat: "json";
|
|
108
|
+
status: 400 | 403 | 429;
|
|
109
|
+
} | {
|
|
110
|
+
input: {};
|
|
111
|
+
output: {
|
|
112
|
+
data: {
|
|
113
|
+
id: string;
|
|
114
|
+
personId: string;
|
|
115
|
+
kind: "wishlist" | "notify" | "inquiry" | "request_offer" | "referral";
|
|
116
|
+
source: "admin" | "form" | "phone" | "website" | "booking" | "abandoned_cart";
|
|
117
|
+
status: "expired" | "converted" | "lost" | "new" | "contacted" | "qualified";
|
|
118
|
+
duplicate: boolean;
|
|
119
|
+
doubleOptIn: "not_configured" | "requested";
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
outputFormat: "json";
|
|
123
|
+
status: 202;
|
|
124
|
+
};
|
|
125
|
+
};
|
|
73
126
|
} & {
|
|
74
127
|
"/departures/:departureId": {
|
|
75
128
|
$get: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"routes-public.d.ts","sourceRoot":"","sources":["../src/routes-public.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAK9C,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAA;AAgBrB,KAAK,GAAG,GAAG;IACT,SAAS,EAAE;QACT,EAAE,EAAE,OAAO,CAAA;QACX,QAAQ,CAAC,EAAE,QAAQ,CAAA;KACpB,CAAA;CACF,CAAA;AAED,wBAAgB,4BAA4B,CAAC,OAAO,CAAC,EAAE,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BA+L9E;AAED,MAAM,MAAM,sBAAsB,GAAG,UAAU,CAAC,OAAO,4BAA4B,CAAC,CAAA"}
|
package/dist/routes-public.js
CHANGED
|
@@ -1,20 +1,56 @@
|
|
|
1
1
|
import { parseJsonBody, parseQuery } from "@voyantjs/hono";
|
|
2
2
|
import { Hono } from "hono";
|
|
3
3
|
import { createStorefrontService, } from "./service.js";
|
|
4
|
-
import { storefrontDepartureListQuerySchema, storefrontDeparturePricePreviewInputSchema, storefrontOfferApplyInputSchema, storefrontOfferRedeemInputSchema, storefrontProductAvailabilitySummaryQuerySchema, storefrontProductExtensionsQuerySchema, storefrontPromotionalOfferListQuerySchema, } from "./validation.js";
|
|
4
|
+
import { storefrontDepartureListQuerySchema, storefrontDeparturePricePreviewInputSchema, storefrontLeadIntakeInputSchema, storefrontNewsletterSubscribeInputSchema, storefrontOfferApplyInputSchema, storefrontOfferRedeemInputSchema, storefrontProductAvailabilitySummaryQuerySchema, storefrontProductExtensionsQuerySchema, storefrontPromotionalOfferListQuerySchema, } from "./validation.js";
|
|
5
5
|
import { storefrontTransportEligibilityInputSchema } from "./validation-transport-eligibility.js";
|
|
6
6
|
export function createStorefrontPublicRoutes(options) {
|
|
7
7
|
const storefrontService = createStorefrontService(options);
|
|
8
8
|
function getRequestContext(c) {
|
|
9
9
|
return {
|
|
10
10
|
db: c.get("db"),
|
|
11
|
+
eventBus: c.get("eventBus"),
|
|
11
12
|
env: c.env,
|
|
12
13
|
context: c,
|
|
13
14
|
};
|
|
14
15
|
}
|
|
16
|
+
async function runIntakeGuard(input) {
|
|
17
|
+
const decision = await storefrontService.checkIntakeGuard(input);
|
|
18
|
+
if (!decision || decision.allowed)
|
|
19
|
+
return null;
|
|
20
|
+
return {
|
|
21
|
+
status: decision.status ?? 403,
|
|
22
|
+
error: decision.error ?? "Storefront intake rejected",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
15
25
|
return new Hono()
|
|
16
26
|
.get("/settings", async (c) => {
|
|
17
27
|
return c.json({ data: await storefrontService.resolveSettings(getRequestContext(c)) });
|
|
28
|
+
})
|
|
29
|
+
.post("/leads", async (c) => {
|
|
30
|
+
const context = getRequestContext(c);
|
|
31
|
+
const body = await parseJsonBody(c, storefrontLeadIntakeInputSchema);
|
|
32
|
+
const rejected = await runIntakeGuard({ kind: "lead", body, context });
|
|
33
|
+
if (rejected)
|
|
34
|
+
return c.json({ error: rejected.error }, rejected.status);
|
|
35
|
+
return c.json({
|
|
36
|
+
data: await storefrontService.createLead({
|
|
37
|
+
body,
|
|
38
|
+
context,
|
|
39
|
+
}),
|
|
40
|
+
}, 201);
|
|
41
|
+
})
|
|
42
|
+
.post("/newsletter/subscribe", async (c) => {
|
|
43
|
+
const context = getRequestContext(c);
|
|
44
|
+
const body = await parseJsonBody(c, storefrontNewsletterSubscribeInputSchema);
|
|
45
|
+
const rejected = await runIntakeGuard({ kind: "newsletter", body, context });
|
|
46
|
+
if (rejected)
|
|
47
|
+
return c.json({ error: rejected.error }, rejected.status);
|
|
48
|
+
return c.json({
|
|
49
|
+
data: await storefrontService.subscribeNewsletter({
|
|
50
|
+
body,
|
|
51
|
+
context,
|
|
52
|
+
}),
|
|
53
|
+
}, 202);
|
|
18
54
|
})
|
|
19
55
|
.get("/departures/:departureId", async (c) => {
|
|
20
56
|
const departure = await storefrontService.getDeparture(c.get("db"), c.req.param("departureId"));
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CUSTOMER_SIGNAL_CREATED_EVENT } from "@voyantjs/crm/events";
|
|
2
|
+
import type { StorefrontRequestContext } from "./service.js";
|
|
3
|
+
import type { StorefrontIntakeResponse, StorefrontLeadIntakeInput, StorefrontNewsletterSubscribeInput, StorefrontNewsletterSubscribeResponse } from "./validation.js";
|
|
4
|
+
export { CUSTOMER_SIGNAL_CREATED_EVENT };
|
|
5
|
+
export interface StorefrontIntakeGuardDecision {
|
|
6
|
+
allowed: boolean;
|
|
7
|
+
status?: 400 | 403 | 429;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
export type StorefrontIntakeGuard = (input: {
|
|
11
|
+
kind: "lead";
|
|
12
|
+
body: StorefrontLeadIntakeInput;
|
|
13
|
+
context: StorefrontRequestContext;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "newsletter";
|
|
16
|
+
body: StorefrontNewsletterSubscribeInput;
|
|
17
|
+
context: StorefrontRequestContext;
|
|
18
|
+
}) => Promise<StorefrontIntakeGuardDecision | undefined> | StorefrontIntakeGuardDecision | undefined;
|
|
19
|
+
export type StorefrontNewsletterDoubleOptInHook = (input: {
|
|
20
|
+
email: string;
|
|
21
|
+
personId: string;
|
|
22
|
+
signalId: string;
|
|
23
|
+
sourceSubmissionId: string;
|
|
24
|
+
body: StorefrontNewsletterSubscribeInput;
|
|
25
|
+
context: StorefrontRequestContext;
|
|
26
|
+
}) => Promise<void> | void;
|
|
27
|
+
export interface StorefrontIntakeOptions {
|
|
28
|
+
guard?: StorefrontIntakeGuard;
|
|
29
|
+
requestNewsletterDoubleOptIn?: StorefrontNewsletterDoubleOptInHook;
|
|
30
|
+
}
|
|
31
|
+
export declare function createStorefrontLeadSignal(input: {
|
|
32
|
+
body: StorefrontLeadIntakeInput;
|
|
33
|
+
context: StorefrontRequestContext;
|
|
34
|
+
}): Promise<StorefrontIntakeResponse>;
|
|
35
|
+
export declare function subscribeStorefrontNewsletter(input: {
|
|
36
|
+
body: StorefrontNewsletterSubscribeInput;
|
|
37
|
+
context: StorefrontRequestContext;
|
|
38
|
+
requestDoubleOptIn?: StorefrontNewsletterDoubleOptInHook;
|
|
39
|
+
}): Promise<StorefrontNewsletterSubscribeResponse>;
|
|
40
|
+
//# sourceMappingURL=service-intake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-intake.d.ts","sourceRoot":"","sources":["../src/service-intake.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,6BAA6B,EAA6B,MAAM,sBAAsB,CAAA;AAI/F,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAC5D,OAAO,KAAK,EACV,wBAAwB,EAExB,yBAAyB,EACzB,kCAAkC,EAClC,qCAAqC,EACtC,MAAM,iBAAiB,CAAA;AAExB,OAAO,EAAE,6BAA6B,EAAE,CAAA;AAExC,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,KAAK,EACD;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,yBAAyB,CAAA;IAC/B,OAAO,EAAE,wBAAwB,CAAA;CAClC,GACD;IACE,IAAI,EAAE,YAAY,CAAA;IAClB,IAAI,EAAE,kCAAkC,CAAA;IACxC,OAAO,EAAE,wBAAwB,CAAA;CAClC,KACF,OAAO,CAAC,6BAA6B,GAAG,SAAS,CAAC,GAAG,6BAA6B,GAAG,SAAS,CAAA;AAEnG,MAAM,MAAM,mCAAmC,GAAG,CAAC,KAAK,EAAE;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,IAAI,EAAE,kCAAkC,CAAA;IACxC,OAAO,EAAE,wBAAwB,CAAA;CAClC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAE1B,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,qBAAqB,CAAA;IAC7B,4BAA4B,CAAC,EAAE,mCAAmC,CAAA;CACnE;AA+GD,wBAAsB,0BAA0B,CAAC,KAAK,EAAE;IACtD,IAAI,EAAE,yBAAyB,CAAA;IAC/B,OAAO,EAAE,wBAAwB,CAAA;CAClC,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA8DpC;AAED,wBAAsB,6BAA6B,CAAC,KAAK,EAAE;IACzD,IAAI,EAAE,kCAAkC,CAAA;IACxC,OAAO,EAAE,wBAAwB,CAAA;IACjC,kBAAkB,CAAC,EAAE,mCAAmC,CAAA;CACzD,GAAG,OAAO,CAAC,qCAAqC,CAAC,CA6FjD"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { crmService } from "@voyantjs/crm";
|
|
2
|
+
import { CUSTOMER_SIGNAL_CREATED_EVENT, emitCustomerSignalCreated } from "@voyantjs/crm/events";
|
|
3
|
+
import { customerSignals } from "@voyantjs/crm/schema";
|
|
4
|
+
import { and, eq } from "drizzle-orm";
|
|
5
|
+
export { CUSTOMER_SIGNAL_CREATED_EVENT };
|
|
6
|
+
function requireDb(context) {
|
|
7
|
+
if (!context.db) {
|
|
8
|
+
throw new Error("Storefront intake requires a request database");
|
|
9
|
+
}
|
|
10
|
+
return context.db;
|
|
11
|
+
}
|
|
12
|
+
function splitName(name) {
|
|
13
|
+
if (!name)
|
|
14
|
+
return {};
|
|
15
|
+
const parts = name.trim().split(/\s+/);
|
|
16
|
+
if (parts.length === 0)
|
|
17
|
+
return {};
|
|
18
|
+
if (parts.length === 1)
|
|
19
|
+
return { firstName: parts[0] };
|
|
20
|
+
return { firstName: parts[0], lastName: parts.slice(1).join(" ") };
|
|
21
|
+
}
|
|
22
|
+
function personNameFromContact(contact) {
|
|
23
|
+
const split = splitName(contact.name);
|
|
24
|
+
return {
|
|
25
|
+
firstName: contact.firstName ?? split.firstName ?? "Storefront",
|
|
26
|
+
lastName: contact.lastName ?? split.lastName ?? "Lead",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function personNameFromNewsletter(input) {
|
|
30
|
+
const split = splitName(input.name);
|
|
31
|
+
const emailLocalPart = input.email
|
|
32
|
+
.split("@")[0]
|
|
33
|
+
?.replace(/[._-]+/g, " ")
|
|
34
|
+
.trim();
|
|
35
|
+
return {
|
|
36
|
+
firstName: input.firstName ?? split.firstName ?? emailLocalPart ?? "Newsletter",
|
|
37
|
+
lastName: input.lastName ?? split.lastName ?? "Subscriber",
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function normalizeEmail(email) {
|
|
41
|
+
return email.trim().toLowerCase();
|
|
42
|
+
}
|
|
43
|
+
function defaultNewsletterSubmissionId(email) {
|
|
44
|
+
return `newsletter:${normalizeEmail(email)}`;
|
|
45
|
+
}
|
|
46
|
+
async function findExistingSignal(db, input) {
|
|
47
|
+
if (!input.sourceSubmissionId)
|
|
48
|
+
return null;
|
|
49
|
+
const [row] = await db
|
|
50
|
+
.select()
|
|
51
|
+
.from(customerSignals)
|
|
52
|
+
.where(and(eq(customerSignals.kind, input.kind), eq(customerSignals.sourceSubmissionId, input.sourceSubmissionId)))
|
|
53
|
+
.limit(1);
|
|
54
|
+
return row ?? null;
|
|
55
|
+
}
|
|
56
|
+
function leadResponse(signal, duplicate) {
|
|
57
|
+
return {
|
|
58
|
+
id: signal.id,
|
|
59
|
+
personId: signal.personId,
|
|
60
|
+
kind: signal.kind,
|
|
61
|
+
source: signal.source,
|
|
62
|
+
status: signal.status,
|
|
63
|
+
duplicate,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function newsletterDoubleOptInFromSignal(signal) {
|
|
67
|
+
const metadata = signal.metadata;
|
|
68
|
+
const newsletter = metadata && typeof metadata === "object" && "newsletter" in metadata
|
|
69
|
+
? metadata.newsletter
|
|
70
|
+
: null;
|
|
71
|
+
if (!newsletter || typeof newsletter !== "object" || !("doubleOptIn" in newsletter)) {
|
|
72
|
+
return "not_configured";
|
|
73
|
+
}
|
|
74
|
+
return newsletter.doubleOptIn === "requested" ? "requested" : "not_configured";
|
|
75
|
+
}
|
|
76
|
+
function newsletterSignalMetadata(input) {
|
|
77
|
+
return {
|
|
78
|
+
intake: { surface: "storefront", type: "newsletter" },
|
|
79
|
+
newsletter: { email: input.email, doubleOptIn: input.doubleOptIn },
|
|
80
|
+
payload: input.body.payload,
|
|
81
|
+
consent: input.body.consent,
|
|
82
|
+
source: {
|
|
83
|
+
url: input.body.sourceUrl ?? null,
|
|
84
|
+
locale: input.body.locale ?? null,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export async function createStorefrontLeadSignal(input) {
|
|
89
|
+
const db = requireDb(input.context);
|
|
90
|
+
const existing = await findExistingSignal(db, {
|
|
91
|
+
kind: input.body.kind,
|
|
92
|
+
sourceSubmissionId: input.body.sourceSubmissionId,
|
|
93
|
+
});
|
|
94
|
+
if (existing)
|
|
95
|
+
return leadResponse(existing, true);
|
|
96
|
+
const { firstName, lastName } = personNameFromContact(input.body.contact);
|
|
97
|
+
const person = await crmService.createPerson(db, {
|
|
98
|
+
firstName,
|
|
99
|
+
lastName,
|
|
100
|
+
status: "active",
|
|
101
|
+
website: null,
|
|
102
|
+
email: input.body.contact.email ? normalizeEmail(input.body.contact.email) : null,
|
|
103
|
+
phone: input.body.contact.phone ?? null,
|
|
104
|
+
source: "storefront",
|
|
105
|
+
sourceRef: input.body.sourceSubmissionId ?? null,
|
|
106
|
+
tags: input.body.tags,
|
|
107
|
+
});
|
|
108
|
+
if (!person)
|
|
109
|
+
throw new Error("Failed to create CRM person for storefront lead");
|
|
110
|
+
const signal = await crmService.createCustomerSignal(db, {
|
|
111
|
+
personId: person.id,
|
|
112
|
+
productId: input.body.productId ?? null,
|
|
113
|
+
optionUnitId: input.body.optionUnitId ?? null,
|
|
114
|
+
kind: input.body.kind,
|
|
115
|
+
source: input.body.source,
|
|
116
|
+
status: "new",
|
|
117
|
+
priority: "normal",
|
|
118
|
+
notes: input.body.notes ?? null,
|
|
119
|
+
tags: input.body.tags,
|
|
120
|
+
sourceSubmissionId: input.body.sourceSubmissionId ?? null,
|
|
121
|
+
metadata: {
|
|
122
|
+
intake: { surface: "storefront", type: "lead" },
|
|
123
|
+
payload: input.body.payload,
|
|
124
|
+
consent: input.body.consent,
|
|
125
|
+
source: {
|
|
126
|
+
url: input.body.sourceUrl ?? null,
|
|
127
|
+
locale: input.body.locale ?? null,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
if (!signal)
|
|
132
|
+
throw new Error("Failed to create CRM customer signal for storefront lead");
|
|
133
|
+
await emitCustomerSignalCreated(input.context.eventBus, {
|
|
134
|
+
id: signal.id,
|
|
135
|
+
personId: signal.personId,
|
|
136
|
+
kind: signal.kind,
|
|
137
|
+
source: signal.source,
|
|
138
|
+
status: signal.status,
|
|
139
|
+
productId: signal.productId,
|
|
140
|
+
optionUnitId: signal.optionUnitId,
|
|
141
|
+
sourceSubmissionId: signal.sourceSubmissionId,
|
|
142
|
+
intake: { surface: "storefront", type: "lead" },
|
|
143
|
+
}, "route");
|
|
144
|
+
return leadResponse(signal, false);
|
|
145
|
+
}
|
|
146
|
+
export async function subscribeStorefrontNewsletter(input) {
|
|
147
|
+
const db = requireDb(input.context);
|
|
148
|
+
const email = normalizeEmail(input.body.email);
|
|
149
|
+
const sourceSubmissionId = input.body.sourceSubmissionId ?? defaultNewsletterSubmissionId(input.body.email);
|
|
150
|
+
const existing = await findExistingSignal(db, {
|
|
151
|
+
kind: "notify",
|
|
152
|
+
sourceSubmissionId,
|
|
153
|
+
});
|
|
154
|
+
if (existing) {
|
|
155
|
+
return {
|
|
156
|
+
...leadResponse(existing, true),
|
|
157
|
+
doubleOptIn: newsletterDoubleOptInFromSignal(existing),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const { firstName, lastName } = personNameFromNewsletter(input.body);
|
|
161
|
+
const person = await crmService.createPerson(db, {
|
|
162
|
+
firstName,
|
|
163
|
+
lastName,
|
|
164
|
+
status: "active",
|
|
165
|
+
website: null,
|
|
166
|
+
email,
|
|
167
|
+
source: "storefront-newsletter",
|
|
168
|
+
sourceRef: sourceSubmissionId,
|
|
169
|
+
tags: input.body.tags,
|
|
170
|
+
});
|
|
171
|
+
if (!person)
|
|
172
|
+
throw new Error("Failed to create CRM person for newsletter subscription");
|
|
173
|
+
const doubleOptIn = input.requestDoubleOptIn ? "requested" : "not_configured";
|
|
174
|
+
let signal = await crmService.createCustomerSignal(db, {
|
|
175
|
+
personId: person.id,
|
|
176
|
+
kind: "notify",
|
|
177
|
+
source: input.body.source,
|
|
178
|
+
status: "new",
|
|
179
|
+
priority: "normal",
|
|
180
|
+
notes: "Newsletter subscription",
|
|
181
|
+
tags: input.body.tags,
|
|
182
|
+
sourceSubmissionId,
|
|
183
|
+
metadata: newsletterSignalMetadata({
|
|
184
|
+
email,
|
|
185
|
+
doubleOptIn: "not_configured",
|
|
186
|
+
body: input.body,
|
|
187
|
+
}),
|
|
188
|
+
});
|
|
189
|
+
if (!signal)
|
|
190
|
+
throw new Error("Failed to create CRM customer signal for newsletter subscription");
|
|
191
|
+
if (input.requestDoubleOptIn) {
|
|
192
|
+
try {
|
|
193
|
+
await input.requestDoubleOptIn({
|
|
194
|
+
email,
|
|
195
|
+
personId: person.id,
|
|
196
|
+
signalId: signal.id,
|
|
197
|
+
sourceSubmissionId,
|
|
198
|
+
body: input.body,
|
|
199
|
+
context: input.context,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
await crmService.deleteCustomerSignal(db, signal.id).catch(() => null);
|
|
204
|
+
await crmService.deletePerson(db, person.id).catch(() => null);
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
signal =
|
|
208
|
+
(await crmService.updateCustomerSignal(db, signal.id, {
|
|
209
|
+
metadata: newsletterSignalMetadata({
|
|
210
|
+
email,
|
|
211
|
+
doubleOptIn,
|
|
212
|
+
body: input.body,
|
|
213
|
+
}),
|
|
214
|
+
})) ?? signal;
|
|
215
|
+
}
|
|
216
|
+
await emitCustomerSignalCreated(input.context.eventBus, {
|
|
217
|
+
id: signal.id,
|
|
218
|
+
personId: signal.personId,
|
|
219
|
+
kind: signal.kind,
|
|
220
|
+
source: signal.source,
|
|
221
|
+
status: signal.status,
|
|
222
|
+
productId: signal.productId,
|
|
223
|
+
optionUnitId: signal.optionUnitId,
|
|
224
|
+
sourceSubmissionId: signal.sourceSubmissionId,
|
|
225
|
+
intake: { surface: "storefront", type: "newsletter", doubleOptIn },
|
|
226
|
+
}, "route");
|
|
227
|
+
return {
|
|
228
|
+
...leadResponse(signal, false),
|
|
229
|
+
doubleOptIn,
|
|
230
|
+
};
|
|
231
|
+
}
|
package/dist/service.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { EventBus } from "@voyantjs/core";
|
|
1
2
|
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
|
-
import { type
|
|
3
|
+
import { type StorefrontIntakeGuard, type StorefrontIntakeOptions } from "./service-intake.js";
|
|
4
|
+
import { type StorefrontDepartureListQuery, type StorefrontDeparturePricePreviewInput, type StorefrontLeadIntakeInput, type StorefrontNewsletterSubscribeInput, type StorefrontOfferApplyInput, type StorefrontOfferMutationResult, type StorefrontOfferRedeemInput, type StorefrontProductAvailabilitySummaryQuery, type StorefrontPromotionalOffer, type StorefrontSettings, type StorefrontSettingsInput } from "./validation.js";
|
|
3
5
|
import type { StorefrontTransportEligibilityInput, StorefrontTransportEligibilityResult, StorefrontTransportEligibilityRuleInput } from "./validation-transport-eligibility.js";
|
|
4
6
|
export interface StorefrontServiceOptions {
|
|
5
7
|
settings?: StorefrontSettingsInput;
|
|
@@ -13,9 +15,11 @@ export interface StorefrontServiceOptions {
|
|
|
13
15
|
travelStartsOn?: string | null;
|
|
14
16
|
travelEndsOn?: string | null;
|
|
15
17
|
} & StorefrontRequestContext) => Promise<StorefrontTransportEligibilityRuleInput[]> | StorefrontTransportEligibilityRuleInput[];
|
|
18
|
+
intake?: StorefrontIntakeOptions;
|
|
16
19
|
}
|
|
17
20
|
export interface StorefrontRequestContext {
|
|
18
21
|
db?: PostgresJsDatabase;
|
|
22
|
+
eventBus?: EventBus;
|
|
19
23
|
env?: unknown;
|
|
20
24
|
context?: unknown;
|
|
21
25
|
}
|
|
@@ -87,9 +91,9 @@ export declare function createStorefrontService(options?: StorefrontServiceOptio
|
|
|
87
91
|
};
|
|
88
92
|
};
|
|
89
93
|
payment: {
|
|
90
|
-
defaultMethod: "voucher" | "
|
|
94
|
+
defaultMethod: "voucher" | "bank_transfer" | "card" | "cash" | "invoice" | null;
|
|
91
95
|
methods: {
|
|
92
|
-
code: "voucher" | "
|
|
96
|
+
code: "voucher" | "bank_transfer" | "card" | "cash" | "invoice";
|
|
93
97
|
label: string;
|
|
94
98
|
description: string | null;
|
|
95
99
|
enabled: boolean;
|
|
@@ -330,5 +334,38 @@ export declare function createStorefrontService(options?: StorefrontServiceOptio
|
|
|
330
334
|
body: StorefrontOfferRedeemInput;
|
|
331
335
|
context?: StorefrontRequestContext;
|
|
332
336
|
}): Promise<StorefrontOfferMutationResult | null>;
|
|
337
|
+
checkIntakeGuard: (input: {
|
|
338
|
+
kind: "lead";
|
|
339
|
+
body: StorefrontLeadIntakeInput;
|
|
340
|
+
context: StorefrontRequestContext;
|
|
341
|
+
} | {
|
|
342
|
+
kind: "newsletter";
|
|
343
|
+
body: StorefrontNewsletterSubscribeInput;
|
|
344
|
+
context: StorefrontRequestContext;
|
|
345
|
+
}) => Promise<import("./service-intake.js").StorefrontIntakeGuardDecision | undefined>;
|
|
346
|
+
createLead(input: {
|
|
347
|
+
body: StorefrontLeadIntakeInput;
|
|
348
|
+
context: StorefrontRequestContext;
|
|
349
|
+
}): Promise<{
|
|
350
|
+
id: string;
|
|
351
|
+
personId: string;
|
|
352
|
+
kind: "wishlist" | "notify" | "inquiry" | "request_offer" | "referral";
|
|
353
|
+
source: "admin" | "form" | "phone" | "website" | "booking" | "abandoned_cart";
|
|
354
|
+
status: "expired" | "converted" | "lost" | "new" | "contacted" | "qualified";
|
|
355
|
+
duplicate: boolean;
|
|
356
|
+
}>;
|
|
357
|
+
subscribeNewsletter(input: {
|
|
358
|
+
body: StorefrontNewsletterSubscribeInput;
|
|
359
|
+
context: StorefrontRequestContext;
|
|
360
|
+
}): Promise<{
|
|
361
|
+
id: string;
|
|
362
|
+
personId: string;
|
|
363
|
+
kind: "wishlist" | "notify" | "inquiry" | "request_offer" | "referral";
|
|
364
|
+
source: "admin" | "form" | "phone" | "website" | "booking" | "abandoned_cart";
|
|
365
|
+
status: "expired" | "converted" | "lost" | "new" | "contacted" | "qualified";
|
|
366
|
+
duplicate: boolean;
|
|
367
|
+
doubleOptIn: "not_configured" | "requested";
|
|
368
|
+
}>;
|
|
333
369
|
};
|
|
370
|
+
export type { StorefrontIntakeGuard, StorefrontIntakeOptions };
|
|
334
371
|
//# sourceMappingURL=service.d.ts.map
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/dist/service.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getStorefrontDeparture, getStorefrontDepartureItinerary, getStorefrontProductAvailabilitySummary, getStorefrontProductExtensions, listStorefrontProductDepartures, previewStorefrontDeparturePrice, } from "./service-departures.js";
|
|
2
|
+
import { createStorefrontLeadSignal, subscribeStorefrontNewsletter, } from "./service-intake.js";
|
|
2
3
|
import { evaluateStorefrontTransportEligibility } from "./service-transport-eligibility.js";
|
|
3
4
|
import { storefrontSettingsInputSchema, storefrontSettingsSchema, } from "./validation.js";
|
|
4
5
|
const defaultPaymentLabels = {
|
|
@@ -74,6 +75,9 @@ export function createStorefrontService(options) {
|
|
|
74
75
|
options?.transportEligibilityRules ??
|
|
75
76
|
[]);
|
|
76
77
|
}
|
|
78
|
+
async function checkIntakeGuard(input) {
|
|
79
|
+
return options?.intake?.guard?.(input);
|
|
80
|
+
}
|
|
77
81
|
return {
|
|
78
82
|
getSettings() {
|
|
79
83
|
return settings;
|
|
@@ -137,5 +141,15 @@ export function createStorefrontService(options) {
|
|
|
137
141
|
const { context, ...offerInput } = input;
|
|
138
142
|
return ((await resolveOffers(context)?.then((resolvers) => resolvers?.redeemOffer?.({ ...offerInput, ...(context ?? {}) }))) ?? null);
|
|
139
143
|
},
|
|
144
|
+
checkIntakeGuard,
|
|
145
|
+
createLead(input) {
|
|
146
|
+
return createStorefrontLeadSignal(input);
|
|
147
|
+
},
|
|
148
|
+
subscribeNewsletter(input) {
|
|
149
|
+
return subscribeStorefrontNewsletter({
|
|
150
|
+
...input,
|
|
151
|
+
requestDoubleOptIn: options?.intake?.requestNewsletterDoubleOptIn,
|
|
152
|
+
});
|
|
153
|
+
},
|
|
140
154
|
};
|
|
141
155
|
}
|
package/dist/validation.d.ts
CHANGED
|
@@ -1,8 +1,153 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
export declare const storefrontIntakeConsentSchema: z.ZodObject<{
|
|
3
|
+
marketing: z.ZodDefault<z.ZodBoolean>;
|
|
4
|
+
newsletter: z.ZodDefault<z.ZodBoolean>;
|
|
5
|
+
gdpr: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
7
|
+
acceptedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export declare const storefrontLeadContactSchema: z.ZodObject<{
|
|
10
|
+
name: z.ZodOptional<z.ZodString>;
|
|
11
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
12
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
13
|
+
email: z.ZodOptional<z.ZodEmail>;
|
|
14
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
export declare const storefrontLeadIntakeInputSchema: z.ZodObject<{
|
|
17
|
+
kind: z.ZodDefault<z.ZodEnum<{
|
|
18
|
+
wishlist: "wishlist";
|
|
19
|
+
notify: "notify";
|
|
20
|
+
inquiry: "inquiry";
|
|
21
|
+
request_offer: "request_offer";
|
|
22
|
+
referral: "referral";
|
|
23
|
+
}>>;
|
|
24
|
+
source: z.ZodDefault<z.ZodEnum<{
|
|
25
|
+
admin: "admin";
|
|
26
|
+
form: "form";
|
|
27
|
+
phone: "phone";
|
|
28
|
+
website: "website";
|
|
29
|
+
booking: "booking";
|
|
30
|
+
abandoned_cart: "abandoned_cart";
|
|
31
|
+
}>>;
|
|
32
|
+
contact: z.ZodObject<{
|
|
33
|
+
name: z.ZodOptional<z.ZodString>;
|
|
34
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
35
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
36
|
+
email: z.ZodOptional<z.ZodEmail>;
|
|
37
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
productId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
40
|
+
optionUnitId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
41
|
+
notes: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
42
|
+
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
43
|
+
sourceSubmissionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
44
|
+
sourceUrl: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
|
|
45
|
+
locale: z.ZodOptional<z.ZodString>;
|
|
46
|
+
payload: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
47
|
+
consent: z.ZodDefault<z.ZodObject<{
|
|
48
|
+
marketing: z.ZodDefault<z.ZodBoolean>;
|
|
49
|
+
newsletter: z.ZodDefault<z.ZodBoolean>;
|
|
50
|
+
gdpr: z.ZodDefault<z.ZodBoolean>;
|
|
51
|
+
scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
52
|
+
acceptedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
53
|
+
}, z.core.$strip>>;
|
|
54
|
+
}, z.core.$strip>;
|
|
55
|
+
export declare const storefrontNewsletterSubscribeInputSchema: z.ZodObject<{
|
|
56
|
+
email: z.ZodEmail;
|
|
57
|
+
name: z.ZodOptional<z.ZodString>;
|
|
58
|
+
firstName: z.ZodOptional<z.ZodString>;
|
|
59
|
+
lastName: z.ZodOptional<z.ZodString>;
|
|
60
|
+
source: z.ZodDefault<z.ZodEnum<{
|
|
61
|
+
admin: "admin";
|
|
62
|
+
form: "form";
|
|
63
|
+
phone: "phone";
|
|
64
|
+
website: "website";
|
|
65
|
+
booking: "booking";
|
|
66
|
+
abandoned_cart: "abandoned_cart";
|
|
67
|
+
}>>;
|
|
68
|
+
sourceSubmissionId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
69
|
+
sourceUrl: z.ZodOptional<z.ZodNullable<z.ZodURL>>;
|
|
70
|
+
locale: z.ZodOptional<z.ZodString>;
|
|
71
|
+
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
72
|
+
payload: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
73
|
+
consent: z.ZodObject<{
|
|
74
|
+
marketing: z.ZodDefault<z.ZodBoolean>;
|
|
75
|
+
gdpr: z.ZodDefault<z.ZodBoolean>;
|
|
76
|
+
scope: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
77
|
+
acceptedAt: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
78
|
+
newsletter: z.ZodLiteral<true>;
|
|
79
|
+
}, z.core.$strip>;
|
|
80
|
+
}, z.core.$strip>;
|
|
81
|
+
export declare const storefrontIntakeResponseSchema: z.ZodObject<{
|
|
82
|
+
id: z.ZodString;
|
|
83
|
+
personId: z.ZodString;
|
|
84
|
+
kind: z.ZodEnum<{
|
|
85
|
+
wishlist: "wishlist";
|
|
86
|
+
notify: "notify";
|
|
87
|
+
inquiry: "inquiry";
|
|
88
|
+
request_offer: "request_offer";
|
|
89
|
+
referral: "referral";
|
|
90
|
+
}>;
|
|
91
|
+
source: z.ZodEnum<{
|
|
92
|
+
admin: "admin";
|
|
93
|
+
form: "form";
|
|
94
|
+
phone: "phone";
|
|
95
|
+
website: "website";
|
|
96
|
+
booking: "booking";
|
|
97
|
+
abandoned_cart: "abandoned_cart";
|
|
98
|
+
}>;
|
|
99
|
+
status: z.ZodEnum<{
|
|
100
|
+
expired: "expired";
|
|
101
|
+
converted: "converted";
|
|
102
|
+
lost: "lost";
|
|
103
|
+
new: "new";
|
|
104
|
+
contacted: "contacted";
|
|
105
|
+
qualified: "qualified";
|
|
106
|
+
}>;
|
|
107
|
+
duplicate: z.ZodBoolean;
|
|
108
|
+
}, z.core.$strip>;
|
|
109
|
+
export declare const storefrontNewsletterSubscribeResponseSchema: z.ZodObject<{
|
|
110
|
+
id: z.ZodString;
|
|
111
|
+
personId: z.ZodString;
|
|
112
|
+
kind: z.ZodEnum<{
|
|
113
|
+
wishlist: "wishlist";
|
|
114
|
+
notify: "notify";
|
|
115
|
+
inquiry: "inquiry";
|
|
116
|
+
request_offer: "request_offer";
|
|
117
|
+
referral: "referral";
|
|
118
|
+
}>;
|
|
119
|
+
source: z.ZodEnum<{
|
|
120
|
+
admin: "admin";
|
|
121
|
+
form: "form";
|
|
122
|
+
phone: "phone";
|
|
123
|
+
website: "website";
|
|
124
|
+
booking: "booking";
|
|
125
|
+
abandoned_cart: "abandoned_cart";
|
|
126
|
+
}>;
|
|
127
|
+
status: z.ZodEnum<{
|
|
128
|
+
expired: "expired";
|
|
129
|
+
converted: "converted";
|
|
130
|
+
lost: "lost";
|
|
131
|
+
new: "new";
|
|
132
|
+
contacted: "contacted";
|
|
133
|
+
qualified: "qualified";
|
|
134
|
+
}>;
|
|
135
|
+
duplicate: z.ZodBoolean;
|
|
136
|
+
doubleOptIn: z.ZodEnum<{
|
|
137
|
+
not_configured: "not_configured";
|
|
138
|
+
requested: "requested";
|
|
139
|
+
}>;
|
|
140
|
+
}, z.core.$strip>;
|
|
141
|
+
export type StorefrontIntakeConsent = z.infer<typeof storefrontIntakeConsentSchema>;
|
|
142
|
+
export type StorefrontLeadContact = z.infer<typeof storefrontLeadContactSchema>;
|
|
143
|
+
export type StorefrontLeadIntakeInput = z.infer<typeof storefrontLeadIntakeInputSchema>;
|
|
144
|
+
export type StorefrontNewsletterSubscribeInput = z.infer<typeof storefrontNewsletterSubscribeInputSchema>;
|
|
145
|
+
export type StorefrontIntakeResponse = z.infer<typeof storefrontIntakeResponseSchema>;
|
|
146
|
+
export type StorefrontNewsletterSubscribeResponse = z.infer<typeof storefrontNewsletterSubscribeResponseSchema>;
|
|
2
147
|
export declare const storefrontPaymentMethodCodeSchema: z.ZodEnum<{
|
|
3
148
|
voucher: "voucher";
|
|
4
|
-
card: "card";
|
|
5
149
|
bank_transfer: "bank_transfer";
|
|
150
|
+
card: "card";
|
|
6
151
|
cash: "cash";
|
|
7
152
|
invoice: "invoice";
|
|
8
153
|
}>;
|
|
@@ -67,8 +212,8 @@ export declare const storefrontFormFieldSchema: z.ZodObject<{
|
|
|
67
212
|
export declare const storefrontPaymentMethodInputSchema: z.ZodObject<{
|
|
68
213
|
code: z.ZodEnum<{
|
|
69
214
|
voucher: "voucher";
|
|
70
|
-
card: "card";
|
|
71
215
|
bank_transfer: "bank_transfer";
|
|
216
|
+
card: "card";
|
|
72
217
|
cash: "cash";
|
|
73
218
|
invoice: "invoice";
|
|
74
219
|
}>;
|
|
@@ -79,8 +224,8 @@ export declare const storefrontPaymentMethodInputSchema: z.ZodObject<{
|
|
|
79
224
|
export declare const storefrontPaymentMethodSchema: z.ZodObject<{
|
|
80
225
|
code: z.ZodEnum<{
|
|
81
226
|
voucher: "voucher";
|
|
82
|
-
card: "card";
|
|
83
227
|
bank_transfer: "bank_transfer";
|
|
228
|
+
card: "card";
|
|
84
229
|
cash: "cash";
|
|
85
230
|
invoice: "invoice";
|
|
86
231
|
}>;
|
|
@@ -155,16 +300,16 @@ export declare const storefrontSettingsInputSchema: z.ZodObject<{
|
|
|
155
300
|
payment: z.ZodOptional<z.ZodObject<{
|
|
156
301
|
defaultMethod: z.ZodNullable<z.ZodOptional<z.ZodEnum<{
|
|
157
302
|
voucher: "voucher";
|
|
158
|
-
card: "card";
|
|
159
303
|
bank_transfer: "bank_transfer";
|
|
304
|
+
card: "card";
|
|
160
305
|
cash: "cash";
|
|
161
306
|
invoice: "invoice";
|
|
162
307
|
}>>>;
|
|
163
308
|
methods: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
164
309
|
code: z.ZodEnum<{
|
|
165
310
|
voucher: "voucher";
|
|
166
|
-
card: "card";
|
|
167
311
|
bank_transfer: "bank_transfer";
|
|
312
|
+
card: "card";
|
|
168
313
|
cash: "cash";
|
|
169
314
|
invoice: "invoice";
|
|
170
315
|
}>;
|
|
@@ -241,16 +386,16 @@ export declare const storefrontSettingsSchema: z.ZodObject<{
|
|
|
241
386
|
payment: z.ZodObject<{
|
|
242
387
|
defaultMethod: z.ZodNullable<z.ZodEnum<{
|
|
243
388
|
voucher: "voucher";
|
|
244
|
-
card: "card";
|
|
245
389
|
bank_transfer: "bank_transfer";
|
|
390
|
+
card: "card";
|
|
246
391
|
cash: "cash";
|
|
247
392
|
invoice: "invoice";
|
|
248
393
|
}>>;
|
|
249
394
|
methods: z.ZodArray<z.ZodObject<{
|
|
250
395
|
code: z.ZodEnum<{
|
|
251
396
|
voucher: "voucher";
|
|
252
|
-
card: "card";
|
|
253
397
|
bank_transfer: "bank_transfer";
|
|
398
|
+
card: "card";
|
|
254
399
|
cash: "cash";
|
|
255
400
|
invoice: "invoice";
|
|
256
401
|
}>;
|
package/dist/validation.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
|
package/dist/validation.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { availabilitySlotStatusSchema } from "@voyantjs/availability/validation";
|
|
2
|
+
import { customerSignalKindSchema, customerSignalSourceSchema, customerSignalStatusSchema, } from "@voyantjs/crm/validation";
|
|
2
3
|
import { extraPricingModeSchema } from "@voyantjs/extras/validation";
|
|
3
4
|
import { z } from "zod";
|
|
4
5
|
const languageTagSchema = z
|
|
@@ -6,6 +7,72 @@ const languageTagSchema = z
|
|
|
6
7
|
.trim()
|
|
7
8
|
.regex(/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$/);
|
|
8
9
|
const urlOrNullSchema = z.url().nullable();
|
|
10
|
+
const boundedRecordSchema = z
|
|
11
|
+
.record(z.string(), z.unknown())
|
|
12
|
+
.refine((value) => JSON.stringify(value).length <= 8000, {
|
|
13
|
+
message: "Object payload must be 8KB or smaller",
|
|
14
|
+
});
|
|
15
|
+
const storefrontIntakeTagsSchema = z.array(z.string().trim().min(1).max(64)).max(20).default([]);
|
|
16
|
+
export const storefrontIntakeConsentSchema = z.object({
|
|
17
|
+
marketing: z.boolean().default(false),
|
|
18
|
+
newsletter: z.boolean().default(false),
|
|
19
|
+
gdpr: z.boolean().default(false),
|
|
20
|
+
scope: z.string().trim().min(1).max(120).nullable().optional(),
|
|
21
|
+
acceptedAt: z.string().datetime().nullable().optional(),
|
|
22
|
+
});
|
|
23
|
+
export const storefrontLeadContactSchema = z
|
|
24
|
+
.object({
|
|
25
|
+
name: z.string().trim().min(1).max(240).optional(),
|
|
26
|
+
firstName: z.string().trim().min(1).max(120).optional(),
|
|
27
|
+
lastName: z.string().trim().min(1).max(120).optional(),
|
|
28
|
+
email: z.email().max(320).optional(),
|
|
29
|
+
phone: z.string().trim().min(3).max(64).optional(),
|
|
30
|
+
})
|
|
31
|
+
.refine((value) => Boolean(value.email || value.phone), {
|
|
32
|
+
message: "Either contact.email or contact.phone is required",
|
|
33
|
+
});
|
|
34
|
+
export const storefrontLeadIntakeInputSchema = z.object({
|
|
35
|
+
kind: customerSignalKindSchema.default("inquiry"),
|
|
36
|
+
source: customerSignalSourceSchema.default("website"),
|
|
37
|
+
contact: storefrontLeadContactSchema,
|
|
38
|
+
productId: z.string().trim().min(1).max(160).nullable().optional(),
|
|
39
|
+
optionUnitId: z.string().trim().min(1).max(160).nullable().optional(),
|
|
40
|
+
notes: z.string().trim().max(4000).nullable().optional(),
|
|
41
|
+
tags: storefrontIntakeTagsSchema,
|
|
42
|
+
sourceSubmissionId: z.string().trim().min(1).max(160).nullable().optional(),
|
|
43
|
+
sourceUrl: z.url().nullable().optional(),
|
|
44
|
+
locale: languageTagSchema.optional(),
|
|
45
|
+
payload: boundedRecordSchema.default({}),
|
|
46
|
+
consent: storefrontIntakeConsentSchema.default({
|
|
47
|
+
marketing: false,
|
|
48
|
+
newsletter: false,
|
|
49
|
+
gdpr: false,
|
|
50
|
+
}),
|
|
51
|
+
});
|
|
52
|
+
export const storefrontNewsletterSubscribeInputSchema = z.object({
|
|
53
|
+
email: z.email().max(320),
|
|
54
|
+
name: z.string().trim().min(1).max(240).optional(),
|
|
55
|
+
firstName: z.string().trim().min(1).max(120).optional(),
|
|
56
|
+
lastName: z.string().trim().min(1).max(120).optional(),
|
|
57
|
+
source: customerSignalSourceSchema.default("website"),
|
|
58
|
+
sourceSubmissionId: z.string().trim().min(1).max(160).nullable().optional(),
|
|
59
|
+
sourceUrl: z.url().nullable().optional(),
|
|
60
|
+
locale: languageTagSchema.optional(),
|
|
61
|
+
tags: storefrontIntakeTagsSchema,
|
|
62
|
+
payload: boundedRecordSchema.default({}),
|
|
63
|
+
consent: storefrontIntakeConsentSchema.extend({ newsletter: z.literal(true) }),
|
|
64
|
+
});
|
|
65
|
+
export const storefrontIntakeResponseSchema = z.object({
|
|
66
|
+
id: z.string(),
|
|
67
|
+
personId: z.string(),
|
|
68
|
+
kind: customerSignalKindSchema,
|
|
69
|
+
source: customerSignalSourceSchema,
|
|
70
|
+
status: customerSignalStatusSchema,
|
|
71
|
+
duplicate: z.boolean(),
|
|
72
|
+
});
|
|
73
|
+
export const storefrontNewsletterSubscribeResponseSchema = storefrontIntakeResponseSchema.extend({
|
|
74
|
+
doubleOptIn: z.enum(["not_configured", "requested"]),
|
|
75
|
+
});
|
|
9
76
|
export const storefrontPaymentMethodCodeSchema = z.enum([
|
|
10
77
|
"card",
|
|
11
78
|
"bank_transfer",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/storefront",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -34,18 +34,19 @@
|
|
|
34
34
|
"drizzle-orm": "^0.45.2",
|
|
35
35
|
"hono": "^4.12.10",
|
|
36
36
|
"zod": "^4.3.6",
|
|
37
|
-
"@voyantjs/
|
|
38
|
-
"@voyantjs/
|
|
39
|
-
"@voyantjs/extras": "0.
|
|
40
|
-
"@voyantjs/hono": "0.
|
|
41
|
-
"@voyantjs/pricing": "0.
|
|
42
|
-
"@voyantjs/products": "0.
|
|
43
|
-
"@voyantjs/sellability": "0.
|
|
37
|
+
"@voyantjs/core": "0.49.0",
|
|
38
|
+
"@voyantjs/crm": "0.49.0",
|
|
39
|
+
"@voyantjs/extras": "0.49.0",
|
|
40
|
+
"@voyantjs/hono": "0.49.0",
|
|
41
|
+
"@voyantjs/pricing": "0.49.0",
|
|
42
|
+
"@voyantjs/products": "0.49.0",
|
|
43
|
+
"@voyantjs/sellability": "0.49.0",
|
|
44
|
+
"@voyantjs/availability": "0.49.0"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"typescript": "^6.0.2",
|
|
47
48
|
"vitest": "^4.1.2",
|
|
48
|
-
"@voyantjs/db": "0.
|
|
49
|
+
"@voyantjs/db": "0.49.0",
|
|
49
50
|
"@voyantjs/voyant-typescript-config": "0.1.0"
|
|
50
51
|
},
|
|
51
52
|
"files": [
|