payment-kit 1.13.207 → 1.13.209

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.
@@ -1,3 +1,4 @@
1
+ import Joi from 'joi';
1
2
  import { Op } from 'sequelize';
2
3
  import SqlWhereParser from 'sql-where-parser';
3
4
 
@@ -101,3 +102,37 @@ export const getWhereFromKvQuery = (query?: string) => {
101
102
  }
102
103
  return out;
103
104
  };
105
+
106
+ export function createListParamSchema<T>(schema: any) {
107
+ return Joi.object<T & { page: number; pageSize: number; livemode?: boolean; q?: string; o?: string }>({
108
+ // prettier-ignore
109
+ page: Joi.number()
110
+ .integer()
111
+ .default(1)
112
+ .custom((value) => {
113
+ if (value < 1) {
114
+ return 1;
115
+ }
116
+ return value;
117
+ }, 'page should be valid'),
118
+
119
+ pageSize: Joi.number()
120
+ .integer()
121
+ .default(20)
122
+ .custom((value) => {
123
+ if (value > 100) {
124
+ return 100;
125
+ }
126
+ if (value < 1) {
127
+ return 1;
128
+ }
129
+ return value;
130
+ }, 'pageSize should be valid'),
131
+
132
+ livemode: Joi.boolean().empty(''),
133
+ q: Joi.string().empty(''), // query
134
+ o: Joi.string().empty(''), // order
135
+
136
+ ...schema,
137
+ });
138
+ }
@@ -4,7 +4,7 @@ import Joi from 'joi';
4
4
  import pick from 'lodash/pick';
5
5
 
6
6
  import { getStakeSummaryByDid, getTokenSummaryByDid } from '../integrations/blockchain/stake';
7
- import { getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
7
+ import { createListParamSchema, getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
8
8
  import { authenticate } from '../libs/security';
9
9
  import { formatMetadata } from '../libs/util';
10
10
  import { Customer } from '../store/models/customer';
@@ -21,21 +21,7 @@ const authPortal = authenticate<Customer>({
21
21
  },
22
22
  });
23
23
 
24
- const schema = Joi.object<{
25
- page: number;
26
- pageSize: number;
27
- did?: string;
28
- livemode?: boolean;
29
- q?: string;
30
- o?: string;
31
- }>({
32
- page: Joi.number().integer().min(1).default(1),
33
- pageSize: Joi.number().integer().min(1).max(100).default(20),
34
- did: Joi.string().empty(''),
35
- livemode: Joi.boolean().empty(''),
36
- q: Joi.string().empty(''), // query
37
- o: Joi.string().empty(''), // order
38
- });
24
+ const schema = createListParamSchema<{ did?: string }>({ did: Joi.string().empty('') });
39
25
  router.get('/', auth, async (req, res) => {
40
26
  const { page, pageSize, ...query } = await schema.validateAsync(req.query, { stripUnknown: true });
41
27
  const where = getWhereFromKvQuery(query.q);
@@ -56,28 +42,18 @@ router.get('/', auth, async (req, res) => {
56
42
  include: [],
57
43
  });
58
44
 
59
- res.json({ count, list });
45
+ res.json({ count, list, paging: { page, pageSize } });
60
46
  } catch (err) {
61
47
  console.error(err);
62
- res.json({ count: 0, list: [] });
48
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
63
49
  }
64
50
  });
65
51
 
66
52
  // search customers
67
- const searchSchema = Joi.object<{
68
- page: number;
69
- pageSize: number;
53
+ const searchSchema = createListParamSchema<{
70
54
  query: string;
71
- livemode?: boolean;
72
- q?: string;
73
- o?: string;
74
55
  }>({
75
- page: Joi.number().integer().min(1).default(1),
76
- pageSize: Joi.number().integer().min(1).max(100).default(20),
77
56
  query: Joi.string(),
78
- livemode: Joi.boolean().empty(''),
79
- q: Joi.string().empty(''), // query
80
- o: Joi.string().empty(''), // order
81
57
  });
82
58
  router.get('/search', auth, async (req, res) => {
83
59
  const { page, pageSize, query, livemode, q, o } = await searchSchema.validateAsync(req.query, {
@@ -97,7 +73,7 @@ router.get('/search', auth, async (req, res) => {
97
73
  include: [],
98
74
  });
99
75
 
100
- res.json({ count, list });
76
+ res.json({ count, list, paging: { page, pageSize } });
101
77
  });
102
78
 
103
79
  // eslint-disable-next-line consistent-return
@@ -2,22 +2,17 @@ import { Router } from 'express';
2
2
  import Joi from 'joi';
3
3
  import type { WhereOptions } from 'sequelize';
4
4
 
5
+ import { createListParamSchema } from '../libs/api';
5
6
  import { authenticate } from '../libs/security';
6
7
  import { Event } from '../store/models/event';
7
8
 
8
9
  const router = Router();
9
10
  const auth = authenticate<Event>({ component: true, roles: ['owner', 'admin'] });
10
11
 
11
- const schema = Joi.object<{
12
- page: number;
13
- pageSize: number;
14
- livemode?: boolean;
12
+ const schema = createListParamSchema<{
15
13
  type?: string;
16
14
  object_id?: string;
17
15
  }>({
18
- page: Joi.number().integer().min(1).default(1),
19
- pageSize: Joi.number().integer().min(1).max(100).default(20),
20
- livemode: Joi.boolean().empty(''),
21
16
  type: Joi.string().empty(''),
22
17
  object_id: Joi.string().empty(''),
23
18
  });
@@ -51,10 +46,10 @@ router.get('/', auth, async (req, res) => {
51
46
  include: [],
52
47
  });
53
48
 
54
- res.json({ count, list });
49
+ res.json({ count, list, paging: { page, pageSize } });
55
50
  } catch (err) {
56
51
  console.error(err);
57
- res.json({ count: 0, list: [] });
52
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
58
53
  }
59
54
  });
60
55
 
@@ -6,7 +6,7 @@ import { Op } from 'sequelize';
6
6
 
7
7
  import { syncStripeInvoice } from '../integrations/stripe/handlers/invoice';
8
8
  import { syncStripePayment } from '../integrations/stripe/handlers/payment-intent';
9
- import { getWhereFromKvQuery } from '../libs/api';
9
+ import { createListParamSchema, getWhereFromKvQuery } from '../libs/api';
10
10
  import { authenticate } from '../libs/security';
11
11
  import { expandLineItems } from '../libs/session';
12
12
  import { formatMetadata } from '../libs/util';
@@ -33,30 +33,20 @@ const authPortal = authenticate<Invoice>({
33
33
  },
34
34
  });
35
35
 
36
- const schema = Joi.object<{
37
- page: number;
38
- pageSize: number;
39
- livemode?: boolean;
36
+ const schema = createListParamSchema<{
40
37
  status?: string;
41
38
  customer_id?: string;
42
39
  customer_did?: string;
43
40
  subscription_id?: string;
44
41
  currency_id?: string;
45
42
  ignoreZero?: boolean;
46
- q?: string;
47
- o?: string;
48
43
  }>({
49
- page: Joi.number().integer().min(1).default(1),
50
- pageSize: Joi.number().integer().min(1).max(100).default(20),
51
- livemode: Joi.boolean().empty(''),
52
44
  status: Joi.string().empty(''),
53
45
  customer_id: Joi.string().empty(''),
54
46
  customer_did: Joi.string().empty(''),
55
47
  subscription_id: Joi.string().empty(''),
56
48
  currency_id: Joi.string().empty(''),
57
49
  ignoreZero: Joi.boolean().empty(false),
58
- q: Joi.string().empty(''), // query
59
- o: Joi.string().empty(''), // order
60
50
  });
61
51
  router.get('/', authMine, async (req, res) => {
62
52
  const { page, pageSize, livemode, status, ignoreZero, ...query } = await schema.validateAsync(req.query, {
@@ -85,7 +75,7 @@ router.get('/', authMine, async (req, res) => {
85
75
  if (customer) {
86
76
  where.customer_id = customer.id;
87
77
  } else {
88
- res.json({ count: 0, list: [] });
78
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
89
79
  return;
90
80
  }
91
81
  }
@@ -174,26 +164,14 @@ router.get('/', authMine, async (req, res) => {
174
164
  }
175
165
  }
176
166
 
177
- res.json({ count, list, subscription });
167
+ res.json({ count, list, subscription, paging: { page, pageSize } });
178
168
  } catch (err) {
179
169
  console.error(err);
180
- res.json({ count: 0, list: [] });
170
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
181
171
  }
182
172
  });
183
173
 
184
- const searchSchema = Joi.object<{
185
- page: number;
186
- pageSize: number;
187
- livemode?: boolean;
188
- q: string;
189
- o?: string;
190
- }>({
191
- page: Joi.number().integer().min(1).default(1),
192
- pageSize: Joi.number().integer().min(1).max(100).default(20),
193
- livemode: Joi.boolean().empty(''),
194
- q: Joi.string().empty(''), // query
195
- o: Joi.string().empty(''), // order
196
- });
174
+ const searchSchema = createListParamSchema<{}>({});
197
175
  router.get('/search', authMine, async (req, res) => {
198
176
  const { page, pageSize, livemode, q, o } = await searchSchema.validateAsync(req.query, {
199
177
  stripUnknown: false,
@@ -217,7 +195,7 @@ router.get('/search', authMine, async (req, res) => {
217
195
  ],
218
196
  });
219
197
 
220
- res.json({ count, list });
198
+ res.json({ count, list, paging: { page, pageSize } });
221
199
  });
222
200
 
223
201
  router.get('/:id', authPortal, async (req, res) => {
@@ -5,7 +5,7 @@ import pick from 'lodash/pick';
5
5
 
6
6
  import { syncStripeInvoice } from '../integrations/stripe/handlers/invoice';
7
7
  import { syncStripePayment } from '../integrations/stripe/handlers/payment-intent';
8
- import { getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
8
+ import { createListParamSchema, getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
9
9
  import { authenticate } from '../libs/security';
10
10
  import { formatMetadata } from '../libs/util';
11
11
  import { CheckoutSession } from '../store/models/checkout-session';
@@ -30,28 +30,18 @@ const authPortal = authenticate<PaymentIntent>({
30
30
  });
31
31
 
32
32
  // list payment intents
33
- const paginationSchema = Joi.object<{
34
- page: number;
35
- pageSize: number;
33
+ const paginationSchema = createListParamSchema<{
36
34
  status?: string;
37
- livemode?: boolean;
38
35
  invoice_id?: string;
39
36
  customer_id?: string;
40
37
  customer_did?: string;
41
38
  currency_id?: string;
42
- q?: string;
43
- o?: string;
44
39
  }>({
45
- page: Joi.number().integer().min(1).default(1),
46
- pageSize: Joi.number().integer().min(1).max(100).default(20),
47
40
  status: Joi.string().empty(''),
48
- livemode: Joi.boolean().empty(''),
49
41
  invoice_id: Joi.string().empty(''),
50
42
  customer_id: Joi.string().empty(''),
51
43
  customer_did: Joi.string().empty(''),
52
44
  currency_id: Joi.string().empty(''),
53
- q: Joi.string().empty(''), // query
54
- o: Joi.string().empty(''), // order
55
45
  });
56
46
  router.get('/', authMine, async (req, res) => {
57
47
  const { page, pageSize, status, livemode, ...query } = await paginationSchema.validateAsync(req.query, {
@@ -110,28 +100,18 @@ router.get('/', authMine, async (req, res) => {
110
100
  ],
111
101
  });
112
102
 
113
- res.json({ count, list });
103
+ res.json({ count, list, paging: { page, pageSize } });
114
104
  } catch (err) {
115
105
  console.error(err);
116
- res.json({ count: 0, list: [] });
106
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
117
107
  }
118
108
  });
119
109
 
120
110
  // search payment intents
121
- const searchSchema = Joi.object<{
122
- page: number;
123
- pageSize: number;
111
+ const searchSchema = createListParamSchema<{
124
112
  query: string;
125
- livemode?: boolean;
126
- q?: string;
127
- o?: string;
128
113
  }>({
129
- page: Joi.number().integer().min(1).default(1),
130
- pageSize: Joi.number().integer().min(1).max(100).default(20),
131
114
  query: Joi.string(),
132
- livemode: Joi.boolean().empty(''),
133
- q: Joi.string().empty(''), // query
134
- o: Joi.string().empty(''), // order
135
115
  });
136
116
  router.get('/search', authMine, async (req, res) => {
137
117
  const { page, pageSize, query, livemode, q, o } = await searchSchema.validateAsync(req.query, {
@@ -156,7 +136,7 @@ router.get('/search', authMine, async (req, res) => {
156
136
  ],
157
137
  });
158
138
 
159
- res.json({ count, list });
139
+ res.json({ count, list, paging: { page, pageSize } });
160
140
  });
161
141
 
162
142
  router.get('/:id', authPortal, async (req, res) => {
@@ -3,6 +3,7 @@ import Joi from 'joi';
3
3
  import pick from 'lodash/pick';
4
4
  import type { WhereOptions } from 'sequelize';
5
5
 
6
+ import { createListParamSchema } from '../libs/api';
6
7
  import logger from '../libs/logger';
7
8
  import { authenticate } from '../libs/security';
8
9
  import { isLineItemAligned } from '../libs/session';
@@ -145,17 +146,7 @@ router.post('/', auth, async (req, res) => {
145
146
  });
146
147
 
147
148
  // list payment links
148
- const paginationSchema = Joi.object<{
149
- page: number;
150
- pageSize: number;
151
- active?: boolean;
152
- livemode?: boolean;
153
- }>({
154
- page: Joi.number().integer().min(1).default(1),
155
- pageSize: Joi.number().integer().min(1).max(100).default(20),
156
- active: Joi.boolean().empty(''),
157
- livemode: Joi.boolean().empty(''),
158
- });
149
+ const paginationSchema = createListParamSchema<{ active?: boolean }>({ active: Joi.boolean().empty('') });
159
150
  router.get('/', auth, async (req, res) => {
160
151
  const { page, pageSize, ...query } = await paginationSchema.validateAsync(req.query, { stripUnknown: true });
161
152
  const where: WhereOptions<PaymentLink> = { 'metadata.preview': null };
@@ -186,10 +177,10 @@ router.get('/', auth, async (req, res) => {
186
177
  });
187
178
  });
188
179
 
189
- res.json({ count, list });
180
+ res.json({ count, list, paging: { page, pageSize } });
190
181
  } catch (err) {
191
182
  console.error(err);
192
- res.json({ count: 0, list: [] });
183
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
193
184
  }
194
185
  });
195
186
 
@@ -4,7 +4,7 @@ import Joi from 'joi';
4
4
  import pick from 'lodash/pick';
5
5
  import type { WhereOptions } from 'sequelize';
6
6
 
7
- import { getWhereFromQuery } from '../libs/api';
7
+ import { createListParamSchema, getWhereFromQuery } from '../libs/api';
8
8
  import logger from '../libs/logger';
9
9
  import { authenticate } from '../libs/security';
10
10
  import { canUpsell } from '../libs/session';
@@ -43,19 +43,13 @@ export async function getExpandedPrice(id: string) {
43
43
  }
44
44
 
45
45
  // list prices
46
- const paginationSchema = Joi.object<{
47
- page: number;
48
- pageSize: number;
49
- livemode?: boolean;
46
+ const paginationSchema = createListParamSchema<{
50
47
  active?: boolean;
51
48
  type?: string;
52
49
  currency_id?: string;
53
50
  product_id?: string;
54
51
  lookup_key?: string;
55
52
  }>({
56
- page: Joi.number().integer().min(1).default(1),
57
- pageSize: Joi.number().integer().min(1).max(100).default(20),
58
- livemode: Joi.boolean().empty(''),
59
53
  active: Joi.boolean().empty(''),
60
54
  type: Joi.string().empty(''),
61
55
  currency_id: Joi.string().empty(''),
@@ -98,20 +92,14 @@ router.get('/', auth, async (req, res) => {
98
92
  limit: pageSize,
99
93
  });
100
94
 
101
- res.json({ count, list: await Promise.all(rows.map((x) => getExpandedPrice(x.id))) });
95
+ res.json({ count, list: await Promise.all(rows.map((x) => getExpandedPrice(x.id))), paging: { page, pageSize } });
102
96
  });
103
97
 
104
98
  // search prices
105
- const searchSchema = Joi.object<{
106
- page: number;
107
- pageSize: number;
99
+ const searchSchema = createListParamSchema<{
108
100
  query: string;
109
- livemode?: boolean;
110
101
  }>({
111
- page: Joi.number().integer().min(1).default(1),
112
- pageSize: Joi.number().integer().min(1).max(100).default(20),
113
102
  query: Joi.string(),
114
- livemode: Joi.boolean().empty(''),
115
103
  });
116
104
  router.get('/search', auth, async (req, res) => {
117
105
  const { page, pageSize, query, livemode } = await searchSchema.validateAsync(req.query, {
@@ -7,6 +7,7 @@ import uniq from 'lodash/uniq';
7
7
  import type { WhereOptions } from 'sequelize';
8
8
 
9
9
  import { checkPassportForPricingTable } from '../integrations/blocklet/passport';
10
+ import { createListParamSchema } from '../libs/api';
10
11
  import logger from '../libs/logger';
11
12
  import { authenticate } from '../libs/security';
12
13
  import { getBillingThreshold, isLineItemCurrencyAligned } from '../libs/session';
@@ -49,16 +50,10 @@ router.post('/', auth, async (req, res) => {
49
50
  });
50
51
 
51
52
  // list pricing tables
52
- const paginationSchema = Joi.object<{
53
- page: number;
54
- pageSize: number;
53
+ const paginationSchema = createListParamSchema<{
55
54
  active?: boolean;
56
- livemode?: boolean;
57
55
  }>({
58
- page: Joi.number().integer().min(1).default(1),
59
- pageSize: Joi.number().integer().min(1).max(100).default(20),
60
56
  active: Joi.boolean().empty(''),
61
- livemode: Joi.boolean().empty(''),
62
57
  });
63
58
  router.get('/', auth, async (req, res) => {
64
59
  const { page, pageSize, ...query } = await paginationSchema.validateAsync(req.query, { stripUnknown: true });
@@ -93,10 +88,10 @@ router.get('/', auth, async (req, res) => {
93
88
  });
94
89
  });
95
90
 
96
- res.json({ count, list });
91
+ res.json({ count, list, paging: { page, pageSize } });
97
92
  } catch (err) {
98
93
  console.error(err);
99
- res.json({ count: 0, list: [] });
94
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
100
95
  }
101
96
  });
102
97
 
@@ -3,7 +3,7 @@ import { Router } from 'express';
3
3
  import Joi from 'joi';
4
4
  import pick from 'lodash/pick';
5
5
 
6
- import { getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
6
+ import { createListParamSchema, getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
7
7
  import logger from '../libs/logger';
8
8
  import { authenticate } from '../libs/security';
9
9
  import { formatMetadata } from '../libs/util';
@@ -106,26 +106,16 @@ router.post('/', auth, async (req, res) => {
106
106
  });
107
107
 
108
108
  // list products and prices
109
- const paginationSchema = Joi.object<{
110
- page: number;
111
- pageSize: number;
112
- livemode?: boolean;
109
+ const paginationSchema = createListParamSchema<{
113
110
  active?: boolean;
114
111
  status?: string;
115
112
  name?: string;
116
113
  description?: string;
117
- q?: string;
118
- o?: string;
119
114
  }>({
120
- page: Joi.number().integer().min(1).default(1),
121
- pageSize: Joi.number().integer().min(1).max(100).default(20),
122
- livemode: Joi.boolean().empty(''),
123
115
  active: Joi.boolean().empty(''),
124
116
  status: Joi.string().empty(''),
125
117
  name: Joi.string().empty(''),
126
118
  description: Joi.string().empty(''),
127
- q: Joi.string().empty(''), // query
128
- o: Joi.string().empty(''), // order
129
119
  });
130
120
  router.get('/', auth, async (req, res) => {
131
121
  const { page, pageSize, active, livemode, name, description, ...query } = await paginationSchema.validateAsync(
@@ -168,22 +158,14 @@ router.get('/', auth, async (req, res) => {
168
158
  distinct: true,
169
159
  });
170
160
 
171
- res.json({ count, list });
161
+ res.json({ count, list, paging: { page, pageSize } });
172
162
  });
173
163
 
174
164
  // search products
175
- const searchSchema = Joi.object<{
176
- page: number;
177
- pageSize: number;
165
+ const searchSchema = createListParamSchema<{
178
166
  query: string;
179
- livemode?: boolean;
180
- q?: string;
181
167
  }>({
182
- page: Joi.number().integer().min(1).default(1),
183
- pageSize: Joi.number().integer().min(1).max(100).default(20),
184
168
  query: Joi.string(),
185
- livemode: Joi.boolean().empty(''),
186
- q: Joi.string().empty(''), // query
187
169
  });
188
170
  router.get('/search', auth, async (req, res) => {
189
171
  const { page, pageSize, query, livemode, q } = await searchSchema.validateAsync(req.query, {
@@ -3,7 +3,7 @@ import { Router } from 'express';
3
3
  import Joi from 'joi';
4
4
  import pick from 'lodash/pick';
5
5
 
6
- import { getWhereFromKvQuery } from '../libs/api';
6
+ import { createListParamSchema, getWhereFromKvQuery } from '../libs/api';
7
7
  import { authenticate } from '../libs/security';
8
8
  import { formatMetadata } from '../libs/util';
9
9
  import {
@@ -29,28 +29,18 @@ const auth = authenticate<Invoice>({
29
29
  },
30
30
  });
31
31
 
32
- const paginationSchema = Joi.object<{
33
- page: number;
34
- pageSize: number;
35
- livemode?: boolean;
32
+ const paginationSchema = createListParamSchema<{
36
33
  status?: string;
37
34
  invoice_id: string;
38
35
  subscription_id: string;
39
36
  currency_id: string;
40
37
  customer_id: string;
41
- q?: string;
42
- o?: string;
43
38
  }>({
44
- page: Joi.number().integer().min(1).default(1),
45
- pageSize: Joi.number().integer().min(1).max(100).default(20),
46
- livemode: Joi.boolean().empty(''),
47
39
  status: Joi.string().empty(''),
48
40
  invoice_id: Joi.string().empty(''),
49
41
  currency_id: Joi.string().empty(''),
50
42
  subscription_id: Joi.string().empty(''),
51
43
  customer_id: Joi.string().empty(''),
52
- q: Joi.string().empty(''), // query
53
- o: Joi.string().empty(''), // order
54
44
  });
55
45
  router.get('/', auth, async (req, res) => {
56
46
  const { page, pageSize, livemode, status, ...query } = await paginationSchema.validateAsync(req.query, {
@@ -109,23 +99,10 @@ router.get('/', auth, async (req, res) => {
109
99
  distinct: true,
110
100
  });
111
101
 
112
- res.json({ count, list });
113
- });
114
-
115
- const searchSchema = Joi.object<{
116
- page: number;
117
- pageSize: number;
118
- livemode?: boolean;
119
- q: string;
120
- o?: string;
121
- }>({
122
- page: Joi.number().integer().min(1).default(1),
123
- pageSize: Joi.number().integer().min(1).max(100).default(20),
124
- livemode: Joi.boolean().empty(''),
125
- q: Joi.string().empty(''), // query
126
- o: Joi.string().empty(''), // order
102
+ res.json({ count, list, paging: { page, pageSize } });
127
103
  });
128
104
 
105
+ const searchSchema = createListParamSchema<{}>({});
129
106
  router.get('/search', auth, async (req, res) => {
130
107
  const { page, pageSize, livemode, q, o } = await searchSchema.validateAsync(req.query, {
131
108
  stripUnknown: false,
@@ -148,7 +125,7 @@ router.get('/search', auth, async (req, res) => {
148
125
  ],
149
126
  });
150
127
 
151
- res.json({ count, list });
128
+ res.json({ count, list, paging: { page, pageSize } });
152
129
  });
153
130
 
154
131
  router.get('/:id', auth, async (req, res) => {
@@ -3,6 +3,7 @@ import Joi from 'joi';
3
3
  import pick from 'lodash/pick';
4
4
  import type { WhereOptions } from 'sequelize';
5
5
 
6
+ import { createListParamSchema } from '../libs/api';
6
7
  import { authenticate } from '../libs/security';
7
8
  import { expandLineItems } from '../libs/session';
8
9
  import { formatMetadata } from '../libs/util';
@@ -38,18 +39,12 @@ router.post('/', auth, async (req, res) => {
38
39
  });
39
40
 
40
41
  // @link https://stripe.com/docs/api/subscription_items/list
41
- const schema = Joi.object<{
42
- page: number;
43
- pageSize: number;
42
+ const schema = createListParamSchema<{
44
43
  subscription_id: string;
45
44
  price_id: string;
46
- livemode?: boolean;
47
45
  }>({
48
- page: Joi.number().integer().min(1).default(1),
49
- pageSize: Joi.number().integer().min(1).max(100).default(20),
50
46
  subscription_id: Joi.string(),
51
47
  price_id: Joi.string(),
52
- livemode: Joi.boolean().empty(''),
53
48
  });
54
49
  router.get('/', auth, async (req, res) => {
55
50
  const { page, pageSize, ...query } = await schema.validateAsync(req.query, { stripUnknown: true });
@@ -82,10 +77,10 @@ router.get('/', auth, async (req, res) => {
82
77
  // @ts-ignore
83
78
  expandLineItems(list, products, prices);
84
79
  }
85
- res.json({ count, list });
80
+ res.json({ count, list, paging: { page, pageSize } });
86
81
  } catch (err) {
87
82
  console.error(err);
88
- res.json({ count: 0, list: [] });
83
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
89
84
  }
90
85
  });
91
86
 
@@ -6,7 +6,7 @@ import pick from 'lodash/pick';
6
6
  import uniq from 'lodash/uniq';
7
7
 
8
8
  import { ensureStripeSubscription } from '../integrations/stripe/resource';
9
- import { getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
9
+ import { createListParamSchema, getWhereFromKvQuery, getWhereFromQuery } from '../libs/api';
10
10
  import dayjs from '../libs/dayjs';
11
11
  import logger from '../libs/logger';
12
12
  import { isDelegationSufficientForPayment } from '../libs/payment';
@@ -60,24 +60,14 @@ const updateStripeSubscription = async (doc: Subscription, updates: any) => {
60
60
  }
61
61
  };
62
62
 
63
- const schema = Joi.object<{
64
- page: number;
65
- pageSize: number;
63
+ const schema = createListParamSchema<{
66
64
  status?: string;
67
65
  customer_id?: string;
68
66
  customer_did?: string;
69
- livemode?: boolean;
70
- q?: string;
71
- o?: string;
72
67
  }>({
73
- page: Joi.number().integer().min(1).default(1),
74
- pageSize: Joi.number().integer().min(1).max(100).default(20),
75
68
  status: Joi.string().empty(''),
76
69
  customer_id: Joi.string().empty(''),
77
70
  customer_did: Joi.string().empty(''),
78
- livemode: Joi.boolean().empty(''),
79
- q: Joi.string().empty(''), // query
80
- o: Joi.string().empty(''), // order
81
71
  });
82
72
  router.get('/', authMine, async (req, res) => {
83
73
  const { page, pageSize, status, livemode, ...query } = await schema.validateAsync(req.query, {
@@ -100,7 +90,7 @@ router.get('/', authMine, async (req, res) => {
100
90
  if (customer) {
101
91
  where.customer_id = customer.id;
102
92
  } else {
103
- res.json({ count: 0, list: [] });
93
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
104
94
  return;
105
95
  }
106
96
  }
@@ -137,28 +127,18 @@ router.get('/', authMine, async (req, res) => {
137
127
  // @ts-ignore
138
128
  docs.forEach((x) => expandLineItems(x.items, products, prices));
139
129
 
140
- res.json({ count, list: docs });
130
+ res.json({ count, list: docs, paging: { page, pageSize } });
141
131
  } catch (err) {
142
132
  console.error(err);
143
- res.json({ count: 0, list: [] });
133
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
144
134
  }
145
135
  });
146
136
 
147
137
  // search subscriptions
148
- const searchSchema = Joi.object<{
149
- page: number;
150
- pageSize: number;
138
+ const searchSchema = createListParamSchema<{
151
139
  query: string;
152
- livemode?: boolean;
153
- q?: string;
154
- o?: string;
155
140
  }>({
156
- page: Joi.number().integer().min(1).default(1),
157
- pageSize: Joi.number().integer().min(1).max(100).default(20),
158
141
  query: Joi.string(),
159
- livemode: Joi.boolean().empty(''),
160
- q: Joi.string().empty(''), // query
161
- o: Joi.string().empty(''), // order
162
142
  });
163
143
  router.get('/search', auth, async (req, res) => {
164
144
  const { page, pageSize, query, livemode, q, o } = await searchSchema.validateAsync(req.query, {
@@ -190,7 +170,7 @@ router.get('/search', auth, async (req, res) => {
190
170
  const docs = list.map((x) => x.toJSON());
191
171
  // @ts-ignore
192
172
  docs.forEach((x) => expandLineItems(x.items, products, prices));
193
- res.json({ count, list: docs });
173
+ res.json({ count, list: docs, paging: { page, pageSize } });
194
174
  });
195
175
 
196
176
  // FIXME: exclude some sensitive fields from PaymentMethod
@@ -5,6 +5,7 @@ import pick from 'lodash/pick';
5
5
  import { Op } from 'sequelize';
6
6
 
7
7
  import { forwardUsageRecordToStripe } from '../integrations/stripe/resource';
8
+ import { createListParamSchema } from '../libs/api';
8
9
  import dayjs from '../libs/dayjs';
9
10
  import { authenticate } from '../libs/security';
10
11
  import { usageRecordQueue } from '../queues/usage-record';
@@ -75,16 +76,10 @@ router.post('/', auth, async (req, res) => {
75
76
  });
76
77
 
77
78
  // @link https://stripe.com/docs/api/usage_records/subscription_item_summary_list
78
- const schema = Joi.object<{
79
- page: number;
80
- pageSize: number;
79
+ const schema = createListParamSchema<{
81
80
  subscription_item_id: string;
82
- livemode?: boolean;
83
81
  }>({
84
- page: Joi.number().integer().min(1).default(1),
85
- pageSize: Joi.number().integer().min(1).max(100).default(20),
86
82
  subscription_item_id: Joi.string().required(),
87
- livemode: Joi.boolean().empty(''),
88
83
  });
89
84
  router.get('/summary', auth, async (req, res) => {
90
85
  const { page, pageSize, ...query } = await schema.validateAsync(req.query, { stripUnknown: true });
@@ -127,10 +122,10 @@ router.get('/summary', auth, async (req, res) => {
127
122
  })
128
123
  );
129
124
 
130
- res.json({ count, list });
125
+ res.json({ count, list, paging: { page, pageSize } });
131
126
  } catch (err) {
132
127
  console.error(err);
133
- res.json({ count: 0, list: [] });
128
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
134
129
  }
135
130
  });
136
131
 
@@ -2,22 +2,17 @@ import { Router } from 'express';
2
2
  import Joi from 'joi';
3
3
  import type { WhereOptions } from 'sequelize';
4
4
 
5
+ import { createListParamSchema } from '../libs/api';
5
6
  import { authenticate } from '../libs/security';
6
7
  import { Event, WebhookAttempt, WebhookEndpoint } from '../store/models';
7
8
 
8
9
  const router = Router();
9
10
  const auth = authenticate<WebhookAttempt>({ component: true, roles: ['owner', 'admin'] });
10
11
 
11
- const schema = Joi.object<{
12
- page: number;
13
- pageSize: number;
14
- livemode?: boolean;
12
+ const schema = createListParamSchema<{
15
13
  event_id?: string;
16
14
  webhook_endpoint_id?: string;
17
15
  }>({
18
- page: Joi.number().integer().min(1).default(1),
19
- pageSize: Joi.number().integer().min(1).max(100).default(20),
20
- livemode: Joi.boolean().empty(''),
21
16
  event_id: Joi.string().empty(''),
22
17
  webhook_endpoint_id: Joi.string().empty(''),
23
18
  });
@@ -47,10 +42,10 @@ router.get('/', auth, async (req, res) => {
47
42
  ],
48
43
  });
49
44
 
50
- res.json({ count, list });
45
+ res.json({ count, list, paging: { page, pageSize } });
51
46
  } catch (err) {
52
47
  console.error(err);
53
- res.json({ count: 0, list: [] });
48
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
54
49
  }
55
50
  });
56
51
 
@@ -3,6 +3,7 @@ import Joi from 'joi';
3
3
  import pick from 'lodash/pick';
4
4
  import type { WhereOptions } from 'sequelize';
5
5
 
6
+ import { createListParamSchema } from '../libs/api';
6
7
  import { authenticate } from '../libs/security';
7
8
  import { formatMetadata } from '../libs/util';
8
9
  import { WebhookEndpoint } from '../store/models';
@@ -28,16 +29,10 @@ router.post('/', auth, async (req, res) => {
28
29
  return res.json(doc);
29
30
  });
30
31
 
31
- const schema = Joi.object<{
32
- page: number;
33
- pageSize: number;
32
+ const schema = createListParamSchema<{
34
33
  status?: string;
35
- livemode?: boolean;
36
34
  }>({
37
- page: Joi.number().integer().min(1).default(1),
38
- pageSize: Joi.number().integer().min(1).max(100).default(20),
39
35
  status: Joi.string().empty(''),
40
- livemode: Joi.boolean().empty(''),
41
36
  });
42
37
  router.get('/', auth, async (req, res) => {
43
38
  const { page, pageSize, status, ...query } = await schema.validateAsync(req.query, { stripUnknown: true });
@@ -68,10 +63,10 @@ router.get('/', auth, async (req, res) => {
68
63
  include: [],
69
64
  });
70
65
 
71
- res.json({ count, list });
66
+ res.json({ count, list, paging: { page, pageSize } });
72
67
  } catch (err) {
73
68
  console.error(err);
74
- res.json({ count: 0, list: [] });
69
+ res.json({ count: 0, list: [], paging: { page, pageSize } });
75
70
  }
76
71
  });
77
72
 
package/blocklet.yml CHANGED
@@ -14,7 +14,7 @@ repository:
14
14
  type: git
15
15
  url: git+https://github.com/blocklet/payment-kit.git
16
16
  specVersion: 1.2.8
17
- version: 1.13.207
17
+ version: 1.13.209
18
18
  logo: logo.png
19
19
  files:
20
20
  - dist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payment-kit",
3
- "version": "1.13.207",
3
+ "version": "1.13.209",
4
4
  "scripts": {
5
5
  "dev": "cross-env COMPONENT_STORE_URL=https://test.store.blocklet.dev blocklet dev --open",
6
6
  "eject": "vite eject",
@@ -50,7 +50,7 @@
50
50
  "@arcblock/jwt": "^1.18.113",
51
51
  "@arcblock/ux": "^2.9.63",
52
52
  "@blocklet/logger": "1.16.24",
53
- "@blocklet/payment-react": "1.13.207",
53
+ "@blocklet/payment-react": "1.13.209",
54
54
  "@blocklet/sdk": "1.16.24",
55
55
  "@blocklet/ui-react": "^2.9.63",
56
56
  "@blocklet/uploader": "^0.0.75",
@@ -110,7 +110,7 @@
110
110
  "devDependencies": {
111
111
  "@abtnode/types": "1.16.24",
112
112
  "@arcblock/eslint-config-ts": "^0.3.0",
113
- "@blocklet/payment-types": "1.13.207",
113
+ "@blocklet/payment-types": "1.13.209",
114
114
  "@types/cookie-parser": "^1.4.6",
115
115
  "@types/cors": "^2.8.17",
116
116
  "@types/dotenv-flow": "^3.3.3",
@@ -118,7 +118,7 @@
118
118
  "@types/node": "^18.19.14",
119
119
  "@types/react": "^18.2.55",
120
120
  "@types/react-dom": "^18.2.18",
121
- "@vitejs/plugin-react": "^2.2.0",
121
+ "@vitejs/plugin-react": "^4.2.1",
122
122
  "bumpp": "^8.2.1",
123
123
  "cross-env": "^7.0.3",
124
124
  "eslint": "^8.56.0",
@@ -133,10 +133,10 @@
133
133
  "ts-node": "^10.9.2",
134
134
  "type-fest": "^4.10.2",
135
135
  "typescript": "^4.9.5",
136
- "vite": "^4.5.2",
137
- "vite-plugin-blocklet": "^0.7.5",
138
- "vite-plugin-node-polyfills": "^0.7.0",
139
- "vite-plugin-svgr": "^2.4.0",
136
+ "vite": "^5.2.7",
137
+ "vite-plugin-blocklet": "^0.7.6",
138
+ "vite-plugin-node-polyfills": "^0.21.0",
139
+ "vite-plugin-svgr": "^4.2.0",
140
140
  "zx": "^7.2.3"
141
141
  },
142
142
  "importSort": {
@@ -149,5 +149,5 @@
149
149
  "parser": "typescript"
150
150
  }
151
151
  },
152
- "gitHead": "7b4918ac7bb09317df0b2a78e337312cc4b50b67"
152
+ "gitHead": "24391eee3017ca20e40a595334e1adccbadc85cd"
153
153
  }
@@ -4,11 +4,11 @@ import Toast from '@arcblock/ux/lib/Toast';
4
4
  import { CustomerInvoiceList, PaymentProvider, formatError, getPrefix } from '@blocklet/payment-react';
5
5
  import type { GroupedBN, TCustomerExpanded } from '@blocklet/payment-types';
6
6
  import { Edit } from '@mui/icons-material';
7
- import { Alert, Box, Button, CircularProgress, Grid, Stack, Tooltip } from '@mui/material';
7
+ import { Alert, Box, Button, Grid, Stack, Tooltip } from '@mui/material';
8
8
  import { styled } from '@mui/system';
9
- import { useRequest, useSetState } from 'ahooks';
9
+ import { useSetState } from 'ahooks';
10
10
  import { isEmpty } from 'lodash';
11
- import { useEffect } from 'react';
11
+ import { useEffect, useState } from 'react';
12
12
  import { FlagEmoji } from 'react-international-phone';
13
13
  import { useNavigate } from 'react-router-dom';
14
14
  import { joinURL } from 'ufo';
@@ -34,22 +34,21 @@ export default function CustomerHome() {
34
34
  const navigate = useNavigate();
35
35
  const { isPending, startTransition } = useTransitionContext();
36
36
 
37
- const { loading, error, data, runAsync } = useRequest(fetchData);
37
+ const [data, setData] = useState(null as any);
38
+
39
+ const runAsync = () => {
40
+ fetchData().then((res) => {
41
+ setData(res as any);
42
+ });
43
+ };
38
44
 
39
45
  useEffect(() => {
46
+ runAsync();
40
47
  events.once('switch-did', () => {
41
- runAsync().catch(console.error);
48
+ runAsync();
42
49
  });
43
50
  }, []);
44
51
 
45
- if (error) {
46
- return <Alert severity="error">{formatError(error)}</Alert>;
47
- }
48
-
49
- if (loading) {
50
- return <CircularProgress />;
51
- }
52
-
53
52
  if (!data) {
54
53
  return (
55
54
  <Alert sx={{ mt: 3 }} severity="info">
@@ -83,7 +82,9 @@ export default function CustomerHome() {
83
82
  <Box className="section-body">
84
83
  <CurrentSubscriptions
85
84
  id={data.id}
86
- onChange={runAsync}
85
+ onChange={() => {
86
+ runAsync();
87
+ }}
87
88
  style={{
88
89
  cursor: 'pointer',
89
90
  }}