@btst/plugin-affiliate 0.0.0-stage → 1.0.0-beta.0

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 (79) hide show
  1. package/LICENSE.md +17 -0
  2. package/dist/api/getters.cjs +182 -0
  3. package/dist/api/getters.mjs +166 -0
  4. package/dist/api/index.cjs +49 -0
  5. package/dist/api/index.d.cts +975 -0
  6. package/dist/api/index.d.mts +975 -0
  7. package/dist/api/index.d.ts +975 -0
  8. package/dist/api/index.mjs +7 -0
  9. package/dist/api/mutations.cjs +362 -0
  10. package/dist/api/mutations.mjs +352 -0
  11. package/dist/api/operations.cjs +328 -0
  12. package/dist/api/operations.mjs +326 -0
  13. package/dist/api/plugin.cjs +146 -0
  14. package/dist/api/plugin.mjs +144 -0
  15. package/dist/attribution.cjs +92 -0
  16. package/dist/attribution.d.cts +20 -0
  17. package/dist/attribution.d.mts +20 -0
  18. package/dist/attribution.d.ts +20 -0
  19. package/dist/attribution.mjs +82 -0
  20. package/dist/client/components/index.cjs +12 -0
  21. package/dist/client/components/index.d.cts +13 -0
  22. package/dist/client/components/index.d.mts +13 -0
  23. package/dist/client/components/index.d.ts +13 -0
  24. package/dist/client/components/index.mjs +1 -0
  25. package/dist/client/components/pages/affiliate-apply-page.internal.cjs +59 -0
  26. package/dist/client/components/pages/affiliate-apply-page.internal.mjs +57 -0
  27. package/dist/client/components/pages/affiliate-detail-page.internal.cjs +112 -0
  28. package/dist/client/components/pages/affiliate-detail-page.internal.mjs +110 -0
  29. package/dist/client/components/pages/affiliate-portal-page.internal.cjs +252 -0
  30. package/dist/client/components/pages/affiliate-portal-page.internal.mjs +250 -0
  31. package/dist/client/components/pages/affiliates-page.internal.cjs +160 -0
  32. package/dist/client/components/pages/affiliates-page.internal.mjs +158 -0
  33. package/dist/client/components/pages/commissions-page.internal.cjs +151 -0
  34. package/dist/client/components/pages/commissions-page.internal.mjs +149 -0
  35. package/dist/client/components/pages/payouts-page.internal.cjs +230 -0
  36. package/dist/client/components/pages/payouts-page.internal.mjs +228 -0
  37. package/dist/client/components/pages.cjs +145 -0
  38. package/dist/client/components/pages.mjs +138 -0
  39. package/dist/client/components/shared.cjs +331 -0
  40. package/dist/client/components/shared.mjs +316 -0
  41. package/dist/client/constants.cjs +5 -0
  42. package/dist/client/constants.mjs +3 -0
  43. package/dist/client/hooks/index.cjs +77 -0
  44. package/dist/client/hooks/index.d.cts +39 -0
  45. package/dist/client/hooks/index.d.mts +39 -0
  46. package/dist/client/hooks/index.d.ts +39 -0
  47. package/dist/client/hooks/index.mjs +61 -0
  48. package/dist/client/index.cjs +7 -0
  49. package/dist/client/index.d.cts +110 -0
  50. package/dist/client/index.d.mts +110 -0
  51. package/dist/client/index.d.ts +110 -0
  52. package/dist/client/index.mjs +1 -0
  53. package/dist/client/plugin.cjs +77 -0
  54. package/dist/client/plugin.mjs +75 -0
  55. package/dist/client.css +311 -0
  56. package/dist/commission.cjs +24 -0
  57. package/dist/commission.mjs +22 -0
  58. package/dist/db.cjs +74 -0
  59. package/dist/db.mjs +72 -0
  60. package/dist/permissions.cjs +53 -0
  61. package/dist/permissions.d.cts +78 -0
  62. package/dist/permissions.d.mts +78 -0
  63. package/dist/permissions.d.ts +78 -0
  64. package/dist/permissions.mjs +51 -0
  65. package/dist/query-keys.cjs +152 -0
  66. package/dist/query-keys.d.cts +394 -0
  67. package/dist/query-keys.d.mts +394 -0
  68. package/dist/query-keys.d.ts +394 -0
  69. package/dist/query-keys.mjs +149 -0
  70. package/dist/schemas.cjs +95 -0
  71. package/dist/schemas.mjs +77 -0
  72. package/dist/style.css +313 -0
  73. package/dist/types.cjs +2 -0
  74. package/dist/types.d.cts +176 -0
  75. package/dist/types.d.mts +176 -0
  76. package/dist/types.d.ts +176 -0
  77. package/dist/types.mjs +1 -0
  78. package/package.json +159 -3
  79. package/README.md +0 -3
@@ -0,0 +1,311 @@
1
+
2
+ .affiliate-page {
3
+ max-width: 1160px;
4
+ margin: 0 auto;
5
+ padding: 32px 24px;
6
+ color: var(--foreground, #0f172a);
7
+ font: inherit;
8
+ font-size: 14px;
9
+ line-height: 1.5;
10
+ }
11
+ .affiliate-page > * + * {
12
+ margin-top: 24px;
13
+ }
14
+ .affiliate-page h1 {
15
+ margin: 0;
16
+ font-size: 30px;
17
+ font-weight: 600;
18
+ letter-spacing: -0.025em;
19
+ overflow-wrap: anywhere;
20
+ }
21
+ .affiliate-page h2 {
22
+ margin: 0;
23
+ font-size: 20px;
24
+ font-weight: 500;
25
+ }
26
+ .affiliate-page p {
27
+ margin: 0;
28
+ max-width: 75ch;
29
+ overflow-wrap: anywhere;
30
+ }
31
+ .affiliate-heading,
32
+ .affiliate-section-heading,
33
+ .affiliate-pagination {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: space-between;
37
+ flex-wrap: wrap;
38
+ gap: 16px;
39
+ }
40
+ .affiliate-heading > div {
41
+ min-width: 0;
42
+ flex: 1;
43
+ }
44
+ .affiliate-heading p {
45
+ margin-top: 8px;
46
+ font-size: 16px;
47
+ }
48
+ .affiliate-nav,
49
+ .affiliate-actions {
50
+ display: flex;
51
+ align-items: center;
52
+ flex-wrap: wrap;
53
+ gap: 12px;
54
+ }
55
+ .affiliate-nav {
56
+ border-bottom: 1px solid var(--border, #e2e8f0);
57
+ gap: 24px;
58
+ padding-bottom: 12px;
59
+ }
60
+ .affiliate-page a {
61
+ color: inherit;
62
+ text-underline-offset: 4px;
63
+ }
64
+ .affiliate-page a:hover {
65
+ text-decoration: underline;
66
+ }
67
+ .affiliate-nav a {
68
+ min-height: 44px;
69
+ display: inline-flex;
70
+ align-items: center;
71
+ font-weight: 500;
72
+ }
73
+ .affiliate-muted {
74
+ color: var(--muted-foreground, #64748b);
75
+ }
76
+ .affiliate-small {
77
+ font-size: 12px;
78
+ }
79
+ .affiliate-page :is(button, input, textarea, select, .affiliate-primary) {
80
+ font: inherit;
81
+ border: 1px solid var(--border, #e2e8f0);
82
+ border-radius: 6px;
83
+ min-height: 44px;
84
+ padding: 10px 12px;
85
+ color: inherit;
86
+ background: var(--background, #fff);
87
+ }
88
+ .affiliate-page :is(input, textarea, select) {
89
+ width: 100%;
90
+ min-width: 0;
91
+ }
92
+ .affiliate-page textarea {
93
+ resize: vertical;
94
+ }
95
+ .affiliate-page button {
96
+ cursor: pointer;
97
+ }
98
+ .affiliate-page button:hover {
99
+ background: var(--muted, #f1f5f9);
100
+ }
101
+ .affiliate-page :is(button, input, textarea, select):disabled {
102
+ opacity: 0.6;
103
+ cursor: default;
104
+ }
105
+ .affiliate-page
106
+ :is(button, input, textarea, select, a, [tabindex]):focus-visible {
107
+ outline: 2px solid var(--ring, #2563eb);
108
+ outline-offset: 3px;
109
+ }
110
+ .affiliate-page .affiliate-primary {
111
+ display: inline-flex;
112
+ justify-content: center;
113
+ align-items: center;
114
+ background: var(--primary, #2563eb);
115
+ color: var(--primary-foreground, #fff);
116
+ border-color: transparent;
117
+ font-weight: 500;
118
+ text-decoration: none;
119
+ }
120
+ .affiliate-page .affiliate-primary:hover {
121
+ background: var(--primary, #2563eb);
122
+ opacity: 0.9;
123
+ text-decoration: none;
124
+ }
125
+ .affiliate-page fieldset {
126
+ padding: 0;
127
+ margin: 0;
128
+ border: 0;
129
+ min-width: 0;
130
+ }
131
+ .affiliate-page fieldset > * + * {
132
+ margin-top: 20px;
133
+ }
134
+ .affiliate-form-grid {
135
+ display: grid;
136
+ grid-template-columns: repeat(2, minmax(0, 1fr));
137
+ gap: 20px 28px;
138
+ align-items: start;
139
+ }
140
+ .affiliate-field {
141
+ display: grid;
142
+ gap: 8px;
143
+ min-width: 0;
144
+ }
145
+ .affiliate-field > span:first-child {
146
+ font-weight: 500;
147
+ }
148
+ .affiliate-stack > * + * {
149
+ margin-top: 16px;
150
+ }
151
+ .affiliate-panel {
152
+ padding: 24px;
153
+ border: 1px solid var(--border, #e2e8f0);
154
+ border-radius: 8px;
155
+ }
156
+ .affiliate-section {
157
+ border-top: 1px solid var(--border, #e2e8f0);
158
+ padding-top: 28px;
159
+ }
160
+ .affiliate-toolbar {
161
+ display: flex;
162
+ align-items: end;
163
+ flex-wrap: wrap;
164
+ gap: 16px;
165
+ }
166
+ .affiliate-toolbar > .affiliate-field {
167
+ flex: 1;
168
+ min-width: min(240px, 100%);
169
+ }
170
+ .affiliate-table-scroll {
171
+ max-width: 100%;
172
+ overflow-x: auto;
173
+ }
174
+ .affiliate-page table {
175
+ width: 100%;
176
+ border-collapse: collapse;
177
+ text-align: left;
178
+ font-variant-numeric: tabular-nums;
179
+ }
180
+ .affiliate-page th,
181
+ .affiliate-page td {
182
+ padding: 16px;
183
+ border-bottom: 1px solid var(--border, #e2e8f0);
184
+ vertical-align: top;
185
+ max-width: 350px;
186
+ min-width: 110px;
187
+ overflow-wrap: anywhere;
188
+ }
189
+ .affiliate-page th {
190
+ font-weight: 500;
191
+ font-size: 12px;
192
+ color: var(--muted-foreground, #64748b);
193
+ }
194
+ .affiliate-page :is(th, td):first-child {
195
+ padding-left: 0;
196
+ }
197
+ .affiliate-page :is(th, td):last-child {
198
+ padding-right: 0;
199
+ }
200
+ .affiliate-page td p {
201
+ margin-top: 5px;
202
+ }
203
+ .affiliate-page .affiliate-number {
204
+ text-align: right;
205
+ white-space: nowrap;
206
+ }
207
+ .affiliate-record-link {
208
+ font-weight: 500;
209
+ }
210
+ .affiliate-status {
211
+ display: inline-block;
212
+ padding: 3px 8px;
213
+ border-radius: 4px;
214
+ font-size: 12px;
215
+ font-weight: 500;
216
+ background: var(--muted, #f1f5f9);
217
+ }
218
+ .affiliate-status:is(
219
+ [data-status="approved"],
220
+ [data-status="sent"],
221
+ [data-status="paid"]
222
+ ) {
223
+ box-shadow: inset 3px 0 #16a34a;
224
+ padding-left: 10px;
225
+ }
226
+ .affiliate-status[data-status="pending"] {
227
+ box-shadow: inset 3px 0 #d97706;
228
+ padding-left: 10px;
229
+ }
230
+ .affiliate-status:is(
231
+ [data-status="failed"],
232
+ [data-status="suspended"],
233
+ [data-status="voided"]
234
+ ) {
235
+ box-shadow: inset 3px 0 var(--destructive, #dc2626);
236
+ padding-left: 10px;
237
+ }
238
+ .affiliate-empty {
239
+ padding: 32px 0;
240
+ color: var(--muted-foreground, #64748b);
241
+ }
242
+ .affiliate-metrics {
243
+ display: flex;
244
+ flex-wrap: wrap;
245
+ gap: 24px 64px;
246
+ margin: 0 0 20px;
247
+ }
248
+ .affiliate-metrics dt {
249
+ color: var(--muted-foreground, #64748b);
250
+ }
251
+ .affiliate-metrics dd {
252
+ margin: 4px 0 0;
253
+ font-size: 30px;
254
+ font-weight: 600;
255
+ font-variant-numeric: tabular-nums;
256
+ }
257
+ .affiliate-application {
258
+ max-width: 760px;
259
+ }
260
+ .affiliate-notice {
261
+ padding: 16px;
262
+ border-left: 3px solid var(--border, #e2e8f0);
263
+ background: var(--muted, #f1f5f9);
264
+ }
265
+ .affiliate-error {
266
+ color: var(--destructive, #b91c1c);
267
+ }
268
+ .affiliate-assets {
269
+ list-style: none;
270
+ padding: 0;
271
+ margin: 0;
272
+ }
273
+ .affiliate-assets > li {
274
+ padding: 16px 0;
275
+ border-bottom: 1px solid var(--border, #e2e8f0);
276
+ }
277
+ .affiliate-assets .affiliate-actions {
278
+ margin-top: 8px;
279
+ }
280
+ .affiliate-sr-only {
281
+ position: absolute;
282
+ width: 1px;
283
+ height: 1px;
284
+ padding: 0;
285
+ margin: -1px;
286
+ overflow: hidden;
287
+ clip-path: inset(50%);
288
+ white-space: nowrap;
289
+ border: 0;
290
+ }
291
+ @media (max-width: 640px) {
292
+ .affiliate-page {
293
+ padding: 24px 16px;
294
+ }
295
+ .affiliate-page h1 {
296
+ font-size: 26px;
297
+ }
298
+ .affiliate-form-grid {
299
+ grid-template-columns: minmax(0, 1fr);
300
+ }
301
+ .affiliate-panel {
302
+ padding: 20px 16px;
303
+ }
304
+ .affiliate-nav {
305
+ gap: 20px;
306
+ }
307
+ .affiliate-page th,
308
+ .affiliate-page td {
309
+ padding: 12px;
310
+ }
311
+ }
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ function calculateCommission(amount, type, value) {
4
+ if (!Number.isSafeInteger(amount) || amount < 0 || !Number.isFinite(value) || value < 0) {
5
+ throw new Error("Invalid commission amount or rule");
6
+ }
7
+ if (type === "flat") {
8
+ if (!Number.isSafeInteger(value))
9
+ throw new Error("Flat commissions require integer minor units");
10
+ return value;
11
+ }
12
+ if (value > 100 || Math.abs(value * 100 - Math.round(value * 100)) > 1e-8) {
13
+ throw new Error(
14
+ "Commission percent must be between 0 and 100 with up to two decimal places"
15
+ );
16
+ }
17
+ const basisPoints = BigInt(Math.round(value * 100));
18
+ const result = Number((BigInt(amount) * basisPoints + 5000n) / 10000n);
19
+ if (!Number.isSafeInteger(result))
20
+ throw new Error("Commission exceeds safe integer range");
21
+ return result;
22
+ }
23
+
24
+ exports.calculateCommission = calculateCommission;
@@ -0,0 +1,22 @@
1
+ function calculateCommission(amount, type, value) {
2
+ if (!Number.isSafeInteger(amount) || amount < 0 || !Number.isFinite(value) || value < 0) {
3
+ throw new Error("Invalid commission amount or rule");
4
+ }
5
+ if (type === "flat") {
6
+ if (!Number.isSafeInteger(value))
7
+ throw new Error("Flat commissions require integer minor units");
8
+ return value;
9
+ }
10
+ if (value > 100 || Math.abs(value * 100 - Math.round(value * 100)) > 1e-8) {
11
+ throw new Error(
12
+ "Commission percent must be between 0 and 100 with up to two decimal places"
13
+ );
14
+ }
15
+ const basisPoints = BigInt(Math.round(value * 100));
16
+ const result = Number((BigInt(amount) * basisPoints + 5000n) / 10000n);
17
+ if (!Number.isSafeInteger(result))
18
+ throw new Error("Commission exceeds safe integer range");
19
+ return result;
20
+ }
21
+
22
+ export { calculateCommission };
package/dist/db.cjs ADDED
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ const db = require('@btst/db');
4
+
5
+ const affiliateSchema = db.createDbPlugin("affiliate", {
6
+ affiliate: {
7
+ modelName: "affiliate",
8
+ fields: {
9
+ userId: { type: "string", required: true, unique: true },
10
+ name: { type: "string", required: true },
11
+ email: { type: "string", required: true, unique: true },
12
+ code: { type: "string", required: true, unique: true },
13
+ status: { type: "string", required: true, defaultValue: "pending" },
14
+ payoutDetails: { type: "string", required: false },
15
+ notes: { type: "string", required: false },
16
+ commissionType: { type: "string", required: false },
17
+ commissionValue: { type: "number", required: false },
18
+ lockVersion: { type: "string", defaultValue: () => crypto.randomUUID() },
19
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() },
20
+ updatedAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
21
+ }
22
+ },
23
+ referralClick: {
24
+ modelName: "referralClick",
25
+ fields: {
26
+ affiliateId: { type: "string", required: true },
27
+ code: { type: "string", required: true },
28
+ landingPath: { type: "string", required: false },
29
+ referrer: { type: "string", required: false },
30
+ ipHash: { type: "string", required: false },
31
+ userAgent: { type: "string", required: false },
32
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
33
+ }
34
+ },
35
+ conversion: {
36
+ modelName: "affiliateConversion",
37
+ fields: {
38
+ affiliateId: { type: "string", required: true },
39
+ clickId: { type: "string", required: false },
40
+ externalRef: { type: "string", required: false, unique: true },
41
+ amount: { type: "number", required: true },
42
+ currency: { type: "string", required: true, defaultValue: "USD" },
43
+ status: { type: "string", required: true, defaultValue: "pending" },
44
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
45
+ }
46
+ },
47
+ commission: {
48
+ modelName: "affiliateCommission",
49
+ fields: {
50
+ affiliateId: { type: "string", required: true },
51
+ conversionId: { type: "string", required: true, unique: true },
52
+ payoutId: { type: "string", required: true, defaultValue: "" },
53
+ amount: { type: "number", required: true },
54
+ currency: { type: "string", required: true, defaultValue: "USD" },
55
+ status: { type: "string", required: true, defaultValue: "pending" },
56
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() },
57
+ updatedAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
58
+ }
59
+ },
60
+ payout: {
61
+ modelName: "affiliatePayout",
62
+ fields: {
63
+ affiliateId: { type: "string", required: true },
64
+ amount: { type: "number", required: true },
65
+ currency: { type: "string", required: true, defaultValue: "USD" },
66
+ status: { type: "string", required: true, defaultValue: "pending" },
67
+ reference: { type: "string", required: false },
68
+ paidAt: { type: "date", required: false },
69
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
70
+ }
71
+ }
72
+ });
73
+
74
+ exports.affiliateSchema = affiliateSchema;
package/dist/db.mjs ADDED
@@ -0,0 +1,72 @@
1
+ import { createDbPlugin } from '@btst/db';
2
+
3
+ const affiliateSchema = createDbPlugin("affiliate", {
4
+ affiliate: {
5
+ modelName: "affiliate",
6
+ fields: {
7
+ userId: { type: "string", required: true, unique: true },
8
+ name: { type: "string", required: true },
9
+ email: { type: "string", required: true, unique: true },
10
+ code: { type: "string", required: true, unique: true },
11
+ status: { type: "string", required: true, defaultValue: "pending" },
12
+ payoutDetails: { type: "string", required: false },
13
+ notes: { type: "string", required: false },
14
+ commissionType: { type: "string", required: false },
15
+ commissionValue: { type: "number", required: false },
16
+ lockVersion: { type: "string", defaultValue: () => crypto.randomUUID() },
17
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() },
18
+ updatedAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
19
+ }
20
+ },
21
+ referralClick: {
22
+ modelName: "referralClick",
23
+ fields: {
24
+ affiliateId: { type: "string", required: true },
25
+ code: { type: "string", required: true },
26
+ landingPath: { type: "string", required: false },
27
+ referrer: { type: "string", required: false },
28
+ ipHash: { type: "string", required: false },
29
+ userAgent: { type: "string", required: false },
30
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
31
+ }
32
+ },
33
+ conversion: {
34
+ modelName: "affiliateConversion",
35
+ fields: {
36
+ affiliateId: { type: "string", required: true },
37
+ clickId: { type: "string", required: false },
38
+ externalRef: { type: "string", required: false, unique: true },
39
+ amount: { type: "number", required: true },
40
+ currency: { type: "string", required: true, defaultValue: "USD" },
41
+ status: { type: "string", required: true, defaultValue: "pending" },
42
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
43
+ }
44
+ },
45
+ commission: {
46
+ modelName: "affiliateCommission",
47
+ fields: {
48
+ affiliateId: { type: "string", required: true },
49
+ conversionId: { type: "string", required: true, unique: true },
50
+ payoutId: { type: "string", required: true, defaultValue: "" },
51
+ amount: { type: "number", required: true },
52
+ currency: { type: "string", required: true, defaultValue: "USD" },
53
+ status: { type: "string", required: true, defaultValue: "pending" },
54
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() },
55
+ updatedAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
56
+ }
57
+ },
58
+ payout: {
59
+ modelName: "affiliatePayout",
60
+ fields: {
61
+ affiliateId: { type: "string", required: true },
62
+ amount: { type: "number", required: true },
63
+ currency: { type: "string", required: true, defaultValue: "USD" },
64
+ status: { type: "string", required: true, defaultValue: "pending" },
65
+ reference: { type: "string", required: false },
66
+ paidAt: { type: "date", required: false },
67
+ createdAt: { type: "date", defaultValue: () => /* @__PURE__ */ new Date() }
68
+ }
69
+ }
70
+ });
71
+
72
+ export { affiliateSchema };
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ const authorization = require('@btst/stack/authorization');
4
+ const zod = require('zod');
5
+
6
+ const affiliateFacts = zod.z.object({
7
+ affiliateId: zod.z.string(),
8
+ userId: zod.z.string(),
9
+ status: zod.z.enum(["pending", "approved", "suspended"])
10
+ });
11
+ const affiliatePermissions = authorization.definePermissions("affiliate", {
12
+ affiliate: {
13
+ read: authorization.permission(
14
+ zod.z.discriminatedUnion("scope", [
15
+ zod.z.object({ scope: zod.z.literal("collection") }),
16
+ zod.z.object({ scope: zod.z.literal("record"), affiliateId: zod.z.string() })
17
+ ])
18
+ ),
19
+ create: authorization.permission(),
20
+ update: authorization.permission(affiliateFacts),
21
+ delete: authorization.permission(affiliateFacts)
22
+ },
23
+ application: { create: authorization.permission() },
24
+ portal: { read: authorization.permission(), update: authorization.permission() },
25
+ tracking: { track: authorization.permission() },
26
+ conversion: { create: authorization.permission() },
27
+ commission: {
28
+ read: authorization.permission(),
29
+ update: authorization.permission(
30
+ zod.z.object({
31
+ commissionId: zod.z.string(),
32
+ affiliateId: zod.z.string(),
33
+ status: zod.z.enum(["pending", "approved", "paid", "voided"])
34
+ })
35
+ )
36
+ },
37
+ payout: {
38
+ read: authorization.permission(),
39
+ create: authorization.permission(
40
+ zod.z.object({ affiliateId: zod.z.string(), currency: zod.z.string() })
41
+ ),
42
+ update: authorization.permission(
43
+ zod.z.object({
44
+ payoutId: zod.z.string(),
45
+ affiliateId: zod.z.string(),
46
+ status: zod.z.enum(["pending", "sent", "failed"])
47
+ })
48
+ ),
49
+ export: authorization.permission()
50
+ }
51
+ });
52
+
53
+ exports.affiliatePermissions = affiliatePermissions;
@@ -0,0 +1,78 @@
1
+ import * as _btst_stack_authorization from '@btst/stack/authorization';
2
+ import { z } from 'zod';
3
+
4
+ /** Administrative permissions are separate from identity-scoped portal access. */
5
+ declare const affiliatePermissions: _btst_stack_authorization.PermissionCatalog<"affiliate", {
6
+ readonly affiliate: {
7
+ readonly read: _btst_stack_authorization.PermissionSeed<z.ZodDiscriminatedUnion<[z.ZodObject<{
8
+ scope: z.ZodLiteral<"collection">;
9
+ }, z.core.$strip>, z.ZodObject<{
10
+ scope: z.ZodLiteral<"record">;
11
+ affiliateId: z.ZodString;
12
+ }, z.core.$strip>], "scope">>;
13
+ readonly create: _btst_stack_authorization.PermissionSeed<undefined>;
14
+ readonly update: _btst_stack_authorization.PermissionSeed<z.ZodObject<{
15
+ affiliateId: z.ZodString;
16
+ userId: z.ZodString;
17
+ status: z.ZodEnum<{
18
+ pending: "pending";
19
+ approved: "approved";
20
+ suspended: "suspended";
21
+ }>;
22
+ }, z.core.$strip>>;
23
+ readonly delete: _btst_stack_authorization.PermissionSeed<z.ZodObject<{
24
+ affiliateId: z.ZodString;
25
+ userId: z.ZodString;
26
+ status: z.ZodEnum<{
27
+ pending: "pending";
28
+ approved: "approved";
29
+ suspended: "suspended";
30
+ }>;
31
+ }, z.core.$strip>>;
32
+ };
33
+ readonly application: {
34
+ readonly create: _btst_stack_authorization.PermissionSeed<undefined>;
35
+ };
36
+ readonly portal: {
37
+ readonly read: _btst_stack_authorization.PermissionSeed<undefined>;
38
+ readonly update: _btst_stack_authorization.PermissionSeed<undefined>;
39
+ };
40
+ readonly tracking: {
41
+ readonly track: _btst_stack_authorization.PermissionSeed<undefined>;
42
+ };
43
+ readonly conversion: {
44
+ readonly create: _btst_stack_authorization.PermissionSeed<undefined>;
45
+ };
46
+ readonly commission: {
47
+ readonly read: _btst_stack_authorization.PermissionSeed<undefined>;
48
+ readonly update: _btst_stack_authorization.PermissionSeed<z.ZodObject<{
49
+ commissionId: z.ZodString;
50
+ affiliateId: z.ZodString;
51
+ status: z.ZodEnum<{
52
+ pending: "pending";
53
+ approved: "approved";
54
+ paid: "paid";
55
+ voided: "voided";
56
+ }>;
57
+ }, z.core.$strip>>;
58
+ };
59
+ readonly payout: {
60
+ readonly read: _btst_stack_authorization.PermissionSeed<undefined>;
61
+ readonly create: _btst_stack_authorization.PermissionSeed<z.ZodObject<{
62
+ affiliateId: z.ZodString;
63
+ currency: z.ZodString;
64
+ }, z.core.$strip>>;
65
+ readonly update: _btst_stack_authorization.PermissionSeed<z.ZodObject<{
66
+ payoutId: z.ZodString;
67
+ affiliateId: z.ZodString;
68
+ status: z.ZodEnum<{
69
+ pending: "pending";
70
+ sent: "sent";
71
+ failed: "failed";
72
+ }>;
73
+ }, z.core.$strip>>;
74
+ readonly export: _btst_stack_authorization.PermissionSeed<undefined>;
75
+ };
76
+ }>;
77
+
78
+ export { affiliatePermissions };