@jwerre/vellum 1.3.0-next.1 → 1.3.0-next.3
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 +205 -81
- package/dist/Collection.svelte.d.ts +16 -4
- package/dist/Collection.svelte.js +11 -4
- package/dist/Model.svelte.d.ts +73 -39
- package/dist/Model.svelte.js +99 -42
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Vellum
|
|
2
2
|
|
|
3
|
-
Vellum is a lightweight, structural state management library for Svelte 5. Vellum provides a robust Model and Collection base powered by Svelte Runes. It bridges the gap between raw objects and complex state logic, offering a typed, class-based approach to managing data-heavy applications.
|
|
3
|
+
Vellum is a lightweight, structural state management library for Svelte 5. Vellum provides a robust Model and Collection base that is inspired by Backbone.js but powered by Svelte Runes. It bridges the gap between raw objects and complex state logic, offering a typed, class-based approach to managing data-heavy applications.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -61,9 +61,7 @@ interface BookSchema {
|
|
|
61
61
|
|
|
62
62
|
export class Book extends Model<BookSchema> {
|
|
63
63
|
|
|
64
|
-
endpoint
|
|
65
|
-
return `/v1/books`;
|
|
66
|
-
}
|
|
64
|
+
endpoint = `/v1/books`;
|
|
67
65
|
|
|
68
66
|
defaults() {
|
|
69
67
|
return {
|
|
@@ -108,10 +106,7 @@ import { Book } from './Book.svelte.js';
|
|
|
108
106
|
|
|
109
107
|
export class Books extends Collection<Book, BookSchema> {
|
|
110
108
|
model = Book;
|
|
111
|
-
|
|
112
|
-
endpoint() {
|
|
113
|
-
return `/v1/books`;
|
|
114
|
-
}
|
|
109
|
+
endpoint = `/v1/books`;
|
|
115
110
|
|
|
116
111
|
// Derived state for the entire collection
|
|
117
112
|
classicCount = $derived(this.items.filter((u) => u.isClassic()).length);
|
|
@@ -124,40 +119,20 @@ Vellum works seamlessly with Svelte 5 components.
|
|
|
124
119
|
|
|
125
120
|
```svelte
|
|
126
121
|
<script lang="ts">
|
|
127
|
-
import {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
year: 1960,
|
|
142
|
-
genre: 'literature'
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
id: 3,
|
|
146
|
-
title: 'The Pillars of the Earth',
|
|
147
|
-
author: 'Ken Follett',
|
|
148
|
-
year: 1989,
|
|
149
|
-
genre: 'literature'
|
|
150
|
-
}
|
|
151
|
-
]);
|
|
152
|
-
|
|
153
|
-
function addBook() {
|
|
154
|
-
books.add({
|
|
155
|
-
title: 'Moby Dick',
|
|
156
|
-
author: 'Herman Melville',
|
|
157
|
-
year: 1851,
|
|
158
|
-
genre: 'Adventure',
|
|
159
|
-
summary: 'The obsessive quest of Captain Ahab to seek revenge on the white whale.'
|
|
160
|
-
});
|
|
122
|
+
import { Book } from './Book.svelte.js';
|
|
123
|
+
import { Books } from './Books.svelte.js';
|
|
124
|
+
|
|
125
|
+
const books = new Books();
|
|
126
|
+
await books.fetch();
|
|
127
|
+
|
|
128
|
+
async function onSubmitBook(e: Event) {
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
const form = e.target as HTMLFormElement;
|
|
131
|
+
const formData = new FormData(form);
|
|
132
|
+
const data = Object.fromEntries(formData) as BookSchema;
|
|
133
|
+
const book = new Book(data);
|
|
134
|
+
await book.save();
|
|
135
|
+
books.add(book);
|
|
161
136
|
}
|
|
162
137
|
</script>
|
|
163
138
|
|
|
@@ -170,8 +145,18 @@ Vellum works seamlessly with Svelte 5 components.
|
|
|
170
145
|
{/if}
|
|
171
146
|
{/each}
|
|
172
147
|
</ul>
|
|
173
|
-
|
|
174
|
-
<
|
|
148
|
+
<form onsubmit={onSubmitBook}>
|
|
149
|
+
<div>
|
|
150
|
+
<label for="title">Title</label>
|
|
151
|
+
<input type="text" id="title" name="title" />
|
|
152
|
+
</div>
|
|
153
|
+
<div>
|
|
154
|
+
<label for="author">Author</label>
|
|
155
|
+
<input type="text" id="author" name="author" />
|
|
156
|
+
</div>
|
|
157
|
+
...
|
|
158
|
+
<button type="submit">+ Add book</button>
|
|
159
|
+
</form>
|
|
175
160
|
```
|
|
176
161
|
|
|
177
162
|
### Working example
|
|
@@ -199,60 +184,72 @@ There is a working example of Vellum in the `routes` directory. To run it, clone
|
|
|
199
184
|
- [idAttribute](#idattribute)
|
|
200
185
|
- [Examples](#examples-2)
|
|
201
186
|
- [validationError](#validationerror)
|
|
187
|
+
- [changed](#changed)
|
|
188
|
+
- [previous](#previous)
|
|
202
189
|
- [defaults](#defaults)
|
|
203
190
|
- [Examples](#examples-3)
|
|
204
|
-
- [
|
|
191
|
+
- [hasChanged](#haschanged)
|
|
205
192
|
- [Parameters](#parameters-2)
|
|
206
193
|
- [Examples](#examples-4)
|
|
207
|
-
- [
|
|
194
|
+
- [get](#get)
|
|
208
195
|
- [Parameters](#parameters-3)
|
|
209
196
|
- [Examples](#examples-5)
|
|
210
|
-
- [
|
|
197
|
+
- [has](#has)
|
|
211
198
|
- [Parameters](#parameters-4)
|
|
212
199
|
- [Examples](#examples-6)
|
|
213
|
-
- [
|
|
214
|
-
- [Examples](#examples-7)
|
|
215
|
-
- [escape](#escape)
|
|
200
|
+
- [unset](#unset)
|
|
216
201
|
- [Parameters](#parameters-5)
|
|
202
|
+
- [Examples](#examples-7)
|
|
203
|
+
- [clear](#clear)
|
|
217
204
|
- [Examples](#examples-8)
|
|
218
|
-
- [
|
|
219
|
-
- [isValid](#isvalid)
|
|
205
|
+
- [escape](#escape)
|
|
220
206
|
- [Parameters](#parameters-6)
|
|
221
207
|
- [Examples](#examples-9)
|
|
222
|
-
- [
|
|
208
|
+
- [isNew](#isnew)
|
|
209
|
+
- [isValid](#isvalid)
|
|
223
210
|
- [Parameters](#parameters-7)
|
|
224
211
|
- [Examples](#examples-10)
|
|
225
|
-
- [
|
|
212
|
+
- [validate](#validate)
|
|
226
213
|
- [Parameters](#parameters-8)
|
|
227
214
|
- [Examples](#examples-11)
|
|
228
|
-
- [
|
|
229
|
-
- [Examples](#examples-12)
|
|
230
|
-
- [save](#save)
|
|
215
|
+
- [clone](#clone)
|
|
231
216
|
- [Parameters](#parameters-9)
|
|
217
|
+
- [Examples](#examples-12)
|
|
218
|
+
- [sync](#sync)
|
|
219
|
+
- [Parameters](#parameters-10)
|
|
232
220
|
- [Examples](#examples-13)
|
|
233
|
-
- [
|
|
221
|
+
- [fetch](#fetch)
|
|
234
222
|
- [Examples](#examples-14)
|
|
235
|
-
- [
|
|
223
|
+
- [save](#save)
|
|
224
|
+
- [Parameters](#parameters-11)
|
|
236
225
|
- [Examples](#examples-15)
|
|
226
|
+
- [destroy](#destroy)
|
|
227
|
+
- [Examples](#examples-16)
|
|
228
|
+
- [toJSON](#tojson)
|
|
229
|
+
- [Examples](#examples-17)
|
|
230
|
+
- [attributes](#attributes)
|
|
237
231
|
- [validationError](#validationerror-1)
|
|
232
|
+
- [changed](#changed-1)
|
|
233
|
+
- [previous](#previous-1)
|
|
238
234
|
- [Collection](#collection)
|
|
239
|
-
- [Parameters](#parameters-
|
|
240
|
-
- [Examples](#examples-
|
|
235
|
+
- [Parameters](#parameters-12)
|
|
236
|
+
- [Examples](#examples-18)
|
|
241
237
|
- [items](#items)
|
|
242
238
|
- [length](#length)
|
|
243
239
|
- [add](#add)
|
|
244
|
-
- [Parameters](#parameters-
|
|
245
|
-
- [Examples](#examples-
|
|
240
|
+
- [Parameters](#parameters-13)
|
|
241
|
+
- [Examples](#examples-19)
|
|
246
242
|
- [sort](#sort)
|
|
243
|
+
- [Examples](#examples-20)
|
|
247
244
|
- [reset](#reset)
|
|
248
|
-
- [Parameters](#parameters-
|
|
249
|
-
- [Examples](#examples-
|
|
245
|
+
- [Parameters](#parameters-14)
|
|
246
|
+
- [Examples](#examples-21)
|
|
250
247
|
- [find](#find)
|
|
251
|
-
- [Parameters](#parameters-
|
|
252
|
-
- [Examples](#examples-
|
|
248
|
+
- [Parameters](#parameters-15)
|
|
249
|
+
- [Examples](#examples-22)
|
|
253
250
|
- [fetch](#fetch-1)
|
|
254
|
-
- [Parameters](#parameters-
|
|
255
|
-
- [Examples](#examples-
|
|
251
|
+
- [Parameters](#parameters-16)
|
|
252
|
+
- [Examples](#examples-23)
|
|
256
253
|
|
|
257
254
|
### vellumConfig
|
|
258
255
|
|
|
@@ -329,9 +326,8 @@ interface UserAttributes {
|
|
|
329
326
|
}
|
|
330
327
|
|
|
331
328
|
class User extends Model<UserAttributes> {
|
|
332
|
-
endpoint
|
|
333
|
-
|
|
334
|
-
}
|
|
329
|
+
endpoint = '/users';
|
|
330
|
+
|
|
335
331
|
defaults() {
|
|
336
332
|
return { name: '', createdAt: new Date() };
|
|
337
333
|
}
|
|
@@ -365,9 +361,7 @@ const user = new User({ id: 1, name: 'John' });
|
|
|
365
361
|
// Custom ID attribute can be specified in constructor options
|
|
366
362
|
class User extends Model<UserSchema> {
|
|
367
363
|
idAttribute = '_id
|
|
368
|
-
endpoint
|
|
369
|
-
return '/users';
|
|
370
|
-
}
|
|
364
|
+
endpoint = '/users';
|
|
371
365
|
}
|
|
372
366
|
const user = new User({ _id: '507f1f77bcf86cd799439011', name: 'John' });
|
|
373
367
|
```
|
|
@@ -376,6 +370,20 @@ const user = new User({ _id: '507f1f77bcf86cd799439011', name: 'John' });
|
|
|
376
370
|
|
|
377
371
|
Gets the latest validation error.
|
|
378
372
|
|
|
373
|
+
#### changed
|
|
374
|
+
|
|
375
|
+
Gets the hash of attributes that have changed since the last set call.
|
|
376
|
+
This is a readonly accessor - the changed object cannot be modified directly.
|
|
377
|
+
|
|
378
|
+
Returns **Partial\<T>** An object containing all attributes that have changed
|
|
379
|
+
|
|
380
|
+
#### previous
|
|
381
|
+
|
|
382
|
+
Gets the hash of previous attribute values before they were changed.
|
|
383
|
+
This is a readonly accessor - the previous object cannot be modified directly.
|
|
384
|
+
|
|
385
|
+
Returns **Partial\<T>** An object containing the previous values of changed attributes
|
|
386
|
+
|
|
379
387
|
#### defaults
|
|
380
388
|
|
|
381
389
|
Provides default attribute values for new model instances.
|
|
@@ -410,6 +418,37 @@ const user = new User({ name: 'John' });
|
|
|
410
418
|
|
|
411
419
|
Returns **Partial\<T>** A partial object containing default attribute values
|
|
412
420
|
|
|
421
|
+
#### hasChanged
|
|
422
|
+
|
|
423
|
+
Determines if attributes have changed since the last set call.
|
|
424
|
+
|
|
425
|
+
This method checks whether any attributes were modified in the most recent
|
|
426
|
+
set operation. When called without arguments, it returns true if any attributes
|
|
427
|
+
have changed. When called with a specific attribute key, it returns true only
|
|
428
|
+
if that particular attribute was changed.
|
|
429
|
+
|
|
430
|
+
##### Parameters
|
|
431
|
+
|
|
432
|
+
- `attr`  
|
|
433
|
+
|
|
434
|
+
##### Examples
|
|
435
|
+
|
|
436
|
+
```javascript
|
|
437
|
+
// Check if any attributes changed
|
|
438
|
+
const user = new User({ name: 'John', email: 'john@example.com' });
|
|
439
|
+
user.set('name', 'Jane');
|
|
440
|
+
user.hasChanged(); // Returns true
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
```javascript
|
|
444
|
+
// Check if a specific attribute changed
|
|
445
|
+
user.set('name', 'Jane');
|
|
446
|
+
user.hasChanged('name'); // Returns true
|
|
447
|
+
user.hasChanged('email'); // Returns false
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** True if attributes have changed, false otherwise
|
|
451
|
+
|
|
413
452
|
#### get
|
|
414
453
|
|
|
415
454
|
Retrieves the value of a specific attribute from the model.
|
|
@@ -638,19 +677,62 @@ validate(attributes: Partial<UserAttributes>) {
|
|
|
638
677
|
|
|
639
678
|
Returns **any** Returns undefined if valid, or an error (string/object) if invalid
|
|
640
679
|
|
|
680
|
+
#### clone
|
|
681
|
+
|
|
682
|
+
Creates a new instance of the model with identical attributes.
|
|
683
|
+
|
|
684
|
+
This method returns a new model instance that is a clone of the current model,
|
|
685
|
+
with all attributes copied to the new instance. The clone is a separate object
|
|
686
|
+
with its own state, so modifications to the clone will not affect the original
|
|
687
|
+
model and vice versa. By default, the ID is removed so the cloned instance is
|
|
688
|
+
considered "new" (isNew() returns true).
|
|
689
|
+
|
|
690
|
+
##### Parameters
|
|
691
|
+
|
|
692
|
+
- `options` **CloneOptions?** Configuration options for cloning
|
|
693
|
+
- `options.keepId` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** If true, preserves the ID in the clone (optional, default `false`)
|
|
694
|
+
- `options.deep` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** If true, performs a deep clone of nested objects/arrays (optional, default `false`)
|
|
695
|
+
|
|
696
|
+
##### Examples
|
|
697
|
+
|
|
698
|
+
```javascript
|
|
699
|
+
// Clone a user model (default - no ID)
|
|
700
|
+
const user = new User({ id: 1, name: 'John', email: 'john@example.com' });
|
|
701
|
+
const userCopy = user.clone();
|
|
702
|
+
console.log(userCopy.isNew()); // true
|
|
703
|
+
console.log(userCopy.get('id')); // undefined
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
```javascript
|
|
707
|
+
// Clone with ID preserved
|
|
708
|
+
const userCopy = user.clone({ keepId: true });
|
|
709
|
+
console.log(userCopy.isNew()); // false
|
|
710
|
+
console.log(userCopy.get('id')); // 1
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
```javascript
|
|
714
|
+
// Deep clone for nested objects
|
|
715
|
+
const user = new User({ id: 1, name: 'John', settings: { theme: 'dark' } });
|
|
716
|
+
const userCopy = user.clone({ deep: true });
|
|
717
|
+
userCopy.get('settings').theme = 'light';
|
|
718
|
+
console.log(user.get('settings').theme); // 'dark' (unchanged)
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
Returns **this** A new instance of the same model class with cloned attributes
|
|
722
|
+
|
|
641
723
|
#### sync
|
|
642
724
|
|
|
643
725
|
Performs HTTP synchronization with the server for CRUD operations.
|
|
644
726
|
|
|
645
727
|
This method handles all HTTP communication between the model and the server,
|
|
646
728
|
automatically constructing the appropriate URL based on the model's ID and
|
|
647
|
-
endpoint
|
|
729
|
+
endpoint. It supports all standard REST operations and provides type-safe
|
|
648
730
|
response handling.
|
|
649
731
|
|
|
650
732
|
The URL construction follows REST conventions:
|
|
651
733
|
|
|
652
|
-
- For new models (no ID): uses collection endpoint `${baseUrl}${endpoint
|
|
653
|
-
- For existing models (with ID): uses resource endpoint `${baseUrl}${endpoint
|
|
734
|
+
- For new models (no ID): uses collection endpoint `${baseUrl}${endpoint}`
|
|
735
|
+
- For existing models (with ID): uses resource endpoint `${baseUrl}${endpoint}/${id}`
|
|
654
736
|
|
|
655
737
|
##### Parameters
|
|
656
738
|
|
|
@@ -759,7 +841,7 @@ on the server). If the model is new and has no ID, the method will return withou
|
|
|
759
841
|
performing any operation.
|
|
760
842
|
|
|
761
843
|
The DELETE request is sent to the model's specific resource endpoint using the
|
|
762
|
-
pattern `${baseUrl}${endpoint
|
|
844
|
+
pattern `${baseUrl}${endpoint}/${id}`. After successful deletion, the model
|
|
763
845
|
instance remains in memory but the corresponding server resource is removed.
|
|
764
846
|
|
|
765
847
|
##### Examples
|
|
@@ -805,11 +887,35 @@ const jsonString = JSON.stringify(user.toJSON());
|
|
|
805
887
|
|
|
806
888
|
Returns **T** A plain object containing all of the model's attributes
|
|
807
889
|
|
|
890
|
+
### attributes
|
|
891
|
+
|
|
892
|
+
Internal reactive storage for all model attributes.
|
|
893
|
+
|
|
894
|
+
This private field uses Svelte's $state rune to create a reactive object that
|
|
895
|
+
holds all the model's attribute data. When attributes are modified, this reactivity
|
|
896
|
+
ensures that any Svelte components using the model will automatically re-render
|
|
897
|
+
to reflect the changes.
|
|
898
|
+
|
|
899
|
+
The attributes are initialized as an empty object cast to type T, and are populated
|
|
900
|
+
during construction by merging default values with provided data. All attribute
|
|
901
|
+
access and modification should go through the public API methods (get, set, has, etc.)
|
|
902
|
+
rather than directly accessing this field.
|
|
903
|
+
|
|
808
904
|
### validationError
|
|
809
905
|
|
|
810
906
|
Validation error property that gets set when validation fails.
|
|
811
907
|
This property contains the error returned by the validate method.
|
|
812
908
|
|
|
909
|
+
### changed
|
|
910
|
+
|
|
911
|
+
Internal hash containing all attributes that have changed since the last set call.
|
|
912
|
+
This property tracks which attributes have been modified and their new values.
|
|
913
|
+
|
|
914
|
+
### previous
|
|
915
|
+
|
|
916
|
+
Internal hash containing the previous values of attributes before they were changed.
|
|
917
|
+
This property stores the original values of attributes from before the last set call.
|
|
918
|
+
|
|
813
919
|
### Collection
|
|
814
920
|
|
|
815
921
|
Abstract base class for managing collections of Model instances.
|
|
@@ -827,7 +933,7 @@ system for automatic UI updates.
|
|
|
827
933
|
```javascript
|
|
828
934
|
class UserCollection extends Collection<UserModel, User> {
|
|
829
935
|
model = UserModel;
|
|
830
|
-
endpoint =
|
|
936
|
+
endpoint = '/api/users';
|
|
831
937
|
}
|
|
832
938
|
|
|
833
939
|
const users = new UserCollection();
|
|
@@ -867,7 +973,25 @@ Returns **any** The model instance that was added to the collection
|
|
|
867
973
|
#### sort
|
|
868
974
|
|
|
869
975
|
Sorts the collection using the comparator if one is defined.
|
|
870
|
-
|
|
976
|
+
|
|
977
|
+
This method is called automatically when items are added to the collection via `add()` or `reset()`.
|
|
978
|
+
You can also call it manually to re-sort the collection after modifying model attributes.
|
|
979
|
+
|
|
980
|
+
The sorting behavior depends on the type of comparator defined:
|
|
981
|
+
|
|
982
|
+
- **String attribute**: Sorts by the specified model attribute in ascending order
|
|
983
|
+
- **sortBy function** (1 argument): Sorts by the return value of the function in ascending order
|
|
984
|
+
- **sort function** (2 arguments): Uses a custom comparator that returns -1, 0, or 1
|
|
985
|
+
|
|
986
|
+
If no comparator is defined or the comparator returns undefined, no sorting is performed.
|
|
987
|
+
|
|
988
|
+
##### Examples
|
|
989
|
+
|
|
990
|
+
```javascript
|
|
991
|
+
// Manual sorting after updating a model
|
|
992
|
+
user.set('priority', 5);
|
|
993
|
+
collection.sort();
|
|
994
|
+
```
|
|
871
995
|
|
|
872
996
|
#### reset
|
|
873
997
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Model } from './Model.svelte';
|
|
2
2
|
import { type VellumConfig } from './config.svelte';
|
|
3
|
+
export interface CollectionOptions extends Partial<VellumConfig> {
|
|
4
|
+
model?: unknown;
|
|
5
|
+
}
|
|
3
6
|
export interface FetchOptions extends Partial<VellumConfig> {
|
|
4
7
|
endpoint?: string;
|
|
5
8
|
search?: Record<string, string | number | boolean>;
|
|
@@ -17,7 +20,7 @@ export interface FetchOptions extends Partial<VellumConfig> {
|
|
|
17
20
|
* @example
|
|
18
21
|
* class UserCollection extends Collection<UserModel, User> {
|
|
19
22
|
* model = UserModel;
|
|
20
|
-
* endpoint =
|
|
23
|
+
* endpoint = '/api/users';
|
|
21
24
|
* }
|
|
22
25
|
*
|
|
23
26
|
* const users = new UserCollection();
|
|
@@ -31,8 +34,16 @@ export declare abstract class Collection<M extends Model<T>, T extends object> {
|
|
|
31
34
|
abstract model: {
|
|
32
35
|
new (data: Partial<T>): M;
|
|
33
36
|
};
|
|
34
|
-
/**
|
|
35
|
-
|
|
37
|
+
/**
|
|
38
|
+
* The base URL path for API endpoints related to this model.
|
|
39
|
+
*
|
|
40
|
+
* Define this as a property in your subclass.
|
|
41
|
+
* @example
|
|
42
|
+
* class User extends Collection<UserSchema> {
|
|
43
|
+
* endpoint = '/users';
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
protected abstract endpoint: string;
|
|
36
47
|
/**
|
|
37
48
|
* Optional comparator for sorting the collection.
|
|
38
49
|
*
|
|
@@ -83,7 +94,8 @@ export declare abstract class Collection<M extends Model<T>, T extends object> {
|
|
|
83
94
|
* const collection = new UserCollection();
|
|
84
95
|
*
|
|
85
96
|
* // Create collection with initial data
|
|
86
|
-
* const collection = new UserCollection(
|
|
97
|
+
* const collection = new UserCollection();
|
|
98
|
+
* collection.reset([
|
|
87
99
|
* { id: 1, name: 'John' },
|
|
88
100
|
* { id: 2, name: 'Jane' }
|
|
89
101
|
* ]);
|
|
@@ -14,7 +14,7 @@ import { vellumConfig } from './config.svelte';
|
|
|
14
14
|
* @example
|
|
15
15
|
* class UserCollection extends Collection<UserModel, User> {
|
|
16
16
|
* model = UserModel;
|
|
17
|
-
* endpoint =
|
|
17
|
+
* endpoint = '/api/users';
|
|
18
18
|
* }
|
|
19
19
|
*
|
|
20
20
|
* const users = new UserCollection();
|
|
@@ -34,14 +34,21 @@ export class Collection {
|
|
|
34
34
|
* const collection = new UserCollection();
|
|
35
35
|
*
|
|
36
36
|
* // Create collection with initial data
|
|
37
|
-
* const collection = new UserCollection(
|
|
37
|
+
* const collection = new UserCollection();
|
|
38
|
+
* collection.reset([
|
|
38
39
|
* { id: 1, name: 'John' },
|
|
39
40
|
* { id: 2, name: 'Jane' }
|
|
40
41
|
* ]);
|
|
41
42
|
*/
|
|
42
43
|
constructor(models = []) {
|
|
43
44
|
if (models.length > 0) {
|
|
44
|
-
|
|
45
|
+
try {
|
|
46
|
+
this.reset(models);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error('Failed to initialize collection with data:', error);
|
|
50
|
+
console.error('Initializing the collection with data requires model to be defined as getter since model is not available in constructor.');
|
|
51
|
+
}
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
54
|
/** Gets the number of items in the collection */
|
|
@@ -194,7 +201,7 @@ export class Collection {
|
|
|
194
201
|
}
|
|
195
202
|
query = `?${params.toString()}`;
|
|
196
203
|
}
|
|
197
|
-
const endpoint = options?.endpoint?.length ? options.endpoint : this.endpoint
|
|
204
|
+
const endpoint = options?.endpoint?.length ? options.endpoint : this.endpoint;
|
|
198
205
|
const fullUrl = `${vellumConfig.origin}${endpoint}${query}`;
|
|
199
206
|
const response = await fetch(fullUrl, {
|
|
200
207
|
headers: { ...vellumConfig.headers }
|
package/dist/Model.svelte.d.ts
CHANGED
|
@@ -8,6 +8,10 @@ export interface ValidationOptions {
|
|
|
8
8
|
silent?: boolean;
|
|
9
9
|
[key: string]: unknown;
|
|
10
10
|
}
|
|
11
|
+
export interface CloneOptions {
|
|
12
|
+
keepId?: boolean;
|
|
13
|
+
deep?: boolean;
|
|
14
|
+
}
|
|
11
15
|
/**
|
|
12
16
|
* Abstract base class for creating model instances that interact with RESTful APIs.
|
|
13
17
|
*
|
|
@@ -37,9 +41,8 @@ export interface ValidationOptions {
|
|
|
37
41
|
* }
|
|
38
42
|
*
|
|
39
43
|
* class User extends Model<UserAttributes> {
|
|
40
|
-
* endpoint
|
|
41
|
-
|
|
42
|
-
* }
|
|
44
|
+
* endpoint = '/users';
|
|
45
|
+
|
|
43
46
|
* defaults() {
|
|
44
47
|
* return { name: '', createdAt: new Date() };
|
|
45
48
|
* }
|
|
@@ -59,18 +62,16 @@ export declare abstract class Model<T extends object> {
|
|
|
59
62
|
* for API endpoints related to this model.
|
|
60
63
|
*
|
|
61
64
|
* This method returns the root URL segment that will be appended to the base API URL
|
|
62
|
-
* to form complete endpoints for CRUD operations. For example, if endpoint
|
|
65
|
+
* to form complete endpoints for CRUD operations. For example, if endpoint is set to
|
|
63
66
|
* '/users', the full URL for API calls would be `${baseUrl}/users` for collections
|
|
64
67
|
* or `${baseUrl}/users/{id}` for individual resources.
|
|
65
68
|
*
|
|
66
69
|
* @returns {string} The root URL path for this model's API endpoints (e.g., '/users', '/posts')
|
|
67
70
|
* @example
|
|
68
71
|
* // In a User model subclass:
|
|
69
|
-
* endpoint
|
|
70
|
-
* return '/users';
|
|
71
|
-
* }
|
|
72
|
+
* endpoint = '/users';
|
|
72
73
|
*/
|
|
73
|
-
protected abstract endpoint
|
|
74
|
+
protected abstract endpoint: string;
|
|
74
75
|
/**
|
|
75
76
|
* The name of the attribute that serves as the unique identifier for this model instance.
|
|
76
77
|
*
|
|
@@ -89,9 +90,7 @@ export declare abstract class Model<T extends object> {
|
|
|
89
90
|
* // Custom ID attribute can be specified in constructor options
|
|
90
91
|
* class User extends Model<UserSchema> {
|
|
91
92
|
* idAttribute = '_id
|
|
92
|
-
* endpoint
|
|
93
|
-
* return '/users';
|
|
94
|
-
* }
|
|
93
|
+
* endpoint = '/users';
|
|
95
94
|
* }
|
|
96
95
|
* const user = new User({ _id: '507f1f77bcf86cd799439011', name: 'John' });
|
|
97
96
|
*/
|
|
@@ -120,30 +119,6 @@ export declare abstract class Model<T extends object> {
|
|
|
120
119
|
* @returns {Partial<T>} An object containing the previous values of changed attributes
|
|
121
120
|
*/
|
|
122
121
|
get previous(): Partial<T>;
|
|
123
|
-
/**
|
|
124
|
-
* Determines if attributes have changed since the last set call.
|
|
125
|
-
*
|
|
126
|
-
* This method checks whether any attributes were modified in the most recent
|
|
127
|
-
* set operation. When called without arguments, it returns true if any attributes
|
|
128
|
-
* have changed. When called with a specific attribute key, it returns true only
|
|
129
|
-
* if that particular attribute was changed.
|
|
130
|
-
*
|
|
131
|
-
* @param {keyof T} [attr] - Optional attribute key to check for changes
|
|
132
|
-
* @returns {boolean} True if attributes have changed, false otherwise
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* // Check if any attributes changed
|
|
136
|
-
* const user = new User({ name: 'John', email: 'john@example.com' });
|
|
137
|
-
* user.set('name', 'Jane');
|
|
138
|
-
* user.hasChanged(); // Returns true
|
|
139
|
-
*
|
|
140
|
-
* @example
|
|
141
|
-
* // Check if a specific attribute changed
|
|
142
|
-
* user.set('name', 'Jane');
|
|
143
|
-
* user.hasChanged('name'); // Returns true
|
|
144
|
-
* user.hasChanged('email'); // Returns false
|
|
145
|
-
*/
|
|
146
|
-
hasChanged(attr?: keyof T): boolean;
|
|
147
122
|
/**
|
|
148
123
|
* Provides default attribute values for new model instances.
|
|
149
124
|
*
|
|
@@ -175,6 +150,30 @@ export declare abstract class Model<T extends object> {
|
|
|
175
150
|
* // Resulting attributes: { role: 'user', isActive: true, createdAt: Date, name: 'John' }
|
|
176
151
|
*/
|
|
177
152
|
protected defaults(): Partial<T>;
|
|
153
|
+
/**
|
|
154
|
+
* Determines if attributes have changed since the last set call.
|
|
155
|
+
*
|
|
156
|
+
* This method checks whether any attributes were modified in the most recent
|
|
157
|
+
* set operation. When called without arguments, it returns true if any attributes
|
|
158
|
+
* have changed. When called with a specific attribute key, it returns true only
|
|
159
|
+
* if that particular attribute was changed.
|
|
160
|
+
*
|
|
161
|
+
* @param {keyof T} [attr] - Optional attribute key to check for changes
|
|
162
|
+
* @returns {boolean} True if attributes have changed, false otherwise
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* // Check if any attributes changed
|
|
166
|
+
* const user = new User({ name: 'John', email: 'john@example.com' });
|
|
167
|
+
* user.set('name', 'Jane');
|
|
168
|
+
* user.hasChanged(); // Returns true
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* // Check if a specific attribute changed
|
|
172
|
+
* user.set('name', 'Jane');
|
|
173
|
+
* user.hasChanged('name'); // Returns true
|
|
174
|
+
* user.hasChanged('email'); // Returns false
|
|
175
|
+
*/
|
|
176
|
+
hasChanged(attr?: keyof T): boolean;
|
|
178
177
|
/**
|
|
179
178
|
* Retrieves the value of a specific attribute from the model.
|
|
180
179
|
*
|
|
@@ -412,17 +411,52 @@ export declare abstract class Model<T extends object> {
|
|
|
412
411
|
* }
|
|
413
412
|
*/
|
|
414
413
|
validate(attributes: Partial<T>, options?: ValidationOptions): string | undefined;
|
|
414
|
+
/**
|
|
415
|
+
* Creates a new instance of the model with identical attributes.
|
|
416
|
+
*
|
|
417
|
+
* This method returns a new model instance that is a clone of the current model,
|
|
418
|
+
* with all attributes copied to the new instance. The clone is a separate object
|
|
419
|
+
* with its own state, so modifications to the clone will not affect the original
|
|
420
|
+
* model and vice versa. By default, the ID is removed so the cloned instance is
|
|
421
|
+
* considered "new" (isNew() returns true).
|
|
422
|
+
*
|
|
423
|
+
* @param {CloneOptions} [options] - Configuration options for cloning
|
|
424
|
+
* @param {boolean} [options.keepId=false] - If true, preserves the ID in the clone
|
|
425
|
+
* @param {boolean} [options.deep=false] - If true, performs a deep clone of nested objects/arrays
|
|
426
|
+
* @returns {this} A new instance of the same model class with cloned attributes
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* // Clone a user model (default - no ID)
|
|
430
|
+
* const user = new User({ id: 1, name: 'John', email: 'john@example.com' });
|
|
431
|
+
* const userCopy = user.clone();
|
|
432
|
+
* console.log(userCopy.isNew()); // true
|
|
433
|
+
* console.log(userCopy.get('id')); // undefined
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* // Clone with ID preserved
|
|
437
|
+
* const userCopy = user.clone({ keepId: true });
|
|
438
|
+
* console.log(userCopy.isNew()); // false
|
|
439
|
+
* console.log(userCopy.get('id')); // 1
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* // Deep clone for nested objects
|
|
443
|
+
* const user = new User({ id: 1, name: 'John', settings: { theme: 'dark' } });
|
|
444
|
+
* const userCopy = user.clone({ deep: true });
|
|
445
|
+
* userCopy.get('settings').theme = 'light';
|
|
446
|
+
* console.log(user.get('settings').theme); // 'dark' (unchanged)
|
|
447
|
+
*/
|
|
448
|
+
clone(options?: CloneOptions): this;
|
|
415
449
|
/**
|
|
416
450
|
* Performs HTTP synchronization with the server for CRUD operations.
|
|
417
451
|
*
|
|
418
452
|
* This method handles all HTTP communication between the model and the server,
|
|
419
453
|
* automatically constructing the appropriate URL based on the model's ID and
|
|
420
|
-
* endpoint
|
|
454
|
+
* endpoint. It supports all standard REST operations and provides type-safe
|
|
421
455
|
* response handling.
|
|
422
456
|
*
|
|
423
457
|
* The URL construction follows REST conventions:
|
|
424
|
-
* - For new models (no ID): uses collection endpoint `${baseUrl}${endpoint
|
|
425
|
-
* - For existing models (with ID): uses resource endpoint `${baseUrl}${endpoint
|
|
458
|
+
* - For new models (no ID): uses collection endpoint `${baseUrl}${endpoint}`
|
|
459
|
+
* - For existing models (with ID): uses resource endpoint `${baseUrl}${endpoint}/${id}`
|
|
426
460
|
*
|
|
427
461
|
* @template R - The expected response type, defaults to T (the model's attribute type)
|
|
428
462
|
* @param {('GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE')} [method='GET'] - The HTTP method to use (defaults to 'GET')
|
|
@@ -518,7 +552,7 @@ export declare abstract class Model<T extends object> {
|
|
|
518
552
|
* performing any operation.
|
|
519
553
|
*
|
|
520
554
|
* The DELETE request is sent to the model's specific resource endpoint using the
|
|
521
|
-
* pattern `${baseUrl}${endpoint
|
|
555
|
+
* pattern `${baseUrl}${endpoint}/${id}`. After successful deletion, the model
|
|
522
556
|
* instance remains in memory but the corresponding server resource is removed.
|
|
523
557
|
*
|
|
524
558
|
* @returns {Promise<void>} A promise that resolves when the delete operation completes
|
package/dist/Model.svelte.js
CHANGED
|
@@ -30,9 +30,8 @@ import { escapeHTML } from './utils.js';
|
|
|
30
30
|
* }
|
|
31
31
|
*
|
|
32
32
|
* class User extends Model<UserAttributes> {
|
|
33
|
-
* endpoint
|
|
34
|
-
|
|
35
|
-
* }
|
|
33
|
+
* endpoint = '/users';
|
|
34
|
+
|
|
36
35
|
* defaults() {
|
|
37
36
|
* return { name: '', createdAt: new Date() };
|
|
38
37
|
* }
|
|
@@ -46,6 +45,19 @@ import { escapeHTML } from './utils.js';
|
|
|
46
45
|
* await user.destroy(); // Deletes user
|
|
47
46
|
*/
|
|
48
47
|
export class Model {
|
|
48
|
+
/**
|
|
49
|
+
* Internal reactive storage for all model attributes.
|
|
50
|
+
*
|
|
51
|
+
* This private field uses Svelte's $state rune to create a reactive object that
|
|
52
|
+
* holds all the model's attribute data. When attributes are modified, this reactivity
|
|
53
|
+
* ensures that any Svelte components using the model will automatically re-render
|
|
54
|
+
* to reflect the changes.
|
|
55
|
+
*
|
|
56
|
+
* The attributes are initialized as an empty object cast to type T, and are populated
|
|
57
|
+
* during construction by merging default values with provided data. All attribute
|
|
58
|
+
* access and modification should go through the public API methods (get, set, has, etc.)
|
|
59
|
+
* rather than directly accessing this field.
|
|
60
|
+
*/
|
|
49
61
|
#attributes = $state({});
|
|
50
62
|
/**
|
|
51
63
|
* Validation error property that gets set when validation fails.
|
|
@@ -56,12 +68,12 @@ export class Model {
|
|
|
56
68
|
* Internal hash containing all attributes that have changed since the last set call.
|
|
57
69
|
* This property tracks which attributes have been modified and their new values.
|
|
58
70
|
*/
|
|
59
|
-
#changed = {};
|
|
71
|
+
#changed = $state({});
|
|
60
72
|
/**
|
|
61
73
|
* Internal hash containing the previous values of attributes before they were changed.
|
|
62
74
|
* This property stores the original values of attributes from before the last set call.
|
|
63
75
|
*/
|
|
64
|
-
#previous = {};
|
|
76
|
+
#previous = $state({});
|
|
65
77
|
/**
|
|
66
78
|
* The name of the attribute that serves as the unique identifier for this model instance.
|
|
67
79
|
*
|
|
@@ -80,9 +92,7 @@ export class Model {
|
|
|
80
92
|
* // Custom ID attribute can be specified in constructor options
|
|
81
93
|
* class User extends Model<UserSchema> {
|
|
82
94
|
* idAttribute = '_id
|
|
83
|
-
* endpoint
|
|
84
|
-
* return '/users';
|
|
85
|
-
* }
|
|
95
|
+
* endpoint = '/users';
|
|
86
96
|
* }
|
|
87
97
|
* const user = new User({ _id: '507f1f77bcf86cd799439011', name: 'John' });
|
|
88
98
|
*/
|
|
@@ -120,35 +130,6 @@ export class Model {
|
|
|
120
130
|
get previous() {
|
|
121
131
|
return this.#previous;
|
|
122
132
|
}
|
|
123
|
-
/**
|
|
124
|
-
* Determines if attributes have changed since the last set call.
|
|
125
|
-
*
|
|
126
|
-
* This method checks whether any attributes were modified in the most recent
|
|
127
|
-
* set operation. When called without arguments, it returns true if any attributes
|
|
128
|
-
* have changed. When called with a specific attribute key, it returns true only
|
|
129
|
-
* if that particular attribute was changed.
|
|
130
|
-
*
|
|
131
|
-
* @param {keyof T} [attr] - Optional attribute key to check for changes
|
|
132
|
-
* @returns {boolean} True if attributes have changed, false otherwise
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* // Check if any attributes changed
|
|
136
|
-
* const user = new User({ name: 'John', email: 'john@example.com' });
|
|
137
|
-
* user.set('name', 'Jane');
|
|
138
|
-
* user.hasChanged(); // Returns true
|
|
139
|
-
*
|
|
140
|
-
* @example
|
|
141
|
-
* // Check if a specific attribute changed
|
|
142
|
-
* user.set('name', 'Jane');
|
|
143
|
-
* user.hasChanged('name'); // Returns true
|
|
144
|
-
* user.hasChanged('email'); // Returns false
|
|
145
|
-
*/
|
|
146
|
-
hasChanged(attr) {
|
|
147
|
-
if (attr !== undefined) {
|
|
148
|
-
return attr in this.#changed;
|
|
149
|
-
}
|
|
150
|
-
return Object.keys(this.#changed).length > 0;
|
|
151
|
-
}
|
|
152
133
|
/**
|
|
153
134
|
* Provides default attribute values for new model instances.
|
|
154
135
|
*
|
|
@@ -182,6 +163,35 @@ export class Model {
|
|
|
182
163
|
defaults() {
|
|
183
164
|
return {};
|
|
184
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Determines if attributes have changed since the last set call.
|
|
168
|
+
*
|
|
169
|
+
* This method checks whether any attributes were modified in the most recent
|
|
170
|
+
* set operation. When called without arguments, it returns true if any attributes
|
|
171
|
+
* have changed. When called with a specific attribute key, it returns true only
|
|
172
|
+
* if that particular attribute was changed.
|
|
173
|
+
*
|
|
174
|
+
* @param {keyof T} [attr] - Optional attribute key to check for changes
|
|
175
|
+
* @returns {boolean} True if attributes have changed, false otherwise
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* // Check if any attributes changed
|
|
179
|
+
* const user = new User({ name: 'John', email: 'john@example.com' });
|
|
180
|
+
* user.set('name', 'Jane');
|
|
181
|
+
* user.hasChanged(); // Returns true
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* // Check if a specific attribute changed
|
|
185
|
+
* user.set('name', 'Jane');
|
|
186
|
+
* user.hasChanged('name'); // Returns true
|
|
187
|
+
* user.hasChanged('email'); // Returns false
|
|
188
|
+
*/
|
|
189
|
+
hasChanged(attr) {
|
|
190
|
+
if (attr !== undefined) {
|
|
191
|
+
return attr in this.#changed;
|
|
192
|
+
}
|
|
193
|
+
return Object.keys(this.#changed).length > 0;
|
|
194
|
+
}
|
|
185
195
|
/**
|
|
186
196
|
* Retrieves the value of a specific attribute from the model.
|
|
187
197
|
*
|
|
@@ -422,17 +432,64 @@ export class Model {
|
|
|
422
432
|
// Default implementation - no validation
|
|
423
433
|
return undefined;
|
|
424
434
|
}
|
|
435
|
+
/**
|
|
436
|
+
* Creates a new instance of the model with identical attributes.
|
|
437
|
+
*
|
|
438
|
+
* This method returns a new model instance that is a clone of the current model,
|
|
439
|
+
* with all attributes copied to the new instance. The clone is a separate object
|
|
440
|
+
* with its own state, so modifications to the clone will not affect the original
|
|
441
|
+
* model and vice versa. By default, the ID is removed so the cloned instance is
|
|
442
|
+
* considered "new" (isNew() returns true).
|
|
443
|
+
*
|
|
444
|
+
* @param {CloneOptions} [options] - Configuration options for cloning
|
|
445
|
+
* @param {boolean} [options.keepId=false] - If true, preserves the ID in the clone
|
|
446
|
+
* @param {boolean} [options.deep=false] - If true, performs a deep clone of nested objects/arrays
|
|
447
|
+
* @returns {this} A new instance of the same model class with cloned attributes
|
|
448
|
+
*
|
|
449
|
+
* @example
|
|
450
|
+
* // Clone a user model (default - no ID)
|
|
451
|
+
* const user = new User({ id: 1, name: 'John', email: 'john@example.com' });
|
|
452
|
+
* const userCopy = user.clone();
|
|
453
|
+
* console.log(userCopy.isNew()); // true
|
|
454
|
+
* console.log(userCopy.get('id')); // undefined
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* // Clone with ID preserved
|
|
458
|
+
* const userCopy = user.clone({ keepId: true });
|
|
459
|
+
* console.log(userCopy.isNew()); // false
|
|
460
|
+
* console.log(userCopy.get('id')); // 1
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* // Deep clone for nested objects
|
|
464
|
+
* const user = new User({ id: 1, name: 'John', settings: { theme: 'dark' } });
|
|
465
|
+
* const userCopy = user.clone({ deep: true });
|
|
466
|
+
* userCopy.get('settings').theme = 'light';
|
|
467
|
+
* console.log(user.get('settings').theme); // 'dark' (unchanged)
|
|
468
|
+
*/
|
|
469
|
+
clone(options) {
|
|
470
|
+
const Constructor = this.constructor;
|
|
471
|
+
let attrs = this.toJSON();
|
|
472
|
+
// Remove ID unless keepId is true
|
|
473
|
+
if (!options?.keepId) {
|
|
474
|
+
delete attrs[this.idAttribute];
|
|
475
|
+
}
|
|
476
|
+
// Perform deep clone if requested
|
|
477
|
+
if (options?.deep) {
|
|
478
|
+
attrs = structuredClone(attrs);
|
|
479
|
+
}
|
|
480
|
+
return new Constructor(attrs);
|
|
481
|
+
}
|
|
425
482
|
/**
|
|
426
483
|
* Performs HTTP synchronization with the server for CRUD operations.
|
|
427
484
|
*
|
|
428
485
|
* This method handles all HTTP communication between the model and the server,
|
|
429
486
|
* automatically constructing the appropriate URL based on the model's ID and
|
|
430
|
-
* endpoint
|
|
487
|
+
* endpoint. It supports all standard REST operations and provides type-safe
|
|
431
488
|
* response handling.
|
|
432
489
|
*
|
|
433
490
|
* The URL construction follows REST conventions:
|
|
434
|
-
* - For new models (no ID): uses collection endpoint `${baseUrl}${endpoint
|
|
435
|
-
* - For existing models (with ID): uses resource endpoint `${baseUrl}${endpoint
|
|
491
|
+
* - For new models (no ID): uses collection endpoint `${baseUrl}${endpoint}`
|
|
492
|
+
* - For existing models (with ID): uses resource endpoint `${baseUrl}${endpoint}/${id}`
|
|
436
493
|
*
|
|
437
494
|
* @template R - The expected response type, defaults to T (the model's attribute type)
|
|
438
495
|
* @param {('GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE')} [method='GET'] - The HTTP method to use (defaults to 'GET')
|
|
@@ -455,7 +512,7 @@ export class Model {
|
|
|
455
512
|
*/
|
|
456
513
|
async sync(method = 'GET', body, options = {}) {
|
|
457
514
|
const id = this.#getId();
|
|
458
|
-
const endpoint = options?.endpoint?.length ? options.endpoint : this.endpoint
|
|
515
|
+
const endpoint = options?.endpoint?.length ? options.endpoint : this.endpoint;
|
|
459
516
|
const fullUrl = `${vellumConfig.origin}${endpoint}`;
|
|
460
517
|
const url = id ? `${fullUrl}/${id}` : fullUrl;
|
|
461
518
|
const fetchOpts = {
|
|
@@ -569,7 +626,7 @@ export class Model {
|
|
|
569
626
|
* performing any operation.
|
|
570
627
|
*
|
|
571
628
|
* The DELETE request is sent to the model's specific resource endpoint using the
|
|
572
|
-
* pattern `${baseUrl}${endpoint
|
|
629
|
+
* pattern `${baseUrl}${endpoint}/${id}`. After successful deletion, the model
|
|
573
630
|
* instance remains in memory but the corresponding server resource is removed.
|
|
574
631
|
*
|
|
575
632
|
* @returns {Promise<void>} A promise that resolves when the delete operation completes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { vellumConfig, configureVellum } from './config.svelte.js';
|
|
2
2
|
export { type ValidationDetails, ValidationError } from './errors/validation_error.js';
|
|
3
3
|
export { type SyncOptions, type ValidationOptions, Model } from './Model.svelte.js';
|
|
4
|
-
export { type FetchOptions, Collection } from './Collection.svelte.js';
|
|
4
|
+
export { type CollectionOptions, type FetchOptions, Collection } from './Collection.svelte.js';
|
|
5
5
|
export * as utils from './utils.js';
|