medusa-contact-us 0.0.2 → 0.0.8
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/.medusa/server/src/admin/index.js +176 -1
- package/.medusa/server/src/admin/index.mjs +176 -1
- package/.medusa/server/src/api/admin/contact-email-subscriptions/route.js +29 -0
- package/.medusa/server/src/api/admin/contact-email-subscriptions/validators.js +12 -0
- package/.medusa/server/src/api/store/contact-email-subscriptions/route.js +19 -0
- package/.medusa/server/src/api/store/contact-email-subscriptions/validators.js +15 -0
- package/.medusa/server/src/constants.js +3 -2
- package/.medusa/server/src/helpers/__tests__/contact-subscription.test.js +109 -0
- package/.medusa/server/src/helpers/__tests__/submit-contact-request.test.js +33 -1
- package/.medusa/server/src/helpers/base-client.js +36 -0
- package/.medusa/server/src/helpers/contact-subscription.js +45 -0
- package/.medusa/server/src/helpers/index.js +5 -2
- package/.medusa/server/src/helpers/submit-contact-request.js +8 -29
- package/.medusa/server/src/index.js +7 -2
- package/.medusa/server/src/modules/contact-requests/migrations/Migration20241124090000.js +7 -2
- package/.medusa/server/src/modules/contact-requests/models/contact-request-comment.js +1 -2
- package/.medusa/server/src/modules/contact-requests/models/contact-request.js +1 -3
- package/.medusa/server/src/modules/contact-subscriptions/index.js +15 -0
- package/.medusa/server/src/modules/contact-subscriptions/migrations/Migration20241126103000.js +38 -0
- package/.medusa/server/src/modules/contact-subscriptions/models/contact-email-subscription.js +13 -0
- package/.medusa/server/src/modules/contact-subscriptions/service.js +57 -0
- package/README.md +132 -12
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ Collect, triage, and resolve storefront “contact us” submissions inside the
|
|
|
10
10
|
- 🗒️ Admin-only comment trail per request with rich status history
|
|
11
11
|
- 🖥️ React Admin extension with list + detail views, filters, status change controls, and comment composer
|
|
12
12
|
- 🔌 Frontend helper (`submitContactRequest`) to abstract API wiring
|
|
13
|
+
- ✉️ Storefront opt-in helper + admin list for email subscriptions (subscribed/unsubscribed)
|
|
13
14
|
- 🧪 Table-driven tests for payload validation and helper logic
|
|
14
15
|
|
|
15
16
|
## Installation
|
|
@@ -29,6 +30,7 @@ import type { ConfigModule } from "@medusajs/framework/types"
|
|
|
29
30
|
import {
|
|
30
31
|
defineContactUsPluginOptions,
|
|
31
32
|
ContactRequestModule,
|
|
33
|
+
ContactSubscriptionModule,
|
|
32
34
|
} from "medusa-contact-us"
|
|
33
35
|
|
|
34
36
|
const plugins = [
|
|
@@ -174,7 +176,7 @@ const plugins = [
|
|
|
174
176
|
]
|
|
175
177
|
|
|
176
178
|
// Register the ContactRequestModule
|
|
177
|
-
const modules = [ContactRequestModule]
|
|
179
|
+
const modules = [ContactRequestModule, ContactSubscriptionModule]
|
|
178
180
|
|
|
179
181
|
export default {
|
|
180
182
|
projectConfig: {
|
|
@@ -235,6 +237,38 @@ Response:
|
|
|
235
237
|
}
|
|
236
238
|
```
|
|
237
239
|
|
|
240
|
+
#### Email subscriptions
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
curl -X POST https://your-medusa.com/store/contact-email-subscriptions \
|
|
244
|
+
-H "Content-Type: application/json" \
|
|
245
|
+
-H "x-publishable-api-key: pk_storefront" \
|
|
246
|
+
-d '{
|
|
247
|
+
"email": "newsletter@example.com",
|
|
248
|
+
"status": "subscribed",
|
|
249
|
+
"source": "footer"
|
|
250
|
+
}'
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Body fields:
|
|
254
|
+
- `email` – required, unique per entry (case-insensitive).
|
|
255
|
+
- `status` – optional, defaults to `subscribed`. Pass `"unsubscribed"` to honor opt-outs.
|
|
256
|
+
- `metadata` / `source` – optional context stored alongside the entry.
|
|
257
|
+
|
|
258
|
+
Response:
|
|
259
|
+
|
|
260
|
+
```json
|
|
261
|
+
{
|
|
262
|
+
"subscription": {
|
|
263
|
+
"id": "csub_123",
|
|
264
|
+
"email": "newsletter@example.com",
|
|
265
|
+
"status": "subscribed",
|
|
266
|
+
"source": "footer",
|
|
267
|
+
"created_at": "2024-11-26T10:00:00.000Z"
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
238
272
|
### Admin (requires admin auth cookie/token)
|
|
239
273
|
|
|
240
274
|
List:
|
|
@@ -276,37 +310,123 @@ After running `medusa admin dev --plugins medusa-contact-us`, the sidebar will i
|
|
|
276
310
|
- **List view** – search by email, filter by status, inspect creation dates, open details with a single click.
|
|
277
311
|
- **Detail view** – see submitted fields, live status badge, change status (with optional notes), inspect the full history timeline, and append internal comments.
|
|
278
312
|
- **Comments** – only admins can add comments. Comments are persisted and shown newest first.
|
|
313
|
+
- **Contact email list** – dedicated table that displays every storefront opt-in, highlights unsubscribes, and supports filtering/searching by status or email.
|
|
279
314
|
|
|
280
315
|
All UI components follow the Medusa UI kit spacing (8pt grid), color, and accessibility guidelines.
|
|
281
316
|
|
|
282
317
|
## Frontend helper
|
|
283
318
|
|
|
284
|
-
Skip hand-writing `fetch` calls by importing the provided
|
|
319
|
+
Skip hand-writing `fetch` calls by importing the provided helpers. **Storefront requests must include a publishable API key** (create one under `Settings → API Keys` in the Medusa admin). The helpers automatically attach the header for you.
|
|
320
|
+
|
|
321
|
+
### Contact requests
|
|
285
322
|
|
|
286
323
|
```ts
|
|
287
324
|
import { submitContactRequest } from "medusa-contact-us"
|
|
288
325
|
|
|
289
|
-
await submitContactRequest(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
326
|
+
await submitContactRequest(
|
|
327
|
+
{
|
|
328
|
+
email: "customer@example.com",
|
|
329
|
+
payload: { subject: "Question", priority: "high" },
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
baseUrl: "https://store.myshop.com",
|
|
333
|
+
publishableApiKey: "pk_test_storefront",
|
|
334
|
+
}
|
|
335
|
+
)
|
|
293
336
|
```
|
|
294
337
|
|
|
295
|
-
|
|
338
|
+
Using a Medusa JS client keeps credentials in one place while still letting you override headers (including publishable keys) per call:
|
|
296
339
|
|
|
297
340
|
```ts
|
|
298
341
|
import Medusa from "@medusajs/medusa-js"
|
|
299
342
|
import { submitContactRequest } from "medusa-contact-us"
|
|
300
343
|
|
|
301
|
-
const
|
|
344
|
+
const medusa = new Medusa({
|
|
345
|
+
baseUrl: "https://store.myshop.com",
|
|
346
|
+
publishableKey: "pk_live_client",
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
await submitContactRequest(
|
|
350
|
+
{
|
|
351
|
+
email: "customer@example.com",
|
|
352
|
+
payload: { subject: "Returns" },
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
client: medusa,
|
|
356
|
+
publishableApiKey: "pk_live_client",
|
|
357
|
+
headers: {
|
|
358
|
+
Cookie: "connect.sid=...",
|
|
359
|
+
},
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
For SSR or edge runtimes, preconfigure the helper once:
|
|
302
365
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
366
|
+
```ts
|
|
367
|
+
import { createSubmitContactRequest } from "medusa-contact-us"
|
|
368
|
+
|
|
369
|
+
const submitContactRequest = createSubmitContactRequest({
|
|
370
|
+
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_URL,
|
|
371
|
+
publishableApiKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
|
|
307
372
|
})
|
|
373
|
+
|
|
374
|
+
export async function action(formData: FormData) {
|
|
375
|
+
await submitContactRequest({
|
|
376
|
+
email: formData.get("email") as string,
|
|
377
|
+
payload: {
|
|
378
|
+
subject: formData.get("subject"),
|
|
379
|
+
message: formData.get("message"),
|
|
380
|
+
},
|
|
381
|
+
})
|
|
382
|
+
}
|
|
308
383
|
```
|
|
309
384
|
|
|
385
|
+
### Email subscriptions
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
import { upsertContactSubscription } from "medusa-contact-us"
|
|
389
|
+
|
|
390
|
+
await upsertContactSubscription(
|
|
391
|
+
{
|
|
392
|
+
email: "newsletter@example.com",
|
|
393
|
+
status: "subscribed",
|
|
394
|
+
metadata: { channel: "footer" },
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
baseUrl: "https://store.myshop.com",
|
|
398
|
+
publishableApiKey: "pk_test_storefront",
|
|
399
|
+
}
|
|
400
|
+
)
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
To keep deploys DRY, build a preconfigured helper and reuse it everywhere:
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
import { createUpsertContactSubscription } from "medusa-contact-us"
|
|
407
|
+
|
|
408
|
+
export const upsertSubscription = createUpsertContactSubscription({
|
|
409
|
+
baseUrl: process.env.NEXT_PUBLIC_MEDUSA_URL,
|
|
410
|
+
publishableApiKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY,
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
await upsertSubscription({
|
|
414
|
+
email: input.email,
|
|
415
|
+
status: input.unsubscribe ? "unsubscribed" : "subscribed",
|
|
416
|
+
source: input.source ?? "footer_form",
|
|
417
|
+
})
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Shared helper options
|
|
421
|
+
|
|
422
|
+
- `publishableApiKey` – Automatically sets the `x-publishable-api-key` header when no Medusa client is used.
|
|
423
|
+
- `baseUrl` – Storefront API origin (ignored when `client` is provided).
|
|
424
|
+
- `client` – Pre-configured Medusa JS/SDK instance (reuses its base URL and publishable key).
|
|
425
|
+
- `fetchImpl` – Custom fetch implementation (SSR, React Native, etc.).
|
|
426
|
+
- `headers` – Additional headers merged into the request (e.g., session cookie, localization). Values you pass here override the defaults, including the publishable key header if you need a per-request key.
|
|
427
|
+
|
|
428
|
+
Customer-authenticated endpoints (like submitting a request from a logged-in area) still require the appropriate session cookie or JWT. Provide those via the `headers` option if they’re not already managed by the browser fetch call.
|
|
429
|
+
|
|
310
430
|
## Workflows & notifications
|
|
311
431
|
|
|
312
432
|
- `createContactRequestWorkflow` validates payloads, persists the request, and optionally fires an acknowledgement email.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "medusa-contact-us",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "A starter for Medusa plugins.",
|
|
5
5
|
"author": "Medusa (https://medusajs.com)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"exports": {
|
|
11
11
|
"./package.json": "./package.json",
|
|
12
12
|
"./workflows": "./.medusa/server/src/workflows/index.js",
|
|
13
|
+
"./helpers": "./.medusa/server/src/helpers/index.js",
|
|
13
14
|
"./.medusa/server/src/modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
14
15
|
"./modules/*": "./.medusa/server/src/modules/*/index.js",
|
|
15
16
|
"./providers/*": "./.medusa/server/src/providers/*/index.js",
|