@bernierllc/email 1.0.1 → 1.1.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 +76 -217
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/simple-email-service.d.ts +58 -0
- package/dist/simple-email-service.d.ts.map +1 -0
- package/dist/simple-email-service.js +416 -0
- package/dist/simple-email-service.js.map +1 -0
- package/dist/types.d.ts +311 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +33 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -22
- package/.eslintrc.json +0 -112
- package/.flake8 +0 -18
- package/.github/workflows/ci.yml +0 -300
- package/EXTRACTION_SUMMARY.md +0 -265
- package/IMPLEMENTATION_STATUS.md +0 -159
- package/OPEN_SOURCE_SETUP.md +0 -420
- package/PACKAGE_USAGE.md +0 -471
- package/examples/fastapi-example/main.py +0 -257
- package/examples/nextjs-example/next-env.d.ts +0 -13
- package/examples/nextjs-example/package.json +0 -26
- package/examples/nextjs-example/pages/admin/templates.tsx +0 -157
- package/examples/nextjs-example/tsconfig.json +0 -28
- package/packages/core/package.json +0 -70
- package/packages/core/rollup.config.js +0 -37
- package/packages/core/specification.md +0 -416
- package/packages/core/src/adapters/supabase.ts +0 -291
- package/packages/core/src/core/scheduler.ts +0 -356
- package/packages/core/src/core/template-manager.ts +0 -388
- package/packages/core/src/index.ts +0 -30
- package/packages/core/src/providers/base.ts +0 -104
- package/packages/core/src/providers/sendgrid.ts +0 -368
- package/packages/core/src/types/provider.ts +0 -91
- package/packages/core/src/types/scheduled.ts +0 -78
- package/packages/core/src/types/template.ts +0 -97
- package/packages/core/tsconfig.json +0 -23
- package/packages/python/README.md +0 -106
- package/packages/python/email_template_manager/__init__.py +0 -66
- package/packages/python/email_template_manager/config.py +0 -98
- package/packages/python/email_template_manager/core/magic_links.py +0 -245
- package/packages/python/email_template_manager/core/manager.py +0 -344
- package/packages/python/email_template_manager/core/scheduler.py +0 -473
- package/packages/python/email_template_manager/exceptions.py +0 -67
- package/packages/python/email_template_manager/models/magic_link.py +0 -59
- package/packages/python/email_template_manager/models/scheduled.py +0 -78
- package/packages/python/email_template_manager/models/template.py +0 -90
- package/packages/python/email_template_manager/providers/aws_ses.py +0 -44
- package/packages/python/email_template_manager/providers/base.py +0 -94
- package/packages/python/email_template_manager/providers/sendgrid.py +0 -325
- package/packages/python/email_template_manager/providers/smtp.py +0 -44
- package/packages/python/pyproject.toml +0 -133
- package/packages/python/setup.py +0 -93
- package/packages/python/specification.md +0 -930
- package/packages/react/README.md +0 -13
- package/packages/react/package.json +0 -105
- package/packages/react/rollup.config.js +0 -37
- package/packages/react/specification.md +0 -569
- package/packages/react/src/index.ts +0 -20
- package/packages/react/tsconfig.json +0 -24
- package/plans/email-template-manager_app-admin.md +0 -590
- package/src/index.js +0 -1
- package/test_package.py +0 -125
package/PACKAGE_USAGE.md
DELETED
|
@@ -1,471 +0,0 @@
|
|
|
1
|
-
# Email Template Manager - Package Usage Guide
|
|
2
|
-
|
|
3
|
-
This guide shows how to use the Email Template Manager as importable packages in your Python, React, and Next.js applications.
|
|
4
|
-
|
|
5
|
-
## Python Package Usage
|
|
6
|
-
|
|
7
|
-
### Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# Basic installation
|
|
11
|
-
pip install email-template-manager
|
|
12
|
-
|
|
13
|
-
# With SendGrid support
|
|
14
|
-
pip install email-template-manager[sendgrid]
|
|
15
|
-
|
|
16
|
-
# With FastAPI integration
|
|
17
|
-
pip install email-template-manager[fastapi,sendgrid]
|
|
18
|
-
|
|
19
|
-
# With all providers and frameworks
|
|
20
|
-
pip install email-template-manager[all]
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Basic Python Usage
|
|
24
|
-
|
|
25
|
-
```python
|
|
26
|
-
from email_template_manager import (
|
|
27
|
-
EmailTemplateManager,
|
|
28
|
-
EmailScheduler,
|
|
29
|
-
SendGridProvider,
|
|
30
|
-
EmailTemplate,
|
|
31
|
-
ScheduledEmail
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
# Initialize the email provider
|
|
35
|
-
email_provider = SendGridProvider({
|
|
36
|
-
'api_key': 'your-sendgrid-api-key',
|
|
37
|
-
'from_email': 'noreply@yourapp.com',
|
|
38
|
-
'from_name': 'Your App'
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
# Initialize the template manager
|
|
42
|
-
template_manager = EmailTemplateManager(
|
|
43
|
-
database_url='postgresql://user:pass@localhost/db'
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
# Initialize the scheduler
|
|
47
|
-
scheduler = EmailScheduler(template_manager, email_provider)
|
|
48
|
-
|
|
49
|
-
# Create an email template
|
|
50
|
-
template = EmailTemplate(
|
|
51
|
-
name='Welcome Email',
|
|
52
|
-
subject='Welcome to {{app_name}}!',
|
|
53
|
-
html_body='<h1>Hello {{name}}!</h1><p>Welcome to {{app_name}}.</p>',
|
|
54
|
-
text_body='Hello {{name}}! Welcome to {{app_name}}.',
|
|
55
|
-
variables=[
|
|
56
|
-
{'name': 'name', 'type': 'text', 'required': True},
|
|
57
|
-
{'name': 'app_name', 'type': 'text', 'required': True}
|
|
58
|
-
]
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
# Save the template
|
|
62
|
-
saved_template = await template_manager.create_template(template)
|
|
63
|
-
|
|
64
|
-
# Schedule an email
|
|
65
|
-
scheduled_email = ScheduledEmail(
|
|
66
|
-
template_id=saved_template.id,
|
|
67
|
-
recipient_email='user@example.com',
|
|
68
|
-
recipient_name='John Doe',
|
|
69
|
-
variables={
|
|
70
|
-
'name': 'John Doe',
|
|
71
|
-
'app_name': 'My Amazing App'
|
|
72
|
-
},
|
|
73
|
-
trigger_type='immediate'
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
result = await scheduler.schedule_email(scheduled_email)
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### FastAPI Integration
|
|
80
|
-
|
|
81
|
-
```python
|
|
82
|
-
from fastapi import FastAPI, BackgroundTasks
|
|
83
|
-
from email_template_manager import EmailTemplateManager, EmailScheduler, SendGridProvider
|
|
84
|
-
from email_template_manager.integrations.fastapi import create_email_router
|
|
85
|
-
|
|
86
|
-
app = FastAPI()
|
|
87
|
-
|
|
88
|
-
# Initialize components
|
|
89
|
-
template_manager = EmailTemplateManager('postgresql://user:pass@localhost/db')
|
|
90
|
-
email_provider = SendGridProvider({
|
|
91
|
-
'api_key': 'your-sendgrid-api-key',
|
|
92
|
-
'from_email': 'noreply@yourapp.com'
|
|
93
|
-
})
|
|
94
|
-
scheduler = EmailScheduler(template_manager, email_provider)
|
|
95
|
-
|
|
96
|
-
# Add the email management router
|
|
97
|
-
email_router = create_email_router(
|
|
98
|
-
get_template_manager=lambda: template_manager,
|
|
99
|
-
get_scheduler=lambda: scheduler
|
|
100
|
-
)
|
|
101
|
-
app.include_router(email_router, prefix='/api/email', tags=['email'])
|
|
102
|
-
|
|
103
|
-
# Custom endpoint using the email system
|
|
104
|
-
@app.post('/send-welcome-email')
|
|
105
|
-
async def send_welcome_email(
|
|
106
|
-
user_email: str,
|
|
107
|
-
user_name: str,
|
|
108
|
-
background_tasks: BackgroundTasks
|
|
109
|
-
):
|
|
110
|
-
# Find welcome template
|
|
111
|
-
templates = await template_manager.list_templates(
|
|
112
|
-
filters={'name': 'Welcome Email'}
|
|
113
|
-
)
|
|
114
|
-
|
|
115
|
-
if templates:
|
|
116
|
-
scheduled_email = ScheduledEmail(
|
|
117
|
-
template_id=templates[0].id,
|
|
118
|
-
recipient_email=user_email,
|
|
119
|
-
recipient_name=user_name,
|
|
120
|
-
variables={'name': user_name, 'app_name': 'My App'},
|
|
121
|
-
trigger_type='immediate'
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
await scheduler.schedule_email(scheduled_email)
|
|
125
|
-
background_tasks.add_task(scheduler.process_pending_emails)
|
|
126
|
-
|
|
127
|
-
return {'status': 'success', 'message': 'Welcome email scheduled'}
|
|
128
|
-
|
|
129
|
-
return {'status': 'error', 'message': 'Welcome template not found'}
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
## NPM/TypeScript Package Usage
|
|
133
|
-
|
|
134
|
-
### Installation
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
# For React/Next.js projects
|
|
138
|
-
npm install @email-template-manager/core @email-template-manager/react
|
|
139
|
-
|
|
140
|
-
# For vanilla JavaScript/TypeScript
|
|
141
|
-
npm install @email-template-manager/core
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Basic TypeScript Usage
|
|
145
|
-
|
|
146
|
-
```typescript
|
|
147
|
-
import {
|
|
148
|
-
EmailTemplateManager,
|
|
149
|
-
EmailScheduler,
|
|
150
|
-
SendGridProvider,
|
|
151
|
-
EmailTemplate,
|
|
152
|
-
ScheduledEmail
|
|
153
|
-
} from '@email-template-manager/core';
|
|
154
|
-
|
|
155
|
-
// Initialize the email provider
|
|
156
|
-
const emailProvider = new SendGridProvider({
|
|
157
|
-
apiKey: 'your-sendgrid-api-key',
|
|
158
|
-
fromEmail: 'noreply@yourapp.com',
|
|
159
|
-
fromName: 'Your App'
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Initialize the template manager
|
|
163
|
-
const templateManager = new EmailTemplateManager({
|
|
164
|
-
database: {
|
|
165
|
-
type: 'postgresql',
|
|
166
|
-
connectionString: 'postgresql://user:pass@localhost/db'
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// Initialize the scheduler
|
|
171
|
-
const scheduler = new EmailScheduler(templateManager, emailProvider);
|
|
172
|
-
|
|
173
|
-
// Create an email template
|
|
174
|
-
const template: EmailTemplate = {
|
|
175
|
-
name: 'Welcome Email',
|
|
176
|
-
subject: 'Welcome to {{app_name}}!',
|
|
177
|
-
htmlBody: '<h1>Hello {{name}}!</h1><p>Welcome to {{app_name}}.</p>',
|
|
178
|
-
textBody: 'Hello {{name}}! Welcome to {{app_name}}.',
|
|
179
|
-
variables: [
|
|
180
|
-
{ name: 'name', type: 'text', required: true },
|
|
181
|
-
{ name: 'app_name', type: 'text', required: true }
|
|
182
|
-
],
|
|
183
|
-
tags: ['welcome'],
|
|
184
|
-
isActive: true,
|
|
185
|
-
version: 1
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
// Save the template
|
|
189
|
-
const savedTemplate = await templateManager.createTemplate(template);
|
|
190
|
-
|
|
191
|
-
// Schedule an email
|
|
192
|
-
const scheduledEmail: ScheduledEmail = {
|
|
193
|
-
templateId: savedTemplate.id!,
|
|
194
|
-
recipientEmail: 'user@example.com',
|
|
195
|
-
recipientName: 'John Doe',
|
|
196
|
-
variables: {
|
|
197
|
-
name: 'John Doe',
|
|
198
|
-
app_name: 'My Amazing App'
|
|
199
|
-
},
|
|
200
|
-
triggerType: 'immediate',
|
|
201
|
-
status: 'pending',
|
|
202
|
-
retryCount: 0,
|
|
203
|
-
maxRetries: 3,
|
|
204
|
-
metadata: {}
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const result = await scheduler.scheduleEmail(scheduledEmail);
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### React Component Usage
|
|
211
|
-
|
|
212
|
-
```tsx
|
|
213
|
-
import React from 'react';
|
|
214
|
-
import {
|
|
215
|
-
EmailTemplateProvider,
|
|
216
|
-
EmailTemplateList,
|
|
217
|
-
EmailTemplateEditor,
|
|
218
|
-
useEmailTemplates
|
|
219
|
-
} from '@email-template-manager/react';
|
|
220
|
-
import { EmailManagerConfig } from '@email-template-manager/core';
|
|
221
|
-
|
|
222
|
-
const config: EmailManagerConfig = {
|
|
223
|
-
database: {
|
|
224
|
-
type: 'postgresql',
|
|
225
|
-
connectionString: process.env.DATABASE_URL!
|
|
226
|
-
},
|
|
227
|
-
emailProvider: {
|
|
228
|
-
provider: 'sendgrid',
|
|
229
|
-
apiKey: process.env.SENDGRID_API_KEY!,
|
|
230
|
-
fromEmail: 'noreply@yourapp.com',
|
|
231
|
-
fromName: 'Your App'
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
function TemplateManager() {
|
|
236
|
-
const {
|
|
237
|
-
templates,
|
|
238
|
-
createTemplate,
|
|
239
|
-
updateTemplate,
|
|
240
|
-
deleteTemplate,
|
|
241
|
-
loading
|
|
242
|
-
} = useEmailTemplates();
|
|
243
|
-
|
|
244
|
-
const handleCreateTemplate = async (templateData: any) => {
|
|
245
|
-
await createTemplate(templateData);
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
return (
|
|
249
|
-
<div className="p-6">
|
|
250
|
-
<h1 className="text-2xl font-bold mb-4">Email Templates</h1>
|
|
251
|
-
|
|
252
|
-
<EmailTemplateList
|
|
253
|
-
templates={templates}
|
|
254
|
-
onEdit={(template) => console.log('Edit:', template)}
|
|
255
|
-
onDelete={(templateId) => deleteTemplate(templateId)}
|
|
256
|
-
loading={loading}
|
|
257
|
-
/>
|
|
258
|
-
|
|
259
|
-
<EmailTemplateEditor
|
|
260
|
-
onSave={handleCreateTemplate}
|
|
261
|
-
onCancel={() => console.log('Cancel')}
|
|
262
|
-
variables={[
|
|
263
|
-
{ name: 'name', type: 'text', required: true },
|
|
264
|
-
{ name: 'email', type: 'email', required: true }
|
|
265
|
-
]}
|
|
266
|
-
previewData={{
|
|
267
|
-
name: 'John Doe',
|
|
268
|
-
email: 'john@example.com'
|
|
269
|
-
}}
|
|
270
|
-
/>
|
|
271
|
-
</div>
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
export default function App() {
|
|
276
|
-
return (
|
|
277
|
-
<EmailTemplateProvider config={config}>
|
|
278
|
-
<TemplateManager />
|
|
279
|
-
</EmailTemplateProvider>
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Next.js API Route Usage
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
// pages/api/email/send-welcome.ts
|
|
288
|
-
import { NextApiRequest, NextApiResponse } from 'next';
|
|
289
|
-
import {
|
|
290
|
-
EmailTemplateManager,
|
|
291
|
-
EmailScheduler,
|
|
292
|
-
SendGridProvider
|
|
293
|
-
} from '@email-template-manager/core';
|
|
294
|
-
|
|
295
|
-
const templateManager = new EmailTemplateManager({
|
|
296
|
-
database: {
|
|
297
|
-
type: 'postgresql',
|
|
298
|
-
connectionString: process.env.DATABASE_URL!
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
const emailProvider = new SendGridProvider({
|
|
303
|
-
apiKey: process.env.SENDGRID_API_KEY!,
|
|
304
|
-
fromEmail: 'noreply@yourapp.com',
|
|
305
|
-
fromName: 'Your App'
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
const scheduler = new EmailScheduler(templateManager, emailProvider);
|
|
309
|
-
|
|
310
|
-
export default async function handler(
|
|
311
|
-
req: NextApiRequest,
|
|
312
|
-
res: NextApiResponse
|
|
313
|
-
) {
|
|
314
|
-
if (req.method !== 'POST') {
|
|
315
|
-
return res.status(405).json({ error: 'Method not allowed' });
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const { userEmail, userName } = req.body;
|
|
319
|
-
|
|
320
|
-
try {
|
|
321
|
-
// Find the welcome email template
|
|
322
|
-
const templates = await templateManager.listTemplates({
|
|
323
|
-
search: 'Welcome Email'
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
if (templates.length === 0) {
|
|
327
|
-
return res.status(404).json({ error: 'Welcome template not found' });
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Schedule the welcome email
|
|
331
|
-
const scheduledEmail = {
|
|
332
|
-
templateId: templates[0].id!,
|
|
333
|
-
recipientEmail: userEmail,
|
|
334
|
-
recipientName: userName,
|
|
335
|
-
variables: {
|
|
336
|
-
name: userName,
|
|
337
|
-
app_name: 'My Next.js App'
|
|
338
|
-
},
|
|
339
|
-
triggerType: 'immediate' as const,
|
|
340
|
-
status: 'pending' as const,
|
|
341
|
-
retryCount: 0,
|
|
342
|
-
maxRetries: 3,
|
|
343
|
-
metadata: { source: 'api' }
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
const result = await scheduler.scheduleEmail(scheduledEmail);
|
|
347
|
-
|
|
348
|
-
// Process emails immediately in the background
|
|
349
|
-
scheduler.processPendingEmails().catch(console.error);
|
|
350
|
-
|
|
351
|
-
res.status(200).json({
|
|
352
|
-
success: true,
|
|
353
|
-
scheduledEmailId: result.id,
|
|
354
|
-
message: 'Welcome email scheduled successfully'
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
} catch (error) {
|
|
358
|
-
console.error('Failed to send welcome email:', error);
|
|
359
|
-
res.status(500).json({
|
|
360
|
-
error: 'Failed to schedule welcome email',
|
|
361
|
-
details: error instanceof Error ? error.message : 'Unknown error'
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
## Environment Configuration
|
|
368
|
-
|
|
369
|
-
### Python Environment Variables
|
|
370
|
-
|
|
371
|
-
```bash
|
|
372
|
-
# Database
|
|
373
|
-
DATABASE_URL=postgresql://user:pass@localhost/email_templates
|
|
374
|
-
|
|
375
|
-
# SendGrid
|
|
376
|
-
SENDGRID_API_KEY=your-sendgrid-api-key
|
|
377
|
-
|
|
378
|
-
# Security
|
|
379
|
-
ENCRYPTION_KEY=your-secret-encryption-key-32-chars
|
|
380
|
-
|
|
381
|
-
# Optional: Other providers
|
|
382
|
-
AWS_ACCESS_KEY_ID=your-aws-key
|
|
383
|
-
AWS_SECRET_ACCESS_KEY=your-aws-secret
|
|
384
|
-
AWS_REGION=us-east-1
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
### Node.js Environment Variables
|
|
388
|
-
|
|
389
|
-
```bash
|
|
390
|
-
# Database
|
|
391
|
-
DATABASE_URL=postgresql://user:pass@localhost/email_templates
|
|
392
|
-
|
|
393
|
-
# SendGrid
|
|
394
|
-
SENDGRID_API_KEY=your-sendgrid-api-key
|
|
395
|
-
|
|
396
|
-
# Security
|
|
397
|
-
ENCRYPTION_KEY=your-secret-encryption-key-32-chars
|
|
398
|
-
|
|
399
|
-
# Next.js specific
|
|
400
|
-
NEXTAUTH_SECRET=your-nextauth-secret
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
## Package Development Setup
|
|
404
|
-
|
|
405
|
-
### Python Development
|
|
406
|
-
|
|
407
|
-
```bash
|
|
408
|
-
# Clone the repository
|
|
409
|
-
git clone https://github.com/mattbernier/email-template-manager.git
|
|
410
|
-
cd email-template-manager
|
|
411
|
-
|
|
412
|
-
# Set up Python virtual environment
|
|
413
|
-
python -m venv venv
|
|
414
|
-
source venv/bin/activate # On Windows: venv\Scripts\activate
|
|
415
|
-
|
|
416
|
-
# Install in development mode
|
|
417
|
-
cd packages/python
|
|
418
|
-
pip install -e .[dev]
|
|
419
|
-
|
|
420
|
-
# Run tests
|
|
421
|
-
pytest
|
|
422
|
-
|
|
423
|
-
# Run linting
|
|
424
|
-
black .
|
|
425
|
-
isort .
|
|
426
|
-
mypy .
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
### NPM Development
|
|
430
|
-
|
|
431
|
-
```bash
|
|
432
|
-
# Install dependencies
|
|
433
|
-
npm install
|
|
434
|
-
|
|
435
|
-
# Build all packages
|
|
436
|
-
npm run build
|
|
437
|
-
|
|
438
|
-
# Run tests
|
|
439
|
-
npm test
|
|
440
|
-
|
|
441
|
-
# Start development mode
|
|
442
|
-
npm run dev
|
|
443
|
-
|
|
444
|
-
# Lint and format
|
|
445
|
-
npm run lint:fix
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
## Publishing Packages
|
|
449
|
-
|
|
450
|
-
### Python Package Publishing
|
|
451
|
-
|
|
452
|
-
```bash
|
|
453
|
-
# Build the package
|
|
454
|
-
cd packages/python
|
|
455
|
-
python -m build
|
|
456
|
-
|
|
457
|
-
# Upload to PyPI
|
|
458
|
-
twine upload dist/*
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
### NPM Package Publishing
|
|
462
|
-
|
|
463
|
-
```bash
|
|
464
|
-
# Build packages
|
|
465
|
-
npm run build
|
|
466
|
-
|
|
467
|
-
# Publish with changesets
|
|
468
|
-
npm run release
|
|
469
|
-
```
|
|
470
|
-
|
|
471
|
-
This setup provides you with fully importable, production-ready packages that you can use across your Python, React, and Next.js applications with comprehensive SendGrid support for all your email template needs!
|