@volchoklv/newsletter-kit 1.0.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/README.md +505 -0
- package/dist/adapters/email/index.d.ts +119 -0
- package/dist/adapters/email/index.js +417 -0
- package/dist/adapters/email/index.js.map +1 -0
- package/dist/adapters/storage/index.d.ts +215 -0
- package/dist/adapters/storage/index.js +415 -0
- package/dist/adapters/storage/index.js.map +1 -0
- package/dist/components/index.d.ts +198 -0
- package/dist/components/index.js +505 -0
- package/dist/components/index.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.js +1762 -0
- package/dist/index.js.map +1 -0
- package/dist/server/index.d.ts +77 -0
- package/dist/server/index.js +530 -0
- package/dist/server/index.js.map +1 -0
- package/dist/types-BmajlhNp.d.ts +226 -0
- package/package.json +95 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
type SubscriptionStatus = 'pending' | 'confirmed' | 'unsubscribed';
|
|
2
|
+
interface Subscriber {
|
|
3
|
+
id: string;
|
|
4
|
+
email: string;
|
|
5
|
+
status: SubscriptionStatus;
|
|
6
|
+
source?: string;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
metadata?: Record<string, unknown>;
|
|
9
|
+
consentIp?: string;
|
|
10
|
+
consentAt?: Date;
|
|
11
|
+
confirmedAt?: Date;
|
|
12
|
+
unsubscribedAt?: Date;
|
|
13
|
+
createdAt: Date;
|
|
14
|
+
updatedAt: Date;
|
|
15
|
+
}
|
|
16
|
+
interface SubscribeInput {
|
|
17
|
+
email: string;
|
|
18
|
+
source?: string;
|
|
19
|
+
tags?: string[];
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
ip?: string;
|
|
22
|
+
}
|
|
23
|
+
interface SubscribeResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
message: string;
|
|
26
|
+
subscriber?: Subscriber;
|
|
27
|
+
requiresConfirmation?: boolean;
|
|
28
|
+
}
|
|
29
|
+
interface ConfirmResult {
|
|
30
|
+
success: boolean;
|
|
31
|
+
message: string;
|
|
32
|
+
subscriber?: Subscriber;
|
|
33
|
+
}
|
|
34
|
+
interface UnsubscribeResult {
|
|
35
|
+
success: boolean;
|
|
36
|
+
message: string;
|
|
37
|
+
}
|
|
38
|
+
interface EmailTemplates {
|
|
39
|
+
confirmation?: {
|
|
40
|
+
subject?: string;
|
|
41
|
+
html?: (data: {
|
|
42
|
+
confirmUrl: string;
|
|
43
|
+
email: string;
|
|
44
|
+
}) => string;
|
|
45
|
+
text?: (data: {
|
|
46
|
+
confirmUrl: string;
|
|
47
|
+
email: string;
|
|
48
|
+
}) => string;
|
|
49
|
+
};
|
|
50
|
+
welcome?: {
|
|
51
|
+
subject?: string;
|
|
52
|
+
html?: (data: {
|
|
53
|
+
email: string;
|
|
54
|
+
}) => string;
|
|
55
|
+
text?: (data: {
|
|
56
|
+
email: string;
|
|
57
|
+
}) => string;
|
|
58
|
+
};
|
|
59
|
+
unsubscribed?: {
|
|
60
|
+
subject?: string;
|
|
61
|
+
html?: (data: {
|
|
62
|
+
email: string;
|
|
63
|
+
resubscribeUrl?: string;
|
|
64
|
+
}) => string;
|
|
65
|
+
text?: (data: {
|
|
66
|
+
email: string;
|
|
67
|
+
resubscribeUrl?: string;
|
|
68
|
+
}) => string;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
interface EmailAdapter {
|
|
72
|
+
/**
|
|
73
|
+
* Send confirmation email for double opt-in
|
|
74
|
+
*/
|
|
75
|
+
sendConfirmation(email: string, token: string, confirmUrl: string): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Send welcome email after subscription confirmed
|
|
78
|
+
*/
|
|
79
|
+
sendWelcome(email: string): Promise<void>;
|
|
80
|
+
/**
|
|
81
|
+
* Optional: Send unsubscribe confirmation
|
|
82
|
+
*/
|
|
83
|
+
sendUnsubscribed?(email: string, resubscribeUrl?: string): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Optional: Notify admin of new subscriber
|
|
86
|
+
*/
|
|
87
|
+
notifyAdmin?(subscriber: Subscriber): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
interface EmailAdapterConfig {
|
|
90
|
+
from: string;
|
|
91
|
+
replyTo?: string;
|
|
92
|
+
templates?: EmailTemplates;
|
|
93
|
+
adminEmail?: string;
|
|
94
|
+
}
|
|
95
|
+
interface StorageAdapter {
|
|
96
|
+
/**
|
|
97
|
+
* Create or update a subscriber (upsert behavior)
|
|
98
|
+
*/
|
|
99
|
+
createSubscriber(input: SubscribeInput, token?: string): Promise<Subscriber>;
|
|
100
|
+
/**
|
|
101
|
+
* Get subscriber by email
|
|
102
|
+
*/
|
|
103
|
+
getSubscriberByEmail(email: string): Promise<Subscriber | null>;
|
|
104
|
+
/**
|
|
105
|
+
* Get subscriber by confirmation token
|
|
106
|
+
*/
|
|
107
|
+
getSubscriberByToken(token: string): Promise<Subscriber | null>;
|
|
108
|
+
/**
|
|
109
|
+
* Confirm a subscriber (set status to confirmed)
|
|
110
|
+
*/
|
|
111
|
+
confirmSubscriber(token: string): Promise<Subscriber | null>;
|
|
112
|
+
/**
|
|
113
|
+
* Unsubscribe by email
|
|
114
|
+
*/
|
|
115
|
+
unsubscribe(email: string): Promise<boolean>;
|
|
116
|
+
/**
|
|
117
|
+
* List subscribers with optional filters
|
|
118
|
+
*/
|
|
119
|
+
listSubscribers?(options?: {
|
|
120
|
+
status?: SubscriptionStatus;
|
|
121
|
+
source?: string;
|
|
122
|
+
tags?: string[];
|
|
123
|
+
limit?: number;
|
|
124
|
+
offset?: number;
|
|
125
|
+
}): Promise<{
|
|
126
|
+
subscribers: Subscriber[];
|
|
127
|
+
total: number;
|
|
128
|
+
}>;
|
|
129
|
+
/**
|
|
130
|
+
* Delete subscriber permanently
|
|
131
|
+
*/
|
|
132
|
+
deleteSubscriber?(email: string): Promise<boolean>;
|
|
133
|
+
/**
|
|
134
|
+
* Update subscriber metadata/tags
|
|
135
|
+
*/
|
|
136
|
+
updateSubscriber?(email: string, data: Partial<Subscriber>): Promise<Subscriber | null>;
|
|
137
|
+
}
|
|
138
|
+
interface RateLimitConfig {
|
|
139
|
+
/** Max requests per window */
|
|
140
|
+
max: number;
|
|
141
|
+
/** Window size in seconds */
|
|
142
|
+
windowSeconds: number;
|
|
143
|
+
/** Identifier function - defaults to IP */
|
|
144
|
+
identifier?: (req: Request) => string;
|
|
145
|
+
}
|
|
146
|
+
interface NewsletterConfig {
|
|
147
|
+
/** Email sending adapter */
|
|
148
|
+
emailAdapter: EmailAdapter;
|
|
149
|
+
/** Storage adapter (optional - if not provided, emails are sent but not stored) */
|
|
150
|
+
storageAdapter?: StorageAdapter;
|
|
151
|
+
/** Require email confirmation (double opt-in) */
|
|
152
|
+
doubleOptIn?: boolean;
|
|
153
|
+
/** Base URL for confirmation/unsubscribe links */
|
|
154
|
+
baseUrl: string;
|
|
155
|
+
/** Path for confirmation endpoint */
|
|
156
|
+
confirmPath?: string;
|
|
157
|
+
/** Path for unsubscribe endpoint */
|
|
158
|
+
unsubscribePath?: string;
|
|
159
|
+
/** Honeypot field name for bot protection */
|
|
160
|
+
honeypotField?: string;
|
|
161
|
+
/** Rate limiting config */
|
|
162
|
+
rateLimit?: RateLimitConfig;
|
|
163
|
+
/** Custom validation for email */
|
|
164
|
+
validateEmail?: (email: string) => boolean | Promise<boolean>;
|
|
165
|
+
/** Allowed sources (for source tracking) */
|
|
166
|
+
allowedSources?: string[];
|
|
167
|
+
/** Default tags to apply */
|
|
168
|
+
defaultTags?: string[];
|
|
169
|
+
/** Callbacks */
|
|
170
|
+
onSubscribe?: (subscriber: Subscriber) => void | Promise<void>;
|
|
171
|
+
onConfirm?: (subscriber: Subscriber) => void | Promise<void>;
|
|
172
|
+
onUnsubscribe?: (email: string) => void | Promise<void>;
|
|
173
|
+
onError?: (error: Error, context: string) => void | Promise<void>;
|
|
174
|
+
}
|
|
175
|
+
interface NewsletterFormProps {
|
|
176
|
+
/** API endpoint for subscription */
|
|
177
|
+
endpoint?: string;
|
|
178
|
+
/** Source identifier for tracking */
|
|
179
|
+
source?: string;
|
|
180
|
+
/** Tags to apply to subscriber */
|
|
181
|
+
tags?: string[];
|
|
182
|
+
/** Honeypot field name (must match server config) */
|
|
183
|
+
honeypotField?: string;
|
|
184
|
+
/** Custom class names */
|
|
185
|
+
className?: string;
|
|
186
|
+
formClassName?: string;
|
|
187
|
+
inputClassName?: string;
|
|
188
|
+
buttonClassName?: string;
|
|
189
|
+
messageClassName?: string;
|
|
190
|
+
/** Custom text */
|
|
191
|
+
placeholder?: string;
|
|
192
|
+
buttonText?: string;
|
|
193
|
+
loadingText?: string;
|
|
194
|
+
successMessage?: string;
|
|
195
|
+
errorMessage?: string;
|
|
196
|
+
/** Show inline message or use callback only */
|
|
197
|
+
showMessage?: boolean;
|
|
198
|
+
/** Callbacks */
|
|
199
|
+
onSuccess?: (email: string, message: string) => void;
|
|
200
|
+
onError?: (error: string) => void;
|
|
201
|
+
onSubmit?: (email: string) => void;
|
|
202
|
+
/** Disable the form */
|
|
203
|
+
disabled?: boolean;
|
|
204
|
+
/** Additional metadata to send */
|
|
205
|
+
metadata?: Record<string, unknown>;
|
|
206
|
+
}
|
|
207
|
+
interface NewsletterFormState {
|
|
208
|
+
status: 'idle' | 'loading' | 'success' | 'error';
|
|
209
|
+
message: string;
|
|
210
|
+
email: string;
|
|
211
|
+
}
|
|
212
|
+
interface SubscribeRequest {
|
|
213
|
+
email: string;
|
|
214
|
+
source?: string;
|
|
215
|
+
tags?: string[];
|
|
216
|
+
metadata?: Record<string, unknown>;
|
|
217
|
+
[key: string]: unknown;
|
|
218
|
+
}
|
|
219
|
+
interface APIResponse<T = unknown> {
|
|
220
|
+
success: boolean;
|
|
221
|
+
message: string;
|
|
222
|
+
data?: T;
|
|
223
|
+
error?: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export type { APIResponse as A, ConfirmResult as C, EmailAdapter as E, NewsletterConfig as N, RateLimitConfig as R, StorageAdapter as S, UnsubscribeResult as U, EmailAdapterConfig as a, EmailTemplates as b, NewsletterFormProps as c, NewsletterFormState as d, SubscribeInput as e, SubscribeRequest as f, SubscribeResult as g, Subscriber as h, SubscriptionStatus as i };
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@volchoklv/newsletter-kit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Drop-in newsletter subscription components and API handlers for Next.js with adapter support for email providers and storage backends",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./components": {
|
|
15
|
+
"types": "./dist/components/index.d.ts",
|
|
16
|
+
"import": "./dist/components/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./server": {
|
|
19
|
+
"types": "./dist/server/index.d.ts",
|
|
20
|
+
"import": "./dist/server/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./adapters/email": {
|
|
23
|
+
"types": "./dist/adapters/email/index.d.ts",
|
|
24
|
+
"import": "./dist/adapters/email/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./adapters/storage": {
|
|
27
|
+
"types": "./dist/adapters/storage/index.d.ts",
|
|
28
|
+
"import": "./dist/adapters/storage/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"README.md"
|
|
34
|
+
],
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsup",
|
|
37
|
+
"dev": "tsup --watch",
|
|
38
|
+
"lint": "eslint src/",
|
|
39
|
+
"type-check": "tsc --noEmit",
|
|
40
|
+
"prepublishOnly": "npm run build"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"next": "^14.0.0 || ^15.0.0",
|
|
44
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
45
|
+
"react-dom": "^18.0.0 || ^19.0.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependenciesMeta": {
|
|
48
|
+
"@prisma/client": {
|
|
49
|
+
"optional": true
|
|
50
|
+
},
|
|
51
|
+
"@supabase/supabase-js": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"resend": {
|
|
55
|
+
"optional": true
|
|
56
|
+
},
|
|
57
|
+
"nodemailer": {
|
|
58
|
+
"optional": true
|
|
59
|
+
},
|
|
60
|
+
"@mailchimp/mailchimp_marketing": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@mailchimp/mailchimp_marketing": "^3.0.80",
|
|
66
|
+
"@prisma/client": "^7.3.0",
|
|
67
|
+
"@supabase/supabase-js": "^2.91.1",
|
|
68
|
+
"@types/mailchimp__mailchimp_marketing": "^3.0.22",
|
|
69
|
+
"@types/node": "^20.0.0",
|
|
70
|
+
"@types/nodemailer": "^6.4.14",
|
|
71
|
+
"@types/react": "^18.0.0",
|
|
72
|
+
"eslint": "^8.0.0",
|
|
73
|
+
"resend": "^6.8.0",
|
|
74
|
+
"tsup": "^8.0.0",
|
|
75
|
+
"typescript": "^5.0.0"
|
|
76
|
+
},
|
|
77
|
+
"keywords": [
|
|
78
|
+
"newsletter",
|
|
79
|
+
"email",
|
|
80
|
+
"subscription",
|
|
81
|
+
"nextjs",
|
|
82
|
+
"react",
|
|
83
|
+
"resend",
|
|
84
|
+
"nodemailer",
|
|
85
|
+
"prisma",
|
|
86
|
+
"supabase",
|
|
87
|
+
"shadcn"
|
|
88
|
+
],
|
|
89
|
+
"author": "Volchok",
|
|
90
|
+
"license": "MIT",
|
|
91
|
+
"repository": {
|
|
92
|
+
"type": "git",
|
|
93
|
+
"url": "https://github.com/volchoklv/newsletter-kit"
|
|
94
|
+
}
|
|
95
|
+
}
|