@porulle/plugin-channel-connector 0.73.3 → 0.74.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/dist/index.d.ts +1 -1
- package/dist/index.js +102 -29
- package/dist/live-credentials.d.ts +6 -3
- package/dist/live-credentials.js +22 -6
- package/dist/mock-connector.d.ts +62 -0
- package/dist/mock-connector.js +33 -0
- package/dist/schema.d.ts +82 -2
- package/dist/schema.js +9 -1
- package/dist/service.d.ts +72 -15
- package/dist/service.js +307 -365
- package/package.json +2 -2
- package/src/index.ts +100 -27
- package/src/live-credentials.ts +23 -5
- package/src/mock-connector.ts +34 -0
- package/src/schema.ts +20 -1
- package/src/service.ts +321 -363
package/dist/service.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import type { Actor, ChannelCancelOrderInput, ChannelCatalogItem, ChannelConnector, ChannelOrderSlice, ChannelPushCatalogField, ChannelPushCatalogImage, ChannelPushCatalogItem, ChannelPushCatalogItemOutcome, ChannelPushCatalogResult, ChannelStore, PluginDb, PluginResult, PluginTxFn } from "@porulle/core";
|
|
2
|
+
import type { Actor, ChannelCancelOrderInput, ChannelCatalogItem, ChannelConnector, ChannelWebhookEvent, ChannelOrderSlice, ChannelPushCatalogField, ChannelPushCatalogImage, ChannelPushCatalogItem, ChannelPushCatalogItemOutcome, ChannelPushCatalogResult, ChannelStore, PluginDb, PluginResult, PluginTxFn } from "@porulle/core";
|
|
3
3
|
import type { ChannelCatalogImage } from "@porulle/core";
|
|
4
4
|
import type { FieldOwner, FieldPath } from "@porulle/core";
|
|
5
5
|
import type { JobsAdapter } from "@porulle/core";
|
|
6
6
|
import { type ChannelCatalogPush, type ChannelCatalogConflict, type ChannelOrderExport, type ChannelRefundRequest, type ConnectedStore } from "./schema.js";
|
|
7
|
+
import type { StoreHealth } from "./schema.js";
|
|
7
8
|
import { type CatalogFieldMapping, type CatalogFieldTarget } from "./catalog-field-mapping.js";
|
|
8
9
|
export type ExportState = ChannelOrderExport["state"];
|
|
9
10
|
export type CatalogPushState = ChannelCatalogPush["state"];
|
|
@@ -26,6 +27,10 @@ export declare const CHANNEL_INVENTORY_MAX_ITEMS_PER_INVOCATION = 20;
|
|
|
26
27
|
* The reason a platform order is cancelled under when its STORE cancelled it. The cancel hook skips
|
|
27
28
|
* cancelling at the store for exactly this reason, so the two directions cannot loop.
|
|
28
29
|
*/
|
|
30
|
+
/** How stale a store order may be before a read point queues a refresh of it. */
|
|
31
|
+
export declare const REMOTE_ORDER_REFRESH_MS: number;
|
|
32
|
+
/** How often a merchant's visit may make the plugin call a store to check its health. */
|
|
33
|
+
export declare const STORE_HEALTH_INTERVAL_MS: number;
|
|
29
34
|
export declare const CHANNEL_ORDER_CANCELLED_REASON = "channel_order_cancelled";
|
|
30
35
|
export declare function catalogPushRetryDelayMs(attempts: number): number;
|
|
31
36
|
export interface CatalogPushJobResult extends Record<string, unknown> {
|
|
@@ -374,6 +379,10 @@ export interface CatalogPageConvergence extends Record<string, unknown> {
|
|
|
374
379
|
heroesImported: number;
|
|
375
380
|
mediaFailures: CatalogMediaFailure[];
|
|
376
381
|
deferredMedia: CatalogDeferredMedia[];
|
|
382
|
+
/** Fields the store's value did not overwrite because the platform owns them. */
|
|
383
|
+
skipped: CatalogFieldSkip[];
|
|
384
|
+
/** Shared fields both sides changed, held for an operator. */
|
|
385
|
+
conflicts: CatalogFieldConflict[];
|
|
377
386
|
warnings: string[];
|
|
378
387
|
}
|
|
379
388
|
export interface ImportImageSelection {
|
|
@@ -493,6 +502,8 @@ export declare class ChannelConnectorService {
|
|
|
493
502
|
/** The slug an existing product converges to: its current one while that is still in the family
|
|
494
503
|
* of the handle the store sends, so a slug is never recomputed out from under a shared link. */
|
|
495
504
|
private slugToKeep;
|
|
505
|
+
/** This organization's store of `provider` at `storeDomain`, whatever its status. */
|
|
506
|
+
storeByDomain(orgId: string, provider: string, storeDomain: string): Promise<PublicConnectedStore | undefined>;
|
|
496
507
|
getStoresByDomain(shopDomain: string): Promise<ConnectedStore[]>;
|
|
497
508
|
resolveCatalogFieldMapping(store: Pick<ConnectedStore, "provider" | "catalogFieldMapping">, filterableCustomFields?: ReadonlySet<string> | Readonly<Record<string, boolean>>, warnings?: string[]): CatalogFieldMapping;
|
|
498
509
|
buildCatalogPushItems(orgId: string, storeId: string, entityIds: string[], options?: BuildCatalogPushItemsOptions): Promise<PluginResult<BuildCatalogPushItemsResult>>;
|
|
@@ -511,12 +522,37 @@ export declare class ChannelConnectorService {
|
|
|
511
522
|
* provider that subscribes per store is registered after commit, at an absolute address; the
|
|
512
523
|
* consumer's follow-on work ({@link AfterStoreConnected}) runs after that.
|
|
513
524
|
*/
|
|
525
|
+
/**
|
|
526
|
+
* Connects a store and runs its follow-on work (subscribe, first import) before answering. For a
|
|
527
|
+
* provider whose callback must be answered at once, see {@link saveConnectingStore} and
|
|
528
|
+
* {@link completeConnect}, which this is the two halves of.
|
|
529
|
+
*/
|
|
514
530
|
connectStore(orgId: string, input: {
|
|
515
531
|
provider: string;
|
|
516
532
|
credentials: Record<string, unknown>;
|
|
517
533
|
storeDomain: string;
|
|
518
534
|
webhookSecret?: string;
|
|
519
535
|
}, actor: StoreConnectActor): Promise<PluginResult<PublicConnectedStore>>;
|
|
536
|
+
/**
|
|
537
|
+
* Writes the store with its credentials in status `connecting`, bound to the actor's vendor, and
|
|
538
|
+
* nothing else: no call to the store. Reconnecting a store this organization already has refreshes
|
|
539
|
+
* its row instead of adding one.
|
|
540
|
+
*/
|
|
541
|
+
saveConnectingStore(orgId: string, input: {
|
|
542
|
+
provider: string;
|
|
543
|
+
credentials: Record<string, unknown>;
|
|
544
|
+
storeDomain: string;
|
|
545
|
+
webhookSecret?: string;
|
|
546
|
+
}, actor: StoreConnectActor): Promise<PluginResult<PublicConnectedStore>>;
|
|
547
|
+
/**
|
|
548
|
+
* The work after the credentials are saved: subscribe the store to its connector's topics (all or
|
|
549
|
+
* none — a partial subscription is removed), mark it `connected`, then the host's follow-on work.
|
|
550
|
+
* A failure leaves the store in `error` with the reason the merchant will read, unless the host
|
|
551
|
+
* already moved it (it disconnects a store it refuses).
|
|
552
|
+
*/
|
|
553
|
+
completeConnect(orgId: string, storeId: string, actor: StoreConnectActor): Promise<PluginResult<PublicConnectedStore>>;
|
|
554
|
+
/** Where a store that subscribes per store delivers its webhooks: absolute, on this deployment's public origin. */
|
|
555
|
+
webhookCallbackUrl(storeId: string): string;
|
|
520
556
|
/** The store with credentials good for a call the host makes itself, e.g. its own Admin API write. */
|
|
521
557
|
liveStore(orgId: string, storeId: string): Promise<PluginResult<ChannelStore>>;
|
|
522
558
|
/** The consumer's claims for a connection starting from this request. See {@link ConnectClaims}. */
|
|
@@ -529,6 +565,17 @@ export declare class ChannelConnectorService {
|
|
|
529
565
|
reachableStore(orgId: string, id: string, context: StoreReadContext | undefined): Promise<PluginResult<ConnectedStore>>;
|
|
530
566
|
disconnectStore(orgId: string, id: string, context?: StoreReadContext): Promise<PluginResult<PublicConnectedStore>>;
|
|
531
567
|
disconnectStoreSystem(orgId: string, id: string, redactDomain?: boolean): Promise<PluginResult<PublicConnectedStore>>;
|
|
568
|
+
/**
|
|
569
|
+
* Checks the store's webhook subscriptions and key and repairs what it can, when a merchant looks:
|
|
570
|
+
* there is no scheduled check. At most once per {@link STORE_HEALTH_INTERVAL_MS} per store; inside
|
|
571
|
+
* that window the last result is answered without calling the store.
|
|
572
|
+
*/
|
|
573
|
+
checkStoreHealth(orgId: string, id: string, context?: StoreReadContext): Promise<PluginResult<StoreHealth & {
|
|
574
|
+
status: ConnectedStore["status"];
|
|
575
|
+
statusReason: string | null;
|
|
576
|
+
lastEventAt: Date | null;
|
|
577
|
+
cached: boolean;
|
|
578
|
+
}>>;
|
|
532
579
|
getStore(orgId: string, id: string, context?: StoreReadContext): Promise<PluginResult<PublicConnectedStore>>;
|
|
533
580
|
listStores(orgId: string, context?: StoreReadContext): Promise<PluginResult<PublicConnectedStore[]>>;
|
|
534
581
|
validateLineStock(orgId: string, lines: ChannelStockLine[], timeoutMs?: number): Promise<void>;
|
|
@@ -624,28 +671,38 @@ export declare class ChannelConnectorService {
|
|
|
624
671
|
* the whole inventory and every map row on every 20-level step.
|
|
625
672
|
*/
|
|
626
673
|
private syncInventoryPage;
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
674
|
+
/**
|
|
675
|
+
* One verified store delivery. The store's connector says what it means ({@link ChannelEvent}); this
|
|
676
|
+
* acts on the meaning and never on a topic or payload field. A delivery the connector does not act
|
|
677
|
+
* on is logged as unmapped and answered `processed: false`, never reported as applied.
|
|
678
|
+
*/
|
|
679
|
+
handleWebhook(orgId: string, storeId: string, delivery: ChannelWebhookEvent): Promise<PluginResult<{
|
|
680
|
+
processed: boolean;
|
|
633
681
|
data?: ChannelComplianceData;
|
|
634
682
|
redacted?: number;
|
|
635
683
|
}>>;
|
|
684
|
+
private applyChannelEvent;
|
|
636
685
|
private complianceEmail;
|
|
637
686
|
private channelCustomerExports;
|
|
638
687
|
private channelCustomerDataRequest;
|
|
639
688
|
private redactCustomerData;
|
|
640
689
|
private redactShopData;
|
|
641
|
-
|
|
690
|
+
/**
|
|
691
|
+
* For a read point (a shopper opening their order): each of the order's store orders not read for
|
|
692
|
+
* {@link REMOTE_ORDER_REFRESH_MS} is queued for one refresh, so a store-side cancel, shipment or
|
|
693
|
+
* refund whose delivery never arrived still reaches the platform. No schedule: someone looked.
|
|
694
|
+
* Answers how many were queued.
|
|
695
|
+
*/
|
|
696
|
+
refreshStaleRemoteOrders(orgId: string, orderId: string, jobs: JobsAdapter): Promise<number>;
|
|
697
|
+
/** The store's current state of one order we pushed, applied as if its delivery had arrived. */
|
|
698
|
+
refreshRemoteOrder(orgId: string, storeId: string, remoteOrderId: string): Promise<PluginResult<{
|
|
699
|
+
events: number;
|
|
700
|
+
}>>;
|
|
701
|
+
private orderForRemote;
|
|
642
702
|
/** Archives this store's product mapped to `externalId`, unless the platform owns its status. */
|
|
643
703
|
private archiveMappedProduct;
|
|
644
704
|
private setMappedInventory;
|
|
645
705
|
private setInventoryLevel;
|
|
646
|
-
/** This store's mapped variant whose import recorded `metadata.inventoryItemId`; null when none, or when two claim it. */
|
|
647
|
-
private variantForInventoryItem;
|
|
648
|
-
private convergeCatalogItem;
|
|
649
706
|
private createRefundRequest;
|
|
650
707
|
private executeRefund;
|
|
651
708
|
listRefundRequests(orgId: string): Promise<PluginResult<ChannelRefundRequest[]>>;
|
|
@@ -665,10 +722,10 @@ export declare class ChannelConnectorService {
|
|
|
665
722
|
*/
|
|
666
723
|
cancelRemoteOrders(orgId: string, orderId: string, input: ChannelCancelOrderInput): Promise<PluginResult<number>>;
|
|
667
724
|
/**
|
|
668
|
-
* One core fulfilment record per store
|
|
669
|
-
*
|
|
670
|
-
*
|
|
671
|
-
* records every line not yet fulfilled.
|
|
725
|
+
* One core fulfilment record per store parcel, keyed on the store's parcel id
|
|
726
|
+
* (`metadata.channelFulfillmentId`) so a replay records nothing twice. Each records the lines it
|
|
727
|
+
* shipped, matched by the store's variant id; one whose lines cannot be matched (or that names
|
|
728
|
+
* none) records every line not yet fulfilled.
|
|
672
729
|
*/
|
|
673
730
|
private recordChannelFulfillments;
|
|
674
731
|
/** Every line with quantity still to ship, for a parcel whose own lines could not be matched. */
|