@jwerre/vellum 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 +651 -146
- package/dist/Collection.svelte.d.ts +0 -12
- package/dist/Collection.svelte.js +0 -12
- package/dist/Model.svelte.d.ts +329 -9
- package/dist/Model.svelte.js +357 -27
- package/dist/config.svelte.d.ts +34 -1
- package/dist/config.svelte.js +34 -1
- package/dist/errors/validation_error.d.ts +8 -0
- package/dist/errors/validation_error.js +9 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +10 -0
- package/package.json +3 -1
package/dist/Model.svelte.js
CHANGED
|
@@ -1,20 +1,129 @@
|
|
|
1
1
|
import { vellumConfig } from './config.svelte';
|
|
2
|
+
import { ValidationError } from './errors/validation_error.js';
|
|
3
|
+
import { escapeHTML } from './utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Abstract base class for creating model instances that interact with RESTful APIs.
|
|
6
|
+
*
|
|
7
|
+
* The Model class provides a structured way to manage data objects with full CRUD
|
|
8
|
+
* (Create, Read, Update, Delete) capabilities. It includes built-in HTTP synchronization,
|
|
9
|
+
* attribute management, and data validation features. This class is designed to work
|
|
10
|
+
* with Svelte's reactivity system using the `$state` rune for automatic UI updates.
|
|
11
|
+
*
|
|
12
|
+
* Key features:
|
|
13
|
+
* - Type-safe attribute access and manipulation
|
|
14
|
+
* - Automatic HTTP synchronization with RESTful APIs
|
|
15
|
+
* - Built-in HTML escaping for XSS prevention
|
|
16
|
+
* - Configurable ID attributes for different database schemas
|
|
17
|
+
* - Reactive attributes that integrate with Svelte's state management
|
|
18
|
+
* - Support for both single attribute and bulk attribute operations
|
|
19
|
+
*
|
|
20
|
+
* @template T - The type definition for the model's attributes, must extend object
|
|
21
|
+
* @abstract This class must be extended by concrete model implementations
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Define a User model
|
|
25
|
+
* interface UserAttributes {
|
|
26
|
+
* id?: number;
|
|
27
|
+
* name: string;
|
|
28
|
+
* email: string;
|
|
29
|
+
* createdAt?: Date;
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* class User extends Model<UserAttributes> {
|
|
33
|
+
* endpoint() {
|
|
34
|
+
* return '/users';
|
|
35
|
+
* }
|
|
36
|
+
* defaults() {
|
|
37
|
+
* return { name: '', createdAt: new Date() };
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* // Create and use a model instance
|
|
42
|
+
* const user = new User({ name: 'John Doe', email: 'john@example.com' });
|
|
43
|
+
* await user.save(); // Creates new user on server
|
|
44
|
+
* user.set('name', 'Jane Doe');
|
|
45
|
+
* await user.save(); // Updates existing user
|
|
46
|
+
* await user.destroy(); // Deletes user
|
|
47
|
+
*/
|
|
2
48
|
export class Model {
|
|
3
49
|
#attributes = $state({});
|
|
50
|
+
/**
|
|
51
|
+
* Validation error property that gets set when validation fails.
|
|
52
|
+
* This property contains the error returned by the validate method.
|
|
53
|
+
*/
|
|
54
|
+
#validationError = $state();
|
|
55
|
+
/**
|
|
56
|
+
* The name of the attribute that serves as the unique identifier for this model instance.
|
|
57
|
+
*
|
|
58
|
+
* This private field stores the attribute name that will be used to identify the model's
|
|
59
|
+
* primary key when performing operations like determining if the model is new, constructing
|
|
60
|
+
* URLs for API requests, and managing model identity. The default value is 'id', but it
|
|
61
|
+
* can be customized through the ModelOptions parameter in the constructor.
|
|
62
|
+
*
|
|
63
|
+
* @protected
|
|
64
|
+
* @type {string}
|
|
65
|
+
* @default 'id'
|
|
66
|
+
* @example
|
|
67
|
+
* // Default behavior uses 'id' as the identifier
|
|
68
|
+
* const user = new User({ id: 1, name: 'John' });
|
|
69
|
+
*
|
|
70
|
+
* // Custom ID attribute can be specified in constructor options
|
|
71
|
+
* class User extends Model<UserSchema> {
|
|
72
|
+
* idAttribute = '_id
|
|
73
|
+
* endpoint(): string {
|
|
74
|
+
* return '/users';
|
|
75
|
+
* }
|
|
76
|
+
* }
|
|
77
|
+
* const user = new User({ _id: '507f1f77bcf86cd799439011', name: 'John' });
|
|
78
|
+
*/
|
|
79
|
+
idAttribute = 'id';
|
|
80
|
+
/**
|
|
81
|
+
* Creates a new instance of Model.
|
|
82
|
+
*/
|
|
4
83
|
constructor(data = {}) {
|
|
5
|
-
|
|
84
|
+
// Initialize model attributes with provided data, ensuring type safety
|
|
85
|
+
this.#attributes = { ...this.defaults(), ...data };
|
|
6
86
|
}
|
|
7
87
|
/**
|
|
8
|
-
*
|
|
88
|
+
* Gets the latest validation error.
|
|
89
|
+
*
|
|
90
|
+
* @returns {ValidationError || undefined} An instance of ValidationError if validation failed, otherwise undefined
|
|
9
91
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
92
|
+
get validationError() {
|
|
93
|
+
return this.#validationError;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Provides default attribute values for new model instances.
|
|
97
|
+
*
|
|
98
|
+
* This method is called during model construction to establish initial attribute
|
|
99
|
+
* values before applying any user-provided data. Subclasses can override this
|
|
100
|
+
* method to define default values for their specific attributes, ensuring that
|
|
101
|
+
* models always have sensible initial state.
|
|
102
|
+
*
|
|
103
|
+
* The defaults are applied first, then any data passed to the constructor will
|
|
104
|
+
* override these default values. This allows for flexible model initialization
|
|
105
|
+
* where some attributes have fallback values while others can be explicitly set.
|
|
106
|
+
*
|
|
107
|
+
* @protected
|
|
108
|
+
* @returns {Partial<T>} A partial object containing default attribute values
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* // Override in a User model subclass
|
|
112
|
+
* protected defaults(): Partial<UserAttributes> {
|
|
113
|
+
* return {
|
|
114
|
+
* role: 'user',
|
|
115
|
+
* isActive: true,
|
|
116
|
+
* createdAt: new Date()
|
|
117
|
+
* };
|
|
118
|
+
* }
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* // Creating a model with defaults
|
|
122
|
+
* const user = new User({ name: 'John' });
|
|
123
|
+
* // Resulting attributes: { role: 'user', isActive: true, createdAt: Date, name: 'John' }
|
|
124
|
+
*/
|
|
125
|
+
defaults() {
|
|
126
|
+
return {};
|
|
18
127
|
}
|
|
19
128
|
/**
|
|
20
129
|
* Retrieves the value of a specific attribute from the model.
|
|
@@ -35,30 +144,140 @@ export class Model {
|
|
|
35
144
|
get(key) {
|
|
36
145
|
return this.#attributes[key];
|
|
37
146
|
}
|
|
147
|
+
set(keyOrAttrs, valueOrOptions, options) {
|
|
148
|
+
let attrs = {};
|
|
149
|
+
let opts;
|
|
150
|
+
if (typeof keyOrAttrs === 'object') {
|
|
151
|
+
attrs = keyOrAttrs;
|
|
152
|
+
opts = valueOrOptions;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
attrs[keyOrAttrs] = valueOrOptions;
|
|
156
|
+
opts = options;
|
|
157
|
+
}
|
|
158
|
+
if (opts?.validate && !this.#doValidation({ ...this.#attributes, ...attrs }, opts)) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
Object.assign(this.#attributes, attrs);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Checks whether a specific attribute has a non-null, non-undefined value.
|
|
166
|
+
*
|
|
167
|
+
* This method provides a way to determine if an attribute exists and has a
|
|
168
|
+
* meaningful value. It returns true if the attribute is set to any value
|
|
169
|
+
* other than null or undefined, including falsy values like false, 0, or
|
|
170
|
+
* empty strings, which are considered valid values.
|
|
171
|
+
*
|
|
172
|
+
* @template K - The key type, constrained to keys of T
|
|
173
|
+
* @param {K} key - The attribute key to check
|
|
174
|
+
* @returns {boolean} True if the attribute has a non-null, non-undefined value
|
|
175
|
+
* @example
|
|
176
|
+
* // Assuming a User model with attributes { id: number, name: string, email?: string }
|
|
177
|
+
* const user = new User({ id: 1, name: 'John', email: null });
|
|
178
|
+
*
|
|
179
|
+
* user.has('id'); // Returns true (value is 1)
|
|
180
|
+
* user.has('name'); // Returns true (value is 'John')
|
|
181
|
+
* user.has('email'); // Returns false (value is null)
|
|
182
|
+
*
|
|
183
|
+
* // Even falsy values are considered "set"
|
|
184
|
+
* user.set({ name: '' });
|
|
185
|
+
* user.has('name'); // Returns true (empty string is a valid value)
|
|
186
|
+
*/
|
|
187
|
+
has(key) {
|
|
188
|
+
const value = this.#attributes[key];
|
|
189
|
+
return value !== null && value !== undefined;
|
|
190
|
+
}
|
|
38
191
|
/**
|
|
39
|
-
*
|
|
192
|
+
* Removes a specific attribute from the model by deleting it from the internal attributes hash.
|
|
40
193
|
*
|
|
41
|
-
* This method
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
194
|
+
* This method permanently removes an attribute from the model instance. Once unset,
|
|
195
|
+
* the attribute will no longer exist on the model and subsequent calls to get() for
|
|
196
|
+
* that key will return undefined. This is different from setting an attribute to
|
|
197
|
+
* null or undefined, as the property is completely removed from the attributes object.
|
|
45
198
|
*
|
|
46
|
-
* @
|
|
199
|
+
* @template K - The key type, constrained to keys of T
|
|
200
|
+
* @param {K} key - The attribute key to remove from the model
|
|
47
201
|
* @returns {void}
|
|
48
202
|
* @example
|
|
49
203
|
* // Assuming a User model with attributes { id: number, name: string, email: string }
|
|
50
204
|
* const user = new User({ id: 1, name: 'John', email: 'john@example.com' });
|
|
51
205
|
*
|
|
52
|
-
* //
|
|
206
|
+
* user.has('email'); // Returns true
|
|
207
|
+
* user.unset('email'); // Remove the email attribute
|
|
208
|
+
* user.has('email'); // Returns false
|
|
209
|
+
* user.get('email'); // Returns undefined
|
|
210
|
+
*
|
|
211
|
+
* // The attribute is completely removed, not just set to undefined
|
|
212
|
+
* const userData = user.toJSON(); // { id: 1, name: 'John' }
|
|
213
|
+
*/
|
|
214
|
+
unset(key) {
|
|
215
|
+
// Cast to Record to allow delete operation
|
|
216
|
+
const attrs = this.#attributes;
|
|
217
|
+
delete attrs[key];
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Removes all attributes from the model, including the id attribute.
|
|
221
|
+
*
|
|
222
|
+
* This method completely clears the model instance by removing all stored attributes,
|
|
223
|
+
* effectively resetting it to an empty state. After calling clear(), the model will
|
|
224
|
+
* behave as if it were newly instantiated with no data. This includes removing the
|
|
225
|
+
* ID attribute, which means the model will be considered "new" after clearing.
|
|
226
|
+
*
|
|
227
|
+
* This is useful when you want to reuse a model instance for different data or
|
|
228
|
+
* reset a model to its initial state without creating a new instance.
|
|
229
|
+
*
|
|
230
|
+
* @returns {void}
|
|
231
|
+
* @example
|
|
232
|
+
* // Clear all data from a user model
|
|
233
|
+
* const user = new User({ id: 1, name: 'John', email: 'john@example.com' });
|
|
234
|
+
* user.clear();
|
|
235
|
+
*
|
|
236
|
+
* user.has('id'); // Returns false
|
|
237
|
+
* user.has('name'); // Returns false
|
|
238
|
+
* user.isNew(); // Returns true
|
|
239
|
+
* user.toJSON(); // Returns {}
|
|
240
|
+
*
|
|
241
|
+
* // Model can be reused with new data
|
|
53
242
|
* user.set({ name: 'Jane', email: 'jane@example.com' });
|
|
54
|
-
|
|
243
|
+
*/
|
|
244
|
+
clear() {
|
|
245
|
+
this.#attributes = {};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Retrieves and escapes the HTML content of a specific attribute from the model.
|
|
249
|
+
*
|
|
250
|
+
* This method provides a safe way to access model attributes that may contain
|
|
251
|
+
* user-generated content or data that will be rendered in HTML contexts. It
|
|
252
|
+
* automatically applies HTML escaping to prevent XSS attacks and ensure safe
|
|
253
|
+
* rendering of potentially dangerous content.
|
|
254
|
+
*
|
|
255
|
+
* The method uses the escapeHTML utility function to convert special HTML
|
|
256
|
+
* characters (such as <, >, &, ", and ') into their corresponding HTML entities,
|
|
257
|
+
* making the content safe for direct insertion into HTML templates.
|
|
55
258
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
259
|
+
* @template K - The key type, constrained to keys of T
|
|
260
|
+
* @param {K} key - The attribute key to retrieve and escape the value for
|
|
261
|
+
* @returns {T[K]} The HTML-escaped value associated with the specified key
|
|
262
|
+
* @example
|
|
263
|
+
* // Assuming a Post model with attributes { id: number, title: string, content: string }
|
|
264
|
+
* const post = new Post({
|
|
265
|
+
* id: 1,
|
|
266
|
+
* title: 'Hello <script>alert("XSS")</script>',
|
|
267
|
+
* content: 'This is "safe" & secure content'
|
|
268
|
+
* });
|
|
269
|
+
*
|
|
270
|
+
* const safeTitle = post.escape('title');
|
|
271
|
+
* // Returns: 'Hello <script>alert("XSS")</script>'
|
|
272
|
+
*
|
|
273
|
+
* const safeContent = post.escape('content');
|
|
274
|
+
* // Returns: 'This is "safe" & secure content'
|
|
59
275
|
*/
|
|
60
|
-
|
|
61
|
-
|
|
276
|
+
escape(key) {
|
|
277
|
+
const val = this.#attributes[key];
|
|
278
|
+
if (val === undefined || val === null)
|
|
279
|
+
return '';
|
|
280
|
+
return escapeHTML(val.toString());
|
|
62
281
|
}
|
|
63
282
|
/**
|
|
64
283
|
* Determines whether this model instance is new (not yet persisted).
|
|
@@ -69,6 +288,75 @@ export class Model {
|
|
|
69
288
|
isNew() {
|
|
70
289
|
return !this.#getId();
|
|
71
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Validates the current model instance and returns whether it passes validation.
|
|
293
|
+
*
|
|
294
|
+
* This method performs validation on the model's current attributes using the
|
|
295
|
+
* validate() method defined by the subclass. It's a convenience method that
|
|
296
|
+
* allows you to check if a model is valid without having to manually call
|
|
297
|
+
* the validation logic.
|
|
298
|
+
*
|
|
299
|
+
* If validation fails, the validationError property will be set with details
|
|
300
|
+
* about what went wrong. If validation passes, validationError will be cleared.
|
|
301
|
+
*
|
|
302
|
+
* @param {ValidationOptions} [options] - Optional validation configuration
|
|
303
|
+
* @param {boolean} [options.silent] - If true, suppresses validation error setting
|
|
304
|
+
* @returns {boolean} True if the model passes validation, false otherwise
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* // Check if a user model is valid
|
|
308
|
+
* const user = new User({ name: '', email: 'invalid-email' });
|
|
309
|
+
*
|
|
310
|
+
* if (!user.isValid()) {
|
|
311
|
+
* console.log('Validation failed:', user.validationError);
|
|
312
|
+
* // Handle validation errors
|
|
313
|
+
* } else {
|
|
314
|
+
* // Proceed with saving or other operations
|
|
315
|
+
* await user.save();
|
|
316
|
+
* }
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* // Validate silently without setting validationError
|
|
320
|
+
* const isValid = user.isValid({ silent: true });
|
|
321
|
+
* // user.validationError remains unchanged
|
|
322
|
+
*/
|
|
323
|
+
isValid(options) {
|
|
324
|
+
return this.#doValidation(this.#attributes, { ...options, validate: true });
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Validates the model's attributes using custom validation logic.
|
|
328
|
+
*
|
|
329
|
+
* This method is intended to be overridden by subclasses to implement custom
|
|
330
|
+
* validation rules. By default, it returns undefined (no validation errors).
|
|
331
|
+
* If validation fails, this method should return an error - either a simple
|
|
332
|
+
* string message or a complete error object.
|
|
333
|
+
*
|
|
334
|
+
* The validate method is automatically called by save() before persisting data,
|
|
335
|
+
* and can also be explicitly called by set() when the {validate: true} option
|
|
336
|
+
* is passed. If validation fails, the save operation is aborted and model
|
|
337
|
+
* attributes are not modified.
|
|
338
|
+
*
|
|
339
|
+
* @param {Partial<T>} attributes - The attributes to validate
|
|
340
|
+
* @param {any} [options] - Additional options passed from set() or save()
|
|
341
|
+
* @returns {any} Returns undefined if valid, or an error (string/object) if invalid
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* // Override in a User model subclass
|
|
345
|
+
* validate(attributes: Partial<UserAttributes>) {
|
|
346
|
+
* if (!attributes.email) {
|
|
347
|
+
* return 'Email is required';
|
|
348
|
+
* }
|
|
349
|
+
* if (!attributes.email.includes('@')) {
|
|
350
|
+
* return { email: 'Invalid email format' };
|
|
351
|
+
* }
|
|
352
|
+
* // Return undefined if validation passes
|
|
353
|
+
* }
|
|
354
|
+
*/
|
|
355
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
356
|
+
validate(attributes, options) {
|
|
357
|
+
// Default implementation - no validation
|
|
358
|
+
return undefined;
|
|
359
|
+
}
|
|
72
360
|
/**
|
|
73
361
|
* Performs HTTP synchronization with the server for CRUD operations.
|
|
74
362
|
*
|
|
@@ -167,7 +455,13 @@ export class Model {
|
|
|
167
455
|
* generates additional fields (like timestamps, computed values, or normalized data)
|
|
168
456
|
* during the save process.
|
|
169
457
|
*
|
|
170
|
-
* @
|
|
458
|
+
* @param {ValidationOptions & SyncOptions} [options] - Optional configuration for save behavior
|
|
459
|
+
* @param {boolean} [options.validate] - Whether to validate before saving (defaults to true)
|
|
460
|
+
* @param {boolean} [options.silent] - If true, suppresses validation error setting
|
|
461
|
+
* @param {string} [options.endpoint] - Override the default endpoint for this save operation
|
|
462
|
+
* @param {Record<string, string>} [options.headers] - Additional headers to include in the request
|
|
463
|
+
* @param {string} [options.origin] - Override the base URL origin for this request
|
|
464
|
+
* @returns {Promise<boolean>} A promise that resolves to true if save succeeds, false if validation fails
|
|
171
465
|
* @throws {Error} Throws an error if the HTTP request fails or server returns an error
|
|
172
466
|
*
|
|
173
467
|
* @example
|
|
@@ -178,14 +472,28 @@ export class Model {
|
|
|
178
472
|
* // Update an existing user
|
|
179
473
|
* existingUser.set({ name: 'Jane' });
|
|
180
474
|
* await existingUser.save(); // PUT request with updated data
|
|
475
|
+
*
|
|
476
|
+
* // Save without validation
|
|
477
|
+
* await user.save({ validate: false });
|
|
478
|
+
*
|
|
479
|
+
* // Save with custom endpoint and headers
|
|
480
|
+
* await user.save({
|
|
481
|
+
* endpoint: '/api/v2/users',
|
|
482
|
+
* headers: { 'Custom-Header': 'value' }
|
|
483
|
+
* });
|
|
181
484
|
*/
|
|
182
|
-
async save() {
|
|
485
|
+
async save(options) {
|
|
486
|
+
// Always validates before saving unless {validate: false}
|
|
487
|
+
if (options?.validate !== false && !this.#doValidation(this.#attributes, options)) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
183
490
|
const id = this.#getId();
|
|
184
491
|
const method = id ? 'PUT' : 'POST';
|
|
185
|
-
const data = await this.sync(method, this.toJSON());
|
|
492
|
+
const data = await this.sync(method, this.toJSON(), options);
|
|
186
493
|
if (data && typeof data === 'object') {
|
|
187
|
-
this.set(data);
|
|
494
|
+
this.set(data, { silent: true });
|
|
188
495
|
}
|
|
496
|
+
return true;
|
|
189
497
|
}
|
|
190
498
|
/**
|
|
191
499
|
* Deletes the model from the server.
|
|
@@ -243,4 +551,26 @@ export class Model {
|
|
|
243
551
|
toJSON() {
|
|
244
552
|
return { ...this.#attributes };
|
|
245
553
|
}
|
|
554
|
+
// --------------- PRIVATE METHODS --------------- //
|
|
555
|
+
#getId() {
|
|
556
|
+
const id = this.#attributes[this.idAttribute];
|
|
557
|
+
if (typeof id === 'number' || (typeof id === 'string' && id.length > 0)) {
|
|
558
|
+
return id;
|
|
559
|
+
}
|
|
560
|
+
return undefined;
|
|
561
|
+
}
|
|
562
|
+
#doValidation(attrs, options) {
|
|
563
|
+
if (options?.silent || !this.validate || typeof this.validate !== 'function') {
|
|
564
|
+
this.#validationError = undefined;
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
const errMsg = this.validate(attrs, options);
|
|
568
|
+
// console.log(errMsg);
|
|
569
|
+
if (errMsg && errMsg.length > 0) {
|
|
570
|
+
this.#validationError = new ValidationError(errMsg);
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
this.#validationError = undefined;
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
246
576
|
}
|
package/dist/config.svelte.d.ts
CHANGED
|
@@ -2,8 +2,41 @@ export interface VellumConfig {
|
|
|
2
2
|
origin: string;
|
|
3
3
|
headers: Record<string, string>;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Global reactive state for Vellum configuration. Uses Svelte's $state rune to
|
|
7
|
+
* create a reactive configuration object that automatically triggers updates when modified.
|
|
8
|
+
*
|
|
9
|
+
* @default origin - Empty string (must be configured before use)
|
|
10
|
+
* @default headers - Contains 'Content-Type': 'application/json'
|
|
11
|
+
*/
|
|
5
12
|
export declare const vellumConfig: VellumConfig;
|
|
6
13
|
/**
|
|
7
|
-
* Helper to update global configuration
|
|
14
|
+
* Helper function to update global Vellum configuration
|
|
15
|
+
*
|
|
16
|
+
* Allows partial updates to the global configuration state. Only provided
|
|
17
|
+
* properties will be updated, leaving others unchanged. Headers are merged
|
|
18
|
+
* with existing headers rather than replaced entirely.
|
|
19
|
+
*
|
|
20
|
+
* @param {Partial<VellumConfig>} config - Partial configuration object with properties to update
|
|
21
|
+
* @param {string} [config.origin] - New origin URL to set
|
|
22
|
+
* @param {Record<string, string>} [config.headers] - Headers to merge with existing headers
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Set the API origin
|
|
26
|
+
* configureVellum({ origin: 'https://api.vellum.ai' });
|
|
27
|
+
*
|
|
28
|
+
* // Add custom headers
|
|
29
|
+
* configureVellum({
|
|
30
|
+
* headers: {
|
|
31
|
+
* 'Authorization': 'Bearer token123',
|
|
32
|
+
* 'X-Custom-Header': 'value'
|
|
33
|
+
* }
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Update both origin and headers
|
|
37
|
+
* configureVellum({
|
|
38
|
+
* origin: 'https://api.vellum.ai',
|
|
39
|
+
* headers: { 'Authorization': 'Bearer token123' }
|
|
40
|
+
* });
|
|
8
41
|
*/
|
|
9
42
|
export declare const configureVellum: (config: Partial<VellumConfig>) => void;
|
package/dist/config.svelte.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global reactive state for Vellum configuration. Uses Svelte's $state rune to
|
|
3
|
+
* create a reactive configuration object that automatically triggers updates when modified.
|
|
4
|
+
*
|
|
5
|
+
* @default origin - Empty string (must be configured before use)
|
|
6
|
+
* @default headers - Contains 'Content-Type': 'application/json'
|
|
7
|
+
*/
|
|
1
8
|
export const vellumConfig = $state({
|
|
2
9
|
origin: '',
|
|
3
10
|
headers: {
|
|
@@ -5,7 +12,33 @@ export const vellumConfig = $state({
|
|
|
5
12
|
}
|
|
6
13
|
});
|
|
7
14
|
/**
|
|
8
|
-
* Helper to update global configuration
|
|
15
|
+
* Helper function to update global Vellum configuration
|
|
16
|
+
*
|
|
17
|
+
* Allows partial updates to the global configuration state. Only provided
|
|
18
|
+
* properties will be updated, leaving others unchanged. Headers are merged
|
|
19
|
+
* with existing headers rather than replaced entirely.
|
|
20
|
+
*
|
|
21
|
+
* @param {Partial<VellumConfig>} config - Partial configuration object with properties to update
|
|
22
|
+
* @param {string} [config.origin] - New origin URL to set
|
|
23
|
+
* @param {Record<string, string>} [config.headers] - Headers to merge with existing headers
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Set the API origin
|
|
27
|
+
* configureVellum({ origin: 'https://api.vellum.ai' });
|
|
28
|
+
*
|
|
29
|
+
* // Add custom headers
|
|
30
|
+
* configureVellum({
|
|
31
|
+
* headers: {
|
|
32
|
+
* 'Authorization': 'Bearer token123',
|
|
33
|
+
* 'X-Custom-Header': 'value'
|
|
34
|
+
* }
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* // Update both origin and headers
|
|
38
|
+
* configureVellum({
|
|
39
|
+
* origin: 'https://api.vellum.ai',
|
|
40
|
+
* headers: { 'Authorization': 'Bearer token123' }
|
|
41
|
+
* });
|
|
9
42
|
*/
|
|
10
43
|
export const configureVellum = (config) => {
|
|
11
44
|
if (config.origin)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export { vellumConfig, configureVellum } from './config.svelte.js';
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
2
|
+
export { type ValidationDetails, ValidationError } from './errors/validation_error.js';
|
|
3
|
+
export { type SyncOptions, type ValidationOptions, Model } from './Model.svelte.js';
|
|
4
|
+
export { type FetchOptions, Collection } from './Collection.svelte.js';
|
|
5
|
+
export * as utils from './utils.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// Reexport your entry components here
|
|
2
1
|
export { vellumConfig, configureVellum } from './config.svelte.js';
|
|
2
|
+
export { ValidationError } from './errors/validation_error.js';
|
|
3
3
|
export { Model } from './Model.svelte.js';
|
|
4
4
|
export { Collection } from './Collection.svelte.js';
|
|
5
|
+
export * as utils from './utils.js';
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const escapeHTML: (text: string) => string;
|
package/dist/utils.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jwerre/vellum",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Structural state management library for Svelte 5",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"types:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
33
33
|
"check": "npm audit --audit-level=moderate --omit=dev && npm run format && npm run lint && npm run spell && npm run types && npm test && npm run build && npm run release:dry",
|
|
34
34
|
"dev": "vite dev",
|
|
35
|
+
"docs": "npm run build && documentation readme dist/index.js --section=\"API Documentation\"",
|
|
35
36
|
"format": "prettier --check .",
|
|
36
37
|
"format:write": "prettier --write .",
|
|
37
38
|
"lint": "prettier --check . && eslint .",
|
|
@@ -75,6 +76,7 @@
|
|
|
75
76
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
76
77
|
"@types/node": "^24",
|
|
77
78
|
"cspell": "^9.4.0",
|
|
79
|
+
"documentation": "^14.0.3",
|
|
78
80
|
"eslint": "^9.39.1",
|
|
79
81
|
"eslint-config-prettier": "^10.1.8",
|
|
80
82
|
"eslint-plugin-svelte": "^3.13.1",
|