@webamoki/web-svelte 0.6.3 → 0.7.1
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/dist/components/form/Form.svelte +0 -71
- package/dist/utils/email/README.md +209 -0
- package/dist/utils/email/index.d.ts +1 -0
- package/dist/utils/email/index.js +1 -0
- package/dist/utils/email/ses.d.ts +22 -0
- package/dist/utils/email/ses.js +95 -0
- package/dist/utils/form/index.d.ts +3 -3
- package/dist/utils/form/index.js +5 -5
- package/dist/utils/form/virtual-form.d.ts +1 -1
- package/dist/utils/form/virtual-form.js +6 -6
- package/package.json +6 -1
|
@@ -1,74 +1,3 @@
|
|
|
1
|
-
<!-- <script lang="ts" generics="S extends type.Any<Record<string, unknown>>">
|
|
2
|
-
import { toast } from 'svelte-sonner';
|
|
3
|
-
import { dateTransport } from '../../utils/index.js';
|
|
4
|
-
import { type } from 'arktype';
|
|
5
|
-
import type { Snippet } from 'svelte';
|
|
6
|
-
import type { Readable } from 'svelte/store';
|
|
7
|
-
import { defaults, superForm, type SuperForm, type SuperValidated } from 'sveltekit-superforms';
|
|
8
|
-
import { arktype, arktypeClient } from 'sveltekit-superforms/adapters';
|
|
9
|
-
import type { SuperFormData, SuperFormErrors } from 'sveltekit-superforms/client';
|
|
10
|
-
|
|
11
|
-
interface Props {
|
|
12
|
-
validated?: SuperValidated<S['infer']> | S['infer'];
|
|
13
|
-
schema: S;
|
|
14
|
-
onSuccess?: (
|
|
15
|
-
form: Readonly<SuperValidated<S['infer'], App.Superforms.Message, S['infer']>>
|
|
16
|
-
) => void;
|
|
17
|
-
invalidateAll?: boolean;
|
|
18
|
-
children: Snippet<
|
|
19
|
-
[
|
|
20
|
-
{
|
|
21
|
-
form: SuperForm<S['infer'], App.Superforms.Message>;
|
|
22
|
-
data: SuperFormData<S['infer']>;
|
|
23
|
-
delayed: Readable<boolean>;
|
|
24
|
-
errors: SuperFormErrors<S['infer']>;
|
|
25
|
-
}
|
|
26
|
-
]
|
|
27
|
-
>;
|
|
28
|
-
// TODO: Enforce use of resolve
|
|
29
|
-
action: string;
|
|
30
|
-
actionName?: string;
|
|
31
|
-
class?: string;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
let {
|
|
35
|
-
validated: _validated,
|
|
36
|
-
schema,
|
|
37
|
-
onSuccess,
|
|
38
|
-
invalidateAll = false,
|
|
39
|
-
children,
|
|
40
|
-
action: _action,
|
|
41
|
-
actionName,
|
|
42
|
-
class: className
|
|
43
|
-
}: Props = $props();
|
|
44
|
-
|
|
45
|
-
let validated = _validated ?? defaults(arktype(schema));
|
|
46
|
-
const form = superForm(validated, {
|
|
47
|
-
validators: arktypeClient(schema),
|
|
48
|
-
dataType: 'json',
|
|
49
|
-
invalidateAll,
|
|
50
|
-
transport: dateTransport,
|
|
51
|
-
onUpdated({ form }) {
|
|
52
|
-
const text = form.message?.text;
|
|
53
|
-
if (text === undefined) return;
|
|
54
|
-
|
|
55
|
-
if (form.message?.success) {
|
|
56
|
-
toast.success(text);
|
|
57
|
-
} else {
|
|
58
|
-
toast.error(text);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (form.valid) {
|
|
62
|
-
onSuccess?.(form);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
const { form: data, delayed, errors } = form;
|
|
67
|
-
</script>
|
|
68
|
-
|
|
69
|
-
<form class={className} action="{_action}?/{actionName}" method="POST" use:form.enhance>
|
|
70
|
-
{@render children({ form, data, delayed, errors })}
|
|
71
|
-
</form> -->
|
|
72
1
|
<script lang="ts" generics="T extends Record<string, unknown>, M">
|
|
73
2
|
import type { FsSuperForm } from 'formsnap';
|
|
74
3
|
import type { Snippet } from 'svelte';
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Email Utility Package
|
|
2
|
+
|
|
3
|
+
This package provides utilities for sending emails using AWS Simple Email Service (SES).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The AWS SES SDK is already included as a dependency. You'll need to configure your AWS credentials and region.
|
|
8
|
+
|
|
9
|
+
## Configuration
|
|
10
|
+
|
|
11
|
+
### Environment Variables
|
|
12
|
+
|
|
13
|
+
The email utility requires the following environment variables:
|
|
14
|
+
|
|
15
|
+
- `AWS_REGION` - AWS region where SES is configured (e.g., `us-east-1`)
|
|
16
|
+
- `AWS_ACCESS_KEY_ID` - AWS access key ID
|
|
17
|
+
- `AWS_SECRET_ACCESS_KEY` - AWS secret access key
|
|
18
|
+
|
|
19
|
+
### SES Setup
|
|
20
|
+
|
|
21
|
+
Before using this utility, ensure:
|
|
22
|
+
|
|
23
|
+
1. Your AWS account has SES enabled in your chosen region
|
|
24
|
+
2. Your sender email address(es) are verified in SES
|
|
25
|
+
3. If in SES sandbox mode, recipient addresses must also be verified
|
|
26
|
+
4. Your account has the necessary IAM permissions to send emails via SES
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Basic Example
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { sendEmail } from '@webamoki/web-svelte/utils/email';
|
|
34
|
+
|
|
35
|
+
// Send a simple text email
|
|
36
|
+
const messageId = await sendEmail({
|
|
37
|
+
to: 'recipient@example.com',
|
|
38
|
+
subject: 'Hello from SES',
|
|
39
|
+
text: 'This is a plain text email.',
|
|
40
|
+
from: 'sender@example.com'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
console.log('Email sent with message ID:', messageId);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### HTML Email
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
await sendEmail({
|
|
50
|
+
to: 'recipient@example.com',
|
|
51
|
+
subject: 'Welcome!',
|
|
52
|
+
html: '<h1>Welcome to our service!</h1><p>Thanks for signing up.</p>',
|
|
53
|
+
text: 'Welcome to our service! Thanks for signing up.', // Fallback for email clients that don't support HTML
|
|
54
|
+
from: 'noreply@example.com',
|
|
55
|
+
fromName: 'My Application'
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Multiple Recipients
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
await sendEmail({
|
|
63
|
+
to: ['user1@example.com', 'user2@example.com'],
|
|
64
|
+
cc: 'manager@example.com',
|
|
65
|
+
bcc: ['archive@example.com', 'backup@example.com'],
|
|
66
|
+
subject: 'Team Update',
|
|
67
|
+
text: 'This is a team-wide announcement.',
|
|
68
|
+
from: 'team@example.com'
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### With Reply-To
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
await sendEmail({
|
|
76
|
+
to: 'customer@example.com',
|
|
77
|
+
subject: 'Your order confirmation',
|
|
78
|
+
html: '<p>Your order has been confirmed!</p>',
|
|
79
|
+
from: 'noreply@example.com',
|
|
80
|
+
fromName: 'Order System',
|
|
81
|
+
replyTo: 'support@example.com'
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### `sendEmail(options: SendEmailOptions): Promise<string>`
|
|
88
|
+
|
|
89
|
+
Sends an email via AWS SES.
|
|
90
|
+
|
|
91
|
+
**Returns:** Promise that resolves to the SES message ID (string) on success.
|
|
92
|
+
|
|
93
|
+
**Throws:** Error with descriptive message if:
|
|
94
|
+
|
|
95
|
+
- Validation fails (missing required fields, invalid recipients, etc.)
|
|
96
|
+
- AWS SES returns an error (credentials, permissions, service issues)
|
|
97
|
+
- SES response does not contain a MessageId (unlikely but handled explicitly)
|
|
98
|
+
|
|
99
|
+
### `SendEmailOptions`
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
interface SendEmailOptions {
|
|
103
|
+
to: string | string[]; // Required: recipient email address(es)
|
|
104
|
+
cc?: string | string[]; // Optional: CC recipients
|
|
105
|
+
bcc?: string | string[]; // Optional: BCC recipients
|
|
106
|
+
subject: string; // Required: email subject
|
|
107
|
+
text?: string; // Optional: plain text body
|
|
108
|
+
html?: string; // Optional: HTML body
|
|
109
|
+
from: string; // Required: sender email
|
|
110
|
+
fromName?: string; // Optional: sender display name
|
|
111
|
+
replyTo?: string | string[]; // Optional: reply-to address(es)
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Error Handling
|
|
116
|
+
|
|
117
|
+
The `sendEmail` function validates inputs and will throw errors for:
|
|
118
|
+
|
|
119
|
+
- Missing required fields (`to`, `from`, `subject`, at least one of `text` or `html`)
|
|
120
|
+
- Empty recipient list (no valid email addresses after filtering)
|
|
121
|
+
- AWS SES errors (credentials, permissions, service issues)
|
|
122
|
+
|
|
123
|
+
**Note:** The function automatically filters out empty strings and whitespace-only values from recipient arrays (`to`, `cc`, `bcc`, `replyTo`). For example, `['', 'valid@example.com', ' ']` will be processed as `['valid@example.com']`.
|
|
124
|
+
|
|
125
|
+
Always wrap calls in try-catch:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
try {
|
|
129
|
+
const messageId = await sendEmail({
|
|
130
|
+
to: 'user@example.com',
|
|
131
|
+
subject: 'Test',
|
|
132
|
+
text: 'Hello!',
|
|
133
|
+
from: 'sender@example.com'
|
|
134
|
+
});
|
|
135
|
+
console.log('Success:', messageId);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('Failed to send email:', error.message);
|
|
138
|
+
// Handle error appropriately
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## SvelteKit Integration
|
|
143
|
+
|
|
144
|
+
### Server-Only Usage
|
|
145
|
+
|
|
146
|
+
⚠️ **Important:** This utility should only be used in server-side code (e.g., `+page.server.ts`, `+server.ts`, or server-side functions) as it requires AWS credentials.
|
|
147
|
+
|
|
148
|
+
### Example: Contact Form Handler
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
// src/routes/contact/+page.server.ts
|
|
152
|
+
import { sendEmail } from '@webamoki/web-svelte/utils/email';
|
|
153
|
+
import type { Actions } from './$types';
|
|
154
|
+
|
|
155
|
+
export const actions: Actions = {
|
|
156
|
+
default: async ({ request }) => {
|
|
157
|
+
const formData = await request.formData();
|
|
158
|
+
const email = formData.get('email') as string;
|
|
159
|
+
const message = formData.get('message') as string;
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
await sendEmail({
|
|
163
|
+
to: 'admin@example.com',
|
|
164
|
+
subject: `Contact form submission from ${email}`,
|
|
165
|
+
text: message,
|
|
166
|
+
from: 'noreply@example.com',
|
|
167
|
+
replyTo: email
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
return { success: true };
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error('Email error:', error);
|
|
173
|
+
return { success: false, error: 'Failed to send message' };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Best Practices
|
|
180
|
+
|
|
181
|
+
1. **Never expose AWS credentials in client-side code**
|
|
182
|
+
2. **Use environment variables for configuration**
|
|
183
|
+
3. **Verify sender addresses in SES before deploying**
|
|
184
|
+
4. **Always provide both `text` and `html` versions when sending HTML emails**
|
|
185
|
+
5. **Handle errors gracefully and log failures for monitoring**
|
|
186
|
+
6. **Consider rate limits** - SES has sending limits based on your account status
|
|
187
|
+
7. **Use BCC for bulk emails** to avoid exposing all recipients
|
|
188
|
+
8. **Set appropriate Reply-To addresses** for better user experience
|
|
189
|
+
|
|
190
|
+
## Troubleshooting
|
|
191
|
+
|
|
192
|
+
### "Sender not verified" error
|
|
193
|
+
|
|
194
|
+
Verify your sender email address in the AWS SES console for your region.
|
|
195
|
+
|
|
196
|
+
### "Access Denied" error
|
|
197
|
+
|
|
198
|
+
Ensure your AWS credentials have the `ses:SendEmail` permission.
|
|
199
|
+
|
|
200
|
+
### Emails not arriving
|
|
201
|
+
|
|
202
|
+
- Check SES sending statistics in AWS console
|
|
203
|
+
- Verify you're not in sandbox mode (or that recipients are verified)
|
|
204
|
+
- Check spam folders
|
|
205
|
+
- Review bounce and complaint notifications in SES
|
|
206
|
+
|
|
207
|
+
## License
|
|
208
|
+
|
|
209
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sendEmail, type SendEmailOptions } from './ses.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sendEmail } from './ses.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface SendEmailOptions {
|
|
2
|
+
to: string | string[];
|
|
3
|
+
cc?: string | string[];
|
|
4
|
+
bcc?: string | string[];
|
|
5
|
+
subject: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
html?: string;
|
|
8
|
+
from: string;
|
|
9
|
+
fromName?: string;
|
|
10
|
+
replyTo?: string | string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Send an email using AWS SES.
|
|
14
|
+
*
|
|
15
|
+
* Environment variables required:
|
|
16
|
+
* - AWS_REGION
|
|
17
|
+
* - AWS_ACCESS_KEY_ID
|
|
18
|
+
* - AWS_SECRET_ACCESS_KEY
|
|
19
|
+
*
|
|
20
|
+
* @returns messageId returned by SES
|
|
21
|
+
*/
|
|
22
|
+
export declare function sendEmail(options: SendEmailOptions): Promise<string>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
|
|
2
|
+
// Create SES client once at module level for reuse across function calls
|
|
3
|
+
const sesClient = new SESClient({ region: process.env.AWS_REGION });
|
|
4
|
+
/**
|
|
5
|
+
* Send an email using AWS SES.
|
|
6
|
+
*
|
|
7
|
+
* Environment variables required:
|
|
8
|
+
* - AWS_REGION
|
|
9
|
+
* - AWS_ACCESS_KEY_ID
|
|
10
|
+
* - AWS_SECRET_ACCESS_KEY
|
|
11
|
+
*
|
|
12
|
+
* @returns messageId returned by SES
|
|
13
|
+
*/
|
|
14
|
+
export async function sendEmail(options) {
|
|
15
|
+
if (!options)
|
|
16
|
+
throw new Error('sendEmail: options is required');
|
|
17
|
+
const { to, cc, bcc, subject, text, html, from, fromName, replyTo } = options;
|
|
18
|
+
if (!subject) {
|
|
19
|
+
throw new Error('sendEmail: subject is required');
|
|
20
|
+
}
|
|
21
|
+
if (!text && !html) {
|
|
22
|
+
throw new Error('sendEmail: at least one of text or html body must be provided');
|
|
23
|
+
}
|
|
24
|
+
if (!from) {
|
|
25
|
+
throw new Error('sendEmail: sender `from` is required');
|
|
26
|
+
}
|
|
27
|
+
// Normalize and validate addresses: convert to array and filter out empty/whitespace strings
|
|
28
|
+
const normalizeAddresses = (addr) => {
|
|
29
|
+
if (addr === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
const addresses = Array.isArray(addr) ? addr : [addr];
|
|
32
|
+
const filtered = addresses.filter((a) => a && a.trim() !== '');
|
|
33
|
+
return filtered.length > 0 ? filtered : undefined;
|
|
34
|
+
};
|
|
35
|
+
const toAddresses = normalizeAddresses(to);
|
|
36
|
+
const ccAddresses = normalizeAddresses(cc);
|
|
37
|
+
const bccAddresses = normalizeAddresses(bcc);
|
|
38
|
+
const replyToAddresses = normalizeAddresses(replyTo);
|
|
39
|
+
if (!toAddresses || toAddresses.length === 0) {
|
|
40
|
+
throw new Error('sendEmail: at least one valid recipient is required (to)');
|
|
41
|
+
}
|
|
42
|
+
// Format source with optional fromName
|
|
43
|
+
const source = fromName ? `${fromName} <${from}>` : from;
|
|
44
|
+
// Build message body
|
|
45
|
+
const Message = {
|
|
46
|
+
Subject: {
|
|
47
|
+
Charset: 'UTF-8',
|
|
48
|
+
Data: subject
|
|
49
|
+
},
|
|
50
|
+
Body: {}
|
|
51
|
+
};
|
|
52
|
+
if (html) {
|
|
53
|
+
Message.Body.Html = {
|
|
54
|
+
Charset: 'UTF-8',
|
|
55
|
+
Data: html
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (text) {
|
|
59
|
+
Message.Body.Text = {
|
|
60
|
+
Charset: 'UTF-8',
|
|
61
|
+
Data: text
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const params = {
|
|
65
|
+
Source: source,
|
|
66
|
+
Destination: {
|
|
67
|
+
ToAddresses: toAddresses,
|
|
68
|
+
CcAddresses: ccAddresses,
|
|
69
|
+
BccAddresses: bccAddresses
|
|
70
|
+
},
|
|
71
|
+
Message,
|
|
72
|
+
ReplyToAddresses: replyToAddresses
|
|
73
|
+
};
|
|
74
|
+
try {
|
|
75
|
+
const command = new SendEmailCommand(params);
|
|
76
|
+
const res = await sesClient.send(command);
|
|
77
|
+
if (!res.MessageId) {
|
|
78
|
+
throw new Error('sendEmail: SES response did not contain a MessageId');
|
|
79
|
+
}
|
|
80
|
+
return res.MessageId;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
// Normalize error for callers
|
|
84
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
85
|
+
let code;
|
|
86
|
+
if (err && typeof err === 'object') {
|
|
87
|
+
const e = err;
|
|
88
|
+
if (typeof e['name'] === 'string')
|
|
89
|
+
code = e['name'];
|
|
90
|
+
}
|
|
91
|
+
const details = { message, code };
|
|
92
|
+
// Re-throw a clear error for the caller to handle
|
|
93
|
+
throw new Error(`sendEmail: failed to send email: ${JSON.stringify(details)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type } from 'arktype';
|
|
2
2
|
import { type SuperValidated } from 'sveltekit-superforms';
|
|
3
3
|
export * from './virtual-form.js';
|
|
4
|
-
export declare function prepareForm<S extends type.Any<Record<string, unknown>>>(validated: SuperValidated<S['infer']> | S['infer'],
|
|
4
|
+
export declare function prepareForm<S extends type.Any<Record<string, unknown>>>(schema: S, validated: SuperValidated<S['infer']> | S['infer'], options?: Partial<{
|
|
5
5
|
invalidateAll: boolean;
|
|
6
6
|
resetForm: boolean;
|
|
7
7
|
onSuccess: (form: Readonly<SuperValidated<S['infer'], App.Superforms.Message, S['infer']>>) => void;
|
|
@@ -9,7 +9,7 @@ export declare function prepareForm<S extends type.Any<Record<string, unknown>>>
|
|
|
9
9
|
}>): {
|
|
10
10
|
form: import("sveltekit-superforms").SuperForm<S["infer"], any>;
|
|
11
11
|
data: import("sveltekit-superforms/client").SuperFormData<S["infer"]>;
|
|
12
|
-
|
|
12
|
+
isProcessing: import("svelte/store").Readable<boolean>;
|
|
13
13
|
errors: import("sveltekit-superforms/client").SuperFormErrors<S["infer"]>;
|
|
14
14
|
};
|
|
15
15
|
export declare function prepareEmptyForm<S extends type.Any<Record<string, unknown>>>(schema: S, options?: Partial<{
|
|
@@ -20,6 +20,6 @@ export declare function prepareEmptyForm<S extends type.Any<Record<string, unkno
|
|
|
20
20
|
}>): {
|
|
21
21
|
form: import("sveltekit-superforms").SuperForm<S["infer"], any>;
|
|
22
22
|
data: import("sveltekit-superforms/client").SuperFormData<S["infer"]>;
|
|
23
|
-
|
|
23
|
+
isProcessing: import("svelte/store").Readable<boolean>;
|
|
24
24
|
errors: import("sveltekit-superforms/client").SuperFormErrors<S["infer"]>;
|
|
25
25
|
};
|
package/dist/utils/form/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { defaults, superForm } from 'sveltekit-superforms';
|
|
|
4
4
|
import { arktype, arktypeClient } from 'sveltekit-superforms/adapters';
|
|
5
5
|
import { dateTransport } from '../datetime/index.js';
|
|
6
6
|
export * from './virtual-form.js';
|
|
7
|
-
export function prepareForm(
|
|
7
|
+
export function prepareForm(schema, validated, options) {
|
|
8
8
|
const form = superForm(validated, {
|
|
9
9
|
validators: arktypeClient(schema),
|
|
10
10
|
dataType: 'json',
|
|
@@ -31,9 +31,9 @@ export function prepareForm(validated, schema, options) {
|
|
|
31
31
|
toast.error(`${status} - ${message}`);
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
|
-
const
|
|
34
|
+
const isProcessing = form.delayed;
|
|
35
35
|
const errors = form.errors;
|
|
36
|
-
return { form, data: form.form,
|
|
36
|
+
return { form, data: form.form, isProcessing, errors };
|
|
37
37
|
}
|
|
38
38
|
export function prepareEmptyForm(schema, options) {
|
|
39
39
|
const form = superForm(defaults(arktype(schema)), {
|
|
@@ -62,7 +62,7 @@ export function prepareEmptyForm(schema, options) {
|
|
|
62
62
|
toast.error(`${status} - ${message}`);
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
|
-
const
|
|
65
|
+
const isProcessing = form.delayed;
|
|
66
66
|
const errors = form.errors;
|
|
67
|
-
return { form, data: form.form,
|
|
67
|
+
return { form, data: form.form, isProcessing, errors };
|
|
68
68
|
}
|
|
@@ -5,7 +5,7 @@ import { parse, stringify } from 'devalue';
|
|
|
5
5
|
import { dateTransport } from '../datetime/index.js';
|
|
6
6
|
export class VirtualForm {
|
|
7
7
|
// state storage
|
|
8
|
-
#
|
|
8
|
+
#isProcessing = false;
|
|
9
9
|
#url = '';
|
|
10
10
|
#schema;
|
|
11
11
|
#transport;
|
|
@@ -70,7 +70,7 @@ export class VirtualForm {
|
|
|
70
70
|
return result;
|
|
71
71
|
}
|
|
72
72
|
async submit(data) {
|
|
73
|
-
this.#
|
|
73
|
+
this.#isProcessing = true;
|
|
74
74
|
this.#update();
|
|
75
75
|
// Validate data against schema
|
|
76
76
|
const validated = this.#schema(data);
|
|
@@ -99,7 +99,7 @@ export class VirtualForm {
|
|
|
99
99
|
if (!res.ok || result.status === 400) {
|
|
100
100
|
console.error('Request failed:', result);
|
|
101
101
|
this.#onError?.(result);
|
|
102
|
-
this.#
|
|
102
|
+
this.#isProcessing = false;
|
|
103
103
|
this.#update();
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
@@ -124,11 +124,11 @@ export class VirtualForm {
|
|
|
124
124
|
console.error(err);
|
|
125
125
|
this.#onError?.({ text: 'Network error', data: err, success: false, showToast: false });
|
|
126
126
|
}
|
|
127
|
-
this.#
|
|
127
|
+
this.#isProcessing = false;
|
|
128
128
|
this.#update();
|
|
129
129
|
}
|
|
130
|
-
get
|
|
130
|
+
get isProcessing() {
|
|
131
131
|
this.#subscribe();
|
|
132
|
-
return this.#
|
|
132
|
+
return this.#isProcessing;
|
|
133
133
|
}
|
|
134
134
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.7.1",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"files": [
|
|
9
9
|
"dist",
|
|
@@ -43,6 +43,10 @@
|
|
|
43
43
|
"types": "./dist/utils/form/index.d.ts",
|
|
44
44
|
"import": "./dist/utils/form/index.js"
|
|
45
45
|
},
|
|
46
|
+
"./utils/email": {
|
|
47
|
+
"types": "./dist/utils/email/index.d.ts",
|
|
48
|
+
"import": "./dist/utils/email/index.js"
|
|
49
|
+
},
|
|
46
50
|
"./server/form-handler": {
|
|
47
51
|
"types": "./dist/server/form-handler.d.ts",
|
|
48
52
|
"import": "./dist/server/form-handler.js"
|
|
@@ -102,6 +106,7 @@
|
|
|
102
106
|
"svelte"
|
|
103
107
|
],
|
|
104
108
|
"dependencies": {
|
|
109
|
+
"@aws-sdk/client-ses": "^3.948.0",
|
|
105
110
|
"@internationalized/date": "^3.10.0",
|
|
106
111
|
"@lucide/svelte": "^0.553.0",
|
|
107
112
|
"@sveltejs/adapter-auto": "^7.0.0",
|