UNPKG

8.68 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13Object.defineProperty(exports, "__esModule", { value: true });
14exports.buildMiddleware = void 0;
15var app_bridge_1 = require("@shopify/app-bridge");
16var validator_1 = require("@shopify/app-bridge/actions/validator");
17var Error_1 = require("@shopify/app-bridge/actions/Error");
18var collection_1 = require("@shopify/app-bridge/util/collection");
19var actions_1 = require("./actions");
20var clientValidator_1 = require("./clientValidator");
21var store_1 = require("./store");
22function buildMiddleware(key, dispatchClientEventHandler) {
23 var transports = [];
24 var transportListener = app_bridge_1.createTransportListener();
25 var subscribe = transportListener.createSubscribeHandler();
26 var store;
27 var actionsQueue;
28 var middleware = function (hostStore) {
29 store = hostStore;
30 actionsQueue = store_1.createActionsQueue(store);
31 return function (next) { return function (action) {
32 if (validator_1.isAppBridgeAction(action)) {
33 for (var _i = 0, transports_1 = transports; _i < transports_1.length; _i++) {
34 var transport = transports_1[_i];
35 var features = store.getState()[key].features[transport.context];
36 if (validator_1.isPermitted(features, action, app_bridge_1.PermissionType.Subscribe)) {
37 transport.dispatch({
38 payload: action,
39 type: 'dispatch',
40 });
41 }
42 }
43 }
44 if (actions_1.isLoadReducerCompleteAction(action)) {
45 actionsQueue.resolve(action.payload.feature);
46 }
47 return next(action);
48 }; };
49 };
50 middleware.load = function provideApplicationInterface(data) {
51 var config = data.config;
52 var clientHandlers = createClientHandlers();
53 store.dispatch(actions_1.apiClientLoad(config));
54 return {
55 attach: function (to) {
56 var _this = this;
57 var contextualClientHandlers = clientHandlers[to.context];
58 contextualClientHandlers.unsubscribe();
59 actionsQueue.clear(to.context);
60 var unsubscribe = to.subscribe(function (event) {
61 var context = to.context;
62 var message = event.data;
63 var type = message === null || message === void 0 ? void 0 : message.type;
64 var action = message === null || message === void 0 ? void 0 : message.payload;
65 var source = message === null || message === void 0 ? void 0 : message.source;
66 if (!clientValidator_1.isValidConfig(source, config)) {
67 clientValidator_1.throwInvalidConfigError(source, config, action);
68 }
69 if (to.frameWindow !== event.source) {
70 return;
71 }
72 transportListener.handleMessage(message);
73 switch (type) {
74 case 'dispatch':
75 var appState = _this.getState();
76 var features = appState.features[context];
77 if (!features || !validator_1.isPermitted(features, action, app_bridge_1.PermissionType.Dispatch)) {
78 store.dispatch(Error_1.permissionAction(action));
79 return;
80 }
81 transportListener.handleActionDispatch(action);
82 if (store_1.isReducerLoaded(appState, action)) {
83 store.dispatch(__assign(__assign({}, action), { source: source }));
84 }
85 else {
86 actionsQueue.add(to.context, action);
87 }
88 if (dispatchClientEventHandler) {
89 var appId = config.appId, shopId = config.shopId;
90 dispatchClientEventHandler({
91 action: action,
92 appId: appId,
93 shopId: shopId,
94 });
95 }
96 break;
97 case 'getState':
98 var defaultState = _this.getState();
99 var state = __assign(__assign({}, defaultState), { features: defaultState.features[context], context: context });
100 to.dispatch({
101 type: type,
102 payload: state,
103 });
104 break;
105 case 'subscribe':
106 contextualClientHandlers.subscribe(action);
107 break;
108 case 'unsubscribe':
109 contextualClientHandlers.unsubscribe(action);
110 break;
111 default:
112 Error_1.throwError(Error_1.Action.INVALID_ACTION, message, 'Unknown message type. Expected `dispatch` or `getState`.');
113 }
114 });
115 var detach = collection_1.addAndRemoveFromCollection(transports, to, unsubscribe);
116 return function (unload) {
117 if (unload === void 0) { unload = true; }
118 var origin = new URL(config.url).origin;
119 var removed = detach() && !transports.find(function (transport) { return transport.localOrigin === origin; });
120 contextualClientHandlers.unsubscribe();
121 if (removed) {
122 actionsQueue.clear(to.context);
123 }
124 if (removed && unload) {
125 store.dispatch(actions_1.apiClientUnload(config));
126 }
127 };
128 },
129 dispatch: function (action) {
130 store.dispatch(action);
131 },
132 getState: function () {
133 return store.getState()[key];
134 },
135 subscribe: subscribe,
136 isTransportSubscribed: function (context, type, id) {
137 return clientHandlers[context].isSubscribed(type, id);
138 },
139 };
140 };
141 return middleware;
142}
143exports.buildMiddleware = buildMiddleware;
144function createClientHandlers() {
145 var _a, _b;
146 var subscriptions = (_a = {}, _a[app_bridge_1.Context.Main] = {}, _a[app_bridge_1.Context.Modal] = {}, _a);
147 return _b = {},
148 _b[app_bridge_1.Context.Main] = createSubscriptionsHandler(subscriptions[app_bridge_1.Context.Main]),
149 _b[app_bridge_1.Context.Modal] = createSubscriptionsHandler(subscriptions[app_bridge_1.Context.Modal]),
150 _b;
151}
152function createSubscriptionsHandler(subscriptions) {
153 return {
154 isSubscribed: function (type, id) {
155 var contextSubscribers = subscriptions[type] || [];
156 var subscribers = contextSubscribers.filter(function (sub) { return sub.id === id; });
157 return subscribers.length > 0;
158 },
159 subscribe: function (payload) {
160 var type = payload.type;
161 if (!subscriptions[type]) {
162 subscriptions[type] = [];
163 }
164 var eventSubscriptions = subscriptions[type] || [];
165 collection_1.addAndRemoveFromCollection(eventSubscriptions, payload);
166 },
167 unsubscribe: function (payload) {
168 if (!payload) {
169 subscriptions = {};
170 return;
171 }
172 var type = payload.type, id = payload.id;
173 var eventSubscriptions = subscriptions[type];
174 if (!eventSubscriptions) {
175 return;
176 }
177 if (id) {
178 var index = eventSubscriptions.findIndex(function (sub) { return sub.id === id; });
179 if (index >= 0) {
180 return eventSubscriptions.splice(index);
181 }
182 }
183 eventSubscriptions.pop();
184 },
185 };
186}