@jytextiles/medusa-plugin-faire-store-sync 0.1.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/.medusa/server/src/__tests__/ingest-faire-order-support.spec.js +74 -0
- package/.medusa/server/src/__tests__/webhook.spec.js +77 -0
- package/.medusa/server/src/admin/index.js +960 -0
- package/.medusa/server/src/admin/index.mjs +959 -0
- package/.medusa/server/src/api/admin/faire/auth/authorize/route.js +12 -0
- package/.medusa/server/src/api/admin/faire/auth/callback/route.js +25 -0
- package/.medusa/server/src/api/admin/faire/auth/disconnect/route.js +12 -0
- package/.medusa/server/src/api/admin/faire/brand/route.js +14 -0
- package/.medusa/server/src/api/admin/faire/ingest/orders/[batchId]/route.js +27 -0
- package/.medusa/server/src/api/admin/faire/ingest/orders/route.js +20 -0
- package/.medusa/server/src/api/admin/faire/products/route.js +16 -0
- package/.medusa/server/src/api/admin/faire/settings/route.js +19 -0
- package/.medusa/server/src/api/admin/faire/status/product/[id]/route.js +30 -0
- package/.medusa/server/src/api/admin/faire/status/route.js +46 -0
- package/.medusa/server/src/api/admin/faire/sync/bulk/[batchId]/route.js +29 -0
- package/.medusa/server/src/api/admin/faire/sync/bulk/route.js +20 -0
- package/.medusa/server/src/api/admin/faire/sync/product/[id]/route.js +14 -0
- package/.medusa/server/src/api/admin/faire/syncs/[id]/route.js +32 -0
- package/.medusa/server/src/api/admin/faire/syncs/route.js +18 -0
- package/.medusa/server/src/api/webhooks/faire/route.js +125 -0
- package/.medusa/server/src/jobs/pull-faire-orders.js +32 -0
- package/.medusa/server/src/jobs/refresh-faire-token.js +25 -0
- package/.medusa/server/src/lib/faire-client.js +321 -0
- package/.medusa/server/src/lib/types.js +10 -0
- package/.medusa/server/src/lib/webhook.js +58 -0
- package/.medusa/server/src/links/product-faire-sync-link.js +57 -0
- package/.medusa/server/src/modules/faire-sync/index.js +15 -0
- package/.medusa/server/src/modules/faire-sync/migrations/Migration20260707211346.js +34 -0
- package/.medusa/server/src/modules/faire-sync/models/faire-order.js +21 -0
- package/.medusa/server/src/modules/faire-sync/models/faire-sync-account.js +17 -0
- package/.medusa/server/src/modules/faire-sync/models/faire-sync-batch.js +18 -0
- package/.medusa/server/src/modules/faire-sync/models/faire-sync-record.js +22 -0
- package/.medusa/server/src/modules/faire-sync/models/faire-sync-settings.js +26 -0
- package/.medusa/server/src/modules/faire-sync/models/faire-webhook-event.js +21 -0
- package/.medusa/server/src/modules/faire-sync/service.js +222 -0
- package/.medusa/server/src/subscribers/faire-inventory-sync.js +87 -0
- package/.medusa/server/src/subscribers/faire-listing-events.js +46 -0
- package/.medusa/server/src/subscribers/faire-order-ingest.js +54 -0
- package/.medusa/server/src/subscribers/faire-order-lifecycle.js +71 -0
- package/.medusa/server/src/subscribers/faire-product-status-sync.js +71 -0
- package/.medusa/server/src/workflows/index.js +21 -0
- package/.medusa/server/src/workflows/ingest-faire-order-support.js +76 -0
- package/.medusa/server/src/workflows/ingest-faire-order.js +148 -0
- package/.medusa/server/src/workflows/ingest-faire-orders-bulk.js +124 -0
- package/.medusa/server/src/workflows/refresh-faire-token.js +20 -0
- package/.medusa/server/src/workflows/sync-product-to-faire.js +262 -0
- package/.medusa/server/src/workflows/sync-products-to-faire.js +90 -0
- package/LICENSE +21 -0
- package/README.md +180 -0
- package/package.json +84 -0
- package/scripts/postbuild.js +36 -0
- package/src/__tests__/ingest-faire-order-support.spec.ts +77 -0
- package/src/__tests__/webhook.spec.ts +81 -0
- package/src/admin/lib/api.ts +88 -0
- package/src/admin/routes/settings/faire/[id]/page.tsx +184 -0
- package/src/admin/routes/settings/faire/hooks/use-faire-sync-columns.tsx +80 -0
- package/src/admin/routes/settings/faire/page.tsx +445 -0
- package/src/admin/routes/settings/faire/settings/page.tsx +286 -0
- package/src/admin/routes/settings/oauth/faire/callback/page.tsx +67 -0
- package/src/admin/widgets/faire-product-widget.tsx +180 -0
- package/src/api/admin/faire/auth/authorize/route.ts +10 -0
- package/src/api/admin/faire/auth/callback/route.ts +29 -0
- package/src/api/admin/faire/auth/disconnect/route.ts +10 -0
- package/src/api/admin/faire/brand/route.ts +12 -0
- package/src/api/admin/faire/ingest/orders/[batchId]/route.ts +31 -0
- package/src/api/admin/faire/ingest/orders/route.ts +29 -0
- package/src/api/admin/faire/products/route.ts +14 -0
- package/src/api/admin/faire/settings/route.ts +17 -0
- package/src/api/admin/faire/status/product/[id]/route.ts +30 -0
- package/src/api/admin/faire/status/route.ts +47 -0
- package/src/api/admin/faire/sync/bulk/[batchId]/route.ts +33 -0
- package/src/api/admin/faire/sync/bulk/route.ts +27 -0
- package/src/api/admin/faire/sync/product/[id]/route.ts +13 -0
- package/src/api/admin/faire/syncs/[id]/route.ts +32 -0
- package/src/api/admin/faire/syncs/route.ts +17 -0
- package/src/api/webhooks/faire/route.ts +133 -0
- package/src/jobs/pull-faire-orders.ts +30 -0
- package/src/jobs/refresh-faire-token.ts +23 -0
- package/src/lib/faire-client.ts +436 -0
- package/src/lib/types.ts +117 -0
- package/src/lib/webhook.ts +85 -0
- package/src/links/product-faire-sync-link.ts +56 -0
- package/src/modules/faire-sync/index.ts +11 -0
- package/src/modules/faire-sync/migrations/.snapshot-medusa-faire-sync.json +1486 -0
- package/src/modules/faire-sync/migrations/Migration20260707211346.ts +43 -0
- package/src/modules/faire-sync/models/faire-order.ts +20 -0
- package/src/modules/faire-sync/models/faire-sync-account.ts +16 -0
- package/src/modules/faire-sync/models/faire-sync-batch.ts +17 -0
- package/src/modules/faire-sync/models/faire-sync-record.ts +21 -0
- package/src/modules/faire-sync/models/faire-sync-settings.ts +25 -0
- package/src/modules/faire-sync/models/faire-webhook-event.ts +20 -0
- package/src/modules/faire-sync/service.ts +252 -0
- package/src/subscribers/faire-inventory-sync.ts +97 -0
- package/src/subscribers/faire-listing-events.ts +48 -0
- package/src/subscribers/faire-order-ingest.ts +61 -0
- package/src/subscribers/faire-order-lifecycle.ts +81 -0
- package/src/subscribers/faire-product-status-sync.ts +76 -0
- package/src/workflows/index.ts +4 -0
- package/src/workflows/ingest-faire-order-support.ts +96 -0
- package/src/workflows/ingest-faire-order.ts +212 -0
- package/src/workflows/ingest-faire-orders-bulk.ts +168 -0
- package/src/workflows/refresh-faire-token.ts +28 -0
- package/src/workflows/sync-product-to-faire.ts +375 -0
- package/src/workflows/sync-products-to-faire.ts +133 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
4
|
+
/**
|
|
5
|
+
* Singleton settings row. Holds publish-readiness defaults plus the in-flight
|
|
6
|
+
* OAuth `state` (keyed by it) so the callback can verify the round-trip.
|
|
7
|
+
*
|
|
8
|
+
* Faire-flavored readiness: connection, brand id, wholesale pricing strategy,
|
|
9
|
+
* and shipping policy. Missing fields sync products as drafts rather than
|
|
10
|
+
* publishing them.
|
|
11
|
+
*/
|
|
12
|
+
const FaireSyncSettings = utils_1.model.define("faire_sync_settings", {
|
|
13
|
+
id: utils_1.model.id().primaryKey(),
|
|
14
|
+
account_id: utils_1.model.text().nullable(),
|
|
15
|
+
default_brand_id: utils_1.model.text().nullable(),
|
|
16
|
+
default_wholesale_markup_percent: utils_1.model.number().nullable(),
|
|
17
|
+
default_min_order_quantity: utils_1.model.number().default(1),
|
|
18
|
+
default_lead_time_days: utils_1.model.number().nullable(),
|
|
19
|
+
default_shipping_policy_id: utils_1.model.text().nullable(),
|
|
20
|
+
default_category: utils_1.model.text().nullable(),
|
|
21
|
+
auto_publish: utils_1.model.boolean().default(false),
|
|
22
|
+
follow_product_status: utils_1.model.boolean().default(true),
|
|
23
|
+
pending_oauth: utils_1.model.json().nullable(),
|
|
24
|
+
});
|
|
25
|
+
exports.default = FaireSyncSettings;
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpcmUtc3luYy1zZXR0aW5ncy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2ZhaXJlLXN5bmMvbW9kZWxzL2ZhaXJlLXN5bmMtc2V0dGluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBaUQ7QUFFakQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0saUJBQWlCLEdBQUcsYUFBSyxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRTtJQUM1RCxFQUFFLEVBQUUsYUFBSyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsRUFBRTtJQUMzQixVQUFVLEVBQUUsYUFBSyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUNuQyxnQkFBZ0IsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ3pDLGdDQUFnQyxFQUFFLGFBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDM0QsMEJBQTBCLEVBQUUsYUFBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDckQsc0JBQXNCLEVBQUUsYUFBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUNqRCwwQkFBMEIsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ25ELGdCQUFnQixFQUFFLGFBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxRQUFRLEVBQUU7SUFDekMsWUFBWSxFQUFFLGFBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO0lBQzVDLHFCQUFxQixFQUFFLGFBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0lBQ3BELGFBQWEsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFO0NBQ3ZDLENBQUMsQ0FBQTtBQUVGLGtCQUFlLGlCQUFpQixDQUFBIn0=
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
4
|
+
/**
|
|
5
|
+
* Durable record of an inbound Faire webhook delivery. `webhook_id` is the
|
|
6
|
+
* delivery id Faire sends (unique) so retries are idempotent.
|
|
7
|
+
*/
|
|
8
|
+
const FaireWebhookEvent = utils_1.model.define("faire_webhook_event", {
|
|
9
|
+
id: utils_1.model.id().primaryKey(),
|
|
10
|
+
webhook_id: utils_1.model.text().unique(),
|
|
11
|
+
event_type: utils_1.model.text(),
|
|
12
|
+
brand_id: utils_1.model.text().nullable(),
|
|
13
|
+
resource_url: utils_1.model.text().nullable(),
|
|
14
|
+
payload: utils_1.model.json().nullable(),
|
|
15
|
+
resource: utils_1.model.json().nullable(),
|
|
16
|
+
processed: utils_1.model.boolean().default(false),
|
|
17
|
+
error: utils_1.model.text().nullable(),
|
|
18
|
+
received_at: utils_1.model.dateTime().nullable(),
|
|
19
|
+
});
|
|
20
|
+
exports.default = FaireWebhookEvent;
|
|
21
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpcmUtd2ViaG9vay1ldmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2ZhaXJlLXN5bmMvbW9kZWxzL2ZhaXJlLXdlYmhvb2stZXZlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBaUQ7QUFFakQ7OztHQUdHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxhQUFLLENBQUMsTUFBTSxDQUFDLHFCQUFxQixFQUFFO0lBQzVELEVBQUUsRUFBRSxhQUFLLENBQUMsRUFBRSxFQUFFLENBQUMsVUFBVSxFQUFFO0lBQzNCLFVBQVUsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxFQUFFO0lBQ2pDLFVBQVUsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFO0lBQ3hCLFFBQVEsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ2pDLFlBQVksRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ3JDLE9BQU8sRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ2hDLFFBQVEsRUFBRSxhQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ2pDLFNBQVMsRUFBRSxhQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztJQUN6QyxLQUFLLEVBQUUsYUFBSyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUM5QixXQUFXLEVBQUUsYUFBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsRUFBRTtDQUN6QyxDQUFDLENBQUE7QUFFRixrQkFBZSxpQkFBaUIsQ0FBQSJ9
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
7
|
+
const faire_sync_account_1 = __importDefault(require("./models/faire-sync-account"));
|
|
8
|
+
const faire_sync_record_1 = __importDefault(require("./models/faire-sync-record"));
|
|
9
|
+
const faire_sync_settings_1 = __importDefault(require("./models/faire-sync-settings"));
|
|
10
|
+
const faire_sync_batch_1 = __importDefault(require("./models/faire-sync-batch"));
|
|
11
|
+
const faire_webhook_event_1 = __importDefault(require("./models/faire-webhook-event"));
|
|
12
|
+
const faire_order_1 = __importDefault(require("./models/faire-order"));
|
|
13
|
+
const faire_client_1 = require("../../lib/faire-client");
|
|
14
|
+
function readOption(options, key) {
|
|
15
|
+
try {
|
|
16
|
+
const value = options?.[key];
|
|
17
|
+
return typeof value === "string" ? value : undefined;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function toMedusaError(err) {
|
|
24
|
+
if (err instanceof utils_1.MedusaError)
|
|
25
|
+
return err;
|
|
26
|
+
const status = err?.status;
|
|
27
|
+
const body = err?.body;
|
|
28
|
+
const message = body?.error_description || body?.error || err?.message || "Faire request failed";
|
|
29
|
+
if (status === 400 && /invalid_grant|invalid code|already used/i.test(message)) {
|
|
30
|
+
return new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Faire authorization expired or was already used. Please reconnect.");
|
|
31
|
+
}
|
|
32
|
+
if (/brand/i.test(message) && /(no|not|own)/i.test(message)) {
|
|
33
|
+
return new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, message);
|
|
34
|
+
}
|
|
35
|
+
if (status === 401 || status === 403) {
|
|
36
|
+
return new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, message);
|
|
37
|
+
}
|
|
38
|
+
if (status === 404) {
|
|
39
|
+
return new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, message);
|
|
40
|
+
}
|
|
41
|
+
if (status === 400 || status === 422) {
|
|
42
|
+
return new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, message);
|
|
43
|
+
}
|
|
44
|
+
return new utils_1.MedusaError(utils_1.MedusaError.Types.UNEXPECTED_STATE, message);
|
|
45
|
+
}
|
|
46
|
+
function resolveFaireOptions(options) {
|
|
47
|
+
return {
|
|
48
|
+
clientId: process.env.FAIRE_CLIENT_ID ?? readOption(options, "clientId") ?? "",
|
|
49
|
+
clientSecret: process.env.FAIRE_CLIENT_SECRET ?? readOption(options, "clientSecret") ?? "",
|
|
50
|
+
redirectUri: process.env.FAIRE_REDIRECT_URI ??
|
|
51
|
+
readOption(options, "redirectUri") ??
|
|
52
|
+
"http://localhost:9000/app/settings/oauth/faire/callback",
|
|
53
|
+
apiBase: process.env.FAIRE_API_BASE ?? readOption(options, "apiBase"),
|
|
54
|
+
authUrl: process.env.FAIRE_AUTH_URL ?? readOption(options, "authUrl"),
|
|
55
|
+
tokenUrl: process.env.FAIRE_TOKEN_URL ?? readOption(options, "tokenUrl"),
|
|
56
|
+
scope: process.env.FAIRE_SCOPE ?? readOption(options, "scope") ?? "",
|
|
57
|
+
webhookSecret: process.env.FAIRE_WEBHOOK_SECRET ?? readOption(options, "webhookSecret") ?? "",
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
class FaireSyncService extends (0, utils_1.MedusaService)({
|
|
61
|
+
FaireSyncAccount: faire_sync_account_1.default,
|
|
62
|
+
FaireSyncRecord: faire_sync_record_1.default,
|
|
63
|
+
FaireSyncSettings: faire_sync_settings_1.default,
|
|
64
|
+
FaireSyncBatch: faire_sync_batch_1.default,
|
|
65
|
+
FaireWebhookEvent: faire_webhook_event_1.default,
|
|
66
|
+
FaireOrder: faire_order_1.default,
|
|
67
|
+
}) {
|
|
68
|
+
constructor(container, options) {
|
|
69
|
+
super(...arguments);
|
|
70
|
+
this.client_ = null;
|
|
71
|
+
this.options_ = resolveFaireOptions(options);
|
|
72
|
+
}
|
|
73
|
+
getClient() {
|
|
74
|
+
if (!this.client_) {
|
|
75
|
+
this.client_ = new faire_client_1.FaireClient(this.options_);
|
|
76
|
+
}
|
|
77
|
+
return this.client_;
|
|
78
|
+
}
|
|
79
|
+
getOptions() {
|
|
80
|
+
return this.options_;
|
|
81
|
+
}
|
|
82
|
+
async getActiveAccount() {
|
|
83
|
+
const [account] = await this.listFaireSyncAccounts({
|
|
84
|
+
is_active: true,
|
|
85
|
+
});
|
|
86
|
+
return account ?? null;
|
|
87
|
+
}
|
|
88
|
+
async saveAccount(token, brand) {
|
|
89
|
+
const existing = await this.getActiveAccount();
|
|
90
|
+
const expiresAt = token.expires_in != null
|
|
91
|
+
? new Date(token.retrieved_at + token.expires_in * 1000)
|
|
92
|
+
: null;
|
|
93
|
+
const payload = {
|
|
94
|
+
brand_id: brand.brand_id,
|
|
95
|
+
brand_name: brand.brand_name,
|
|
96
|
+
currency: brand.currency ?? null,
|
|
97
|
+
country: brand.country ?? null,
|
|
98
|
+
access_token: token.access_token,
|
|
99
|
+
refresh_token: token.refresh_token ?? null,
|
|
100
|
+
token_expires_at: expiresAt,
|
|
101
|
+
brand_info: brand.raw,
|
|
102
|
+
is_active: true,
|
|
103
|
+
};
|
|
104
|
+
if (existing) {
|
|
105
|
+
return this.updateFaireSyncAccounts({
|
|
106
|
+
id: existing.id,
|
|
107
|
+
...payload,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return this.createFaireSyncAccounts(payload);
|
|
111
|
+
}
|
|
112
|
+
async disconnect() {
|
|
113
|
+
const account = await this.getActiveAccount();
|
|
114
|
+
if (!account)
|
|
115
|
+
return;
|
|
116
|
+
await this.updateFaireSyncAccounts({
|
|
117
|
+
id: account.id,
|
|
118
|
+
is_active: false,
|
|
119
|
+
access_token: "",
|
|
120
|
+
refresh_token: null,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
async ensureFreshToken(account) {
|
|
124
|
+
const acct = account ?? (await this.getActiveAccount());
|
|
125
|
+
if (!acct) {
|
|
126
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, "Faire account is not connected");
|
|
127
|
+
}
|
|
128
|
+
if (!acct.token_expires_at) {
|
|
129
|
+
return acct;
|
|
130
|
+
}
|
|
131
|
+
const now = Date.now();
|
|
132
|
+
const expiresAt = new Date(acct.token_expires_at).getTime();
|
|
133
|
+
const fiveMinutes = 5 * 60 * 1000;
|
|
134
|
+
if (expiresAt - now > fiveMinutes) {
|
|
135
|
+
return acct;
|
|
136
|
+
}
|
|
137
|
+
if (!acct.refresh_token) {
|
|
138
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Faire access token has expired. Please reconnect your Faire account.");
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
const client = this.getClient();
|
|
142
|
+
const token = await client.refreshAccessToken(acct.refresh_token);
|
|
143
|
+
return this.updateFaireSyncAccounts({
|
|
144
|
+
id: acct.id,
|
|
145
|
+
access_token: token.access_token,
|
|
146
|
+
refresh_token: token.refresh_token ?? acct.refresh_token,
|
|
147
|
+
token_expires_at: token.expires_in != null
|
|
148
|
+
? new Date(token.retrieved_at + token.expires_in * 1000)
|
|
149
|
+
: null,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
throw toMedusaError(err);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async getSettings() {
|
|
157
|
+
const [settings] = await this.listFaireSyncSettings({}, { take: 1 });
|
|
158
|
+
if (settings)
|
|
159
|
+
return settings;
|
|
160
|
+
return this.createFaireSyncSettings({});
|
|
161
|
+
}
|
|
162
|
+
async updateSettings(data) {
|
|
163
|
+
const settings = await this.getSettings();
|
|
164
|
+
return this.updateFaireSyncSettings({ id: settings.id, ...data });
|
|
165
|
+
}
|
|
166
|
+
async startOAuth() {
|
|
167
|
+
try {
|
|
168
|
+
const state = crypto.randomUUID();
|
|
169
|
+
await this.updateSettings({
|
|
170
|
+
pending_oauth: {
|
|
171
|
+
state,
|
|
172
|
+
created_at: Date.now(),
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
const client = this.getClient();
|
|
176
|
+
return {
|
|
177
|
+
authorization_url: client.getAuthorizationUrl(state),
|
|
178
|
+
state,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (err) {
|
|
182
|
+
throw toMedusaError(err);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async completeOAuth(code, state) {
|
|
186
|
+
const settings = await this.getSettings();
|
|
187
|
+
const pending = settings.pending_oauth;
|
|
188
|
+
if (!pending || pending.state !== state) {
|
|
189
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Invalid or expired OAuth state. Please start the Faire connection again.");
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
const client = this.getClient();
|
|
193
|
+
const token = await client.exchangeCodeForToken(code);
|
|
194
|
+
const brand = await client.getBrand(token.access_token);
|
|
195
|
+
const account = await this.saveAccount(token, brand);
|
|
196
|
+
await this.updateSettings({
|
|
197
|
+
account_id: account.id,
|
|
198
|
+
default_brand_id: brand.brand_id,
|
|
199
|
+
pending_oauth: null,
|
|
200
|
+
});
|
|
201
|
+
return { account, brand };
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
throw toMedusaError(err);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
async createSyncRecord(data) {
|
|
208
|
+
return this.createFaireSyncRecords(data);
|
|
209
|
+
}
|
|
210
|
+
async updateSyncRecord(id, data) {
|
|
211
|
+
return this.updateFaireSyncRecords({ id, ...data });
|
|
212
|
+
}
|
|
213
|
+
async listSyncRecords(filters = {}, take = 20, skip = 0) {
|
|
214
|
+
return this.listAndCountFaireSyncRecords(filters, {
|
|
215
|
+
take,
|
|
216
|
+
skip,
|
|
217
|
+
order: { created_at: "DESC" },
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
exports.default = FaireSyncService;
|
|
222
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL2ZhaXJlLXN5bmMvc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFEQUFzRTtBQUN0RSxxRkFBMEQ7QUFDMUQsbUZBQXdEO0FBQ3hELHVGQUE0RDtBQUM1RCxpRkFBc0Q7QUFDdEQsdUZBQTREO0FBQzVELHVFQUE2QztBQUM3Qyx5REFBb0Q7QUFLcEQsU0FBUyxVQUFVLENBQUMsT0FBWSxFQUFFLEdBQVc7SUFDM0MsSUFBSSxDQUFDO1FBQ0gsTUFBTSxLQUFLLEdBQUcsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDNUIsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFBO0lBQ3RELENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLFNBQVMsQ0FBQTtJQUNsQixDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLEdBQVE7SUFDN0IsSUFBSSxHQUFHLFlBQVksbUJBQVc7UUFBRSxPQUFPLEdBQUcsQ0FBQTtJQUUxQyxNQUFNLE1BQU0sR0FBdUIsR0FBRyxFQUFFLE1BQU0sQ0FBQTtJQUM5QyxNQUFNLElBQUksR0FBUSxHQUFHLEVBQUUsSUFBSSxDQUFBO0lBQzNCLE1BQU0sT0FBTyxHQUNYLElBQUksRUFBRSxpQkFBaUIsSUFBSSxJQUFJLEVBQUUsS0FBSyxJQUFJLEdBQUcsRUFBRSxPQUFPLElBQUksc0JBQXNCLENBQUE7SUFFbEYsSUFBSSxNQUFNLEtBQUssR0FBRyxJQUFJLDBDQUEwQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQy9FLE9BQU8sSUFBSSxtQkFBVyxDQUNwQixtQkFBVyxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQzlCLG9FQUFvRSxDQUNyRSxDQUFBO0lBQ0gsQ0FBQztJ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
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = faireInventorySyncHandler;
|
|
5
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
+
const faire_sync_1 = require("../modules/faire-sync");
|
|
7
|
+
/**
|
|
8
|
+
* React to inventory updates Faire pushes (e.g. a retailer placed an order and
|
|
9
|
+
* Faire decremented stock). We mirror the remote count back onto the linked
|
|
10
|
+
* Medusa variant's inventory so the two systems stay consistent. Best-effort —
|
|
11
|
+
* never throws.
|
|
12
|
+
*/
|
|
13
|
+
async function faireInventorySyncHandler({ event: { data }, container, }) {
|
|
14
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
15
|
+
const service = container.resolve(faire_sync_1.FAIRE_SYNC_MODULE);
|
|
16
|
+
let payload = data?.resource;
|
|
17
|
+
if (!payload && data?.resource_url) {
|
|
18
|
+
try {
|
|
19
|
+
const account = await service.ensureFreshToken();
|
|
20
|
+
payload = await service
|
|
21
|
+
.getClient()
|
|
22
|
+
.fetchResource(account.access_token, data.resource_url);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (!payload)
|
|
29
|
+
return;
|
|
30
|
+
const levels = Array.isArray(payload?.inventory)
|
|
31
|
+
? payload.inventory
|
|
32
|
+
: Array.isArray(payload)
|
|
33
|
+
? payload
|
|
34
|
+
: payload?.items
|
|
35
|
+
? payload.items
|
|
36
|
+
: [];
|
|
37
|
+
if (!levels.length)
|
|
38
|
+
return;
|
|
39
|
+
try {
|
|
40
|
+
const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
|
|
41
|
+
const inventory = container.resolve(utils_1.Modules.INVENTORY);
|
|
42
|
+
for (const lvl of levels) {
|
|
43
|
+
const sku = String(lvl.sku ?? "");
|
|
44
|
+
const count = Number(lvl.current_count ?? lvl.inventory_count);
|
|
45
|
+
if (!sku || !Number.isFinite(count))
|
|
46
|
+
continue;
|
|
47
|
+
// Find the linked Medusa product via sync record matching this SKU's
|
|
48
|
+
// product token, then resolve its inventory item and set the level.
|
|
49
|
+
const productToken = lvl.product_token ? String(lvl.product_token) : null;
|
|
50
|
+
if (!productToken)
|
|
51
|
+
continue;
|
|
52
|
+
const [records] = await service.listSyncRecords({ product_token: productToken }, 1, 0);
|
|
53
|
+
const productId = records?.[0]?.product_id;
|
|
54
|
+
if (!productId)
|
|
55
|
+
continue;
|
|
56
|
+
const { data: products } = await query.graph({
|
|
57
|
+
entity: "product",
|
|
58
|
+
fields: [
|
|
59
|
+
"id",
|
|
60
|
+
"variants.sku",
|
|
61
|
+
"variants.inventory_items.inventory_item_id",
|
|
62
|
+
"variants.inventory_items.inventory.location_levels.location_id",
|
|
63
|
+
"variants.inventory_items.inventory.location_levels.stocked_quantity",
|
|
64
|
+
],
|
|
65
|
+
filters: { id: productId },
|
|
66
|
+
});
|
|
67
|
+
const variant = (products?.[0]?.variants || []).find((v) => v.sku === sku);
|
|
68
|
+
const invItem = (variant?.inventory_items || [])[0];
|
|
69
|
+
const levels2 = invItem?.inventory?.location_levels || [];
|
|
70
|
+
const level = [...levels2].sort((a, b) => Number(b.stocked_quantity) - Number(a.stocked_quantity))[0];
|
|
71
|
+
if (!invItem?.inventory_item_id || !level?.location_id)
|
|
72
|
+
continue;
|
|
73
|
+
const delta = count - Number(level.stocked_quantity || 0);
|
|
74
|
+
if (delta !== 0) {
|
|
75
|
+
await inventory.adjustInventory(invItem.inventory_item_id, level.location_id, delta);
|
|
76
|
+
logger?.info?.(`[faire-inventory] ${sku} adjusted by ${delta} → ${count}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
logger?.warn?.(`[faire-inventory] sync failed: ${err?.message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.config = {
|
|
85
|
+
event: "faire.inventory_updated",
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpcmUtaW52ZW50b3J5LXN5bmMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc3Vic2NyaWJlcnMvZmFpcmUtaW52ZW50b3J5LXN5bmMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBV0EsNENBaUZDO0FBM0ZELHFEQUE4RTtBQUM5RSxzREFBeUQ7QUFHekQ7Ozs7O0dBS0c7QUFDWSxLQUFLLFVBQVUseUJBQXlCLENBQUMsRUFDdEQsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQ2YsU0FBUyxHQUNpRDtJQUMxRCxNQUFNLE1BQU0sR0FBUSxTQUFTLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ3ZFLE1BQU0sT0FBTyxHQUFxQixTQUFTLENBQUMsT0FBTyxDQUFDLDhCQUFpQixDQUFDLENBQUE7SUFFdEUsSUFBSSxPQUFPLEdBQVEsSUFBSSxFQUFFLFFBQVEsQ0FBQTtJQUNqQyxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztRQUNuQyxJQUFJLENBQUM7WUFDSCxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1lBQ2hELE9BQU8sR0FBRyxNQUFNLE9BQU87aUJBQ3BCLFNBQVMsRUFBRTtpQkFDWCxhQUFhLENBQUUsT0FBZSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDcEUsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU07UUFDUixDQUFDO0lBQ0gsQ0FBQztJQUNELElBQUksQ0FBQyxPQUFPO1FBQUUsT0FBTTtJQUVwQixNQUFNLE1BQU0sR0FBVSxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUM7UUFDckQsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTO1FBQ25CLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztZQUN0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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = faireListingEventsHandler;
|
|
5
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
+
/**
|
|
7
|
+
* Surface notable Faire product/listing changes to the admin feed. Faire emits
|
|
8
|
+
* outbound webhooks for product updates; the webhook receiver re-emits internal
|
|
9
|
+
* `faire.product.*` / `faire.listing.*` events that this subscriber turns into
|
|
10
|
+
* admin feed notifications. Extend here to auto-restock or re-list.
|
|
11
|
+
*/
|
|
12
|
+
const LABELS = {
|
|
13
|
+
"faire.product_updated": "was updated on Faire",
|
|
14
|
+
"faire.product_sold_out": "sold out on Faire",
|
|
15
|
+
"faire.product_deactivated": "was deactivated on Faire",
|
|
16
|
+
"faire.listing.deleted": "was removed on Faire",
|
|
17
|
+
};
|
|
18
|
+
async function faireListingEventsHandler({ event, container, }) {
|
|
19
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
20
|
+
const label = LABELS[event.name] || "changed on Faire";
|
|
21
|
+
const token = event.data?.product_token;
|
|
22
|
+
try {
|
|
23
|
+
const notification = container.resolve(utils_1.Modules.NOTIFICATION);
|
|
24
|
+
await notification.createNotifications({
|
|
25
|
+
to: "",
|
|
26
|
+
channel: "feed",
|
|
27
|
+
template: "admin-ui",
|
|
28
|
+
data: {
|
|
29
|
+
title: "Faire product update",
|
|
30
|
+
description: `Faire product ${token ?? ""} ${label}.`,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
logger?.warn?.(`[faire-listing] notify failed for ${event.name}: ${err?.message}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.config = {
|
|
39
|
+
event: [
|
|
40
|
+
"faire.product_updated",
|
|
41
|
+
"faire.product_sold_out",
|
|
42
|
+
"faire.product_deactivated",
|
|
43
|
+
"faire.listing.deleted",
|
|
44
|
+
],
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpcmUtbGlzdGluZy1ldmVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvc3Vic2NyaWJlcnMvZmFpcmUtbGlzdGluZy1ldmVudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBZ0JBLDRDQXNCQztBQXJDRCxxREFBOEU7QUFFOUU7Ozs7O0dBS0c7QUFDSCxNQUFNLE1BQU0sR0FBMkI7SUFDckMsdUJBQXVCLEVBQUUsc0JBQXNCO0lBQy9DLHdCQUF3QixFQUFFLG1CQUFtQjtJQUM3QywyQkFBMkIsRUFBRSwwQkFBMEI7SUFDdkQsdUJBQXVCLEVBQUUsc0JBQXNCO0NBQ2hELENBQUE7QUFFYyxLQUFLLFVBQVUseUJBQXlCLENBQUMsRUFDdEQsS0FBSyxFQUNMLFNBQVMsR0FDa0Q7SUFDM0QsTUFBTSxNQUFNLEdBQVEsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUN2RSxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLGtCQUFrQixDQUFBO0lBQ3RELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsYUFBYSxDQUFBO0lBRXZDLElBQUksQ0FBQztRQUNILE1BQU0sWUFBWSxHQUFRLFNBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLFlBQVksQ0FBQyxDQUFBO1FBQ2pFLE1BQU0sWUFBWSxDQUFDLG1CQUFtQixDQUFDO1lBQ3JDLEVBQUUsRUFBRSxFQUFFO1lBQ04sT0FBTyxFQUFFLE1BQU07WUFDZixRQUFRLEVBQUUsVUFBVTtZQUNwQixJQUFJLEVBQUU7Z0JBQ0osS0FBSyxFQUFFLHNCQUFzQjtnQkFDN0IsV0FBVyxFQUFFLGlCQUFpQixLQUFLLElBQUksRUFBRSxJQUFJLEtBQUssR0FBRzthQUN0RDtTQUNGLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEdBQVEsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxxQ0FBcUMsS0FBSyxDQUFDLElBQUksS0FBSyxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUNwRixDQUFDO0FBQ0gsQ0FBQztBQUVZLFFBQUEsTUFBTSxHQUFxQjtJQUN0QyxLQUFLLEVBQUU7UUFDTCx1QkFBdUI7UUFDdkIsd0JBQXdCO1FBQ3hCLDJCQUEyQjtRQUMzQix1QkFBdUI7S0FDeEI7Q0FDRixDQUFBIn0=
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = faireOrderIngestHandler;
|
|
5
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
+
const faire_sync_1 = require("../modules/faire-sync");
|
|
7
|
+
const ingest_faire_order_1 = require("../workflows/ingest-faire-order");
|
|
8
|
+
/**
|
|
9
|
+
* Create a Medusa order from a placed Faire order.
|
|
10
|
+
*
|
|
11
|
+
* Fired by the `faire.order_placed` (or `faire.order_created`) event the webhook
|
|
12
|
+
* receiver emits, kept off the webhook request path so the 200 stays fast. The
|
|
13
|
+
* Faire order is carried on the event; if it wasn't fetched at webhook time we
|
|
14
|
+
* refetch from resource_url.
|
|
15
|
+
*
|
|
16
|
+
* Kill switch: set FAIRE_INGEST_ORDERS=false to disable order creation while
|
|
17
|
+
* still recording webhook deliveries.
|
|
18
|
+
*/
|
|
19
|
+
async function faireOrderIngestHandler({ event: { data }, container, }) {
|
|
20
|
+
if (process.env.FAIRE_INGEST_ORDERS === "false")
|
|
21
|
+
return;
|
|
22
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
23
|
+
const service = container.resolve(faire_sync_1.FAIRE_SYNC_MODULE);
|
|
24
|
+
let order = data?.resource;
|
|
25
|
+
if (!order && data?.resource_url) {
|
|
26
|
+
try {
|
|
27
|
+
const account = await service.ensureFreshToken();
|
|
28
|
+
order = await service
|
|
29
|
+
.getClient()
|
|
30
|
+
.fetchResource(account.access_token, data.resource_url);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
logger?.warn?.(`[faire-order] could not fetch order: ${err?.message}`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (!order)
|
|
38
|
+
return;
|
|
39
|
+
try {
|
|
40
|
+
await (0, ingest_faire_order_1.ingestFaireOrderWorkflow)(container).run({
|
|
41
|
+
input: {
|
|
42
|
+
order,
|
|
43
|
+
order_token: order?.order_token != null ? String(order.order_token) : null,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
logger?.warn?.(`[faire-order] ingest failed for order ${order?.order_token}: ${err?.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.config = {
|
|
52
|
+
event: ["faire.order_placed", "faire.order_created"],
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpcmUtb3JkZXItaW5nZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3N1YnNjcmliZXJzL2ZhaXJlLW9yZGVyLWluZ2VzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFpQkEsMENBdUNDO0FBdkRELHFEQUFxRTtBQUNyRSxzREFBeUQ7QUFFekQsd0VBQTBFO0FBRTFFOzs7Ozs7Ozs7O0dBVUc7QUFDWSxLQUFLLFVBQVUsdUJBQXVCLENBQUMsRUFDcEQsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQ2YsU0FBUyxHQUtUO0lBQ0EsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixLQUFLLE9BQU87UUFBRSxPQUFNO0lBRXZELE1BQU0sTUFBTSxHQUFRLFNBQVMsQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDdkUsTUFBTSxPQUFPLEdBQXFCLFNBQVMsQ0FBQyxPQUFPLENBQUMsOEJBQWlCLENBQUMsQ0FBQTtJQUV0RSxJQUFJLEtBQUssR0FBUSxJQUFJLEVBQUUsUUFBUSxDQUFBO0lBQy9CLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO1FBQ2pDLElBQUksQ0FBQztZQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUE7WUFDaEQsS0FBSyxHQUFHLE1BQU0sT0FBTztpQkFDbEIsU0FBUyxFQUFFO2lCQUNYLGFBQWEsQ0FBRSxPQUFlLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQTtRQUNwRSxDQUFDO1FBQUMsT0FBTyxHQUFRLEVBQUUsQ0FBQztZQUNsQixNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsd0NBQXdDLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO1lBQ3RFLE9BQU07UUFDUixDQUFDO0lBQ0gsQ0FBQztJQUNELElBQUksQ0FBQyxLQUFLO1FBQUUsT0FBTTtJQUVsQixJQUFJLENBQUM7UUFDSCxNQUFNLElBQUEsNkNBQXdCLEVBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQzVDLEtBQUssRUFBRTtnQkFDTCxLQUFLO2dCQUNMLFdBQVcsRUFBRSxLQUFLLEVBQUUsV0FBVyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTthQUMzRTtTQUNGLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEdBQVEsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FDWix5Q0FBeUMsS0FBSyxFQUFFLFdBQVcsS0FBSyxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQy9FLENBQUE7SUFDSCxDQUFDO0FBQ0gsQ0FBQztBQUVZLFFBQUEsTUFBTSxHQUFxQjtJQUN0QyxLQUFLLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxxQkFBcUIsQ0FBQztDQUNyRCxDQUFBIn0=
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = faireOrderLifecycleHandler;
|
|
5
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
+
const core_flows_1 = require("@medusajs/medusa/core-flows");
|
|
7
|
+
const faire_sync_1 = require("../modules/faire-sync");
|
|
8
|
+
/**
|
|
9
|
+
* Follow a Faire order's lifecycle onto the Medusa order we created for it:
|
|
10
|
+
* order.canceled → cancel the Medusa order
|
|
11
|
+
* order.shipped → stamp fulfillment status = shipped
|
|
12
|
+
* order.delivered→ stamp fulfillment status = delivered
|
|
13
|
+
*
|
|
14
|
+
* The order must already exist (created on order.placed); if it doesn't yet we
|
|
15
|
+
* simply skip.
|
|
16
|
+
*/
|
|
17
|
+
async function faireOrderLifecycleHandler({ event, container, }) {
|
|
18
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
19
|
+
const service = container.resolve(faire_sync_1.FAIRE_SYNC_MODULE);
|
|
20
|
+
let order = event.data?.resource;
|
|
21
|
+
if (!order && event.data?.resource_url) {
|
|
22
|
+
try {
|
|
23
|
+
const account = await service.ensureFreshToken();
|
|
24
|
+
order = await service
|
|
25
|
+
.getClient()
|
|
26
|
+
.fetchResource(account.access_token, event.data.resource_url);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const orderToken = order?.order_token != null ? String(order.order_token) : null;
|
|
33
|
+
if (!orderToken)
|
|
34
|
+
return;
|
|
35
|
+
const [mapRow] = await service
|
|
36
|
+
.listFaireOrders({ order_token: orderToken })
|
|
37
|
+
.catch(() => []);
|
|
38
|
+
const orderId = mapRow?.order_id;
|
|
39
|
+
if (!orderId)
|
|
40
|
+
return;
|
|
41
|
+
const orderService = container.resolve(utils_1.Modules.ORDER);
|
|
42
|
+
try {
|
|
43
|
+
if (event.name === "faire.order_canceled") {
|
|
44
|
+
await (0, core_flows_1.cancelOrderWorkflow)(container).run({ input: { order_id: orderId } });
|
|
45
|
+
await service.updateFaireOrders({ id: mapRow.id, status: "canceled" });
|
|
46
|
+
logger?.info?.(`[faire-order] canceled Medusa order ${orderId} (Faire ${orderToken})`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const fulfillmentStatus = event.name === "faire.order_delivered" ? "delivered" : "shipped";
|
|
50
|
+
const existing = await orderService
|
|
51
|
+
.retrieveOrder(orderId, { select: ["id", "metadata"] })
|
|
52
|
+
.catch(() => null);
|
|
53
|
+
const metadata = {
|
|
54
|
+
...(existing?.metadata || {}),
|
|
55
|
+
faire_fulfillment_status: fulfillmentStatus,
|
|
56
|
+
};
|
|
57
|
+
await orderService.updateOrders([{ id: orderId, metadata }]);
|
|
58
|
+
await service.updateFaireOrders({
|
|
59
|
+
id: mapRow.id,
|
|
60
|
+
status: fulfillmentStatus,
|
|
61
|
+
});
|
|
62
|
+
logger?.info?.(`[faire-order] order ${orderId} fulfillment → ${fulfillmentStatus} (Faire ${orderToken})`);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
logger?.warn?.(`[faire-order] lifecycle ${event.name} failed for order ${orderId}: ${err?.message}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.config = {
|
|
69
|
+
event: ["faire.order_canceled", "faire.order_shipped", "faire.order_delivered"],
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpcmUtb3JkZXItbGlmZWN5Y2xlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3N1YnNjcmliZXJzL2ZhaXJlLW9yZGVyLWxpZmVjeWNsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFlQSw2Q0E2REM7QUEzRUQscURBQThFO0FBQzlFLDREQUFpRTtBQUNqRSxzREFBeUQ7QUFHekQ7Ozs7Ozs7O0dBUUc7QUFDWSxLQUFLLFVBQVUsMEJBQTBCLENBQUMsRUFDdkQsS0FBSyxFQUNMLFNBQVMsR0FDaUQ7SUFDMUQsTUFBTSxNQUFNLEdBQVEsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUN2RSxNQUFNLE9BQU8sR0FBcUIsU0FBUyxDQUFDLE9BQU8sQ0FBQyw4QkFBaUIsQ0FBQyxDQUFBO0lBRXRFLElBQUksS0FBSyxHQUFRLEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFBO0lBQ3JDLElBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLElBQUksRUFBRSxZQUFZLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUM7WUFDSCxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFBO1lBQ2hELEtBQUssR0FBRyxNQUFNLE9BQU87aUJBQ2xCLFNBQVMsRUFBRTtpQkFDWCxhQUFhLENBQUUsT0FBZSxDQUFDLFlBQVksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO1FBQzFFLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxPQUFNO1FBQ1IsQ0FBQztJQUNILENBQUM7SUFDRCxNQUFNLFVBQVUsR0FDZCxLQUFLLEVBQUUsV0FBVyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO0lBQy9ELElBQUksQ0FBQyxVQUFVO1FBQUUsT0FB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
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.config = void 0;
|
|
4
|
+
exports.default = faireProductStatusSyncHandler;
|
|
5
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
6
|
+
const faire_sync_1 = require("../modules/faire-sync");
|
|
7
|
+
const sync_product_to_faire_1 = require("../workflows/sync-product-to-faire");
|
|
8
|
+
/**
|
|
9
|
+
* Keep an already-synced Faire product in step with its Medusa product's status
|
|
10
|
+
* (the draft → published transition the user cares about).
|
|
11
|
+
*
|
|
12
|
+
* This is an internal Medusa event (Faire has its own outbound webhooks for
|
|
13
|
+
* product changes, handled separately). `product.updated` is high-frequency,
|
|
14
|
+
* so we guard hard to avoid burning Faire's per-second / daily quota:
|
|
15
|
+
* - only products that are ALREADY linked (i.e. synced at least once),
|
|
16
|
+
* - only when `follow_product_status` is on, and
|
|
17
|
+
* - only when the Medusa status ACTUALLY changed since the last sync
|
|
18
|
+
* (compared against `product_status` stored on the link metadata).
|
|
19
|
+
*
|
|
20
|
+
* The sync workflow does not mutate the Medusa product, so this cannot loop.
|
|
21
|
+
*/
|
|
22
|
+
async function faireProductStatusSyncHandler({ event: { data }, container, }) {
|
|
23
|
+
if (!data?.id)
|
|
24
|
+
return;
|
|
25
|
+
const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
26
|
+
const service = container.resolve(faire_sync_1.FAIRE_SYNC_MODULE);
|
|
27
|
+
const account = await service.getActiveAccount();
|
|
28
|
+
if (!account)
|
|
29
|
+
return;
|
|
30
|
+
const settings = await service.getSettings();
|
|
31
|
+
if (settings.follow_product_status === false)
|
|
32
|
+
return;
|
|
33
|
+
const remoteLink = container.resolve(utils_1.ContainerRegistrationKeys.LINK);
|
|
34
|
+
let row;
|
|
35
|
+
try {
|
|
36
|
+
const rows = await remoteLink.list({
|
|
37
|
+
[utils_1.Modules.PRODUCT]: { product_id: data.id },
|
|
38
|
+
[faire_sync_1.FAIRE_SYNC_MODULE]: { faire_sync_account_id: account.id },
|
|
39
|
+
});
|
|
40
|
+
row = rows?.[0];
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!row?.faire_product_token)
|
|
46
|
+
return;
|
|
47
|
+
const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
|
|
48
|
+
const { data: products } = await query.graph({
|
|
49
|
+
entity: "product",
|
|
50
|
+
fields: ["id", "status"],
|
|
51
|
+
filters: { id: data.id },
|
|
52
|
+
});
|
|
53
|
+
const status = products?.[0]?.status;
|
|
54
|
+
if (!status)
|
|
55
|
+
return;
|
|
56
|
+
if (status === row?.metadata?.product_status)
|
|
57
|
+
return;
|
|
58
|
+
try {
|
|
59
|
+
logger?.info?.(`[faire] product ${data.id} status → "${status}" (was "${row?.metadata?.product_status ?? "unknown"}"); re-syncing product ${row.faire_product_token}`);
|
|
60
|
+
await (0, sync_product_to_faire_1.syncProductToFaireWorkflow)(container).run({
|
|
61
|
+
input: { product_id: data.id },
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
logger?.warn?.(`[faire] auto re-sync failed for product ${data.id}: ${err?.message || err}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.config = {
|
|
69
|
+
event: "product.updated",
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFpcmUtcHJvZHVjdC1zdGF0dXMtc3luYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdWJzY3JpYmVycy9mYWlyZS1wcm9kdWN0LXN0YXR1cy1zeW5jLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQXFCQSxnREFrREM7QUF0RUQscURBQThFO0FBRTlFLHNEQUF5RDtBQUV6RCw4RUFBK0U7QUFFL0U7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNZLEtBQUssVUFBVSw2QkFBNkIsQ0FBQyxFQUMxRCxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFDZixTQUFTLEdBQ3NCO0lBQy9CLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUFFLE9BQU07SUFFckIsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxpQ0FBeUIsQ0FBQyxNQUFNLENBQVEsQ0FBQTtJQUN6RSxNQUFNLE9BQU8sR0FBcUIsU0FBUyxDQUFDLE9BQU8sQ0FBQyw4QkFBaUIsQ0FBQyxDQUFBO0lBRXRFLE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLGdCQUFnQixFQUFFLENBQUE7SUFDaEQsSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFNO0lBRXBCLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQzVDLElBQUssUUFBZ0IsQ0FBQyxxQkFBcUIsS0FBSyxLQUFLO1FBQUUsT0FBTTtJQUU3RCxNQUFNLFVBQVUsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLElBQUksQ0FBUyxDQUFBO0lBQzVFLElBQUksR0FBUSxDQUFBO0lBQ1osSUFBSSxDQUFDO1FBQ0gsTUFBTSxJQUFJLEdBQUcsTUFBTSxVQUFVLENBQUMsSUFBSSxDQUFDO1lBQ2pDLENBQUMsZUFBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDMUMsQ0FBQyw4QkFBaUIsQ0FBQyxFQUFFLEVBQUUscUJBQXFCLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRTtTQUMzRCxDQUFDLENBQUE7UUFDRixHQUFHLEdBQUksSUFBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDNUIsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU07SUFDUixDQUFDO0lBQ0QsSUFBSSxDQUFDLEdBQUcsRUFBRSxtQkFBbUI7UUFBRSxPQUFNO0lBRXJDLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsaUNBQXlCLENBQUMsS0FBSyxDQUFRLENBQUE7SUFDdkUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDM0MsTUFBTSxFQUFFLFNBQVM7UUFDakIsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQztRQUN4QixPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtLQUN6QixDQUFDLENBQUE7SUFDRixNQUFNLE1BQU0sR0FBdUIsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFBO0lBQ3hELElBQUksQ0FBQyxNQUFNO1FBQUUsT0FBTTtJQUNuQixJQUFJLE1BQU0sS0FBSyxHQUFHLEVBQUUsUUFBUSxFQUFFLGNBQWM7UUFBRSxPQUFNO0lBRXBELElBQUksQ0FBQztRQUNILE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FDWixtQkFBbUIsSUFBSSxDQUFDLEVBQUUsY0FBYyxNQUFNLFdBQVcsR0FBRyxFQUFFLFFBQVEsRUFBRSxjQUFjLElBQUksU0FBUywwQkFBMEIsR0FBRyxDQUFDLG1CQUFtQixFQUFFLENBQ3ZKLENBQUE7UUFDRCxNQUFNLElBQUEsa0RBQTBCLEVBQUMsU0FBUyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQzlDLEtBQUssRUFBRSxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1NBQy9CLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEdBQVEsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FDWiwyQ0FBMkMsSUFBSSxDQUFDLEVBQUUsS0FBSyxHQUFHLEVBQUUsT0FBTyxJQUFJLEdBQUcsRUFBRSxDQUM3RSxDQUFBO0lBQ0gsQ0FBQztBQUNILENBQUM7QUFFWSxRQUFBLE1BQU0sR0FBcUI7SUFDdEMsS0FBSyxFQUFFLGlCQUFpQjtDQUN6QixDQUFBIn0=
|