@tiledev/sdk-apptile-live-selling 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/README.md +322 -0
- package/android/build.gradle +33 -0
- package/android/src/main/AndroidManifest.xml +7 -0
- package/android/src/main/java/expo/modules/livepip/LivePipModule.kt +310 -0
- package/app.plugin.js +3 -0
- package/dist/auctions.d.ts +3 -0
- package/dist/auctions.d.ts.map +1 -0
- package/dist/auctions.js +152 -0
- package/dist/auctions.js.map +1 -0
- package/dist/client.d.ts +63 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +154 -0
- package/dist/client.js.map +1 -0
- package/dist/clips.d.ts +3 -0
- package/dist/clips.d.ts.map +1 -0
- package/dist/clips.js +53 -0
- package/dist/clips.js.map +1 -0
- package/dist/commentLinks.d.ts +46 -0
- package/dist/commentLinks.d.ts.map +1 -0
- package/dist/commentLinks.js +120 -0
- package/dist/commentLinks.js.map +1 -0
- package/dist/engine.d.ts +13 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +40 -0
- package/dist/engine.js.map +1 -0
- package/dist/engine.native.d.ts +3 -0
- package/dist/engine.native.d.ts.map +1 -0
- package/dist/engine.native.js +815 -0
- package/dist/engine.native.js.map +1 -0
- package/dist/flags.d.ts +5 -0
- package/dist/flags.d.ts.map +1 -0
- package/dist/flags.js +61 -0
- package/dist/flags.js.map +1 -0
- package/dist/guest.d.ts +5 -0
- package/dist/guest.d.ts.map +1 -0
- package/dist/guest.js +89 -0
- package/dist/guest.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/liveSelling.d.ts +3 -0
- package/dist/liveSelling.d.ts.map +1 -0
- package/dist/liveSelling.js +44 -0
- package/dist/liveSelling.js.map +1 -0
- package/dist/nativeViewTag.d.ts +15 -0
- package/dist/nativeViewTag.d.ts.map +1 -0
- package/dist/nativeViewTag.js +23 -0
- package/dist/nativeViewTag.js.map +1 -0
- package/dist/pip.d.ts +14 -0
- package/dist/pip.d.ts.map +1 -0
- package/dist/pip.js +15 -0
- package/dist/pip.js.map +1 -0
- package/dist/pip.native.d.ts +11 -0
- package/dist/pip.native.d.ts.map +1 -0
- package/dist/pip.native.js +47 -0
- package/dist/pip.native.js.map +1 -0
- package/dist/polls.d.ts +11 -0
- package/dist/polls.d.ts.map +1 -0
- package/dist/polls.js +135 -0
- package/dist/polls.js.map +1 -0
- package/dist/react/LiveSellingProvider.d.ts +16 -0
- package/dist/react/LiveSellingProvider.d.ts.map +1 -0
- package/dist/react/LiveSellingProvider.js +49 -0
- package/dist/react/LiveSellingProvider.js.map +1 -0
- package/dist/react/LiveVideoTarget.d.ts +22 -0
- package/dist/react/LiveVideoTarget.d.ts.map +1 -0
- package/dist/react/LiveVideoTarget.js +73 -0
- package/dist/react/LiveVideoTarget.js.map +1 -0
- package/dist/react/index.d.ts +19 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +43 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/useAuction.d.ts +28 -0
- package/dist/react/useAuction.d.ts.map +1 -0
- package/dist/react/useAuction.js +66 -0
- package/dist/react/useAuction.js.map +1 -0
- package/dist/react/useAuctionBidGate.d.ts +48 -0
- package/dist/react/useAuctionBidGate.d.ts.map +1 -0
- package/dist/react/useAuctionBidGate.js +144 -0
- package/dist/react/useAuctionBidGate.js.map +1 -0
- package/dist/react/useAuctionWins.d.ts +51 -0
- package/dist/react/useAuctionWins.d.ts.map +1 -0
- package/dist/react/useAuctionWins.js +268 -0
- package/dist/react/useAuctionWins.js.map +1 -0
- package/dist/react/useClips.d.ts +9 -0
- package/dist/react/useClips.d.ts.map +1 -0
- package/dist/react/useClips.js +37 -0
- package/dist/react/useClips.js.map +1 -0
- package/dist/react/useLiveSession.d.ts +34 -0
- package/dist/react/useLiveSession.d.ts.map +1 -0
- package/dist/react/useLiveSession.js +876 -0
- package/dist/react/useLiveSession.js.map +1 -0
- package/dist/react/useLiveStreams.d.ts +9 -0
- package/dist/react/useLiveStreams.d.ts.map +1 -0
- package/dist/react/useLiveStreams.js +35 -0
- package/dist/react/useLiveStreams.js.map +1 -0
- package/dist/react/useOngoingLive.d.ts +13 -0
- package/dist/react/useOngoingLive.d.ts.map +1 -0
- package/dist/react/useOngoingLive.js +45 -0
- package/dist/react/useOngoingLive.js.map +1 -0
- package/dist/react/useReplays.d.ts +15 -0
- package/dist/react/useReplays.d.ts.map +1 -0
- package/dist/react/useReplays.js +66 -0
- package/dist/react/useReplays.js.map +1 -0
- package/dist/react/useStreamInfo.d.ts +21 -0
- package/dist/react/useStreamInfo.d.ts.map +1 -0
- package/dist/react/useStreamInfo.js +125 -0
- package/dist/react/useStreamInfo.js.map +1 -0
- package/dist/replays.d.ts +3 -0
- package/dist/replays.d.ts.map +1 -0
- package/dist/replays.js +114 -0
- package/dist/replays.js.map +1 -0
- package/dist/session.d.ts +23 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +464 -0
- package/dist/session.js.map +1 -0
- package/dist/sessionTypes.d.ts +462 -0
- package/dist/sessionTypes.d.ts.map +1 -0
- package/dist/sessionTypes.js +55 -0
- package/dist/sessionTypes.js.map +1 -0
- package/dist/streams.d.ts +67 -0
- package/dist/streams.d.ts.map +1 -0
- package/dist/streams.js +170 -0
- package/dist/streams.js.map +1 -0
- package/dist/types.d.ts +591 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/viewer.d.ts +5 -0
- package/dist/viewer.d.ts.map +1 -0
- package/dist/viewer.js +66 -0
- package/dist/viewer.js.map +1 -0
- package/dist/wire.d.ts +155 -0
- package/dist/wire.d.ts.map +1 -0
- package/dist/wire.js +73 -0
- package/dist/wire.js.map +1 -0
- package/dist/zego.d.ts +83 -0
- package/dist/zego.d.ts.map +1 -0
- package/dist/zego.js +13 -0
- package/dist/zego.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/LivePip.podspec +20 -0
- package/ios/LivePipController.swift +327 -0
- package/ios/LivePipModule.swift +35 -0
- package/package.json +91 -0
- package/plugin/build/index.d.ts +29 -0
- package/plugin/build/index.js +101 -0
- package/react/package.json +6 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auctions.d.ts","sourceRoot":"","sources":["../src/auctions.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,SAAS,CAAC;AAuExE,eAAO,MAAM,QAAQ,EAAE,WAmFtB,CAAC"}
|
package/dist/auctions.js
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.auctions = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Auctions and giveaways.
|
|
6
|
+
*
|
|
7
|
+
* The Zego channels (the live engine) carry the round — who is leading, what the next bid is, when the
|
|
8
|
+
* clock stops — and are authoritative for the UI. These REST calls are the durable path: a bid is
|
|
9
|
+
* recorded so the host has a ledger that survives a dropped socket, a giveaway entry so it outlives the
|
|
10
|
+
* app session. Neither response drives the UI; the host's broadcast does.
|
|
11
|
+
*
|
|
12
|
+
* All anonymous through the company header, save the unpaid-wins read, which needs the customer's own
|
|
13
|
+
* token and so goes through the injected `customerAccountRequest`.
|
|
14
|
+
*/
|
|
15
|
+
const client_1 = require("./client");
|
|
16
|
+
const TERMS_KEY = 'auction.termsAccepted';
|
|
17
|
+
// ─── Unpaid wins (customer-account metafield) ────────────────────────────────
|
|
18
|
+
const UNPAID_WINS_QUERY = /* GraphQL */ `
|
|
19
|
+
query AuctionWins {
|
|
20
|
+
customer {
|
|
21
|
+
metafield(namespace: "auction", key: "winner") {
|
|
22
|
+
value
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
async function fetchWinnerMetafield() {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
const customerAccountRequest = (0, client_1.getCustomerAccountRequest)();
|
|
30
|
+
if (!customerAccountRequest)
|
|
31
|
+
return null;
|
|
32
|
+
const data = await customerAccountRequest(UNPAID_WINS_QUERY);
|
|
33
|
+
const value = (_b = (_a = data.customer) === null || _a === void 0 ? void 0 : _a.metafield) === null || _b === void 0 ? void 0 : _b.value;
|
|
34
|
+
if (!value)
|
|
35
|
+
return null;
|
|
36
|
+
const parsed = JSON.parse(value);
|
|
37
|
+
return parsed && typeof parsed === 'object' ? parsed : null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* An entry there is actually something to charge for.
|
|
41
|
+
*
|
|
42
|
+
* `productId` is the whole test: without it nothing can be resolved, priced or put in a cart, so the
|
|
43
|
+
* entry is unpayable however well-formed the rest of it looks. A missing *variant* is not a defect —
|
|
44
|
+
* the host records no variant when a lot has only one, and the win resolves to it.
|
|
45
|
+
*/
|
|
46
|
+
function isPayable(raw) {
|
|
47
|
+
return !!raw && typeof raw === 'object' && !!raw.productId;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The streams with something payable outstanding — NOT simply the metafield's keys.
|
|
51
|
+
*
|
|
52
|
+
* This is the difference between a gate that can be cleared and one that cannot. The keys and the
|
|
53
|
+
* payable entries are not the same set: a key can survive with an empty array, or with entries that
|
|
54
|
+
* carry no `productId`, and nothing in the system prunes it. Read as "streams owed", such a key blocks
|
|
55
|
+
* bidding on every other stream while `wins()` reports nothing to pay and the wins tab shows an empty
|
|
56
|
+
* list — the customer is locked out with no action available to them, and no support call fixes it
|
|
57
|
+
* either. Both readers now agree because both use this.
|
|
58
|
+
*
|
|
59
|
+
* The error is deliberately one-sided. Skipping an unpayable key can at worst let through a bid the
|
|
60
|
+
* host refuses; counting one blocks a paying customer permanently.
|
|
61
|
+
*/
|
|
62
|
+
function payableStreamIds(parsed) {
|
|
63
|
+
return Object.keys(parsed).filter((streamingId) => {
|
|
64
|
+
const entries = parsed[streamingId];
|
|
65
|
+
return Array.isArray(entries) && entries.some(isPayable);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
// ─── Namespace ─────────────────────────────────────────────────────────────
|
|
69
|
+
exports.auctions = {
|
|
70
|
+
async recordBid(params) {
|
|
71
|
+
var _a;
|
|
72
|
+
await (0, client_1.liveSellingRequest)('/live-streaming/bid/vote', {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
body: {
|
|
75
|
+
streaming_id: params.streamingId,
|
|
76
|
+
company_id: (_a = (0, client_1.getCompanyId)()) !== null && _a !== void 0 ? _a : (0, client_1.getConfig)().companyId,
|
|
77
|
+
bidding_price: params.amount,
|
|
78
|
+
viewer_id: params.bidderId,
|
|
79
|
+
viewer_name: params.bidderName,
|
|
80
|
+
meta: { product_id: params.storeProductId },
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
async enterGiveaway(params) {
|
|
85
|
+
var _a;
|
|
86
|
+
const body = await (0, client_1.liveSellingRequest)('/live-streaming/giveaway/register', {
|
|
87
|
+
method: 'POST',
|
|
88
|
+
body: {
|
|
89
|
+
streaming_id: params.streamingId,
|
|
90
|
+
product_id: params.storeProductId,
|
|
91
|
+
user_id: params.customerGid,
|
|
92
|
+
display_name: params.displayName,
|
|
93
|
+
zego_user_id: params.viewerId,
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
// The host echoes the customer it registered; anything else means the entry did not take.
|
|
97
|
+
return !!((_a = body === null || body === void 0 ? void 0 : body.data) === null || _a === void 0 ? void 0 : _a.user_id);
|
|
98
|
+
},
|
|
99
|
+
async hasAcceptedTerms() {
|
|
100
|
+
return (await (0, client_1.storageGet)(TERMS_KEY)) === 'true';
|
|
101
|
+
},
|
|
102
|
+
async acceptTerms() {
|
|
103
|
+
await (0, client_1.storageSet)(TERMS_KEY, 'true');
|
|
104
|
+
},
|
|
105
|
+
async unpaidStreamIds() {
|
|
106
|
+
try {
|
|
107
|
+
const parsed = await fetchWinnerMetafield();
|
|
108
|
+
return parsed ? payableStreamIds(parsed) : [];
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// A metafield read failing must not lock a customer out of bidding.
|
|
112
|
+
return [];
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
async wins() {
|
|
116
|
+
const parsed = await fetchWinnerMetafield();
|
|
117
|
+
if (!parsed)
|
|
118
|
+
return null;
|
|
119
|
+
/**
|
|
120
|
+
* The first stream with something payable, rather than the first key.
|
|
121
|
+
*
|
|
122
|
+
* One tab per checkout is the host's model — the cart carries a single `auction_id` and the gate
|
|
123
|
+
* stops a customer accruing wins on a second stream while the first is unpaid — so in practice
|
|
124
|
+
* there is one. Taking `Object.keys()[0]` regardless meant a leftover empty key hid a real win
|
|
125
|
+
* sitting behind it, and the customer was blocked by the very win the tab refused to show.
|
|
126
|
+
*/
|
|
127
|
+
const [streamingId] = payableStreamIds(parsed);
|
|
128
|
+
if (!streamingId)
|
|
129
|
+
return null;
|
|
130
|
+
const items = (Array.isArray(parsed[streamingId]) ? parsed[streamingId] : [])
|
|
131
|
+
.filter(isPayable)
|
|
132
|
+
.map((raw) => {
|
|
133
|
+
var _a;
|
|
134
|
+
return ({
|
|
135
|
+
productGid: `gid://shopify/Product/${raw.productId}`,
|
|
136
|
+
variantId: raw.variantId != null && raw.variantId !== '' ? String(raw.variantId) : null,
|
|
137
|
+
winningBid: Number(raw.winningBid) || 0,
|
|
138
|
+
isGiveaway: !!raw.isGiveaway,
|
|
139
|
+
discountCode: (_a = raw.discountCode) !== null && _a !== void 0 ? _a : null,
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
return items.length ? { streamingId, items } : null;
|
|
143
|
+
},
|
|
144
|
+
isBiddingBlocked(unpaidStreamIds, streamingId) {
|
|
145
|
+
if (unpaidStreamIds.length === 0)
|
|
146
|
+
return false;
|
|
147
|
+
if (!streamingId)
|
|
148
|
+
return true;
|
|
149
|
+
return !unpaidStreamIds.includes(streamingId);
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
//# sourceMappingURL=auctions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auctions.js","sourceRoot":"","sources":["../src/auctions.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one transport for the Apptile live-selling gateway, plus the config singleton every namespace
|
|
3
|
+
* reads.
|
|
4
|
+
*
|
|
5
|
+
* Auth is the company id alone: every viewer endpoint is anonymous, and the `x-company-id` header is
|
|
6
|
+
* what scopes the response. This host must never see the customer's bearer token — the single exception
|
|
7
|
+
* is the unpaid-wins read, which the host app supplies as `customerAccountRequest` and which never
|
|
8
|
+
* routes through here.
|
|
9
|
+
*
|
|
10
|
+
* Replaces the app's `APP_CONFIG.liveSelling` / `LIVE_CONFIG` globals with an explicit `configure`.
|
|
11
|
+
*/
|
|
12
|
+
import type { CustomerAccountRequest, LiveSellingConfig, Logger, StorageAdapter } from './types';
|
|
13
|
+
import type { CommerceAdapter, IdentityAdapter } from './sessionTypes';
|
|
14
|
+
/** The service stores bare numeric Shopify ids; everything downstream speaks GIDs. */
|
|
15
|
+
export declare function toProductGid(id: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* A failed gateway call, with the status kept on the error.
|
|
18
|
+
*
|
|
19
|
+
* Callers that can act on *which* failure it was need the code — a guest invite that is expired (410)
|
|
20
|
+
* versus unknown (404) are different things to tell someone.
|
|
21
|
+
*/
|
|
22
|
+
export declare class LiveSellingError extends Error {
|
|
23
|
+
readonly status: number;
|
|
24
|
+
constructor(status: number);
|
|
25
|
+
}
|
|
26
|
+
export declare function setConfig(config: LiveSellingConfig): void;
|
|
27
|
+
export declare function getConfig(): LiveSellingConfig;
|
|
28
|
+
export declare function isConfigured(): boolean;
|
|
29
|
+
export declare function getCompanyId(): string | null;
|
|
30
|
+
export declare function getStorage(): StorageAdapter;
|
|
31
|
+
export declare function getLogger(): Logger;
|
|
32
|
+
/**
|
|
33
|
+
* A handled-data report: `warn` where the host app has one, `error` where it does not.
|
|
34
|
+
*
|
|
35
|
+
* Never silent. A host that has not implemented `warn` still needs to hear that a win names a variant
|
|
36
|
+
* belonging to another product — dropping the report to keep the console clean would trade a merchant's
|
|
37
|
+
* data fault for silence, and that fault reaches a shopper as the wrong size in a cart.
|
|
38
|
+
*/
|
|
39
|
+
export declare function logWarning(error: unknown, context?: Record<string, unknown>): void;
|
|
40
|
+
export declare function getCustomerAccountRequest(): CustomerAccountRequest | null;
|
|
41
|
+
/** Null when the host app configured no storefront; the session then resolves no products. */
|
|
42
|
+
export declare function getCommerce(): CommerceAdapter<unknown> | null;
|
|
43
|
+
/** Null when nobody is identified beyond the per-install viewer id — bidding is then never offered. */
|
|
44
|
+
export declare function getIdentity(): IdentityAdapter | null;
|
|
45
|
+
/**
|
|
46
|
+
* The gateway request. The company header is the only credential; a body implies JSON. `X-Request-Source`
|
|
47
|
+
* marks the traffic as first-party app rather than a web widget.
|
|
48
|
+
*/
|
|
49
|
+
export declare function liveSellingRequest<T>(path: string, options?: {
|
|
50
|
+
params?: Record<string, string | number>;
|
|
51
|
+
method?: 'GET' | 'POST';
|
|
52
|
+
body?: unknown;
|
|
53
|
+
}): Promise<T>;
|
|
54
|
+
/**
|
|
55
|
+
* A stable random id. Uses the platform `crypto.randomUUID` when present (browsers, modern React
|
|
56
|
+
* Native, Node) and falls back to a Math.random hex string — replacing the app's `expo-crypto`
|
|
57
|
+
* dependency so the package carries no native crypto peer.
|
|
58
|
+
*/
|
|
59
|
+
export declare function randomId(length?: number): string;
|
|
60
|
+
/** Storage reads may be sync or async depending on the adapter; normalise to a promise. */
|
|
61
|
+
export declare function storageGet(key: string): Promise<string | null>;
|
|
62
|
+
export declare function storageSet(key: string, value: string): Promise<void>;
|
|
63
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACjG,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAIvE,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAIpC;AA4BD,wBAAgB,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAMzD;AAED,wBAAgB,SAAS,IAAI,iBAAiB,CAG7C;AAED,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAgB,UAAU,IAAI,cAAc,CAE3C;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAIlF;AAED,wBAAgB,yBAAyB,IAAI,sBAAsB,GAAG,IAAI,CAEzE;AAED,8FAA8F;AAC9F,wBAAgB,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,GAAG,IAAI,CAE7D;AAED,uGAAuG;AACvG,wBAAgB,WAAW,IAAI,eAAe,GAAG,IAAI,CAEpD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GACA,OAAO,CAAC,CAAC,CAAC,CAgBZ;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAK,GAAG,MAAM,CAM5C;AAED,2FAA2F;AAC3F,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEpE;AAED,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LiveSellingError = void 0;
|
|
4
|
+
exports.toProductGid = toProductGid;
|
|
5
|
+
exports.setConfig = setConfig;
|
|
6
|
+
exports.getConfig = getConfig;
|
|
7
|
+
exports.isConfigured = isConfigured;
|
|
8
|
+
exports.getCompanyId = getCompanyId;
|
|
9
|
+
exports.getStorage = getStorage;
|
|
10
|
+
exports.getLogger = getLogger;
|
|
11
|
+
exports.logWarning = logWarning;
|
|
12
|
+
exports.getCustomerAccountRequest = getCustomerAccountRequest;
|
|
13
|
+
exports.getCommerce = getCommerce;
|
|
14
|
+
exports.getIdentity = getIdentity;
|
|
15
|
+
exports.liveSellingRequest = liveSellingRequest;
|
|
16
|
+
exports.randomId = randomId;
|
|
17
|
+
exports.storageGet = storageGet;
|
|
18
|
+
exports.storageSet = storageSet;
|
|
19
|
+
const SHOPIFY_PRODUCT_GID = 'gid://shopify/Product/';
|
|
20
|
+
/** The service stores bare numeric Shopify ids; everything downstream speaks GIDs. */
|
|
21
|
+
function toProductGid(id) {
|
|
22
|
+
return id.startsWith('gid://') ? id : `${SHOPIFY_PRODUCT_GID}${id}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A failed gateway call, with the status kept on the error.
|
|
26
|
+
*
|
|
27
|
+
* Callers that can act on *which* failure it was need the code — a guest invite that is expired (410)
|
|
28
|
+
* versus unknown (404) are different things to tell someone.
|
|
29
|
+
*/
|
|
30
|
+
class LiveSellingError extends Error {
|
|
31
|
+
constructor(status) {
|
|
32
|
+
super(`Live-selling API responded ${status}`);
|
|
33
|
+
this.status = status;
|
|
34
|
+
this.name = 'LiveSellingError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.LiveSellingError = LiveSellingError;
|
|
38
|
+
const SILENT = { error: () => undefined };
|
|
39
|
+
/** Prefers `window.localStorage`; falls back to a process-lifetime in-memory map. */
|
|
40
|
+
function defaultStorage() {
|
|
41
|
+
const ls = globalThis.localStorage;
|
|
42
|
+
if (ls && typeof ls.getItem === 'function')
|
|
43
|
+
return ls;
|
|
44
|
+
const mem = new Map();
|
|
45
|
+
return {
|
|
46
|
+
getItem: (key) => (mem.has(key) ? mem.get(key) : null),
|
|
47
|
+
setItem: (key, value) => {
|
|
48
|
+
mem.set(key, value);
|
|
49
|
+
},
|
|
50
|
+
removeItem: (key) => {
|
|
51
|
+
mem.delete(key);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const state = { config: null, storage: defaultStorage(), logger: SILENT };
|
|
56
|
+
function setConfig(config) {
|
|
57
|
+
var _a, _b;
|
|
58
|
+
if (!config.apiUrl)
|
|
59
|
+
throw new Error('liveSelling.configure: apiUrl is required');
|
|
60
|
+
if (!config.companyId)
|
|
61
|
+
throw new Error('liveSelling.configure: companyId is required');
|
|
62
|
+
state.config = config;
|
|
63
|
+
state.storage = (_a = config.storage) !== null && _a !== void 0 ? _a : defaultStorage();
|
|
64
|
+
state.logger = (_b = config.logger) !== null && _b !== void 0 ? _b : SILENT;
|
|
65
|
+
}
|
|
66
|
+
function getConfig() {
|
|
67
|
+
if (!state.config)
|
|
68
|
+
throw new Error('liveSelling.configure() must be called before any other method');
|
|
69
|
+
return state.config;
|
|
70
|
+
}
|
|
71
|
+
function isConfigured() {
|
|
72
|
+
return state.config !== null;
|
|
73
|
+
}
|
|
74
|
+
function getCompanyId() {
|
|
75
|
+
var _a, _b;
|
|
76
|
+
return (_b = (_a = state.config) === null || _a === void 0 ? void 0 : _a.companyId) !== null && _b !== void 0 ? _b : null;
|
|
77
|
+
}
|
|
78
|
+
function getStorage() {
|
|
79
|
+
return state.storage;
|
|
80
|
+
}
|
|
81
|
+
function getLogger() {
|
|
82
|
+
return state.logger;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A handled-data report: `warn` where the host app has one, `error` where it does not.
|
|
86
|
+
*
|
|
87
|
+
* Never silent. A host that has not implemented `warn` still needs to hear that a win names a variant
|
|
88
|
+
* belonging to another product — dropping the report to keep the console clean would trade a merchant's
|
|
89
|
+
* data fault for silence, and that fault reaches a shopper as the wrong size in a cart.
|
|
90
|
+
*/
|
|
91
|
+
function logWarning(error, context) {
|
|
92
|
+
const logger = state.logger;
|
|
93
|
+
if (logger.warn)
|
|
94
|
+
logger.warn(error, context);
|
|
95
|
+
else
|
|
96
|
+
logger.error(error, context);
|
|
97
|
+
}
|
|
98
|
+
function getCustomerAccountRequest() {
|
|
99
|
+
var _a, _b;
|
|
100
|
+
return (_b = (_a = state.config) === null || _a === void 0 ? void 0 : _a.customerAccountRequest) !== null && _b !== void 0 ? _b : null;
|
|
101
|
+
}
|
|
102
|
+
/** Null when the host app configured no storefront; the session then resolves no products. */
|
|
103
|
+
function getCommerce() {
|
|
104
|
+
var _a, _b;
|
|
105
|
+
return (_b = (_a = state.config) === null || _a === void 0 ? void 0 : _a.commerce) !== null && _b !== void 0 ? _b : null;
|
|
106
|
+
}
|
|
107
|
+
/** Null when nobody is identified beyond the per-install viewer id — bidding is then never offered. */
|
|
108
|
+
function getIdentity() {
|
|
109
|
+
var _a, _b;
|
|
110
|
+
return (_b = (_a = state.config) === null || _a === void 0 ? void 0 : _a.identity) !== null && _b !== void 0 ? _b : null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The gateway request. The company header is the only credential; a body implies JSON. `X-Request-Source`
|
|
114
|
+
* marks the traffic as first-party app rather than a web widget.
|
|
115
|
+
*/
|
|
116
|
+
async function liveSellingRequest(path, options) {
|
|
117
|
+
var _a, _b;
|
|
118
|
+
const config = getConfig();
|
|
119
|
+
const query = (options === null || options === void 0 ? void 0 : options.params)
|
|
120
|
+
? `?${new URLSearchParams(Object.entries(options.params).map(([k, v]) => [k, String(v)]))}`
|
|
121
|
+
: '';
|
|
122
|
+
const response = await fetch(`${config.apiUrl}${path}${query}`, {
|
|
123
|
+
method: (_a = options === null || options === void 0 ? void 0 : options.method) !== null && _a !== void 0 ? _a : 'GET',
|
|
124
|
+
headers: {
|
|
125
|
+
'x-company-id': config.companyId,
|
|
126
|
+
'X-Request-Source': (_b = config.requestSource) !== null && _b !== void 0 ? _b : 'APPTILE',
|
|
127
|
+
...((options === null || options === void 0 ? void 0 : options.body) ? { 'Content-Type': 'application/json' } : {}),
|
|
128
|
+
},
|
|
129
|
+
body: (options === null || options === void 0 ? void 0 : options.body) ? JSON.stringify(options.body) : undefined,
|
|
130
|
+
});
|
|
131
|
+
if (!response.ok)
|
|
132
|
+
throw new LiveSellingError(response.status);
|
|
133
|
+
return (await response.json());
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* A stable random id. Uses the platform `crypto.randomUUID` when present (browsers, modern React
|
|
137
|
+
* Native, Node) and falls back to a Math.random hex string — replacing the app's `expo-crypto`
|
|
138
|
+
* dependency so the package carries no native crypto peer.
|
|
139
|
+
*/
|
|
140
|
+
function randomId(length = 16) {
|
|
141
|
+
var _a;
|
|
142
|
+
const uuid = typeof ((_a = globalThis.crypto) === null || _a === void 0 ? void 0 : _a.randomUUID) === 'function'
|
|
143
|
+
? globalThis.crypto.randomUUID()
|
|
144
|
+
: `${Date.now().toString(16)}${Math.random().toString(16).slice(2)}${Math.random().toString(16).slice(2)}`;
|
|
145
|
+
return uuid.replace(/-/g, '').slice(0, length);
|
|
146
|
+
}
|
|
147
|
+
/** Storage reads may be sync or async depending on the adapter; normalise to a promise. */
|
|
148
|
+
async function storageGet(key) {
|
|
149
|
+
return Promise.resolve(getStorage().getItem(key));
|
|
150
|
+
}
|
|
151
|
+
async function storageSet(key, value) {
|
|
152
|
+
await Promise.resolve(getStorage().setItem(key, value));
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/clips.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clips.d.ts","sourceRoot":"","sources":["../src/clips.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,SAAS,CAAC;AAwBlD,eAAO,MAAM,KAAK,EAAE,QAyBnB,CAAC"}
|
package/dist/clips.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clips = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Clips, from the gateway's video collections.
|
|
6
|
+
*
|
|
7
|
+
* A video collection is a merchant-ordered playlist of clips, selected by `videoCollectionId` alone.
|
|
8
|
+
* A clip is not its own recording: every item points at the FULL HLS playlist of the livestream it was
|
|
9
|
+
* cut from and carries the cut as `start`/`end` query params. The CDN ignores them, so the window is
|
|
10
|
+
* the client's to honour — parsed off here into `startMs`/`endMs`. Left on the URL they read as already
|
|
11
|
+
* applied, and each clip silently plays a whole show from the top.
|
|
12
|
+
*/
|
|
13
|
+
const client_1 = require("./client");
|
|
14
|
+
/**
|
|
15
|
+
* Splits the trim window off the playlist URL. Read with a regex rather than `URL.searchParams`, which
|
|
16
|
+
* React Native does not implement for reading a parsed URL back.
|
|
17
|
+
*/
|
|
18
|
+
function readTrimWindow(url) {
|
|
19
|
+
const [videoUrl, query = ''] = url.split('?');
|
|
20
|
+
const readMs = (key) => {
|
|
21
|
+
const found = query.match(new RegExp(`(?:^|&)${key}=(\\d+)`));
|
|
22
|
+
return found ? Number(found[1]) : null;
|
|
23
|
+
};
|
|
24
|
+
return { videoUrl, startMs: readMs('start'), endMs: readMs('end') };
|
|
25
|
+
}
|
|
26
|
+
exports.clips = {
|
|
27
|
+
async list() {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
const { videoCollectionId } = (0, client_1.getConfig)();
|
|
30
|
+
/**
|
|
31
|
+
* No collection means this store has not curated a reel — an empty one, not an error. Worth an
|
|
32
|
+
* early return: the id is not scoped by the company header, so a blank one requests
|
|
33
|
+
* `/video-collections/` and a stale one happily returns another brand's clips with a 200.
|
|
34
|
+
*/
|
|
35
|
+
if (!videoCollectionId)
|
|
36
|
+
return [];
|
|
37
|
+
const body = await (0, client_1.liveSellingRequest)(`/widget/plugin/video-collections/${videoCollectionId}`);
|
|
38
|
+
return ((_b = (_a = body.data) === null || _a === void 0 ? void 0 : _a.items) !== null && _b !== void 0 ? _b : [])
|
|
39
|
+
.filter((item) => !!(item === null || item === void 0 ? void 0 : item.url))
|
|
40
|
+
.map((item, index) => {
|
|
41
|
+
var _a, _b, _c;
|
|
42
|
+
return ({
|
|
43
|
+
// Server-side unique, but an item could arrive without one and two clips must never collide.
|
|
44
|
+
id: item.shoppable_feed_id || `clip-${index}`,
|
|
45
|
+
title: ((_a = item.title) === null || _a === void 0 ? void 0 : _a.trim()) || '',
|
|
46
|
+
posterUrl: ((_b = item.thumbnail) === null || _b === void 0 ? void 0 : _b.trim()) || null,
|
|
47
|
+
productIds: ((_c = item.product_ids) !== null && _c !== void 0 ? _c : []).map(client_1.toProductGid),
|
|
48
|
+
...readTrimWindow(item.url),
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=clips.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clips.js","sourceRoot":"","sources":["../src/clips.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACH,qCAAuE;AAYvE;;;GAGG;AACH,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,CAAC,QAAQ,EAAE,KAAK,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC;QAC9D,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACzC,CAAC,CAAC;IACF,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACtE,CAAC;AAEY,QAAA,KAAK,GAAa;IAC7B,KAAK,CAAC,IAAI;;QACR,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAA,kBAAS,GAAE,CAAC;QAC1C;;;;WAIG;QACH,IAAI,CAAC,iBAAiB;YAAE,OAAO,EAAE,CAAC;QAElC,MAAM,IAAI,GAAG,MAAM,IAAA,2BAAkB,EAElC,oCAAoC,iBAAiB,EAAE,CAAC,CAAC;QAE5D,OAAO,CAAC,MAAA,MAAA,IAAI,CAAC,IAAI,0CAAE,KAAK,mCAAI,EAAE,CAAC;aAC5B,MAAM,CAAC,CAAC,IAAI,EAAoD,EAAE,CAAC,CAAC,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,CAAA,CAAC;aAC/E,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;;YAAC,OAAA,CAAC;gBACrB,6FAA6F;gBAC7F,EAAE,EAAE,IAAI,CAAC,iBAAiB,IAAI,QAAQ,KAAK,EAAE;gBAC7C,KAAK,EAAE,CAAA,MAAA,IAAI,CAAC,KAAK,0CAAE,IAAI,EAAE,KAAI,EAAE;gBAC/B,SAAS,EAAE,CAAA,MAAA,IAAI,CAAC,SAAS,0CAAE,IAAI,EAAE,KAAI,IAAI;gBACzC,UAAU,EAAE,CAAC,MAAA,IAAI,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC,GAAG,CAAC,qBAAY,CAAC;gBACtD,GAAG,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;aAC5B,CAAC,CAAA;SAAA,CAAC,CAAC;IACR,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Links inside live comments: finding them, and deciding where a tap should go.
|
|
3
|
+
*
|
|
4
|
+
* A host pastes storefront links into the chat — "here's the dress" — and a product link should open
|
|
5
|
+
* the app's own Product screen, not bounce the shopper into the browser. Pure and platform-free so the
|
|
6
|
+
* rules can be reasoned about (and tested) without a renderer.
|
|
7
|
+
*
|
|
8
|
+
* `classifyCommentLink` takes the app's own storefront hosts as an argument rather than reading a global
|
|
9
|
+
* config — that is the one piece of app coupling the engine's original had, lifted into a parameter.
|
|
10
|
+
*/
|
|
11
|
+
import type { CommentUrlPreview } from './types';
|
|
12
|
+
export type CommentLink = {
|
|
13
|
+
kind: 'product';
|
|
14
|
+
handle: string;
|
|
15
|
+
variantId: string | null;
|
|
16
|
+
url: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'collection';
|
|
19
|
+
handle: string;
|
|
20
|
+
url: string;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'external';
|
|
23
|
+
url: string;
|
|
24
|
+
};
|
|
25
|
+
export type CommentSegment = {
|
|
26
|
+
kind: 'text';
|
|
27
|
+
text: string;
|
|
28
|
+
} | {
|
|
29
|
+
kind: 'link';
|
|
30
|
+
text: string;
|
|
31
|
+
url: string;
|
|
32
|
+
};
|
|
33
|
+
/** Splits a comment into text and link runs. Every link is kept. */
|
|
34
|
+
export declare function toCommentSegments(text: string): CommentSegment[];
|
|
35
|
+
/** True when the comment has anything tappable. */
|
|
36
|
+
export declare function hasCommentLink(text: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* What a link points at. `storefrontHosts` are the app's own domains; products are checked before
|
|
39
|
+
* collections because Shopify writes nested `/collections/x/products/y` paths.
|
|
40
|
+
*/
|
|
41
|
+
export declare function classifyCommentLink(url: string, storefrontHosts: string[]): CommentLink;
|
|
42
|
+
/** The host's unfurled link card, if the comment carried a usable one. */
|
|
43
|
+
export declare function toUrlPreview(raw: unknown): CommentUrlPreview | undefined;
|
|
44
|
+
/** The domain, for a card's caption. */
|
|
45
|
+
export declare function displayHost(url: string): string;
|
|
46
|
+
//# sourceMappingURL=commentLinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentLinks.d.ts","sourceRoot":"","sources":["../src/commentLinks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAKjD,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAkDhD,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAmBhE;AAED,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,WAAW,CAgBvF;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,GAAG,SAAS,CAWxE;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toCommentSegments = toCommentSegments;
|
|
4
|
+
exports.hasCommentLink = hasCommentLink;
|
|
5
|
+
exports.classifyCommentLink = classifyCommentLink;
|
|
6
|
+
exports.toUrlPreview = toUrlPreview;
|
|
7
|
+
exports.displayHost = displayHost;
|
|
8
|
+
const URL_PATTERN = /(?:https?:\/\/|www\.)[^\s<>"']+/gi;
|
|
9
|
+
const TRAILING_PUNCTUATION = /[.,;:!?'"]+$/;
|
|
10
|
+
function trimUrl(raw) {
|
|
11
|
+
let url = raw.replace(TRAILING_PUNCTUATION, '');
|
|
12
|
+
while ((url.endsWith(')') && !url.includes('(')) || (url.endsWith(']') && !url.includes('['))) {
|
|
13
|
+
url = url.slice(0, -1);
|
|
14
|
+
}
|
|
15
|
+
return url;
|
|
16
|
+
}
|
|
17
|
+
function toHref(url) {
|
|
18
|
+
return /^https?:\/\//i.test(url) ? url : `https://${url}`;
|
|
19
|
+
}
|
|
20
|
+
/** Port, credentials, case and a leading `www.` are all noise — `www.x.com` and `x.com` are one shop. */
|
|
21
|
+
function normaliseHost(raw) {
|
|
22
|
+
return raw
|
|
23
|
+
.split('@')
|
|
24
|
+
.pop()
|
|
25
|
+
.split(':')[0]
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.replace(/^www\./, '');
|
|
28
|
+
}
|
|
29
|
+
function hostOf(url) {
|
|
30
|
+
const match = /^https?:\/\/([^/?#]+)/i.exec(toHref(url));
|
|
31
|
+
return match ? normaliseHost(match[1]) : null;
|
|
32
|
+
}
|
|
33
|
+
function pathOf(url) {
|
|
34
|
+
return toHref(url).replace(/^https?:\/\/[^/?#]*/i, '').replace(/[?#].*$/, '');
|
|
35
|
+
}
|
|
36
|
+
function decodeHandle(raw) {
|
|
37
|
+
try {
|
|
38
|
+
return decodeURIComponent(raw);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return raw;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** The variant a product link points at, promoted to a Storefront gid. */
|
|
45
|
+
function variantIdOf(href) {
|
|
46
|
+
const match = /[?&]variant=([^&#]+)/i.exec(href);
|
|
47
|
+
const raw = (match === null || match === void 0 ? void 0 : match[1]) ? decodeURIComponent(match[1]) : '';
|
|
48
|
+
if (!raw)
|
|
49
|
+
return null;
|
|
50
|
+
if (raw.startsWith('gid://'))
|
|
51
|
+
return raw;
|
|
52
|
+
return /^\d+$/.test(raw) ? `gid://shopify/ProductVariant/${raw}` : null;
|
|
53
|
+
}
|
|
54
|
+
/** Splits a comment into text and link runs. Every link is kept. */
|
|
55
|
+
function toCommentSegments(text) {
|
|
56
|
+
var _a;
|
|
57
|
+
if (!text)
|
|
58
|
+
return [];
|
|
59
|
+
const segments = [];
|
|
60
|
+
let cursor = 0;
|
|
61
|
+
for (const match of text.matchAll(new RegExp(URL_PATTERN))) {
|
|
62
|
+
const raw = match[0];
|
|
63
|
+
const start = (_a = match.index) !== null && _a !== void 0 ? _a : 0;
|
|
64
|
+
const url = trimUrl(raw);
|
|
65
|
+
const dropped = raw.slice(url.length);
|
|
66
|
+
if (start > cursor)
|
|
67
|
+
segments.push({ kind: 'text', text: text.slice(cursor, start) });
|
|
68
|
+
segments.push({ kind: 'link', text: url, url: toHref(url) });
|
|
69
|
+
cursor = start + raw.length;
|
|
70
|
+
if (dropped)
|
|
71
|
+
segments.push({ kind: 'text', text: dropped });
|
|
72
|
+
}
|
|
73
|
+
if (cursor < text.length)
|
|
74
|
+
segments.push({ kind: 'text', text: text.slice(cursor) });
|
|
75
|
+
return segments;
|
|
76
|
+
}
|
|
77
|
+
/** True when the comment has anything tappable. */
|
|
78
|
+
function hasCommentLink(text) {
|
|
79
|
+
return new RegExp(URL_PATTERN).test(text !== null && text !== void 0 ? text : '');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* What a link points at. `storefrontHosts` are the app's own domains; products are checked before
|
|
83
|
+
* collections because Shopify writes nested `/collections/x/products/y` paths.
|
|
84
|
+
*/
|
|
85
|
+
function classifyCommentLink(url, storefrontHosts) {
|
|
86
|
+
const href = toHref(url);
|
|
87
|
+
const host = hostOf(href);
|
|
88
|
+
const ours = !!host && storefrontHosts.some((h) => normaliseHost(h) === host);
|
|
89
|
+
if (!ours)
|
|
90
|
+
return { kind: 'external', url: href };
|
|
91
|
+
const path = pathOf(href);
|
|
92
|
+
const product = /\/products\/([^/]+)/i.exec(path);
|
|
93
|
+
if (product === null || product === void 0 ? void 0 : product[1]) {
|
|
94
|
+
return { kind: 'product', handle: decodeHandle(product[1]), variantId: variantIdOf(href), url: href };
|
|
95
|
+
}
|
|
96
|
+
const collection = /\/collections\/([^/]+)/i.exec(path);
|
|
97
|
+
if (collection === null || collection === void 0 ? void 0 : collection[1])
|
|
98
|
+
return { kind: 'collection', handle: decodeHandle(collection[1]), url: href };
|
|
99
|
+
return { kind: 'external', url: href };
|
|
100
|
+
}
|
|
101
|
+
/** The host's unfurled link card, if the comment carried a usable one. */
|
|
102
|
+
function toUrlPreview(raw) {
|
|
103
|
+
const data = raw;
|
|
104
|
+
const url = typeof (data === null || data === void 0 ? void 0 : data.url) === 'string' ? data.url.trim() : '';
|
|
105
|
+
if (!url)
|
|
106
|
+
return undefined;
|
|
107
|
+
const image = typeof (data === null || data === void 0 ? void 0 : data.image) === 'string' ? data.image : null;
|
|
108
|
+
return {
|
|
109
|
+
url: toHref(url),
|
|
110
|
+
title: typeof (data === null || data === void 0 ? void 0 : data.title) === 'string' && data.title ? data.title : null,
|
|
111
|
+
description: typeof (data === null || data === void 0 ? void 0 : data.description) === 'string' && data.description ? data.description : null,
|
|
112
|
+
image: image ? image.replace(/^http:\/\//i, 'https://') : null,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/** The domain, for a card's caption. */
|
|
116
|
+
function displayHost(url) {
|
|
117
|
+
var _a;
|
|
118
|
+
return (_a = hostOf(url)) !== null && _a !== void 0 ? _a : url;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=commentLinks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commentLinks.js","sourceRoot":"","sources":["../src/commentLinks.ts"],"names":[],"mappings":"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"}
|