@jarwizz/create-jarshop 0.1.4 → 0.1.5
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/dist/template/src/email-smoke.ts +1 -0
- package/dist/template/src/migrations/1787800000000-jarshop-order-email-event-key.ts +60 -0
- package/dist/template/src/migrations/1787900000000-jarshop-email-brand-configuration.ts +32 -0
- package/dist/template/src/plugins/jarshop-checkout/dashboard/index.tsx +213 -32
- package/dist/template/src/plugins/jarshop-checkout/dashboard/order-email-delivery-status.ts +17 -0
- package/dist/template/src/plugins/jarshop-checkout/index.ts +49 -1
- package/dist/template/src/plugins/jarshop-checkout/jarshop-checkout.plugin.ts +146 -5
- package/dist/template/src/plugins/jarshop-checkout/order-email-configuration.entity.ts +61 -0
- package/dist/template/src/plugins/jarshop-checkout/order-email-configuration.ts +190 -0
- package/dist/template/src/plugins/jarshop-checkout/order-email-delivery-core.ts +321 -13
- package/dist/template/src/plugins/jarshop-checkout/order-email-delivery-status.ts +3 -1
- package/dist/template/src/plugins/jarshop-checkout/order-email-delivery.entity.ts +15 -4
- package/dist/template/src/plugins/jarshop-checkout/order-email-lifecycle.ts +335 -0
- package/dist/template/src/plugins/jarshop-checkout/order-email-outbox.ts +308 -15
- package/dist/template/src/plugins/jarshop-checkout/order-email-worker.ts +86 -8
- package/dist/template/src/plugins/jarshop-checkout/order-lifecycle-core.ts +131 -0
- package/dist/template/src/plugins/jarshop-checkout/order-lifecycle-process.ts +102 -0
- package/dist/template-manifest.json +1 -1
- package/package.json +1 -1
|
@@ -14,6 +14,7 @@ async function main(): Promise<void> {
|
|
|
14
14
|
"This is a controlled JarShop SMTP transport smoke message.",
|
|
15
15
|
"No customer order, bearer token, or checkout data is included.",
|
|
16
16
|
].join("\n"),
|
|
17
|
+
html: "<p>This is a controlled JarShop SMTP transport smoke message. No customer order, bearer token, or checkout data is included.</p>",
|
|
17
18
|
},
|
|
18
19
|
});
|
|
19
20
|
console.log("SMTP smoke email was accepted by the configured transport.");
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generalizes confirmation-only deduplication without replacing or deleting
|
|
5
|
+
* existing delivery history. New lifecycle events may omit checkoutAttemptId.
|
|
6
|
+
*/
|
|
7
|
+
export class JarShopOrderEmailEventKey1787800000000 implements MigrationInterface {
|
|
8
|
+
name = "JarShopOrderEmailEventKey1787800000000";
|
|
9
|
+
|
|
10
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
11
|
+
await queryRunner.query(
|
|
12
|
+
`ALTER TABLE "jarshop_order_email_delivery" ADD "eventKey" character varying(255)`,
|
|
13
|
+
);
|
|
14
|
+
await queryRunner.query(`
|
|
15
|
+
UPDATE "jarshop_order_email_delivery"
|
|
16
|
+
SET "eventKey" = 'order:' || "orderId"::text || ':' || "kind"
|
|
17
|
+
WHERE "eventKey" IS NULL
|
|
18
|
+
`);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`ALTER TABLE "jarshop_order_email_delivery" ALTER COLUMN "eventKey" SET NOT NULL`,
|
|
21
|
+
);
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "jarshop_order_email_delivery" ALTER COLUMN "checkoutAttemptId" DROP NOT NULL`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`ALTER TABLE "jarshop_order_email_delivery" DROP CONSTRAINT "UQ_jarshop_order_email_delivery_order_kind"`,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`ALTER TABLE "jarshop_order_email_delivery" ADD CONSTRAINT "UQ_jarshop_order_email_delivery_event_key" UNIQUE ("eventKey")`,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
34
|
+
await queryRunner.query(`
|
|
35
|
+
DO $$
|
|
36
|
+
BEGIN
|
|
37
|
+
IF EXISTS (
|
|
38
|
+
SELECT 1
|
|
39
|
+
FROM "jarshop_order_email_delivery"
|
|
40
|
+
WHERE "checkoutAttemptId" IS NULL OR "kind" <> 'order-confirmation'
|
|
41
|
+
) THEN
|
|
42
|
+
RAISE EXCEPTION 'cannot restore confirmation-only order email schema while lifecycle deliveries exist';
|
|
43
|
+
END IF;
|
|
44
|
+
END
|
|
45
|
+
$$
|
|
46
|
+
`);
|
|
47
|
+
await queryRunner.query(
|
|
48
|
+
`ALTER TABLE "jarshop_order_email_delivery" DROP CONSTRAINT "UQ_jarshop_order_email_delivery_event_key"`,
|
|
49
|
+
);
|
|
50
|
+
await queryRunner.query(
|
|
51
|
+
`ALTER TABLE "jarshop_order_email_delivery" ALTER COLUMN "checkoutAttemptId" SET NOT NULL`,
|
|
52
|
+
);
|
|
53
|
+
await queryRunner.query(
|
|
54
|
+
`ALTER TABLE "jarshop_order_email_delivery" ADD CONSTRAINT "UQ_jarshop_order_email_delivery_order_kind" UNIQUE ("orderId", "kind")`,
|
|
55
|
+
);
|
|
56
|
+
await queryRunner.query(
|
|
57
|
+
`ALTER TABLE "jarshop_order_email_delivery" DROP COLUMN "eventKey"`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class JarShopEmailBrandConfiguration1787900000000 implements MigrationInterface {
|
|
4
|
+
name = "JarShopEmailBrandConfiguration1787900000000";
|
|
5
|
+
|
|
6
|
+
async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(`
|
|
8
|
+
CREATE TABLE "jarshop_email_brand_configuration" (
|
|
9
|
+
"id" SERIAL NOT NULL,
|
|
10
|
+
"channelId" integer NOT NULL,
|
|
11
|
+
"brandName" character varying(120) NOT NULL,
|
|
12
|
+
"logoUrl" character varying(2048),
|
|
13
|
+
"primaryColor" character varying(7) NOT NULL,
|
|
14
|
+
"websiteUrl" character varying(2048) NOT NULL,
|
|
15
|
+
"supportEmail" character varying(320) NOT NULL,
|
|
16
|
+
"companyName" character varying(160) NOT NULL,
|
|
17
|
+
"companyAddress" text NOT NULL,
|
|
18
|
+
"enabledEvents" jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
19
|
+
"shippingMethods" jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
20
|
+
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
|
|
21
|
+
"updatedAt" TIMESTAMP NOT NULL DEFAULT now(),
|
|
22
|
+
CONSTRAINT "PK_jarshop_email_brand_configuration" PRIMARY KEY ("id"),
|
|
23
|
+
CONSTRAINT "UQ_jarshop_email_brand_configuration_channel" UNIQUE ("channelId"),
|
|
24
|
+
CONSTRAINT "FK_jarshop_email_brand_configuration_channel" FOREIGN KEY ("channelId") REFERENCES "channel"("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
25
|
+
)
|
|
26
|
+
`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async down(queryRunner: QueryRunner): Promise<void> {
|
|
30
|
+
await queryRunner.query(`DROP TABLE "jarshop_email_brand_configuration"`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { api, defineDashboardExtension, useQuery } from "@vendure/dashboard";
|
|
2
2
|
import { graphql } from "@/gql";
|
|
3
|
+
import { useState, type FormEvent } from "react";
|
|
3
4
|
import {
|
|
4
5
|
getDashboardOrderId,
|
|
5
|
-
|
|
6
|
+
toOrderEmailDeliveryTimeline,
|
|
6
7
|
} from "./order-email-delivery-status.js";
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
-
query
|
|
10
|
-
|
|
9
|
+
const orderEmailDeliveriesDocument = graphql(`
|
|
10
|
+
query JarShopOrderEmailDeliveries($orderId: ID!) {
|
|
11
|
+
jarShopOrderEmailDeliveries(orderId: $orderId) {
|
|
12
|
+
deliveryId
|
|
13
|
+
kind
|
|
11
14
|
status
|
|
12
15
|
attemptCount
|
|
13
16
|
nextAttemptAt
|
|
@@ -17,6 +20,37 @@ const orderEmailDeliveryStatusDocument = graphql(`
|
|
|
17
20
|
}
|
|
18
21
|
`);
|
|
19
22
|
|
|
23
|
+
const emailBrandConfigurationDocument = graphql(`
|
|
24
|
+
query JarShopEmailBrandConfiguration {
|
|
25
|
+
jarShopEmailBrandConfiguration {
|
|
26
|
+
brandName
|
|
27
|
+
logoUrl
|
|
28
|
+
primaryColor
|
|
29
|
+
websiteUrl
|
|
30
|
+
supportEmail
|
|
31
|
+
companyName
|
|
32
|
+
companyAddress
|
|
33
|
+
enabledEvents
|
|
34
|
+
shippingMethods {
|
|
35
|
+
code
|
|
36
|
+
pickupDetails
|
|
37
|
+
trackingUrlTemplate
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`);
|
|
42
|
+
|
|
43
|
+
const updateEmailBrandConfigurationDocument = graphql(`
|
|
44
|
+
mutation UpdateJarShopEmailBrandConfiguration(
|
|
45
|
+
$input: JarShopEmailBrandConfigurationInput!
|
|
46
|
+
) {
|
|
47
|
+
updateJarShopEmailBrandConfiguration(input: $input) {
|
|
48
|
+
brandName
|
|
49
|
+
enabledEvents
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
`);
|
|
53
|
+
|
|
20
54
|
function formatDateTime(value: string): string {
|
|
21
55
|
return new Intl.DateTimeFormat(undefined, {
|
|
22
56
|
dateStyle: "medium",
|
|
@@ -30,7 +64,7 @@ function OrderEmailDeliveryStatusBlock({ context }: { context: unknown }) {
|
|
|
30
64
|
queryKey: ["jarshop-order-email-delivery-status", orderId],
|
|
31
65
|
enabled: orderId !== undefined,
|
|
32
66
|
queryFn: () =>
|
|
33
|
-
api.query(
|
|
67
|
+
api.query(orderEmailDeliveriesDocument, {
|
|
34
68
|
orderId: orderId ?? "",
|
|
35
69
|
}),
|
|
36
70
|
});
|
|
@@ -49,10 +83,10 @@ function OrderEmailDeliveryStatusBlock({ context }: { context: unknown }) {
|
|
|
49
83
|
);
|
|
50
84
|
}
|
|
51
85
|
|
|
52
|
-
const
|
|
53
|
-
query.data?.
|
|
86
|
+
const timeline = toOrderEmailDeliveryTimeline(
|
|
87
|
+
query.data?.jarShopOrderEmailDeliveries ?? [],
|
|
54
88
|
);
|
|
55
|
-
if (
|
|
89
|
+
if (timeline.length === 0) {
|
|
56
90
|
return (
|
|
57
91
|
<p className="text-sm text-muted-foreground">
|
|
58
92
|
No JarShop order email is queued for this order.
|
|
@@ -61,32 +95,168 @@ function OrderEmailDeliveryStatusBlock({ context }: { context: unknown }) {
|
|
|
61
95
|
}
|
|
62
96
|
|
|
63
97
|
return (
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
98
|
+
<ol className="grid gap-4 text-sm">
|
|
99
|
+
{timeline.map((delivery) => (
|
|
100
|
+
<li key={delivery.deliveryId} className="border-l-2 pl-3">
|
|
101
|
+
<div className="flex justify-between gap-4">
|
|
102
|
+
<strong className="capitalize">{delivery.label}</strong>
|
|
103
|
+
<span className="capitalize">{delivery.status}</span>
|
|
104
|
+
</div>
|
|
105
|
+
<p className="text-muted-foreground">
|
|
106
|
+
Attempts: {delivery.attemptCount} · Next:{" "}
|
|
107
|
+
{formatDateTime(delivery.nextAttemptAt)}
|
|
108
|
+
</p>
|
|
109
|
+
{delivery.sentAt ? (
|
|
110
|
+
<p>Sent: {formatDateTime(delivery.sentAt)}</p>
|
|
111
|
+
) : null}
|
|
112
|
+
{delivery.lastErrorCode ? (
|
|
113
|
+
<p className="font-mono text-xs">{delivery.lastErrorCode}</p>
|
|
114
|
+
) : null}
|
|
115
|
+
</li>
|
|
116
|
+
))}
|
|
117
|
+
</ol>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function EmailBrandConfigurationBlock() {
|
|
122
|
+
const [message, setMessage] = useState<string>();
|
|
123
|
+
const query = useQuery({
|
|
124
|
+
queryKey: ["jarshop-email-brand-configuration"],
|
|
125
|
+
queryFn: () => api.query(emailBrandConfigurationDocument),
|
|
126
|
+
});
|
|
127
|
+
if (query.isPending) return <p>Loading email configuration…</p>;
|
|
128
|
+
if (query.isError)
|
|
129
|
+
return (
|
|
130
|
+
<p className="text-destructive">Email configuration is unavailable.</p>
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const configuration = query.data?.jarShopEmailBrandConfiguration;
|
|
134
|
+
const methods = new Map(
|
|
135
|
+
configuration?.shippingMethods.map((method) => [method.code, method]),
|
|
136
|
+
);
|
|
137
|
+
const enabled = new Set(configuration?.enabledEvents ?? []);
|
|
138
|
+
const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
|
|
139
|
+
event.preventDefault();
|
|
140
|
+
setMessage(undefined);
|
|
141
|
+
const form = new FormData(event.currentTarget);
|
|
142
|
+
try {
|
|
143
|
+
await api.mutate(updateEmailBrandConfigurationDocument, {
|
|
144
|
+
input: {
|
|
145
|
+
brandName: String(form.get("brandName") ?? ""),
|
|
146
|
+
logoUrl: String(form.get("logoUrl") ?? "") || null,
|
|
147
|
+
primaryColor: String(form.get("primaryColor") ?? ""),
|
|
148
|
+
websiteUrl: String(form.get("websiteUrl") ?? ""),
|
|
149
|
+
supportEmail: String(form.get("supportEmail") ?? ""),
|
|
150
|
+
companyName: String(form.get("companyName") ?? ""),
|
|
151
|
+
companyAddress: String(form.get("companyAddress") ?? ""),
|
|
152
|
+
enabledEvents: form.getAll("enabledEvents").map(String),
|
|
153
|
+
shippingMethods: [
|
|
154
|
+
{
|
|
155
|
+
code: "pickup",
|
|
156
|
+
pickupDetails: String(form.get("pickupDetails") ?? ""),
|
|
157
|
+
trackingUrlTemplate: "",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
code: "courier",
|
|
161
|
+
pickupDetails: "",
|
|
162
|
+
trackingUrlTemplate: String(
|
|
163
|
+
form.get("trackingUrlTemplate") ?? "",
|
|
164
|
+
),
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
setMessage("Email configuration saved.");
|
|
170
|
+
await query.refetch();
|
|
171
|
+
} catch {
|
|
172
|
+
setMessage("Email configuration could not be saved.");
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<form
|
|
178
|
+
key={JSON.stringify(configuration)}
|
|
179
|
+
onSubmit={handleSubmit}
|
|
180
|
+
className="grid gap-4 text-sm"
|
|
181
|
+
>
|
|
182
|
+
<div className="grid grid-cols-2 gap-3">
|
|
183
|
+
{[
|
|
184
|
+
["brandName", "Brand name", configuration?.brandName],
|
|
185
|
+
[
|
|
186
|
+
"primaryColor",
|
|
187
|
+
"Primary color",
|
|
188
|
+
configuration?.primaryColor ?? "#111827",
|
|
189
|
+
],
|
|
190
|
+
["websiteUrl", "Website URL", configuration?.websiteUrl],
|
|
191
|
+
["logoUrl", "Logo URL", configuration?.logoUrl],
|
|
192
|
+
["supportEmail", "Support email", configuration?.supportEmail],
|
|
193
|
+
["companyName", "Company name", configuration?.companyName],
|
|
194
|
+
].map(([name, label, value]) => (
|
|
195
|
+
<label key={name} className="grid gap-1">
|
|
196
|
+
<span>{label}</span>
|
|
197
|
+
<input
|
|
198
|
+
className="rounded border bg-background px-3 py-2"
|
|
199
|
+
name={name}
|
|
200
|
+
defaultValue={value ?? ""}
|
|
201
|
+
/>
|
|
202
|
+
</label>
|
|
203
|
+
))}
|
|
72
204
|
</div>
|
|
73
|
-
<
|
|
74
|
-
<
|
|
75
|
-
<
|
|
205
|
+
<label className="grid gap-1">
|
|
206
|
+
<span>Company address</span>
|
|
207
|
+
<textarea
|
|
208
|
+
className="rounded border bg-background px-3 py-2"
|
|
209
|
+
name="companyAddress"
|
|
210
|
+
defaultValue={configuration?.companyAddress ?? ""}
|
|
211
|
+
/>
|
|
212
|
+
</label>
|
|
213
|
+
<label className="grid gap-1">
|
|
214
|
+
<span>Pickup details</span>
|
|
215
|
+
<textarea
|
|
216
|
+
className="rounded border bg-background px-3 py-2"
|
|
217
|
+
name="pickupDetails"
|
|
218
|
+
defaultValue={methods.get("pickup")?.pickupDetails ?? ""}
|
|
219
|
+
/>
|
|
220
|
+
</label>
|
|
221
|
+
<label className="grid gap-1">
|
|
222
|
+
<span>Courier tracking URL template</span>
|
|
223
|
+
<input
|
|
224
|
+
className="rounded border bg-background px-3 py-2"
|
|
225
|
+
name="trackingUrlTemplate"
|
|
226
|
+
placeholder="https://carrier.example/track/{trackingCode}"
|
|
227
|
+
defaultValue={methods.get("courier")?.trackingUrlTemplate ?? ""}
|
|
228
|
+
/>
|
|
229
|
+
</label>
|
|
230
|
+
<fieldset className="grid grid-cols-2 gap-2">
|
|
231
|
+
<legend className="mb-2 font-medium">Enabled lifecycle events</legend>
|
|
232
|
+
{[
|
|
233
|
+
"pickup-ready",
|
|
234
|
+
"pickup-picked-up",
|
|
235
|
+
"shipment-shipped",
|
|
236
|
+
"shipment-delivered",
|
|
237
|
+
"order-cancelled",
|
|
238
|
+
].map((kind) => (
|
|
239
|
+
<label key={kind} className="flex gap-2">
|
|
240
|
+
<input
|
|
241
|
+
type="checkbox"
|
|
242
|
+
name="enabledEvents"
|
|
243
|
+
value={kind}
|
|
244
|
+
defaultChecked={enabled.has(kind)}
|
|
245
|
+
/>
|
|
246
|
+
<span>{kind}</span>
|
|
247
|
+
</label>
|
|
248
|
+
))}
|
|
249
|
+
</fieldset>
|
|
250
|
+
<div className="flex items-center gap-3">
|
|
251
|
+
<button
|
|
252
|
+
type="submit"
|
|
253
|
+
className="rounded bg-primary px-4 py-2 text-primary-foreground"
|
|
254
|
+
>
|
|
255
|
+
Save email configuration
|
|
256
|
+
</button>
|
|
257
|
+
{message ? <span>{message}</span> : null}
|
|
76
258
|
</div>
|
|
77
|
-
|
|
78
|
-
<div className="flex justify-between gap-4">
|
|
79
|
-
<dt className="text-muted-foreground">Sent</dt>
|
|
80
|
-
<dd>{formatDateTime(panel.sentAt)}</dd>
|
|
81
|
-
</div>
|
|
82
|
-
) : null}
|
|
83
|
-
{panel.lastErrorCode ? (
|
|
84
|
-
<div className="flex justify-between gap-4">
|
|
85
|
-
<dt className="text-muted-foreground">Error code</dt>
|
|
86
|
-
<dd className="font-mono text-xs">{panel.lastErrorCode}</dd>
|
|
87
|
-
</div>
|
|
88
|
-
) : null}
|
|
89
|
-
</dl>
|
|
259
|
+
</form>
|
|
90
260
|
);
|
|
91
261
|
}
|
|
92
262
|
|
|
@@ -103,5 +273,16 @@ defineDashboardExtension({
|
|
|
103
273
|
component: OrderEmailDeliveryStatusBlock,
|
|
104
274
|
requiresPermission: "ReadOrder",
|
|
105
275
|
},
|
|
276
|
+
{
|
|
277
|
+
id: "jarshop-email-brand-configuration",
|
|
278
|
+
title: "JarShop lifecycle email",
|
|
279
|
+
location: {
|
|
280
|
+
pageId: "channel-detail",
|
|
281
|
+
column: "main",
|
|
282
|
+
position: { blockId: "channel-defaults", order: "after" },
|
|
283
|
+
},
|
|
284
|
+
component: EmailBrandConfigurationBlock,
|
|
285
|
+
requiresPermission: "UpdateSettings",
|
|
286
|
+
},
|
|
106
287
|
],
|
|
107
288
|
});
|
|
@@ -41,3 +41,20 @@ export function toOrderEmailDeliveryStatusPanel(
|
|
|
41
41
|
lastErrorCode: delivery.lastErrorCode,
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
export function toOrderEmailDeliveryTimeline(
|
|
46
|
+
deliveries: ReadonlyArray<{
|
|
47
|
+
deliveryId: string;
|
|
48
|
+
kind: string;
|
|
49
|
+
status: "pending" | "processing" | "sent" | "failed";
|
|
50
|
+
attemptCount: number;
|
|
51
|
+
nextAttemptAt: string;
|
|
52
|
+
sentAt: string | null;
|
|
53
|
+
lastErrorCode: string | null;
|
|
54
|
+
}>,
|
|
55
|
+
) {
|
|
56
|
+
return deliveries.map((delivery) => ({
|
|
57
|
+
...delivery,
|
|
58
|
+
label: delivery.kind.replaceAll("-", " "),
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
@@ -13,14 +13,50 @@ export {
|
|
|
13
13
|
} from "./confirmation.js";
|
|
14
14
|
export { JarShopLegalConfiguration } from "./legal.entity.js";
|
|
15
15
|
export { JarShopOrderEmailDelivery } from "./order-email-delivery.entity.js";
|
|
16
|
-
export type {
|
|
16
|
+
export type {
|
|
17
|
+
OrderEmailDeliveryKind,
|
|
18
|
+
OrderEmailDeliveryStatus,
|
|
19
|
+
} from "./order-email-delivery.entity.js";
|
|
20
|
+
export { JarShopEmailBrandConfiguration } from "./order-email-configuration.entity.js";
|
|
21
|
+
export type {
|
|
22
|
+
ConfigurableOrderEmailKind,
|
|
23
|
+
OrderEmailShippingMethodConfiguration,
|
|
24
|
+
} from "./order-email-configuration.entity.js";
|
|
25
|
+
export {
|
|
26
|
+
createTrackingUrl,
|
|
27
|
+
isLifecycleEmailEnabled,
|
|
28
|
+
normalizeOrderEmailBrandConfiguration,
|
|
29
|
+
resolveShippingEmailConfiguration,
|
|
30
|
+
toOrderEmailBrandConfiguration,
|
|
31
|
+
validateOrderEmailBrandConfiguration,
|
|
32
|
+
validateTrackingUrlTemplate,
|
|
33
|
+
} from "./order-email-configuration.js";
|
|
34
|
+
export type { OrderEmailBrandConfigurationInput } from "./order-email-configuration.js";
|
|
17
35
|
export {
|
|
18
36
|
assertOrderEmailOutboxEncryptionConfiguration,
|
|
37
|
+
createPendingCancellationEmailDelivery,
|
|
38
|
+
createPendingFulfillmentEmailDelivery,
|
|
39
|
+
createOrderConfirmationEventKey,
|
|
19
40
|
createPendingOrderEmailDelivery,
|
|
20
41
|
decryptOrderEmailOutboxPayload,
|
|
21
42
|
encryptOrderEmailOutboxPayload,
|
|
43
|
+
isLegacyOrderConfirmationOutboxPayload,
|
|
44
|
+
isSnapshotOrderEmailOutboxPayload,
|
|
22
45
|
parseOrderEmailEncryptionKey,
|
|
23
46
|
} from "./order-email-outbox.js";
|
|
47
|
+
export type {
|
|
48
|
+
FulfillmentLifecycleEmailKind,
|
|
49
|
+
FulfillmentLifecycleEmailSnapshot,
|
|
50
|
+
LegacyOrderConfirmationOutboxPayload,
|
|
51
|
+
OrderCancellationEmailSnapshot,
|
|
52
|
+
OrderConfirmationEmailSnapshot,
|
|
53
|
+
OrderEmailLineSnapshot,
|
|
54
|
+
OrderEmailOutboxPayload,
|
|
55
|
+
} from "./order-email-outbox.js";
|
|
56
|
+
export {
|
|
57
|
+
JarShopOrderEmailLifecycleOutbox,
|
|
58
|
+
toEmailLineSnapshots,
|
|
59
|
+
} from "./order-email-lifecycle.js";
|
|
24
60
|
export {
|
|
25
61
|
assertOrderEmailDeliveryConfiguration,
|
|
26
62
|
createFileOrderEmailTransport,
|
|
@@ -29,6 +65,7 @@ export {
|
|
|
29
65
|
readOrderEmailTransportConfiguration,
|
|
30
66
|
registerUniqueScheduledTask,
|
|
31
67
|
renderOrderConfirmationEmail,
|
|
68
|
+
renderOrderLifecycleEmail,
|
|
32
69
|
scheduleOrderEmailRetry,
|
|
33
70
|
sanitizeFileTransportEmail,
|
|
34
71
|
writeSanitizedFileTransport,
|
|
@@ -36,6 +73,7 @@ export {
|
|
|
36
73
|
export type {
|
|
37
74
|
OrderConfirmationEmail,
|
|
38
75
|
OrderConfirmationEmailInput,
|
|
76
|
+
OrderLifecycleEmailInput,
|
|
39
77
|
OrderEmailLanguageCode,
|
|
40
78
|
OrderEmailTransport,
|
|
41
79
|
OrderEmailTransportConfiguration,
|
|
@@ -48,4 +86,14 @@ export {
|
|
|
48
86
|
registerJarShopOrderEmailWorkerTask,
|
|
49
87
|
} from "./order-email-worker.js";
|
|
50
88
|
export { JarShopOrderConsent } from "./order-consent.entity.js";
|
|
89
|
+
export {
|
|
90
|
+
getCourierOrderAlignmentState,
|
|
91
|
+
resolveShippingMethodCodeForOrderLines,
|
|
92
|
+
toFulfillmentLifecycleEmailKind,
|
|
93
|
+
validateFulfillmentTransition,
|
|
94
|
+
} from "./order-lifecycle-core.js";
|
|
95
|
+
export {
|
|
96
|
+
jarShopFulfillmentProcess,
|
|
97
|
+
registerJarShopOrderLifecycle,
|
|
98
|
+
} from "./order-lifecycle-process.js";
|
|
51
99
|
export { JarShopCheckoutPlugin } from "./jarshop-checkout.plugin.js";
|