cloudcommerce 0.0.53 → 0.0.56

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/package.json +6 -6
  3. package/packages/api/lib/index.js +14 -3
  4. package/packages/api/lib/index.js.map +1 -1
  5. package/packages/api/lib/types.d.ts +1 -1
  6. package/packages/api/package.json +1 -1
  7. package/packages/api/src/index.ts +14 -3
  8. package/packages/api/src/types.ts +1 -1
  9. package/packages/apps/discounts/lib/discounts.d.ts +1 -1
  10. package/packages/apps/discounts/lib/discounts.js +2 -3
  11. package/packages/apps/discounts/lib/discounts.js.map +1 -1
  12. package/packages/apps/discounts/lib-cjs/apply-discount.cjs +330 -0
  13. package/packages/apps/discounts/lib-cjs/helpers.cjs +167 -0
  14. package/packages/apps/discounts/package.json +2 -1
  15. package/packages/apps/discounts/src/discounts.ts +2 -3
  16. package/packages/apps/tiny-erp/CHANGELOG.md +1 -0
  17. package/packages/apps/tiny-erp/README.md +1 -0
  18. package/packages/apps/tiny-erp/package.json +27 -0
  19. package/packages/apps/tiny-erp/src/index.ts +0 -0
  20. package/packages/apps/tiny-erp/tsconfig.json +3 -0
  21. package/packages/cli/package.json +1 -1
  22. package/packages/events/package.json +1 -1
  23. package/packages/firebase/lib/config.d.ts +5 -0
  24. package/packages/firebase/lib/config.js +8 -0
  25. package/packages/firebase/lib/config.js.map +1 -1
  26. package/packages/firebase/lib/handlers/check-store-events.js +92 -15
  27. package/packages/firebase/lib/handlers/check-store-events.js.map +1 -1
  28. package/packages/firebase/package.json +1 -1
  29. package/packages/firebase/src/config.ts +9 -0
  30. package/packages/firebase/src/handlers/check-store-events.ts +98 -18
  31. package/packages/modules/lib/firebase/call-app-module.js +36 -2
  32. package/packages/modules/lib/firebase/call-app-module.js.map +1 -1
  33. package/packages/modules/lib/firebase/handle-module.js +6 -1
  34. package/packages/modules/lib/firebase/handle-module.js.map +1 -1
  35. package/packages/modules/package.json +1 -1
  36. package/packages/modules/src/firebase/call-app-module.ts +37 -3
  37. package/packages/modules/src/firebase/handle-module.ts +6 -1
  38. package/packages/passport/package.json +1 -1
  39. package/packages/ssr/package.json +1 -1
  40. package/packages/storefront/package.json +4 -4
  41. package/packages/types/index.ts +4 -1
  42. package/packages/types/package.json +1 -1
  43. package/packages/firebase/lib/types.d.ts +0 -6
  44. package/packages/firebase/lib/types.js +0 -2
  45. package/packages/firebase/lib/types.js.map +0 -1
  46. package/packages/firebase/src/types.ts +0 -11
@@ -0,0 +1,167 @@
1
+ const ecomUtils = require('@ecomplus/utils');
2
+
3
+ const validateDateRange = (rule) => {
4
+ // filter campaings by date
5
+ const timestamp = Date.now();
6
+ if (rule.date_range) {
7
+ if (rule.date_range.start && new Date(rule.date_range.start).getTime() > timestamp) {
8
+ return false;
9
+ }
10
+ if (rule.date_range.end && new Date(rule.date_range.end).getTime() < timestamp) {
11
+ return false;
12
+ }
13
+ }
14
+ return true;
15
+ };
16
+
17
+ const validateCustomerId = (rule, params) => {
18
+ if (
19
+ Array.isArray(rule.customer_ids)
20
+ && rule.customer_ids.length
21
+ && rule.customer_ids.indexOf(params.customer && params.customer._id) === -1
22
+ ) {
23
+ // unavailable for current customer
24
+ return false;
25
+ }
26
+ return true;
27
+ };
28
+
29
+ const checkOpenPromotion = (rule) => {
30
+ return !rule.discount_coupon && !rule.utm_campaign
31
+ && (!Array.isArray(rule.customer_ids) || !rule.customer_ids.length);
32
+ };
33
+
34
+ const getValidDiscountRules = (discountRules, params, items) => {
35
+ if (Array.isArray(discountRules) && discountRules.length) {
36
+ // validate rules objects
37
+ return discountRules.filter((rule) => {
38
+ if (!rule || !validateCustomerId(rule, params)) {
39
+ return false;
40
+ }
41
+
42
+ if (Array.isArray(rule.product_ids) && Array.isArray(items)) {
43
+ const checkProductId = (item) => {
44
+ return (!rule.product_ids.length || rule.product_ids.indexOf(item.product_id) > -1);
45
+ };
46
+ // set/add discount value from lowest item price
47
+ let value;
48
+ if (rule.discount_lowest_price) {
49
+ items.forEach((item) => {
50
+ const price = ecomUtils.price(item);
51
+ if (price > 0 && checkProductId(item) && (!value || value > price)) {
52
+ value = price;
53
+ }
54
+ });
55
+ } else if (rule.discount_kit_subtotal) {
56
+ value = 0;
57
+ items.forEach((item) => {
58
+ const price = ecomUtils.price(item);
59
+ if (price > 0 && checkProductId(item)) {
60
+ value += price * item.quantity;
61
+ }
62
+ });
63
+ }
64
+ if (value) {
65
+ if (rule.discount && rule.discount.value) {
66
+ if (rule.discount.type === 'percentage') {
67
+ value *= rule.discount.value / 100;
68
+ } else {
69
+ value += rule.discount.value;
70
+ }
71
+ }
72
+ rule.discount = {
73
+ ...rule.discount,
74
+ type: 'fixed',
75
+ value,
76
+ };
77
+ }
78
+ }
79
+ if (!rule.discount || !rule.discount.value) {
80
+ return false;
81
+ }
82
+
83
+ return validateDateRange(rule);
84
+ });
85
+ }
86
+
87
+ // returns array anyway
88
+ return [];
89
+ };
90
+
91
+ const matchDiscountRule = (discountRules, params) => {
92
+ // try to match a promotion
93
+ if (params.discount_coupon) {
94
+ // match only by discount coupon
95
+ return {
96
+ discountRule: discountRules.find((rule) => {
97
+ return rule.case_insensitive
98
+ ? typeof rule.discount_coupon === 'string'
99
+ && rule.discount_coupon.toUpperCase() === params.discount_coupon.toUpperCase()
100
+ : rule.discount_coupon === params.discount_coupon;
101
+ }),
102
+ discountMatchEnum: 'COUPON',
103
+ };
104
+ }
105
+
106
+ // try to match by UTM campaign first
107
+ if (params.utm && params.utm.campaign) {
108
+ const discountRule = discountRules.find((rule) => {
109
+ return rule.case_insensitive
110
+ ? typeof rule.utm_campaign === 'string'
111
+ && rule.utm_campaign.toUpperCase() === params.utm.campaign.toUpperCase()
112
+ : rule.utm_campaign === params.utm.campaign;
113
+ });
114
+ if (discountRule) {
115
+ return {
116
+ discountRule,
117
+ discountMatchEnum: 'UTM',
118
+ };
119
+ }
120
+ }
121
+
122
+ // then try to match by customer
123
+ if (params.customer && params.customer._id) {
124
+ const discountRule = discountRules.find((rule) => Array.isArray(rule.customer_ids)
125
+ && rule.customer_ids.indexOf(params.customer._id) > -1);
126
+ if (discountRule) {
127
+ return {
128
+ discountRule,
129
+ discountMatchEnum: 'CUSTOMER',
130
+ };
131
+ }
132
+ }
133
+
134
+ // last try to match by open promotions
135
+ return {
136
+ discountRule: discountRules.find(checkOpenPromotion),
137
+ discountMatchEnum: 'OPEN',
138
+ };
139
+ };
140
+
141
+ const checkCampaignProducts = (campaignProducts, params) => {
142
+ if (Array.isArray(campaignProducts) && campaignProducts.length) {
143
+ // must check at least one campaign product on cart
144
+ let hasProductMatch;
145
+ if (params.items && params.items.length) {
146
+ for (let i = 0; i < campaignProducts.length; i++) {
147
+ if (params.items.find((item) => item.quantity && item.product_id === campaignProducts[i])) {
148
+ hasProductMatch = true;
149
+ break;
150
+ }
151
+ }
152
+ }
153
+ if (!hasProductMatch) {
154
+ return false;
155
+ }
156
+ }
157
+ return true;
158
+ };
159
+
160
+ module.exports = {
161
+ validateDateRange,
162
+ validateCustomerId,
163
+ checkOpenPromotion,
164
+ getValidDiscountRules,
165
+ matchDiscountRule,
166
+ checkCampaignProducts,
167
+ };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/app-discounts",
3
3
  "type": "module",
4
- "version": "0.0.53",
4
+ "version": "0.0.56",
5
5
  "description": "E-Com Plus Cloud Commerce app for complex discount rules",
6
6
  "main": "lib/discounts.js",
7
7
  "repository": {
@@ -21,6 +21,7 @@
21
21
  "dependencies": {
22
22
  "@cloudcommerce/api": "workspace:*",
23
23
  "@cloudcommerce/firebase": "workspace:*",
24
+ "@ecomplus/utils": "^1.4.1",
24
25
  "firebase-admin": "^11.0.1",
25
26
  "firebase-functions": "^3.22.0"
26
27
  },
@@ -1,8 +1,7 @@
1
1
  /* eslint-disable import/prefer-default-export */
2
2
  import type { AppModuleBody } from '@cloudcommerce/types';
3
- import { logger } from 'firebase-functions';
3
+ import * as handleApplyDiscount from '../lib-cjs/apply-discount.cjs';
4
4
 
5
5
  export const applyDiscount = async (modBody: AppModuleBody) => {
6
- logger.info(modBody);
7
- return {};
6
+ return handleApplyDiscount(modBody);
8
7
  };
@@ -0,0 +1 @@
1
+ Please refer to GitHub [repository releases](https://github.com/ecomplus/cloud-commerce/releases) or monorepo unified [CHANGELOG.md](https://github.com/ecomplus/cloud-commerce/blob/main/CHANGELOG.md).
@@ -0,0 +1 @@
1
+ # `@cloudcommerce/tiny`
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@cloudcommerce/app-tiny-erp",
3
+ "type": "module",
4
+ "version": "0.0.56",
5
+ "description": "E-Com Plus Cloud Commerce",
6
+ "main": "lib/index.js",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ecomplus/cloud-commerce.git",
10
+ "directory": "packages/tiny"
11
+ },
12
+ "author": "E-Com Club Softwares para E-commerce <ti@e-com.club>",
13
+ "license": "Apache 2.0 with Commons Clause",
14
+ "bugs": {
15
+ "url": "https://github.com/ecomplus/cloud-commerce/issues"
16
+ },
17
+ "homepage": "https://github.com/ecomplus/cloud-commerce/tree/main/packages/tiny#readme",
18
+ "scripts": {
19
+ "build": "echo '@ecomplus/tiny-erp'"
20
+ },
21
+ "dependencies": {
22
+ "@cloudcommerce/api": "workspace:*"
23
+ },
24
+ "devDependencies": {
25
+ "@cloudcommerce/types": "workspace:*"
26
+ }
27
+ }
File without changes
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "../../tsconfig.json"
3
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/cli",
3
3
  "type": "module",
4
- "version": "0.0.53",
4
+ "version": "0.0.56",
5
5
  "description": "E-Com Plus Cloud Commerce CLI tools",
6
6
  "bin": {
7
7
  "cloudcommerce": "./bin/run.mjs"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/events",
3
3
  "type": "module",
4
- "version": "0.0.53",
4
+ "version": "0.0.56",
5
5
  "description": "E-Com Plus Cloud Commerce app events",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -1,3 +1,4 @@
1
+ import type { AppEventsTopic } from '@cloudcommerce/types';
1
2
  declare const _default: {
2
3
  get(): {
3
4
  hello: string;
@@ -13,6 +14,10 @@ declare const _default: {
13
14
  discounts: {
14
15
  appId: number;
15
16
  };
17
+ tinyErp: {
18
+ appId: number;
19
+ events: AppEventsTopic[];
20
+ };
16
21
  };
17
22
  };
18
23
  set(config: any): void;
@@ -23,6 +23,14 @@ const self = {
23
23
  discounts: {
24
24
  appId: 1252,
25
25
  },
26
+ tinyErp: {
27
+ appId: 105922,
28
+ events: [
29
+ 'orders-anyStatusSet',
30
+ 'products-new',
31
+ 'products-priceSet',
32
+ ],
33
+ },
26
34
  },
27
35
  },
28
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,aAAa;AACb,MAAM,GAAG,GAA8B,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,EAAE,GAAG,CAAC;OAC/E,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC;OACtC,EAAE,CAAC;AAER,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;AAE9B,MAAM,IAAI,GAAG;IACX,QAAQ,EAAE;QACR,KAAK,EAAE,8BAA8B;QACrC,IAAI,EAAE,GAAG,CAAC,SAAS,IAAI,YAAY;QACnC,QAAQ,EAAE,GAAG,CAAC,aAAa,IAAI,gBAAgB;QAC/C,cAAc,EAAE,GAAG,CAAC,oBAAoB,IAAI,uBAAuB;QACnE,WAAW,EAAE,GAAG,CAAC,iBAAiB,IAAI,oBAAoB;QAC1D,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QAClC,oBAAoB,EAAE;YACpB,MAAM,EAAE,GAAG,CAAC,aAAa,IAAI,aAAa;SAC3C;QACD,IAAI,EAAE;YACJ,SAAS,EAAE;gBACT,KAAK,EAAE,IAAI;aACZ;SACF;KACF;CACF,CAAC;AAEF,eAAe;IACb,GAAG;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IACD,GAAG,CAAC,MAAM;QACR,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,OAAO,EAAE;YAClB,GAAG,CAAC,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;SACpC;IACH,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,aAAa;AACb,MAAM,GAAG,GAA8B,CAAC,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,EAAE,GAAG,CAAC;OAC/E,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC;OACtC,EAAE,CAAC;AAER,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;AAE9B,MAAM,IAAI,GAAG;IACX,QAAQ,EAAE;QACR,KAAK,EAAE,8BAA8B;QACrC,IAAI,EAAE,GAAG,CAAC,SAAS,IAAI,YAAY;QACnC,QAAQ,EAAE,GAAG,CAAC,aAAa,IAAI,gBAAgB;QAC/C,cAAc,EAAE,GAAG,CAAC,oBAAoB,IAAI,uBAAuB;QACnE,WAAW,EAAE,GAAG,CAAC,iBAAiB,IAAI,oBAAoB;QAC1D,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QAClC,oBAAoB,EAAE;YACpB,MAAM,EAAE,GAAG,CAAC,aAAa,IAAI,aAAa;SAC3C;QACD,IAAI,EAAE;YACJ,SAAS,EAAE;gBACT,KAAK,EAAE,IAAI;aACZ;YACD,OAAO,EAAE;gBACP,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE;oBACN,qBAAqB;oBACrB,cAAc;oBACd,mBAAmB;iBACA;aACtB;SACF;KACF;CACF,CAAC;AAEF,eAAe;IACb,GAAG;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IACD,GAAG,CAAC,MAAM;QACR,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,OAAO,EAAE;YAClB,GAAG,CAAC,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC;SACpC;IACH,CAAC;CACF,CAAC"}
@@ -1,28 +1,105 @@
1
- // eslint-disable-next-line import/no-unresolved
2
- import { getFirestore } from 'firebase-admin/firestore';
3
1
  import logger from 'firebase-functions/lib/logger';
4
2
  import api from '@cloudcommerce/api';
5
3
  import getEnv from '../env.js';
4
+ import config from '../config.js';
5
+
6
+ const parseEventsTopic = (eventsTopic) => {
7
+ const [resource, eventName] = eventsTopic.split('-');
8
+ const params = {};
9
+ const bodySet = {};
10
+ if (eventName === 'new') {
11
+ params.action = 'create';
12
+ } else {
13
+ switch (resource) {
14
+ case 'orders':
15
+ switch (eventName) {
16
+ case 'paid':
17
+ bodySet['financial_status.current'] = 'paid';
18
+ break;
19
+ case 'readyForShipping':
20
+ bodySet['fulfillment_status.current'] = 'ready_for_shipping';
21
+ break;
22
+ case 'shipped':
23
+ case 'delivered':
24
+ bodySet['fulfillment_status.current'] = eventName;
25
+ break;
26
+ case 'cancelled':
27
+ bodySet.status = 'cancelled';
28
+ break;
29
+ default: // anyStatusSet
30
+ params.modified_fields = [
31
+ 'financial_status',
32
+ 'fulfillment_status',
33
+ 'status',
34
+ ];
35
+ }
36
+ break;
37
+ case 'products':
38
+ params.modified_fields = eventName === 'priceSet'
39
+ ? ['price', 'variations.price']
40
+ : ['quantity']; // quantitySet
41
+ break;
42
+ case 'carts':
43
+ params.modified_fields = ['customers']; // customerSet
44
+ break;
45
+ default:
46
+ }
47
+ }
48
+ Object.keys(bodySet).forEach((field) => {
49
+ params[`body.${field}`] = bodySet[field];
50
+ });
51
+ return { resource, params };
52
+ };
6
53
 
7
54
  export default async () => {
55
+ const { apps } = config.get();
8
56
  const { apiAuth } = getEnv();
9
- const eventsSubs = await getFirestore().collection('eventsSubs').get();
57
+ const subscribersApps = [];
58
+ Object.keys(apps).forEach((appName) => {
59
+ const appObj = apps[appName];
60
+ if (appObj.events && appObj.events.length) {
61
+ subscribersApps.push(appObj);
62
+ }
63
+ });
64
+ const activeSubscribersApps = (await api.get('applications', {
65
+ params: {
66
+ state: 'active',
67
+ app_id: subscribersApps.map(({ appId }) => appId),
68
+ fields: 'app_id',
69
+ },
70
+ })).data.result;
71
+ logger.info({ activeSubscribersApps });
10
72
  const listenedEvents = [];
11
- eventsSubs.forEach((doc) => {
12
- const eventSub = doc.data();
13
- if (!listenedEvents.includes(eventSub.event)) {
14
- listenedEvents.push(eventSub.event);
73
+ subscribersApps.forEach(({ appId, events }) => {
74
+ if (activeSubscribersApps.find((app) => app.app_id === appId)) {
75
+ events.forEach((eventsTopic) => {
76
+ listenedEvents.push(eventsTopic);
77
+ });
15
78
  }
16
79
  });
17
80
  logger.info({ listenedEvents });
18
- [
19
- 'orders',
20
- 'products',
21
- 'carts',
22
- ].forEach(async (resource) => {
23
- const { data: { result } } = await api
24
- .get(`events/${resource}`, apiAuth);
25
- logger.info(`${resource} events: `, result);
81
+ listenedEvents.forEach(async (eventsTopic) => {
82
+ const { resource, params } = parseEventsTopic(eventsTopic);
83
+ let { data: { result } } = await api.get(`events/${resource}`, {
84
+ ...apiAuth,
85
+ params,
86
+ });
87
+ /*
88
+ global.api_events_middleware = async (
89
+ resource: string,
90
+ result: EventsResult,
91
+ }) => {
92
+ if (resource === 'orders') {
93
+ await axios.port(url, result);
94
+ }
95
+ return result;
96
+ };
97
+ */
98
+ const middleware = global.api_events_middleware;
99
+ if (typeof middleware === 'function') {
100
+ result = await middleware(resource, result);
101
+ }
102
+ logger.info(`> '${eventsTopic}' events: `, result);
26
103
  });
27
104
  return true;
28
105
  };
@@ -1 +1 @@
1
- {"version":3,"file":"check-store-events.js","sourceRoot":"","sources":["../../src/handlers/check-store-events.ts"],"names":[],"mappings":"AACA,gDAAgD;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,MAAM,MAAM,+BAA+B,CAAC;AACnD,OAAO,GAAG,MAAM,oBAAoB,CAAC;AACrC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,eAAe,KAAK,IAAI,EAAE;IACxB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAG,MAAM,YAAY,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,CAAC;IACvE,MAAM,cAAc,GAAwB,EAAE,CAAC;IAC/C,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QACzB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAc,CAAC;QACxC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE;YAC5C,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SACrC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;IAChC;QACE,QAAQ;QACR,UAAU;QACV,OAAO;KACR,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;QAC3B,MAAM,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,GAAG;aACnC,GAAG,CAAC,UAAU,QAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,WAAW,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
1
+ {"version":3,"file":"check-store-events.js","sourceRoot":"","sources":["../../src/handlers/check-store-events.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/firebase",
3
3
  "type": "module",
4
- "version": "0.0.53",
4
+ "version": "0.0.56",
5
5
  "description": "E-Com Plus Cloud Commerce on Firebase",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -1,3 +1,4 @@
1
+ import type { AppEventsTopic } from '@cloudcommerce/types';
1
2
  import Deepmerge from '@fastify/deepmerge';
2
3
  import {
3
4
  DEFAULT_LANG,
@@ -28,6 +29,14 @@ const self = {
28
29
  discounts: {
29
30
  appId: 1252,
30
31
  },
32
+ tinyErp: {
33
+ appId: 105922,
34
+ events: [
35
+ 'orders-anyStatusSet',
36
+ 'products-new',
37
+ 'products-priceSet',
38
+ ] as AppEventsTopic[],
39
+ },
31
40
  },
32
41
  },
33
42
  };
@@ -1,29 +1,109 @@
1
- import type { EventSub } from '../types';
2
- // eslint-disable-next-line import/no-unresolved
3
- import { getFirestore } from 'firebase-admin/firestore';
1
+ import type { Resource, AppEventsTopic } from '@cloudcommerce/types';
4
2
  import logger from 'firebase-functions/lib/logger';
5
- import api from '@cloudcommerce/api';
3
+ import api, { ApiConfig } from '@cloudcommerce/api';
6
4
  import getEnv from '../env';
5
+ import config from '../config';
6
+
7
+ const parseEventsTopic = (eventsTopic: AppEventsTopic) => {
8
+ const [resource, eventName] = eventsTopic.split('-');
9
+ const params: ApiConfig['params'] = {};
10
+ const bodySet: { [key: string]: any } = {};
11
+ if (eventName === 'new') {
12
+ params.action = 'create';
13
+ } else {
14
+ switch (resource) {
15
+ case 'orders':
16
+ switch (eventName) {
17
+ case 'paid':
18
+ bodySet['financial_status.current'] = 'paid';
19
+ break;
20
+ case 'readyForShipping':
21
+ bodySet['fulfillment_status.current'] = 'ready_for_shipping';
22
+ break;
23
+ case 'shipped':
24
+ case 'delivered':
25
+ bodySet['fulfillment_status.current'] = eventName;
26
+ break;
27
+ case 'cancelled':
28
+ bodySet.status = 'cancelled';
29
+ break;
30
+ default: // anyStatusSet
31
+ params.modified_fields = [
32
+ 'financial_status',
33
+ 'fulfillment_status',
34
+ 'status',
35
+ ];
36
+ }
37
+ break;
38
+ case 'products':
39
+ params.modified_fields = eventName === 'priceSet'
40
+ ? ['price', 'variations.price']
41
+ : ['quantity']; // quantitySet
42
+ break;
43
+ case 'carts':
44
+ params.modified_fields = ['customers']; // customerSet
45
+ break;
46
+ default:
47
+ }
48
+ }
49
+ Object.keys(bodySet).forEach((field) => {
50
+ params[`body.${field}`] = bodySet[field];
51
+ });
52
+ return { resource, params } as {
53
+ resource: Resource;
54
+ params: ApiConfig['params'];
55
+ };
56
+ };
7
57
 
8
58
  export default async () => {
59
+ const { apps } = config.get();
9
60
  const { apiAuth } = getEnv();
10
- const eventsSubs = await getFirestore().collection('eventsSubs').get();
11
- const listenedEvents: EventSub['event'][] = [];
12
- eventsSubs.forEach((doc) => {
13
- const eventSub = doc.data() as EventSub;
14
- if (!listenedEvents.includes(eventSub.event)) {
15
- listenedEvents.push(eventSub.event);
61
+ const subscribersApps: Array<{ appId: number, events: AppEventsTopic[] }> = [];
62
+ Object.keys(apps).forEach((appName) => {
63
+ const appObj = apps[appName];
64
+ if (appObj.events && appObj.events.length) {
65
+ subscribersApps.push(appObj);
66
+ }
67
+ });
68
+ const activeSubscribersApps = (await api.get('applications', {
69
+ params: {
70
+ state: 'active',
71
+ app_id: subscribersApps.map(({ appId }) => appId),
72
+ fields: 'app_id',
73
+ },
74
+ })).data.result;
75
+ logger.info({ activeSubscribersApps });
76
+ const listenedEvents: AppEventsTopic[] = [];
77
+ subscribersApps.forEach(({ appId, events }) => {
78
+ if (activeSubscribersApps.find((app) => app.app_id === appId)) {
79
+ events.forEach((eventsTopic) => {
80
+ listenedEvents.push(eventsTopic);
81
+ });
16
82
  }
17
83
  });
18
84
  logger.info({ listenedEvents });
19
- [
20
- 'orders',
21
- 'products',
22
- 'carts',
23
- ].forEach(async (resource) => {
24
- const { data: { result } } = await api
25
- .get(`events/${resource as 'orders'}`, apiAuth);
26
- logger.info(`${resource} events: `, result);
85
+ listenedEvents.forEach(async (eventsTopic) => {
86
+ const { resource, params } = parseEventsTopic(eventsTopic);
87
+ let { data: { result } } = await api.get(`events/${resource}`, {
88
+ ...apiAuth,
89
+ params,
90
+ });
91
+ /*
92
+ global.api_events_middleware = async (
93
+ resource: string,
94
+ result: EventsResult,
95
+ }) => {
96
+ if (resource === 'orders') {
97
+ await axios.port(url, result);
98
+ }
99
+ return result;
100
+ };
101
+ */
102
+ const middleware = global.api_events_middleware;
103
+ if (typeof middleware === 'function') {
104
+ result = await middleware(resource, result);
105
+ }
106
+ logger.info(`> '${eventsTopic}' events: `, result);
27
107
  });
28
108
  return true;
29
109
  };
@@ -37,10 +37,44 @@ export default async (appId, modName, url, data, isBigTimeout) => {
37
37
  }
38
38
  }
39
39
  };
40
+ // eslint-disable-next-line no-unused-vars
41
+ let internalModuleFn;
40
42
  if (modName === 'apply_discount') {
41
43
  if (appId === apps.discounts.appId) {
42
- return import('@cloudcommerce/app-discounts')
43
- .then(({ applyDiscount }) => applyDiscount(data));
44
+ internalModuleFn = async (_data = data) => {
45
+ return import('@cloudcommerce/app-discounts')
46
+ .then(({ applyDiscount }) => applyDiscount(_data));
47
+ };
48
+ }
49
+ }
50
+ if (internalModuleFn) {
51
+ /*
52
+ global.app1_apply_discount_middleware = async (
53
+ data: any,
54
+ next: () => Promise<any>,
55
+ ) => {
56
+ if (data.params.x === 'sample') {
57
+ return {};
58
+ }
59
+ return next(data);
60
+ };
61
+ */
62
+ const middleware = global[`app${appId}_${modName}_middleware`];
63
+ try {
64
+ if (typeof middleware === 'function') {
65
+ return await middleware(data, internalModuleFn);
66
+ }
67
+ return await internalModuleFn(data);
68
+ } catch (err) {
69
+ logger.error(err);
70
+ let message = 'Failed to execute module function';
71
+ if (typeof middleware === 'function') {
72
+ message += ' (has middleware)';
73
+ }
74
+ return {
75
+ error: 'INTERNAL_MODULE_ERROR',
76
+ message,
77
+ };
44
78
  }
45
79
  }
46
80
  return axios({
@@ -1 +1 @@
1
- {"version":3,"file":"call-app-module.js","sourceRoot":"","sources":["../../src/firebase/call-app-module.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"call-app-module.js","sourceRoot":"","sources":["../../src/firebase/call-app-module.ts"],"names":[],"mappings":"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"}