@teleporthq/teleport-shared 0.43.67 → 0.43.69
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/__tests__/_helpers/embed-runtime-emitter.ts +197 -0
- package/__tests__/utils/discount-engine.ts +1548 -0
- package/__tests__/utils/product-options.ts +2458 -0
- package/__tests__/utils/rich-text-embeds-runtime-module.ts +34 -0
- package/__tests__/utils/subscription-access.ts +37 -0
- package/dist/cjs/index.d.ts +9 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +17 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils/cart-currency.d.ts +27 -0
- package/dist/cjs/utils/cart-currency.d.ts.map +1 -0
- package/dist/cjs/utils/cart-currency.js +31 -0
- package/dist/cjs/utils/cart-currency.js.map +1 -0
- package/dist/cjs/utils/cart-line-pricing.d.ts +25 -0
- package/dist/cjs/utils/cart-line-pricing.d.ts.map +1 -0
- package/dist/cjs/utils/cart-line-pricing.js +29 -0
- package/dist/cjs/utils/cart-line-pricing.js.map +1 -0
- package/dist/cjs/utils/discount-engine.d.ts +74 -0
- package/dist/cjs/utils/discount-engine.d.ts.map +1 -0
- package/dist/cjs/utils/discount-engine.js +435 -0
- package/dist/cjs/utils/discount-engine.js.map +1 -0
- package/dist/cjs/utils/product-options.d.ts +25 -0
- package/dist/cjs/utils/product-options.d.ts.map +1 -0
- package/dist/cjs/utils/product-options.js +1155 -0
- package/dist/cjs/utils/product-options.js.map +1 -0
- package/dist/cjs/utils/rich-text-embeds-codegen.d.ts +13 -0
- package/dist/cjs/utils/rich-text-embeds-codegen.d.ts.map +1 -1
- package/dist/cjs/utils/rich-text-embeds-codegen.js +15 -104
- package/dist/cjs/utils/rich-text-embeds-codegen.js.map +1 -1
- package/dist/cjs/utils/rich-text-embeds-runtime-source.d.ts +2 -0
- package/dist/cjs/utils/rich-text-embeds-runtime-source.d.ts.map +1 -0
- package/dist/cjs/utils/rich-text-embeds-runtime-source.js +409 -0
- package/dist/cjs/utils/rich-text-embeds-runtime-source.js.map +1 -0
- package/dist/cjs/utils/session-cookie-resolver.d.ts +85 -0
- package/dist/cjs/utils/session-cookie-resolver.d.ts.map +1 -0
- package/dist/cjs/utils/session-cookie-resolver.js +108 -0
- package/dist/cjs/utils/session-cookie-resolver.js.map +1 -0
- package/dist/cjs/utils/subscription-access.d.ts +36 -0
- package/dist/cjs/utils/subscription-access.d.ts.map +1 -0
- package/dist/cjs/utils/subscription-access.js +61 -0
- package/dist/cjs/utils/subscription-access.js.map +1 -0
- package/dist/cjs/utils/table-access.d.ts +114 -0
- package/dist/cjs/utils/table-access.d.ts.map +1 -0
- package/dist/cjs/utils/table-access.js +238 -0
- package/dist/cjs/utils/table-access.js.map +1 -0
- package/dist/cjs/utils/web-push.d.ts +43 -0
- package/dist/cjs/utils/web-push.d.ts.map +1 -0
- package/dist/cjs/utils/web-push.js +62 -0
- package/dist/cjs/utils/web-push.js.map +1 -0
- package/dist/esm/index.d.ts +9 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +9 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils/cart-currency.d.ts +27 -0
- package/dist/esm/utils/cart-currency.d.ts.map +1 -0
- package/dist/esm/utils/cart-currency.js +27 -0
- package/dist/esm/utils/cart-currency.js.map +1 -0
- package/dist/esm/utils/cart-line-pricing.d.ts +25 -0
- package/dist/esm/utils/cart-line-pricing.d.ts.map +1 -0
- package/dist/esm/utils/cart-line-pricing.js +25 -0
- package/dist/esm/utils/cart-line-pricing.js.map +1 -0
- package/dist/esm/utils/discount-engine.d.ts +74 -0
- package/dist/esm/utils/discount-engine.d.ts.map +1 -0
- package/dist/esm/utils/discount-engine.js +431 -0
- package/dist/esm/utils/discount-engine.js.map +1 -0
- package/dist/esm/utils/product-options.d.ts +25 -0
- package/dist/esm/utils/product-options.d.ts.map +1 -0
- package/dist/esm/utils/product-options.js +1151 -0
- package/dist/esm/utils/product-options.js.map +1 -0
- package/dist/esm/utils/rich-text-embeds-codegen.d.ts +13 -0
- package/dist/esm/utils/rich-text-embeds-codegen.d.ts.map +1 -1
- package/dist/esm/utils/rich-text-embeds-codegen.js +16 -105
- package/dist/esm/utils/rich-text-embeds-codegen.js.map +1 -1
- package/dist/esm/utils/rich-text-embeds-runtime-source.d.ts +2 -0
- package/dist/esm/utils/rich-text-embeds-runtime-source.d.ts.map +1 -0
- package/dist/esm/utils/rich-text-embeds-runtime-source.js +406 -0
- package/dist/esm/utils/rich-text-embeds-runtime-source.js.map +1 -0
- package/dist/esm/utils/session-cookie-resolver.d.ts +85 -0
- package/dist/esm/utils/session-cookie-resolver.d.ts.map +1 -0
- package/dist/esm/utils/session-cookie-resolver.js +103 -0
- package/dist/esm/utils/session-cookie-resolver.js.map +1 -0
- package/dist/esm/utils/subscription-access.d.ts +36 -0
- package/dist/esm/utils/subscription-access.d.ts.map +1 -0
- package/dist/esm/utils/subscription-access.js +57 -0
- package/dist/esm/utils/subscription-access.js.map +1 -0
- package/dist/esm/utils/table-access.d.ts +114 -0
- package/dist/esm/utils/table-access.d.ts.map +1 -0
- package/dist/esm/utils/table-access.js +233 -0
- package/dist/esm/utils/table-access.js.map +1 -0
- package/dist/esm/utils/web-push.d.ts +43 -0
- package/dist/esm/utils/web-push.d.ts.map +1 -0
- package/dist/esm/utils/web-push.js +59 -0
- package/dist/esm/utils/web-push.js.map +1 -0
- package/package.json +3 -3
- package/src/index.ts +16 -0
- package/src/utils/cart-currency.ts +76 -0
- package/src/utils/cart-line-pricing.ts +151 -0
- package/src/utils/discount-engine.ts +437 -0
- package/src/utils/product-options.ts +1150 -0
- package/src/utils/rich-text-embeds-codegen.ts +16 -183
- package/src/utils/rich-text-embeds-runtime-source.ts +405 -0
- package/src/utils/session-cookie-resolver.ts +305 -0
- package/src/utils/subscription-access.ts +59 -0
- package/src/utils/table-access.ts +516 -0
- package/src/utils/web-push.ts +61 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The names the published app's service worker, its push routes and the
|
|
3
|
+
* workflow nodes that use them have to agree on. The node handlers are
|
|
4
|
+
* serialized into the generated app as source text, so they interpolate these
|
|
5
|
+
* values at generation time rather than importing them.
|
|
6
|
+
*/
|
|
7
|
+
/** The browsers that agreed to receive the app's push notifications, in the project database. */
|
|
8
|
+
export declare const SUBSCRIPTIONS_TABLE = "teleport_push_subscriptions";
|
|
9
|
+
/** Public: a browser saves (POST) or forgets (DELETE) its own subscription here. */
|
|
10
|
+
export declare const SUBSCRIPTIONS_ROUTE = "/api/push/subscriptions";
|
|
11
|
+
/** Internal: only the app's own server code may send a notification through it. */
|
|
12
|
+
export declare const SEND_ROUTE = "/api/push/send";
|
|
13
|
+
/** What a visitor-facing push step reports when the project has no push keys or no worker. */
|
|
14
|
+
export declare const NOT_CONFIGURED_MESSAGE = "Push notifications are not set up for this site.";
|
|
15
|
+
export declare const PUBLIC_KEY_ENV = "WEB_PUSH_VAPID_PUBLIC_KEY";
|
|
16
|
+
/** Filled at deploy from the project secret of the same name. */
|
|
17
|
+
export declare const PRIVATE_KEY_ENV = "WEB_PUSH_VAPID_PRIVATE_KEY";
|
|
18
|
+
/**
|
|
19
|
+
* The send route accepts a request only when this header carries an HMAC of
|
|
20
|
+
* `SEND_TOKEN_PURPOSE` keyed with the VAPID private key — a value only the
|
|
21
|
+
* app's own server holds, so no extra secret has to be provisioned.
|
|
22
|
+
*/
|
|
23
|
+
export declare const SEND_TOKEN_HEADER = "x-teleport-push-token";
|
|
24
|
+
export declare const SEND_TOKEN_PURPOSE = "teleport-web-push-send";
|
|
25
|
+
/**
|
|
26
|
+
* The page-side API the generated service-worker module publishes on `window`.
|
|
27
|
+
* A workflow node handler has no module scope, so a global is the only way it
|
|
28
|
+
* can reach the worker registration.
|
|
29
|
+
*/
|
|
30
|
+
export declare const SERVICE_WORKER_GLOBAL = "__teleportServiceWorker";
|
|
31
|
+
export declare const SUBSCRIBE_NODE_TYPE = "browser-subscribe-to-push";
|
|
32
|
+
export declare const UNSUBSCRIBE_NODE_TYPE = "browser-unsubscribe-from-push";
|
|
33
|
+
export declare const GET_SUBSCRIPTION_NODE_TYPE = "browser-get-push-subscription";
|
|
34
|
+
export declare const SHOW_NOTIFICATION_NODE_TYPE = "browser-show-notification";
|
|
35
|
+
export declare const SEND_NODE_TYPE = "push-send-notification";
|
|
36
|
+
/** Nodes that manage the visitor's push subscription and therefore need the push routes. */
|
|
37
|
+
export declare const PUSH_NODE_TYPES: ReadonlyArray<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Nodes that need a service worker on the page: push itself, and on-page
|
|
40
|
+
* notifications, which Chrome on Android only shows through a worker.
|
|
41
|
+
*/
|
|
42
|
+
export declare const SERVICE_WORKER_NODE_TYPES: ReadonlyArray<string>;
|
|
43
|
+
//# sourceMappingURL=web-push.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-push.d.ts","sourceRoot":"","sources":["../../../src/utils/web-push.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,iGAAiG;AACjG,eAAO,MAAM,mBAAmB,gCAAgC,CAAA;AAEhE,oFAAoF;AACpF,eAAO,MAAM,mBAAmB,4BAA4B,CAAA;AAE5D,mFAAmF;AACnF,eAAO,MAAM,UAAU,mBAAmB,CAAA;AAE1C,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB,qDAAqD,CAAA;AAExF,eAAO,MAAM,cAAc,8BAA8B,CAAA;AAEzD,iEAAiE;AACjE,eAAO,MAAM,eAAe,+BAA+B,CAAA;AAE3D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,0BAA0B,CAAA;AACxD,eAAO,MAAM,kBAAkB,2BAA2B,CAAA;AAE1D;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,4BAA4B,CAAA;AAE9D,eAAO,MAAM,mBAAmB,8BAA8B,CAAA;AAC9D,eAAO,MAAM,qBAAqB,kCAAkC,CAAA;AACpE,eAAO,MAAM,0BAA0B,kCAAkC,CAAA;AACzE,eAAO,MAAM,2BAA2B,8BAA8B,CAAA;AACtE,eAAO,MAAM,cAAc,2BAA2B,CAAA;AAEtD,4FAA4F;AAC5F,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,MAAM,CAKjD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,yBAAyB,EAAE,aAAa,CAAC,MAAM,CAG3D,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The names the published app's service worker, its push routes and the
|
|
3
|
+
* workflow nodes that use them have to agree on. The node handlers are
|
|
4
|
+
* serialized into the generated app as source text, so they interpolate these
|
|
5
|
+
* values at generation time rather than importing them.
|
|
6
|
+
*/
|
|
7
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
8
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
9
|
+
if (ar || !(i in from)) {
|
|
10
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
11
|
+
ar[i] = from[i];
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
15
|
+
};
|
|
16
|
+
/** The browsers that agreed to receive the app's push notifications, in the project database. */
|
|
17
|
+
export var SUBSCRIPTIONS_TABLE = 'teleport_push_subscriptions';
|
|
18
|
+
/** Public: a browser saves (POST) or forgets (DELETE) its own subscription here. */
|
|
19
|
+
export var SUBSCRIPTIONS_ROUTE = '/api/push/subscriptions';
|
|
20
|
+
/** Internal: only the app's own server code may send a notification through it. */
|
|
21
|
+
export var SEND_ROUTE = '/api/push/send';
|
|
22
|
+
/** What a visitor-facing push step reports when the project has no push keys or no worker. */
|
|
23
|
+
export var NOT_CONFIGURED_MESSAGE = 'Push notifications are not set up for this site.';
|
|
24
|
+
export var PUBLIC_KEY_ENV = 'WEB_PUSH_VAPID_PUBLIC_KEY';
|
|
25
|
+
/** Filled at deploy from the project secret of the same name. */
|
|
26
|
+
export var PRIVATE_KEY_ENV = 'WEB_PUSH_VAPID_PRIVATE_KEY';
|
|
27
|
+
/**
|
|
28
|
+
* The send route accepts a request only when this header carries an HMAC of
|
|
29
|
+
* `SEND_TOKEN_PURPOSE` keyed with the VAPID private key — a value only the
|
|
30
|
+
* app's own server holds, so no extra secret has to be provisioned.
|
|
31
|
+
*/
|
|
32
|
+
export var SEND_TOKEN_HEADER = 'x-teleport-push-token';
|
|
33
|
+
export var SEND_TOKEN_PURPOSE = 'teleport-web-push-send';
|
|
34
|
+
/**
|
|
35
|
+
* The page-side API the generated service-worker module publishes on `window`.
|
|
36
|
+
* A workflow node handler has no module scope, so a global is the only way it
|
|
37
|
+
* can reach the worker registration.
|
|
38
|
+
*/
|
|
39
|
+
export var SERVICE_WORKER_GLOBAL = '__teleportServiceWorker';
|
|
40
|
+
export var SUBSCRIBE_NODE_TYPE = 'browser-subscribe-to-push';
|
|
41
|
+
export var UNSUBSCRIBE_NODE_TYPE = 'browser-unsubscribe-from-push';
|
|
42
|
+
export var GET_SUBSCRIPTION_NODE_TYPE = 'browser-get-push-subscription';
|
|
43
|
+
export var SHOW_NOTIFICATION_NODE_TYPE = 'browser-show-notification';
|
|
44
|
+
export var SEND_NODE_TYPE = 'push-send-notification';
|
|
45
|
+
/** Nodes that manage the visitor's push subscription and therefore need the push routes. */
|
|
46
|
+
export var PUSH_NODE_TYPES = [
|
|
47
|
+
SUBSCRIBE_NODE_TYPE,
|
|
48
|
+
UNSUBSCRIBE_NODE_TYPE,
|
|
49
|
+
GET_SUBSCRIPTION_NODE_TYPE,
|
|
50
|
+
SEND_NODE_TYPE,
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Nodes that need a service worker on the page: push itself, and on-page
|
|
54
|
+
* notifications, which Chrome on Android only shows through a worker.
|
|
55
|
+
*/
|
|
56
|
+
export var SERVICE_WORKER_NODE_TYPES = __spreadArray(__spreadArray([], PUSH_NODE_TYPES, true), [
|
|
57
|
+
SHOW_NOTIFICATION_NODE_TYPE,
|
|
58
|
+
], false);
|
|
59
|
+
//# sourceMappingURL=web-push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-push.js","sourceRoot":"","sources":["../../../src/utils/web-push.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;;;;;;;;;AAEH,iGAAiG;AACjG,MAAM,CAAC,IAAM,mBAAmB,GAAG,6BAA6B,CAAA;AAEhE,oFAAoF;AACpF,MAAM,CAAC,IAAM,mBAAmB,GAAG,yBAAyB,CAAA;AAE5D,mFAAmF;AACnF,MAAM,CAAC,IAAM,UAAU,GAAG,gBAAgB,CAAA;AAE1C,8FAA8F;AAC9F,MAAM,CAAC,IAAM,sBAAsB,GAAG,kDAAkD,CAAA;AAExF,MAAM,CAAC,IAAM,cAAc,GAAG,2BAA2B,CAAA;AAEzD,iEAAiE;AACjE,MAAM,CAAC,IAAM,eAAe,GAAG,4BAA4B,CAAA;AAE3D;;;;GAIG;AACH,MAAM,CAAC,IAAM,iBAAiB,GAAG,uBAAuB,CAAA;AACxD,MAAM,CAAC,IAAM,kBAAkB,GAAG,wBAAwB,CAAA;AAE1D;;;;GAIG;AACH,MAAM,CAAC,IAAM,qBAAqB,GAAG,yBAAyB,CAAA;AAE9D,MAAM,CAAC,IAAM,mBAAmB,GAAG,2BAA2B,CAAA;AAC9D,MAAM,CAAC,IAAM,qBAAqB,GAAG,+BAA+B,CAAA;AACpE,MAAM,CAAC,IAAM,0BAA0B,GAAG,+BAA+B,CAAA;AACzE,MAAM,CAAC,IAAM,2BAA2B,GAAG,2BAA2B,CAAA;AACtE,MAAM,CAAC,IAAM,cAAc,GAAG,wBAAwB,CAAA;AAEtD,4FAA4F;AAC5F,MAAM,CAAC,IAAM,eAAe,GAA0B;IACpD,mBAAmB;IACnB,qBAAqB;IACrB,0BAA0B;IAC1B,cAAc;CACf,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,IAAM,yBAAyB,mCACjC,eAAe;IAClB,2BAA2B;SAC5B,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teleporthq/teleport-shared",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.69",
|
|
4
4
|
"description": "A utility belt for the entire teleportHQ ecosystem",
|
|
5
5
|
"author": "teleportHQ",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@babel/types": "^7.5.5",
|
|
28
|
-
"@teleporthq/teleport-types": "^0.43.
|
|
28
|
+
"@teleporthq/teleport-types": "^0.43.68",
|
|
29
29
|
"jss": "^10.0.0",
|
|
30
30
|
"jss-preset-default": "^10.0.0"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "ff9293d65ac3dd46ac196c5575c65d59e2006a28"
|
|
33
33
|
}
|
package/src/index.ts
CHANGED
|
@@ -15,12 +15,20 @@ import * as StorefrontTax from './utils/storefront-tax'
|
|
|
15
15
|
import * as ProductDiscounts from './utils/product-discounts'
|
|
16
16
|
import * as ProductRatings from './utils/product-ratings'
|
|
17
17
|
import * as RegionalPricing from './utils/regional-pricing'
|
|
18
|
+
import * as DiscountEngine from './utils/discount-engine'
|
|
19
|
+
import * as ProductOptions from './utils/product-options'
|
|
20
|
+
import * as CartLinePricing from './utils/cart-line-pricing'
|
|
21
|
+
import * as CartCurrency from './utils/cart-currency'
|
|
22
|
+
import * as TableAccess from './utils/table-access'
|
|
23
|
+
import * as SessionCookieResolver from './utils/session-cookie-resolver'
|
|
24
|
+
import * as SubscriptionAccess from './utils/subscription-access'
|
|
18
25
|
import * as FontPreconnect from './utils/font-preconnect'
|
|
19
26
|
import * as EmailDate from './utils/email-date'
|
|
20
27
|
import * as RichTextEmbeds from './utils/rich-text-embeds'
|
|
21
28
|
import * as RichTextEmbedsCodegen from './utils/rich-text-embeds-codegen'
|
|
22
29
|
import * as DataCache from './cache'
|
|
23
30
|
import * as PageRevalidate from './page-revalidate'
|
|
31
|
+
import * as WebPush from './utils/web-push'
|
|
24
32
|
|
|
25
33
|
export {
|
|
26
34
|
Constants,
|
|
@@ -40,10 +48,18 @@ export {
|
|
|
40
48
|
ProductDiscounts,
|
|
41
49
|
ProductRatings,
|
|
42
50
|
RegionalPricing,
|
|
51
|
+
DiscountEngine,
|
|
52
|
+
ProductOptions,
|
|
53
|
+
CartLinePricing,
|
|
54
|
+
CartCurrency,
|
|
55
|
+
TableAccess,
|
|
56
|
+
SessionCookieResolver,
|
|
57
|
+
SubscriptionAccess,
|
|
43
58
|
FontPreconnect,
|
|
44
59
|
EmailDate,
|
|
45
60
|
RichTextEmbeds,
|
|
46
61
|
RichTextEmbedsCodegen,
|
|
47
62
|
DataCache,
|
|
48
63
|
PageRevalidate,
|
|
64
|
+
WebPush,
|
|
49
65
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The currency a cart is priced in, as ES5 source for generated runtime code
|
|
3
|
+
* (the add-to-cart node, the storefront cart provider, the cart total and the
|
|
4
|
+
* checkout's server pricing step) that cannot import from this package.
|
|
5
|
+
*
|
|
6
|
+
* Every product carries its own currency, and nothing converts between them:
|
|
7
|
+
* an order is recorded and charged in ONE currency, so a cart holds products
|
|
8
|
+
* of one currency only — the same way it holds one kind of line (see the kind
|
|
9
|
+
* rule beside it in `cart-add-item`). The cart's currency is the currency of
|
|
10
|
+
* its lines; a line that names none (a cart saved before lines carried it)
|
|
11
|
+
* takes no part in the rule.
|
|
12
|
+
*
|
|
13
|
+
* ⚠️ PAIRED with teleport-gui's cart simulator
|
|
14
|
+
* (`features/e-commerce/utils/cart-kinds.ts`): the refusal reason and message
|
|
15
|
+
* must stay byte-identical to what the published store toasts.
|
|
16
|
+
*
|
|
17
|
+
* ⛔ Every helper takes ONE parameter. The block is appended to a serialized
|
|
18
|
+
* handler whose entry point a minified build finds by arity (a 2-param
|
|
19
|
+
* declaration wins — see `resolveHandlerEntryName`), so a 2-param helper would
|
|
20
|
+
* be called in place of the handler. Everything is prefixed `__cc` so the block
|
|
21
|
+
* can be concatenated into any generated module without colliding with its
|
|
22
|
+
* locals.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** The reason an add-to-cart refusal answers for a line of another currency. */
|
|
26
|
+
export const MIXED_CURRENCY_REASON = 'mixed-currency'
|
|
27
|
+
|
|
28
|
+
export const generateCartCurrencyHelperCode = (): string => `
|
|
29
|
+
// ── Cart currency ────────────────────────────────────────────────────────────
|
|
30
|
+
// A three-letter ISO code, upper-cased, or '' for anything else.
|
|
31
|
+
function __ccCode(value) {
|
|
32
|
+
var code = String(value == null ? '' : value).trim().toUpperCase();
|
|
33
|
+
return /^[A-Z]{3}$/.test(code) ? code : '';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// The currency of the cart: the first line that names one, or ''.
|
|
37
|
+
function __ccCartCurrency(lines) {
|
|
38
|
+
if (!lines || typeof lines.length !== 'number') { return ''; }
|
|
39
|
+
for (var i = 0; i < lines.length; i++) {
|
|
40
|
+
var code = __ccCode(lines[i] ? lines[i].currency : '');
|
|
41
|
+
if (code) { return code; }
|
|
42
|
+
}
|
|
43
|
+
return '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Every currency the lines name, in the order they first appear.
|
|
47
|
+
function __ccCurrencies(lines) {
|
|
48
|
+
var codes = [];
|
|
49
|
+
if (!lines || typeof lines.length !== 'number') { return codes; }
|
|
50
|
+
for (var i = 0; i < lines.length; i++) {
|
|
51
|
+
var code = __ccCode(lines[i] ? lines[i].currency : '');
|
|
52
|
+
if (code && codes.indexOf(code) === -1) { codes.push(code); }
|
|
53
|
+
}
|
|
54
|
+
return codes;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Why a line priced in \`input.currency\` cannot join \`input.lines\` (the OTHER
|
|
58
|
+
// lines of the cart), or null when it can.
|
|
59
|
+
function __ccCurrencyRefusal(input) {
|
|
60
|
+
var lineCurrency = __ccCode(input ? input.currency : '');
|
|
61
|
+
var cartCurrency = __ccCartCurrency(input ? input.lines : null);
|
|
62
|
+
if (!lineCurrency || !cartCurrency || lineCurrency === cartCurrency) { return null; }
|
|
63
|
+
return {
|
|
64
|
+
added: false,
|
|
65
|
+
reason: '${MIXED_CURRENCY_REASON}',
|
|
66
|
+
message: 'Products priced in ' + lineCurrency + ' need a separate order. Complete your current order or remove the items priced in ' + cartCurrency + ' from your cart first.'
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// What the checkout says when a cart still holds several currencies (a cart
|
|
71
|
+
// merged at sign-in, or a product whose currency changed after it was added).
|
|
72
|
+
function __ccMixedCartMessage(codes) {
|
|
73
|
+
var named = codes.length > 1 ? codes.slice(0, -1).join(', ') + ' and ' + codes[codes.length - 1] : codes.join('');
|
|
74
|
+
return 'Your cart holds products priced in ' + named + '. Each currency needs its own order: remove the products priced in one of them and try again.';
|
|
75
|
+
}
|
|
76
|
+
`
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What one cart line costs, read off its product (and variant) row, as ES5
|
|
3
|
+
* source for generated runtime code that cannot import from this package.
|
|
4
|
+
*
|
|
5
|
+
* TWO READERS, ONE RULE. The storefront provider re-prices every line with it
|
|
6
|
+
* when it hydrates the cart (`enrichCartItems` in the e-commerce context), and
|
|
7
|
+
* the checkout's server step prices the order with it (`cart-price-order` in
|
|
8
|
+
* the workflows plugin) — so what the buyer is shown and what the order is
|
|
9
|
+
* charged come from the same arithmetic over the same row. A price the
|
|
10
|
+
* browser holds is never an input: the line keeps only what the buyer chose
|
|
11
|
+
* (product, variant, options, quantity).
|
|
12
|
+
*
|
|
13
|
+
* The rule: the variant's price overrides the product's; the per-product
|
|
14
|
+
* markdown live at `nowMs` comes off that NET price; the chosen options'
|
|
15
|
+
* surcharge is added on top of the charged base (options are never marked
|
|
16
|
+
* down). A subscription is one unit.
|
|
17
|
+
*
|
|
18
|
+
* Needs, in the same scope: the per-product discount helpers (`__pd*`,
|
|
19
|
+
* `ProductDiscounts.generateProductDiscountHelperCode`), the product-option
|
|
20
|
+
* helpers (`__po*`, `ProductOptions.generateProductOptionsHelperCode`) and the
|
|
21
|
+
* discount engine's row readers (`__deStringArray`, `__deBool`,
|
|
22
|
+
* `DiscountEngine.generateDiscountEngineHelperCode`).
|
|
23
|
+
*/
|
|
24
|
+
export const generateCartLinePricingHelperCode = (): string => `
|
|
25
|
+
// ── Cart line pricing ────────────────────────────────────────────────────────
|
|
26
|
+
var __CL_BILLING_INTERVALS = ['day', 'week', 'month', 'year'];
|
|
27
|
+
|
|
28
|
+
function __clIsRecurring(product) {
|
|
29
|
+
return String((product && product.payment_type) || '').trim().toLowerCase() === 'recurring';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function __clBillingInterval(value) {
|
|
33
|
+
var normalized = String(value == null ? '' : value).trim().toLowerCase();
|
|
34
|
+
return __CL_BILLING_INTERVALS.indexOf(normalized) !== -1 ? normalized : 'month';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function __clBillingIntervalCount(value) {
|
|
38
|
+
var parsed = Math.floor(Number(value));
|
|
39
|
+
return isFinite(parsed) && parsed >= 1 ? parsed : 1;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function __clPositiveCount(value) {
|
|
43
|
+
if (value === null || value === undefined || value === '') { return null; }
|
|
44
|
+
var parsed = Math.floor(Number(value));
|
|
45
|
+
return isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// The chosen options re-priced from the product's CURRENT definitions on the
|
|
49
|
+
// charged base, and whether the answers still fit (\`configurationStale\`, which
|
|
50
|
+
// the checkout refuses). Null for a line with no answers of a product with no
|
|
51
|
+
// options, which is priced exactly as before; cleared fields for a line that
|
|
52
|
+
// carried options its product no longer has.
|
|
53
|
+
function __clPriceLineOptions(item, product, basePrice) {
|
|
54
|
+
var entries = __poParseEntries(item.configuration);
|
|
55
|
+
if (entries.length === 0 && __poParseGroups(product.option_groups).length === 0) {
|
|
56
|
+
if (item.basePrice == null && item.configurationLabel == null && item.configurationPriceDelta == null && item.configurationStale == null) { return null; }
|
|
57
|
+
return { basePrice: null, configurationLabel: null, configurationPriceDelta: null, configurationStale: null };
|
|
58
|
+
}
|
|
59
|
+
var resolved = __poResolveForRow(product, basePrice, entries);
|
|
60
|
+
return {
|
|
61
|
+
basePrice: basePrice,
|
|
62
|
+
configurationLabel: resolved.label,
|
|
63
|
+
configurationPriceDelta: resolved.delta,
|
|
64
|
+
configurationStale: !resolved.valid
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// "Red / XL" — the variant's value labels along the product's (language-
|
|
69
|
+
// resolved) option axes.
|
|
70
|
+
function __clVariantLabel(variantOptionsRaw, optionsMap) {
|
|
71
|
+
var axes = variantOptionsRaw;
|
|
72
|
+
if (typeof axes === 'string') { try { axes = JSON.parse(axes); } catch (e) { axes = []; } }
|
|
73
|
+
if (!Array.isArray(axes)) { return ''; }
|
|
74
|
+
var opts = optionsMap;
|
|
75
|
+
if (typeof opts === 'string') { try { opts = JSON.parse(opts); } catch (e) { opts = {}; } }
|
|
76
|
+
if (!opts) { opts = {}; }
|
|
77
|
+
var parts = [];
|
|
78
|
+
for (var a = 0; a < axes.length; a++) {
|
|
79
|
+
var axis = axes[a];
|
|
80
|
+
if (!axis || !axis.key) { continue; }
|
|
81
|
+
var valueKey = opts[axis.key];
|
|
82
|
+
if (valueKey == null) { continue; }
|
|
83
|
+
var label = valueKey;
|
|
84
|
+
var values = Array.isArray(axis.values) ? axis.values : [];
|
|
85
|
+
for (var v = 0; v < values.length; v++) { if (values[v] && values[v].value === valueKey) { label = values[v].label || valueKey; break; } }
|
|
86
|
+
parts.push(label);
|
|
87
|
+
}
|
|
88
|
+
return parts.join(' / ');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// The colour(s) of the variant's value on every COLOUR axis, for the swatch
|
|
92
|
+
// shown beside the label.
|
|
93
|
+
function __clVariantSwatches(variantOptionsRaw, optionsMap) {
|
|
94
|
+
var axes = variantOptionsRaw;
|
|
95
|
+
if (typeof axes === 'string') { try { axes = JSON.parse(axes); } catch (e) { axes = []; } }
|
|
96
|
+
if (!Array.isArray(axes)) { return []; }
|
|
97
|
+
var opts = optionsMap;
|
|
98
|
+
if (typeof opts === 'string') { try { opts = JSON.parse(opts); } catch (e) { opts = {}; } }
|
|
99
|
+
if (!opts) { opts = {}; }
|
|
100
|
+
var swatches = [];
|
|
101
|
+
for (var a = 0; a < axes.length; a++) {
|
|
102
|
+
var axis = axes[a];
|
|
103
|
+
if (!axis || !axis.key || axis.type !== 'color') { continue; }
|
|
104
|
+
var valueKey = opts[axis.key];
|
|
105
|
+
if (valueKey == null) { continue; }
|
|
106
|
+
var values = Array.isArray(axis.values) ? axis.values : [];
|
|
107
|
+
for (var v = 0; v < values.length; v++) { if (values[v] && values[v].value === valueKey && values[v].color) { swatches.push({ color: values[v].color }); break; } }
|
|
108
|
+
}
|
|
109
|
+
return swatches;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// The line's price and everything the totals read off its product, for the
|
|
113
|
+
// row as it is at \`nowMs\`. \`withWeight\` adds the weight the regional
|
|
114
|
+
// shipping rates price by.
|
|
115
|
+
function __clPriceLine(item, product, variant, nowMs, withWeight) {
|
|
116
|
+
var price = product.price != null ? Number(product.price) : 0;
|
|
117
|
+
if (variant && variant.price != null) { price = Number(variant.price); }
|
|
118
|
+
var discount = __pdResolveActive(product.discounts, nowMs);
|
|
119
|
+
var listPrice = price;
|
|
120
|
+
price = __pdDiscountedPrice(listPrice, discount);
|
|
121
|
+
var options = __clPriceLineOptions(item, product, price);
|
|
122
|
+
var optionsDelta = options ? options.configurationPriceDelta : null;
|
|
123
|
+
var recurring = __clIsRecurring(product);
|
|
124
|
+
var priced = {
|
|
125
|
+
price: optionsDelta != null ? __poRound2(price + optionsDelta) : price,
|
|
126
|
+
originalPrice: discount ? (optionsDelta != null ? __poRound2(listPrice + optionsDelta) : listPrice) : null,
|
|
127
|
+
discountType: discount ? discount.type : null,
|
|
128
|
+
discountValue: discount ? discount.value : null,
|
|
129
|
+
discountAmount: discount ? __pdDiscountAmount(listPrice, discount) : 0,
|
|
130
|
+
categoryIds: __deStringArray(product.category_filter_ids || product.category_ids),
|
|
131
|
+
isGiftCard: __deBool(product.is_gift_card, false),
|
|
132
|
+
isRecurring: recurring,
|
|
133
|
+
recurringInterval: recurring ? __clBillingInterval(product.recurring_interval) : null,
|
|
134
|
+
recurringIntervalCount: recurring ? __clBillingIntervalCount(product.recurring_interval_count) : null,
|
|
135
|
+
trialDays: recurring ? __clPositiveCount(product.trial_days) : null,
|
|
136
|
+
isDigital: __deBool(product.is_digital, false),
|
|
137
|
+
quantity: recurring ? 1 : item.quantity
|
|
138
|
+
};
|
|
139
|
+
if (withWeight) {
|
|
140
|
+
priced.weight = product.weight != null ? Number(product.weight) : null;
|
|
141
|
+
priced.weightUnit = product.weight_unit || null;
|
|
142
|
+
}
|
|
143
|
+
if (options) {
|
|
144
|
+
priced.basePrice = options.basePrice;
|
|
145
|
+
priced.configurationLabel = options.configurationLabel;
|
|
146
|
+
priced.configurationPriceDelta = options.configurationPriceDelta;
|
|
147
|
+
priced.configurationStale = options.configurationStale;
|
|
148
|
+
}
|
|
149
|
+
return priced;
|
|
150
|
+
}
|
|
151
|
+
`
|