mumz-strapi-plugin-coupon 1.0.7

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 (41) hide show
  1. package/README.md +311 -0
  2. package/dist/bootstrap.d.ts +5 -0
  3. package/dist/bootstrap.js +6 -0
  4. package/dist/config/index.d.ts +5 -0
  5. package/dist/config/index.js +6 -0
  6. package/dist/content-types/coupon/index.d.ts +90 -0
  7. package/dist/content-types/coupon/index.js +9 -0
  8. package/dist/content-types/coupon/schema.d.ts +88 -0
  9. package/dist/content-types/coupon/schema.js +105 -0
  10. package/dist/content-types/index.d.ts +155 -0
  11. package/dist/content-types/index.js +11 -0
  12. package/dist/content-types/redemption/index.d.ts +64 -0
  13. package/dist/content-types/redemption/index.js +9 -0
  14. package/dist/content-types/redemption/schema.d.ts +62 -0
  15. package/dist/content-types/redemption/schema.js +74 -0
  16. package/dist/controllers/coupon.d.ts +41 -0
  17. package/dist/controllers/coupon.js +154 -0
  18. package/dist/controllers/index.d.ts +5 -0
  19. package/dist/controllers/index.js +9 -0
  20. package/dist/destroy.d.ts +5 -0
  21. package/dist/destroy.js +6 -0
  22. package/dist/index.d.ts +201 -0
  23. package/dist/index.js +24 -0
  24. package/dist/middlewares/index.d.ts +4 -0
  25. package/dist/middlewares/index.js +9 -0
  26. package/dist/middlewares/rate-limit.d.ts +6 -0
  27. package/dist/middlewares/rate-limit.js +42 -0
  28. package/dist/register.d.ts +5 -0
  29. package/dist/register.js +6 -0
  30. package/dist/routes/content-api/index.d.ts +23 -0
  31. package/dist/routes/content-api/index.js +76 -0
  32. package/dist/routes/index.d.ts +25 -0
  33. package/dist/routes/index.js +9 -0
  34. package/dist/services/coupon.d.ts +61 -0
  35. package/dist/services/coupon.js +399 -0
  36. package/dist/services/index.d.ts +5 -0
  37. package/dist/services/index.js +9 -0
  38. package/dist/utils/validators.d.ts +14 -0
  39. package/dist/utils/validators.js +41 -0
  40. package/package.json +71 -0
  41. package/strapi-server.js +1 -0
@@ -0,0 +1,201 @@
1
+ import type { Core } from '@strapi/strapi';
2
+ declare const plugin: {
3
+ register: ({ strapi }: {
4
+ strapi: Core.Strapi;
5
+ }) => void;
6
+ bootstrap: ({ strapi }: {
7
+ strapi: Core.Strapi;
8
+ }) => void;
9
+ destroy: ({ strapi }: {
10
+ strapi: Core.Strapi;
11
+ }) => void;
12
+ config: {
13
+ default: {};
14
+ validator(): void;
15
+ };
16
+ controllers: Record<string, (params: {
17
+ strapi: Core.Strapi;
18
+ }) => any>;
19
+ routes: {
20
+ 'content-api': {
21
+ type: string;
22
+ routes: ({
23
+ method: string;
24
+ path: string;
25
+ handler: string;
26
+ config: {
27
+ policies: never[];
28
+ middlewares: ((ctx: any, next: any) => Promise<any>)[];
29
+ auth: boolean;
30
+ };
31
+ } | {
32
+ method: string;
33
+ path: string;
34
+ handler: string;
35
+ config: {
36
+ policies: never[];
37
+ auth: boolean;
38
+ middlewares?: undefined;
39
+ };
40
+ })[];
41
+ };
42
+ };
43
+ services: Record<string, (params: {
44
+ strapi: Core.Strapi;
45
+ }) => any>;
46
+ contentTypes: {
47
+ coupon: {
48
+ schema: {
49
+ kind: string;
50
+ collectionName: string;
51
+ info: {
52
+ singularName: string;
53
+ pluralName: string;
54
+ displayName: string;
55
+ description: string;
56
+ };
57
+ options: {
58
+ draftAndPublish: boolean;
59
+ };
60
+ pluginOptions: {
61
+ 'content-manager': {
62
+ visible: boolean;
63
+ };
64
+ 'content-type-builder': {
65
+ visible: boolean;
66
+ };
67
+ };
68
+ layouts: {
69
+ list: string[];
70
+ edit: {
71
+ name: string;
72
+ size: number;
73
+ }[][];
74
+ };
75
+ attributes: {
76
+ code: {
77
+ type: string;
78
+ required: boolean;
79
+ unique: boolean;
80
+ configurable: boolean;
81
+ };
82
+ discountType: {
83
+ type: string;
84
+ enum: string[];
85
+ required: boolean;
86
+ default: string;
87
+ };
88
+ discountValue: {
89
+ type: string;
90
+ required: boolean;
91
+ min: number;
92
+ };
93
+ maxUsage: {
94
+ type: string;
95
+ required: boolean;
96
+ min: number;
97
+ default: null;
98
+ };
99
+ currentUsage: {
100
+ type: string;
101
+ required: boolean;
102
+ default: number;
103
+ min: number;
104
+ };
105
+ validFrom: {
106
+ type: string;
107
+ required: boolean;
108
+ };
109
+ validTo: {
110
+ type: string;
111
+ required: boolean;
112
+ };
113
+ isActive: {
114
+ type: string;
115
+ default: boolean;
116
+ required: boolean;
117
+ };
118
+ description: {
119
+ type: string;
120
+ required: boolean;
121
+ };
122
+ userRestrictions: {
123
+ type: string;
124
+ required: boolean;
125
+ default: null;
126
+ };
127
+ redemptions: {
128
+ type: string;
129
+ relation: string;
130
+ target: string;
131
+ mappedBy: string;
132
+ };
133
+ };
134
+ };
135
+ };
136
+ redemption: {
137
+ schema: {
138
+ kind: string;
139
+ collectionName: string;
140
+ info: {
141
+ singularName: string;
142
+ pluralName: string;
143
+ displayName: string;
144
+ description: string;
145
+ };
146
+ options: {
147
+ draftAndPublish: boolean;
148
+ };
149
+ pluginOptions: {
150
+ 'content-manager': {
151
+ visible: boolean;
152
+ };
153
+ 'content-type-builder': {
154
+ visible: boolean;
155
+ };
156
+ };
157
+ layouts: {
158
+ list: string[];
159
+ edit: {
160
+ name: string;
161
+ size: number;
162
+ }[][];
163
+ };
164
+ attributes: {
165
+ coupon: {
166
+ type: string;
167
+ relation: string;
168
+ target: string;
169
+ inversedBy: string;
170
+ };
171
+ orderId: {
172
+ type: string;
173
+ required: boolean;
174
+ };
175
+ phoneNumber: {
176
+ type: string;
177
+ required: boolean;
178
+ };
179
+ redemptionDate: {
180
+ type: string;
181
+ required: boolean;
182
+ };
183
+ discountType: {
184
+ type: string;
185
+ required: boolean;
186
+ };
187
+ discountValue: {
188
+ type: string;
189
+ required: boolean;
190
+ };
191
+ metadata: {
192
+ type: string;
193
+ required: boolean;
194
+ default: null;
195
+ };
196
+ };
197
+ };
198
+ };
199
+ };
200
+ };
201
+ export default plugin;
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const register_1 = __importDefault(require("./register"));
7
+ const bootstrap_1 = __importDefault(require("./bootstrap"));
8
+ const destroy_1 = __importDefault(require("./destroy"));
9
+ const config_1 = __importDefault(require("./config"));
10
+ const content_types_1 = __importDefault(require("./content-types"));
11
+ const controllers_1 = __importDefault(require("./controllers"));
12
+ const routes_1 = __importDefault(require("./routes"));
13
+ const services_1 = __importDefault(require("./services"));
14
+ const plugin = {
15
+ register: register_1.default,
16
+ bootstrap: bootstrap_1.default,
17
+ destroy: destroy_1.default,
18
+ config: config_1.default,
19
+ controllers: controllers_1.default,
20
+ routes: routes_1.default,
21
+ services: services_1.default,
22
+ contentTypes: content_types_1.default,
23
+ };
24
+ exports.default = plugin;
@@ -0,0 +1,4 @@
1
+ declare const _default: {
2
+ rateLimit: (config: import("./rate-limit").RateLimitConfig) => (ctx: any, next: any) => Promise<any>;
3
+ };
4
+ export default _default;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const rate_limit_1 = __importDefault(require("./rate-limit"));
7
+ exports.default = {
8
+ rateLimit: rate_limit_1.default,
9
+ };
@@ -0,0 +1,6 @@
1
+ export interface RateLimitConfig {
2
+ maxRequests: number;
3
+ windowMs: number;
4
+ }
5
+ declare const _default: (config: RateLimitConfig) => (ctx: any, next: any) => Promise<any>;
6
+ export default _default;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Simple in-memory rate limiter
4
+ // Uses in-memory storage - suitable for single-instance deployments
5
+ const rateLimitStore = new Map();
6
+ // Clean up old entries every hour
7
+ setInterval(() => {
8
+ const now = Date.now();
9
+ for (const [key, value] of rateLimitStore.entries()) {
10
+ if (now > value.resetAt) {
11
+ rateLimitStore.delete(key);
12
+ }
13
+ }
14
+ }, 3600000); // 1 hour
15
+ exports.default = (config) => {
16
+ return async (ctx, next) => {
17
+ const identifier = ctx.ip || ctx.request.ip || 'unknown';
18
+ const now = Date.now();
19
+ const record = rateLimitStore.get(identifier);
20
+ // No record or expired, create new
21
+ if (!record || now > record.resetAt) {
22
+ rateLimitStore.set(identifier, {
23
+ count: 1,
24
+ resetAt: now + config.windowMs,
25
+ });
26
+ return next();
27
+ }
28
+ // Check if limit reached
29
+ if (record.count >= config.maxRequests) {
30
+ ctx.status = 429;
31
+ ctx.body = {
32
+ error: 'Too many requests',
33
+ message: `Rate limit exceeded. Please try again in ${Math.ceil((record.resetAt - now) / 1000)} seconds.`,
34
+ retryAfter: Math.ceil((record.resetAt - now) / 1000),
35
+ };
36
+ return;
37
+ }
38
+ // Increment counter
39
+ record.count++;
40
+ return next();
41
+ };
42
+ };
@@ -0,0 +1,5 @@
1
+ import type { Core } from '@strapi/strapi';
2
+ declare const _default: ({ strapi }: {
3
+ strapi: Core.Strapi;
4
+ }) => void;
5
+ export default _default;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = ({ strapi }) => {
4
+ // Register plugin custom logic here
5
+ strapi.log.info('Coupon plugin registered');
6
+ };
@@ -0,0 +1,23 @@
1
+ declare const _default: {
2
+ type: string;
3
+ routes: ({
4
+ method: string;
5
+ path: string;
6
+ handler: string;
7
+ config: {
8
+ policies: never[];
9
+ middlewares: ((ctx: any, next: any) => Promise<any>)[];
10
+ auth: boolean;
11
+ };
12
+ } | {
13
+ method: string;
14
+ path: string;
15
+ handler: string;
16
+ config: {
17
+ policies: never[];
18
+ auth: boolean;
19
+ middlewares?: undefined;
20
+ };
21
+ })[];
22
+ };
23
+ export default _default;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const rate_limit_1 = __importDefault(require("../../middlewares/rate-limit"));
7
+ exports.default = {
8
+ type: 'content-api',
9
+ routes: [
10
+ {
11
+ method: 'POST',
12
+ path: '/validate',
13
+ handler: 'coupon.validate',
14
+ config: {
15
+ policies: [],
16
+ middlewares: [(0, rate_limit_1.default)({ maxRequests: 10, windowMs: 60000 })], // 10 requests per minute
17
+ auth: false,
18
+ },
19
+ },
20
+ {
21
+ method: 'POST',
22
+ path: '/redeem',
23
+ handler: 'coupon.redeem',
24
+ config: {
25
+ policies: [],
26
+ middlewares: [(0, rate_limit_1.default)({ maxRequests: 5, windowMs: 60000 })], // 5 requests per minute
27
+ auth: false,
28
+ },
29
+ },
30
+ {
31
+ method: 'POST',
32
+ path: '/',
33
+ handler: 'coupon.create',
34
+ config: {
35
+ policies: [],
36
+ auth: false,
37
+ },
38
+ },
39
+ {
40
+ method: 'GET',
41
+ path: '/',
42
+ handler: 'coupon.find',
43
+ config: {
44
+ policies: [],
45
+ auth: false,
46
+ },
47
+ },
48
+ {
49
+ method: 'GET',
50
+ path: '/:id',
51
+ handler: 'coupon.findOne',
52
+ config: {
53
+ policies: [],
54
+ auth: false,
55
+ },
56
+ },
57
+ {
58
+ method: 'PUT',
59
+ path: '/:id',
60
+ handler: 'coupon.update',
61
+ config: {
62
+ policies: [],
63
+ auth: false,
64
+ },
65
+ },
66
+ {
67
+ method: 'DELETE',
68
+ path: '/:id',
69
+ handler: 'coupon.delete',
70
+ config: {
71
+ policies: [],
72
+ auth: false,
73
+ },
74
+ },
75
+ ],
76
+ };
@@ -0,0 +1,25 @@
1
+ declare const _default: {
2
+ 'content-api': {
3
+ type: string;
4
+ routes: ({
5
+ method: string;
6
+ path: string;
7
+ handler: string;
8
+ config: {
9
+ policies: never[];
10
+ middlewares: ((ctx: any, next: any) => Promise<any>)[];
11
+ auth: boolean;
12
+ };
13
+ } | {
14
+ method: string;
15
+ path: string;
16
+ handler: string;
17
+ config: {
18
+ policies: never[];
19
+ auth: boolean;
20
+ middlewares?: undefined;
21
+ };
22
+ })[];
23
+ };
24
+ };
25
+ export default _default;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const content_api_1 = __importDefault(require("./content-api"));
7
+ exports.default = {
8
+ 'content-api': content_api_1.default,
9
+ };
@@ -0,0 +1,61 @@
1
+ import type { Core } from '@strapi/strapi';
2
+ export declare const ERROR_CODES: {
3
+ readonly COUPON_NOT_FOUND: "COUPON_NOT_FOUND";
4
+ readonly COUPON_EXPIRED: "COUPON_EXPIRED";
5
+ readonly COUPON_ALREADY_USED: "COUPON_ALREADY_USED";
6
+ readonly USAGE_LIMIT_REACHED: "USAGE_LIMIT_REACHED";
7
+ readonly INVALID_REQUEST: "INVALID_REQUEST";
8
+ };
9
+ export declare const ERROR_MESSAGES: {
10
+ readonly COUPON_NOT_FOUND: "Coupon code does not exist.";
11
+ readonly COUPON_EXPIRED: "This coupon has expired.";
12
+ readonly COUPON_ALREADY_USED: "This coupon has been already used.";
13
+ readonly USAGE_LIMIT_REACHED: "Coupon usage limit has been reached.";
14
+ readonly INVALID_REQUEST: "Invalid request parameters.";
15
+ };
16
+ export interface ValidateCouponRequest {
17
+ couponCode: string;
18
+ phoneNumber: string;
19
+ orderAmount?: number;
20
+ }
21
+ export interface RedeemCouponRequest {
22
+ couponCode: string;
23
+ phoneNumber: string;
24
+ orderId: string;
25
+ orderAmount?: number;
26
+ }
27
+ export interface CreateCouponRequest {
28
+ code: string;
29
+ discountType: 'percentage' | 'flat';
30
+ discountValue: number;
31
+ maxUsage?: number;
32
+ validFrom: string;
33
+ validTo: string;
34
+ description?: string;
35
+ userRestrictions?: any;
36
+ }
37
+ export interface ValidationResponse {
38
+ isValid: boolean;
39
+ errorCode?: string;
40
+ message: string;
41
+ discountType?: string;
42
+ discountValue?: number;
43
+ discountAmount?: number;
44
+ finalAmount?: number;
45
+ }
46
+ export interface RedemptionResponse {
47
+ success: boolean;
48
+ errorCode?: string;
49
+ message: string;
50
+ redemptionId?: string;
51
+ }
52
+ export interface CreateResponse {
53
+ success: boolean;
54
+ errorCode?: string;
55
+ message: string;
56
+ couponId?: string;
57
+ }
58
+ declare const couponService: ({ strapi }: {
59
+ strapi: Core.Strapi;
60
+ }) => any;
61
+ export default couponService;