@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.
- package/LICENSE.md +17 -0
- package/dist/api/getters.cjs +182 -0
- package/dist/api/getters.mjs +166 -0
- package/dist/api/index.cjs +49 -0
- package/dist/api/index.d.cts +975 -0
- package/dist/api/index.d.mts +975 -0
- package/dist/api/index.d.ts +975 -0
- package/dist/api/index.mjs +7 -0
- package/dist/api/mutations.cjs +362 -0
- package/dist/api/mutations.mjs +352 -0
- package/dist/api/operations.cjs +328 -0
- package/dist/api/operations.mjs +326 -0
- package/dist/api/plugin.cjs +146 -0
- package/dist/api/plugin.mjs +144 -0
- package/dist/attribution.cjs +92 -0
- package/dist/attribution.d.cts +20 -0
- package/dist/attribution.d.mts +20 -0
- package/dist/attribution.d.ts +20 -0
- package/dist/attribution.mjs +82 -0
- package/dist/client/components/index.cjs +12 -0
- package/dist/client/components/index.d.cts +13 -0
- package/dist/client/components/index.d.mts +13 -0
- package/dist/client/components/index.d.ts +13 -0
- package/dist/client/components/index.mjs +1 -0
- package/dist/client/components/pages/affiliate-apply-page.internal.cjs +59 -0
- package/dist/client/components/pages/affiliate-apply-page.internal.mjs +57 -0
- package/dist/client/components/pages/affiliate-detail-page.internal.cjs +112 -0
- package/dist/client/components/pages/affiliate-detail-page.internal.mjs +110 -0
- package/dist/client/components/pages/affiliate-portal-page.internal.cjs +252 -0
- package/dist/client/components/pages/affiliate-portal-page.internal.mjs +250 -0
- package/dist/client/components/pages/affiliates-page.internal.cjs +160 -0
- package/dist/client/components/pages/affiliates-page.internal.mjs +158 -0
- package/dist/client/components/pages/commissions-page.internal.cjs +151 -0
- package/dist/client/components/pages/commissions-page.internal.mjs +149 -0
- package/dist/client/components/pages/payouts-page.internal.cjs +230 -0
- package/dist/client/components/pages/payouts-page.internal.mjs +228 -0
- package/dist/client/components/pages.cjs +145 -0
- package/dist/client/components/pages.mjs +138 -0
- package/dist/client/components/shared.cjs +331 -0
- package/dist/client/components/shared.mjs +316 -0
- package/dist/client/constants.cjs +5 -0
- package/dist/client/constants.mjs +3 -0
- package/dist/client/hooks/index.cjs +77 -0
- package/dist/client/hooks/index.d.cts +39 -0
- package/dist/client/hooks/index.d.mts +39 -0
- package/dist/client/hooks/index.d.ts +39 -0
- package/dist/client/hooks/index.mjs +61 -0
- package/dist/client/index.cjs +7 -0
- package/dist/client/index.d.cts +110 -0
- package/dist/client/index.d.mts +110 -0
- package/dist/client/index.d.ts +110 -0
- package/dist/client/index.mjs +1 -0
- package/dist/client/plugin.cjs +77 -0
- package/dist/client/plugin.mjs +75 -0
- package/dist/client.css +311 -0
- package/dist/commission.cjs +24 -0
- package/dist/commission.mjs +22 -0
- package/dist/db.cjs +74 -0
- package/dist/db.mjs +72 -0
- package/dist/permissions.cjs +53 -0
- package/dist/permissions.d.cts +78 -0
- package/dist/permissions.d.mts +78 -0
- package/dist/permissions.d.ts +78 -0
- package/dist/permissions.mjs +51 -0
- package/dist/query-keys.cjs +152 -0
- package/dist/query-keys.d.cts +394 -0
- package/dist/query-keys.d.mts +394 -0
- package/dist/query-keys.d.ts +394 -0
- package/dist/query-keys.mjs +149 -0
- package/dist/schemas.cjs +95 -0
- package/dist/schemas.mjs +77 -0
- package/dist/style.css +313 -0
- package/dist/types.cjs +2 -0
- package/dist/types.d.cts +176 -0
- package/dist/types.d.mts +176 -0
- package/dist/types.d.ts +176 -0
- package/dist/types.mjs +1 -0
- package/package.json +159 -3
- package/README.md +0 -3
package/dist/schemas.mjs
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
const affiliateCodeSchema = z.string().trim().min(3).max(64).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
|
|
4
|
+
const moneySchema = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
5
|
+
const currencySchema = z.string().regex(/^[A-Z]{3}$/);
|
|
6
|
+
const affiliateStatusSchema = z.enum([
|
|
7
|
+
"pending",
|
|
8
|
+
"approved",
|
|
9
|
+
"suspended"
|
|
10
|
+
]);
|
|
11
|
+
const commissionTypeSchema = z.enum(["percent", "flat"]);
|
|
12
|
+
z.enum([
|
|
13
|
+
"pending",
|
|
14
|
+
"approved",
|
|
15
|
+
"paid",
|
|
16
|
+
"voided"
|
|
17
|
+
]);
|
|
18
|
+
z.enum(["pending", "sent", "failed"]);
|
|
19
|
+
const idSchema = z.object({ id: z.string().min(1) });
|
|
20
|
+
const listSchema = z.object({
|
|
21
|
+
limit: z.coerce.number().int().min(1).max(100).optional(),
|
|
22
|
+
offset: z.coerce.number().int().nonnegative().optional(),
|
|
23
|
+
affiliateId: z.string().min(1).optional(),
|
|
24
|
+
status: z.string().optional(),
|
|
25
|
+
currency: currencySchema.optional()
|
|
26
|
+
});
|
|
27
|
+
const affiliateListSchema = listSchema.pick({ limit: true, offset: true, status: true }).extend({ status: affiliateStatusSchema.optional() });
|
|
28
|
+
const applicationSchema = z.object({
|
|
29
|
+
name: z.string().trim().min(1).max(200),
|
|
30
|
+
email: z.email().max(320),
|
|
31
|
+
code: affiliateCodeSchema.optional(),
|
|
32
|
+
payoutDetails: z.string().max(1e4).optional()
|
|
33
|
+
});
|
|
34
|
+
const createAffiliateSchema = applicationSchema.extend({
|
|
35
|
+
userId: z.string().min(1)
|
|
36
|
+
});
|
|
37
|
+
const updateAffiliateSchema = applicationSchema.partial().extend({
|
|
38
|
+
payoutDetails: z.string().max(1e4).nullable().optional(),
|
|
39
|
+
status: affiliateStatusSchema.optional(),
|
|
40
|
+
notes: z.string().max(1e4).nullable().optional(),
|
|
41
|
+
commissionType: commissionTypeSchema.nullable().optional(),
|
|
42
|
+
commissionValue: z.number().finite().nonnegative().nullable().optional()
|
|
43
|
+
});
|
|
44
|
+
const updatePortalSchema = applicationSchema.partial().extend({ payoutDetails: z.string().max(1e4).nullable().optional() });
|
|
45
|
+
const trackClickSchema = z.object({
|
|
46
|
+
code: affiliateCodeSchema,
|
|
47
|
+
landingPath: z.string().max(2048).optional(),
|
|
48
|
+
referrer: z.string().max(2048).optional(),
|
|
49
|
+
ipHash: z.string().max(256).optional(),
|
|
50
|
+
userAgent: z.string().max(2048).optional()
|
|
51
|
+
});
|
|
52
|
+
const createConversionSchema = z.object({
|
|
53
|
+
externalRef: z.string().min(1).max(255).optional(),
|
|
54
|
+
amount: moneySchema,
|
|
55
|
+
currency: currencySchema.default("USD"),
|
|
56
|
+
attribution: z.object({
|
|
57
|
+
code: affiliateCodeSchema.optional(),
|
|
58
|
+
clickId: z.string().min(1).optional()
|
|
59
|
+
}).refine(
|
|
60
|
+
(v) => v.code || v.clickId,
|
|
61
|
+
"Attribution requires a code or click ID"
|
|
62
|
+
).optional()
|
|
63
|
+
});
|
|
64
|
+
const updateCommissionSchema = z.object({
|
|
65
|
+
status: z.enum(["approved", "voided"])
|
|
66
|
+
});
|
|
67
|
+
const createPayoutSchema = z.object({
|
|
68
|
+
affiliateId: z.string().min(1),
|
|
69
|
+
currency: currencySchema,
|
|
70
|
+
commissionIds: z.array(z.string().min(1)).min(1).max(1e3).optional()
|
|
71
|
+
});
|
|
72
|
+
const updatePayoutSchema = z.object({
|
|
73
|
+
status: z.enum(["sent", "failed"]),
|
|
74
|
+
reference: z.string().max(1e3).optional()
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
export { affiliateCodeSchema, affiliateListSchema, affiliateStatusSchema, applicationSchema, commissionTypeSchema, createAffiliateSchema, createConversionSchema, createPayoutSchema, currencySchema, idSchema, listSchema, moneySchema, trackClickSchema, updateAffiliateSchema, updateCommissionSchema, updatePayoutSchema, updatePortalSchema };
|
package/dist/style.css
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
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
|
+
}
|
|
312
|
+
|
|
313
|
+
@source "./**/*.{mjs,cjs}";
|
package/dist/types.cjs
ADDED
package/dist/types.d.cts
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/** Application review and referral eligibility state. */
|
|
2
|
+
type AffiliateStatus = "pending" | "approved" | "suspended";
|
|
3
|
+
/** Percentage points or a fixed amount in currency minor units. */
|
|
4
|
+
type CommissionType = "percent" | "flat";
|
|
5
|
+
/** Review and settlement state; payouts alone move commissions to paid. */
|
|
6
|
+
type CommissionStatus = "pending" | "approved" | "paid" | "voided";
|
|
7
|
+
/** Manual payment outcome; failed batches release their reserved commissions. */
|
|
8
|
+
type PayoutStatus = "pending" | "sent" | "failed";
|
|
9
|
+
/** Partner profile with ISO timestamp strings and optional administrative notes. */
|
|
10
|
+
interface Affiliate {
|
|
11
|
+
id: string;
|
|
12
|
+
/** Authenticated account that exclusively owns this profile's portal. */
|
|
13
|
+
userId: string;
|
|
14
|
+
name: string;
|
|
15
|
+
email: string;
|
|
16
|
+
code: string;
|
|
17
|
+
status: AffiliateStatus;
|
|
18
|
+
/** Payment instructions stored as text, without processor-specific validation. */
|
|
19
|
+
payoutDetails?: string | null;
|
|
20
|
+
/** Administrative notes, omitted from portal responses. */
|
|
21
|
+
notes?: string | null;
|
|
22
|
+
commissionType?: CommissionType | null;
|
|
23
|
+
commissionValue?: number | null;
|
|
24
|
+
createdAt: string;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
}
|
|
27
|
+
/** Recorded visit; its stored ISO timestamp determines cookie attribution eligibility. */
|
|
28
|
+
interface ReferralClick {
|
|
29
|
+
id: string;
|
|
30
|
+
affiliateId: string;
|
|
31
|
+
code: string;
|
|
32
|
+
landingPath?: string | null;
|
|
33
|
+
referrer?: string | null;
|
|
34
|
+
/** Optional hash supplied by a trusted integration; HTTP tracking does not collect IPs. */
|
|
35
|
+
ipHash?: string | null;
|
|
36
|
+
userAgent?: string | null;
|
|
37
|
+
createdAt: string;
|
|
38
|
+
}
|
|
39
|
+
/** Attributed order/event with a safe integer amount in currency minor units. */
|
|
40
|
+
interface Conversion {
|
|
41
|
+
id: string;
|
|
42
|
+
affiliateId: string;
|
|
43
|
+
clickId?: string | null;
|
|
44
|
+
/** Stable order/event identifier used to deduplicate conversion retries. */
|
|
45
|
+
externalRef?: string | null;
|
|
46
|
+
amount: number;
|
|
47
|
+
currency: string;
|
|
48
|
+
status: "pending" | "approved" | "rejected";
|
|
49
|
+
createdAt: string;
|
|
50
|
+
}
|
|
51
|
+
/** Earnings from one conversion, expressed in currency minor units with ISO timestamps. */
|
|
52
|
+
interface Commission {
|
|
53
|
+
id: string;
|
|
54
|
+
affiliateId: string;
|
|
55
|
+
conversionId: string;
|
|
56
|
+
/** Pending or settled payout reservation; empty when available for a new batch. */
|
|
57
|
+
payoutId?: string | null;
|
|
58
|
+
amount: number;
|
|
59
|
+
currency: string;
|
|
60
|
+
status: CommissionStatus;
|
|
61
|
+
createdAt: string;
|
|
62
|
+
updatedAt: string;
|
|
63
|
+
}
|
|
64
|
+
/** One affiliate's manual payment batch in one currency; dates are ISO strings. */
|
|
65
|
+
interface Payout {
|
|
66
|
+
id: string;
|
|
67
|
+
affiliateId: string;
|
|
68
|
+
amount: number;
|
|
69
|
+
currency: string;
|
|
70
|
+
status: PayoutStatus;
|
|
71
|
+
reference?: string | null;
|
|
72
|
+
paidAt?: string | null;
|
|
73
|
+
createdAt: string;
|
|
74
|
+
}
|
|
75
|
+
/** Offset pagination and filters for affiliate administration lists. */
|
|
76
|
+
interface ListParams {
|
|
77
|
+
limit?: number;
|
|
78
|
+
offset?: number;
|
|
79
|
+
affiliateId?: string;
|
|
80
|
+
status?: string;
|
|
81
|
+
currency?: string;
|
|
82
|
+
}
|
|
83
|
+
/** A page of records and the total count before pagination. */
|
|
84
|
+
interface ListResult<T> {
|
|
85
|
+
items: T[];
|
|
86
|
+
total: number;
|
|
87
|
+
limit: number;
|
|
88
|
+
offset: number;
|
|
89
|
+
}
|
|
90
|
+
/** Referral counts and commission minor-unit totals, grouped separately per currency. */
|
|
91
|
+
interface AffiliateStats {
|
|
92
|
+
clicks: number;
|
|
93
|
+
conversions: number;
|
|
94
|
+
totals: {
|
|
95
|
+
currency: string;
|
|
96
|
+
pending: number;
|
|
97
|
+
approved: number;
|
|
98
|
+
paid: number;
|
|
99
|
+
voided: number;
|
|
100
|
+
}[];
|
|
101
|
+
}
|
|
102
|
+
/** HTTP(S) landing-page template and optional banner link shown to partners. */
|
|
103
|
+
interface MarketingAsset {
|
|
104
|
+
name: string;
|
|
105
|
+
url: string;
|
|
106
|
+
description?: string;
|
|
107
|
+
bannerUrl?: string;
|
|
108
|
+
}
|
|
109
|
+
/** One account's profile, totals, recent financial history, and program marketing assets. */
|
|
110
|
+
interface AffiliatePortal {
|
|
111
|
+
affiliate: Affiliate | null;
|
|
112
|
+
stats: AffiliateStats;
|
|
113
|
+
commissions: Commission[];
|
|
114
|
+
payouts: Payout[];
|
|
115
|
+
assets: MarketingAsset[];
|
|
116
|
+
}
|
|
117
|
+
/** Pending-profile input; administrators supply ownership, applications use request identity. */
|
|
118
|
+
interface CreateAffiliateInput {
|
|
119
|
+
userId: string;
|
|
120
|
+
name: string;
|
|
121
|
+
email: string;
|
|
122
|
+
code?: string;
|
|
123
|
+
payoutDetails?: string;
|
|
124
|
+
}
|
|
125
|
+
/** Administrative profile edits; commission override type and value must be set or cleared together. */
|
|
126
|
+
interface UpdateAffiliateInput {
|
|
127
|
+
name?: string;
|
|
128
|
+
email?: string;
|
|
129
|
+
code?: string;
|
|
130
|
+
status?: AffiliateStatus;
|
|
131
|
+
payoutDetails?: string | null;
|
|
132
|
+
notes?: string | null;
|
|
133
|
+
commissionType?: CommissionType | null;
|
|
134
|
+
commissionValue?: number | null;
|
|
135
|
+
}
|
|
136
|
+
/** A referral visit and optional metadata supplied by the tracking transport or trusted caller. */
|
|
137
|
+
interface TrackClickInput {
|
|
138
|
+
code: string;
|
|
139
|
+
landingPath?: string;
|
|
140
|
+
referrer?: string;
|
|
141
|
+
ipHash?: string;
|
|
142
|
+
userAgent?: string;
|
|
143
|
+
}
|
|
144
|
+
/** Verified order/event amount and attribution; omitted attribution returns null without a request fallback. */
|
|
145
|
+
interface CreateConversionInput {
|
|
146
|
+
externalRef?: string;
|
|
147
|
+
amount: number;
|
|
148
|
+
currency?: string;
|
|
149
|
+
attribution?: {
|
|
150
|
+
code?: string;
|
|
151
|
+
clickId?: string;
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/** Reserve selected or all available approved commissions for one affiliate and currency. */
|
|
155
|
+
interface CreatePayoutInput {
|
|
156
|
+
affiliateId: string;
|
|
157
|
+
currency: string;
|
|
158
|
+
commissionIds?: string[];
|
|
159
|
+
}
|
|
160
|
+
/** Attribution window, default commission rule, and optional partner marketing assets. */
|
|
161
|
+
interface AffiliateOptions {
|
|
162
|
+
/** Trusted HTTP(S) site origin for tracking redirects when the API uses a separate origin. */
|
|
163
|
+
siteOrigin?: string;
|
|
164
|
+
/** Number of days a stored referral click remains eligible. Defaults to 30. */
|
|
165
|
+
attributionWindowDays?: number;
|
|
166
|
+
/** Whether a new tracked referral replaces the existing cookie. Defaults to last_touch. */
|
|
167
|
+
attributionMode?: "first_touch" | "last_touch";
|
|
168
|
+
/** Default commission rule, unless the affiliate has an override. Defaults to percent. */
|
|
169
|
+
defaultCommissionType?: CommissionType;
|
|
170
|
+
/** Percentage (up to two decimals) or integer minor units for flat rules. Defaults to 20. */
|
|
171
|
+
defaultCommissionValue?: number;
|
|
172
|
+
/** Optional landing page templates and banner metadata displayed in the portal. */
|
|
173
|
+
marketingAssets?: MarketingAsset[];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export type { Affiliate, AffiliateOptions, AffiliatePortal, AffiliateStats, AffiliateStatus, Commission, CommissionStatus, CommissionType, Conversion, CreateAffiliateInput, CreateConversionInput, CreatePayoutInput, ListParams, ListResult, MarketingAsset, Payout, PayoutStatus, ReferralClick, TrackClickInput, UpdateAffiliateInput };
|