notu 0.2.1 → 0.2.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.
@@ -1,125 +0,0 @@
1
- 'use strict';
2
-
3
- import ModelWithState from './ModelWithState';
4
- import Space from './Space';
5
-
6
-
7
- const ATTR_TYPE = {
8
- TEXT: 'TEXT',
9
- NUMBER: 'NUMBER',
10
- BOOLEAN: 'BOOLEAN',
11
- DATE: 'DATE'
12
- };
13
-
14
- export type AttrType = keyof typeof ATTR_TYPE;
15
-
16
-
17
- export default class Attr extends ModelWithState<Attr> {
18
- id: number = 0;
19
-
20
-
21
- private _name: string = '';
22
- get name(): string { return this._name; }
23
- set name(value: string) {
24
- if (value !== this._name) {
25
- this._name = value;
26
- if (this.isClean)
27
- this.dirty();
28
- }
29
- }
30
-
31
- private _type: AttrType = 'TEXT';
32
- get type(): AttrType { return this._type; }
33
- set type(value: AttrType) {
34
- if (!this.isNew)
35
- throw Error('Cannot change an attribute\'s type once it has been created.');
36
- this._type = value;
37
- }
38
-
39
- get isText(): boolean { return this.type == 'TEXT'; }
40
-
41
- get isNumber(): boolean { return this.type == 'NUMBER'; }
42
-
43
- get isBoolean(): boolean { return this.type == 'BOOLEAN'; }
44
-
45
- get isDate(): boolean { return this.type == 'DATE'; }
46
-
47
- asText(): Attr {
48
- this.type = 'TEXT';
49
- return this;
50
- }
51
-
52
- asNumber(): Attr {
53
- this.type = 'NUMBER';
54
- return this;
55
- }
56
-
57
- asBoolean(): Attr {
58
- this.type = 'BOOLEAN';
59
- return this;
60
- }
61
-
62
- asDate(): Attr {
63
- this.type = 'DATE';
64
- return this;
65
- }
66
-
67
-
68
- private _spaceId: number = 0;
69
- get spaceId(): number { return this._spaceId; }
70
- set spaceId(value: number) {
71
- if (value !== this._spaceId) {
72
- this._spaceId = value;
73
- if (value !== this.space?.id ?? 0)
74
- this._space = null;
75
- if (this.isClean)
76
- this.dirty();
77
- }
78
- }
79
-
80
- private _space: Space = null;
81
- get space(): Space { return this._space; }
82
- set space(value: Space) {
83
- this._space = value;
84
- this.spaceId = value?.id ?? 0;
85
- }
86
-
87
-
88
- duplicate(): Attr {
89
- const output = new Attr();
90
- output.id = this.id;
91
- output.name = this.name;
92
- output.type = this.type;
93
- output.space = this.space;
94
- return output;
95
- }
96
-
97
-
98
- validate(throwError: boolean = false): boolean {
99
- let output = null;
100
-
101
- if (this.spaceId <= 0)
102
- output = 'Note spaceId must be greater than zero.';
103
- else if (!this.isNew && this.id <= 0)
104
- output = 'Attr id must be greater than zero if in non-new state.';
105
-
106
- if (throwError && output != null)
107
- throw Error(output);
108
-
109
- return output == null;
110
- }
111
-
112
-
113
- get defaultValue(): any {
114
- switch (this.type) {
115
- case 'TEXT':
116
- return '';
117
- case 'NUMBER':
118
- return 0;
119
- case 'BOOLEAN':
120
- return false;
121
- case 'DATE':
122
- return new Date();
123
- }
124
- }
125
- }
@@ -1,66 +0,0 @@
1
- import { expect, test } from 'vitest';
2
- import ModelWithState from './ModelWithState';
3
-
4
-
5
- class TestModel extends ModelWithState<TestModel> {
6
- }
7
-
8
-
9
- test('state gets defaulted to new', () => {
10
- const model = new ModelWithState<TestModel>();
11
- expect(model.state).toBe('NEW');
12
- });
13
-
14
- test('clean() changes model state', () => {
15
- const model = new ModelWithState<TestModel>().clean();
16
- expect(model.state).toBe('CLEAN');
17
- });
18
-
19
- test('dirty() changes model state', () => {
20
- const model = new ModelWithState<TestModel>().dirty();
21
- expect(model.state).toBe('DIRTY');
22
- });
23
-
24
- test('delete() changes model state', () => {
25
- const model = new ModelWithState<TestModel>().delete();
26
- expect(model.state).toBe('DELETED');
27
- });
28
-
29
- test('new() changes model state', () => {
30
- const model = new ModelWithState<TestModel>().dirty().new();
31
- expect(model.state).toBe('NEW');
32
- });
33
-
34
- test('isNew returns correct value', () => {
35
- const model = new ModelWithState<TestModel>().new();
36
- expect(model.isNew).toBe(true);
37
- model.dirty();
38
- expect(model.isNew).toBe(false);
39
- });
40
-
41
- test('isClean returns correct value', () => {
42
- const model = new ModelWithState<TestModel>().new();
43
- expect(model.isClean).toBe(false);
44
- model.clean();
45
- expect(model.isClean).toBe(true);
46
- });
47
-
48
- test('isDirty returns correct value', () => {
49
- const model = new ModelWithState<TestModel>().new();
50
- expect(model.isDirty).toBe(false);
51
- model.dirty();
52
- expect(model.isDirty).toBe(true);
53
- });
54
-
55
- test('isDeleted returns correct value', () => {
56
- const model = new ModelWithState<TestModel>().new();
57
- expect(model.isDeleted).toBe(false);
58
- model.delete();
59
- expect(model.isDeleted).toBe(true);
60
- });
61
-
62
-
63
- test('validate does nothing', () => {
64
- const model = new ModelWithState<TestModel>().new();
65
- expect(model.validate()).toBe(true);
66
- });
@@ -1,57 +0,0 @@
1
- 'use strict';
2
-
3
-
4
- const MODEL_STATE = {
5
- NEW: 'NEW',
6
- CLEAN: 'CLEAN',
7
- DIRTY: 'DIRTY',
8
- DELETED: 'DELETED'
9
- };
10
-
11
- export type ModelState = keyof typeof MODEL_STATE;
12
-
13
-
14
- export default class ModelWithState<T extends ModelWithState<T>> {
15
- state: ModelState = 'NEW';
16
-
17
- new(): T {
18
- this.state = 'NEW';
19
- return (this as any) as T;
20
- }
21
-
22
- clean(): T {
23
- this.state = 'CLEAN';
24
- return (this as any) as T;
25
- }
26
-
27
- dirty(): T {
28
- this.state = 'DIRTY';
29
- return (this as any) as T;
30
- }
31
-
32
- delete(): T {
33
- this.state = 'DELETED';
34
- return (this as any) as T;
35
- }
36
-
37
- get isNew(): boolean {
38
- return this.state == 'NEW';
39
- }
40
-
41
- get isClean(): boolean {
42
- return this.state == 'CLEAN';
43
- }
44
-
45
- get isDirty(): boolean {
46
- return this.state == 'DIRTY';
47
- }
48
-
49
- get isDeleted(): boolean {
50
- return this.state == 'DELETED';
51
- }
52
-
53
-
54
- validate(throwError: boolean = false): boolean {
55
- return true;
56
- }
57
- }
@@ -1,407 +0,0 @@
1
- import { expect, test } from 'vitest';
2
- import Note from './Note';
3
- import Tag from './Tag';
4
- import Space from './Space';
5
- import Attr from './Attr';
6
-
7
-
8
- function newCleanTag(): Tag {
9
- const tag = new Tag('hello');
10
- tag.id = 123;
11
- tag.clean();
12
- return tag;
13
- }
14
-
15
- function newCleanAttr(): Attr {
16
- const attr = new Attr();
17
- attr.id = 234;
18
- attr.clean();
19
- return attr;
20
- }
21
-
22
-
23
- test('gets initiated with sensible defaults', () => {
24
- const note = new Note();
25
- expect(note.id).toBe(0);
26
- expect(note.date.getTime() / 1000).toBeCloseTo(new Date().getTime() / 1000);
27
- expect(note.text).toBe('');
28
- expect(note.archived).toBe(false);
29
- expect(note.spaceId).toBe(0);
30
- });
31
-
32
- test('can duplicate itself', () => {
33
- const note = new Note().clean();
34
- const space = new Space('hello');
35
- space.id = 123;
36
- note.space = space;
37
- const copy = note.duplicate();
38
- expect(copy.id).toBe(note.id);
39
- expect(copy.date).toBe(note.date);
40
- expect(copy.text).toBe(note.text);
41
- expect(copy.archived).toBe(note.archived);
42
- expect(copy.space).toBe(note.space);
43
- expect(copy.spaceId).toBe(note.spaceId);
44
- expect(copy.state).toBe(note.state);
45
- });
46
-
47
- test('Gets initiated as new', () => {
48
- const note = new Note();
49
- expect(note.isNew).toBe(true);
50
- });
51
-
52
-
53
- test('Set date marks note as dirty if currently clean', () => {
54
- const note = new Note().clean();
55
- note.date = new Date();
56
- expect(note.isDirty).toBe(true);
57
- });
58
-
59
- test('Set date doesnt change note state if new', () => {
60
- const note = new Note().new();
61
- note.date = new Date();
62
- expect(note.isNew).toBe(true);
63
- });
64
-
65
- test('Set date doesnt change note state if value not different', () => {
66
- const note = new Note().clean();
67
- note.date = note.date;
68
- expect(note.isClean).toBe(true);
69
- });
70
-
71
-
72
- test('Set text marks note as dirty if currently clean', () => {
73
- const note = new Note().clean();
74
- note.text = 'asdf';
75
- expect(note.isDirty).toBe(true);
76
- });
77
-
78
- test('Set text doesnt change note state if new', () => {
79
- const note = new Note().new();
80
- note.text = 'asdf';
81
- expect(note.isNew).toBe(true);
82
- });
83
-
84
- test('Set text doesnt change note state if value not different', () => {
85
- const note = new Note().clean();
86
- note.text = '';
87
- expect(note.isClean).toBe(true);
88
- });
89
-
90
-
91
- test('Set archived marks note as dirty if currently clean', () => {
92
- const note = new Note().clean();
93
- note.archived = !note.archived;
94
- expect(note.isDirty).toBe(true);
95
- });
96
-
97
- test('Set archived doesnt change note state if new', () => {
98
- const note = new Note().new();
99
- note.archived = !note.archived;
100
- expect(note.isNew).toBe(true);
101
- });
102
-
103
- test('Set archived doesnt change note state if value not different', () => {
104
- const note = new Note().clean();
105
- note.archived = note.archived;
106
- expect(note.isClean).toBe(true);
107
- });
108
-
109
-
110
- test('Set spaceId marks note as dirty if currently clean', () => {
111
- const note = new Note().clean();
112
- note.spaceId = 123;
113
- expect(note.isDirty).toBe(true);
114
- });
115
-
116
- test('Set spaceId doesnt change note state if new', () => {
117
- const note = new Note().new();
118
- note.spaceId = 123;
119
- expect(note.isNew).toBe(true);
120
- });
121
-
122
- test('Set spaceId doesnt change note state if value not different', () => {
123
- const note = new Note().clean();
124
- note.spaceId = note.spaceId;
125
- expect(note.isClean).toBe(true);
126
- });
127
-
128
- test('setOwnTag doesnt mark note as dirty', () => {
129
- const note = new Note().clean().setOwnTag('hello');
130
- expect(note.isClean).toBe(true);
131
- });
132
-
133
- test('setOwnTag with string creates tag with same id as note', () => {
134
- const note = new Note();
135
- note.id = 123;
136
- note.setOwnTag('hello');
137
- expect(note.ownTag.id).toBe(note.id);
138
- });
139
-
140
- test('setOwnTag can take tag object, rather than just name', () => {
141
- const note = new Note().setOwnTag(new Tag('hello'));
142
- expect(note.ownTag.name).toBe('hello');
143
- });
144
-
145
- test('setOwnTag with tag object will throw error if tag already set', () => {
146
- const note = new Note().setOwnTag('hello');
147
- expect(() => note.setOwnTag(new Tag('goodbye'))).toThrowError();
148
- });
149
-
150
- test('setOwnTag with tag object will throw error if tag id is non-zero and doesnt match note id', () => {
151
- const note = new Note().clean();
152
- note.id = 123;
153
- const tag = new Tag('hello');
154
- tag.id = 57;
155
- expect(() => note.setOwnTag(tag)).toThrowError();
156
- });
157
-
158
- test('removeOwnTag marks existing tag as deleted if clean', () => {
159
- const note = new Note().setOwnTag('hello');
160
- note.ownTag.clean();
161
- note.removeOwnTag();
162
- expect(note.ownTag.isDeleted).toBe(true);
163
- });
164
-
165
- test('removeOwnTag nulls out new tag', () => {
166
- const note = new Note().setOwnTag('hello');
167
- note.removeOwnTag();
168
- expect(note.ownTag).toBeNull();
169
- });
170
-
171
- test('Setting space with id different than current spaceId updates state', () => {
172
- const note = new Note();
173
- note.spaceId = 57;
174
- note.clean();
175
- const space = new Space('hello');
176
- space.id = 60;
177
-
178
- note.space = space;
179
-
180
- expect(note.spaceId).toBe(60);
181
- expect(note.isDirty).toBe(true);
182
- });
183
-
184
- test('Setting space with id same as current spaceId preserves state', () => {
185
- const note = new Note();
186
- note.spaceId = 80;
187
- note.clean();
188
- const space = new Space('hello');
189
- space.id = 80;
190
-
191
- note.space = space;
192
-
193
- expect(note.spaceId).toBe(80);
194
- expect(note.isClean).toBe(true);
195
- });
196
-
197
- test('Setting spaceId to new value removes space object', () => {
198
- const note = new Note();
199
- const space = new Space('hello');
200
- space.id = 80;
201
- note.space = space;
202
-
203
- note.spaceId = 81;
204
-
205
- expect(note.space).toBeNull();
206
- });
207
-
208
- test('Setting spaceId to same as current space id preserves it', () => {
209
- const note = new Note();
210
- const space = new Space('hello');
211
- space.id = 80;
212
- note.space = space;
213
-
214
- note.spaceId = 80;
215
-
216
- expect(note.space.name).toBe('hello');
217
- });
218
-
219
-
220
- test('validate fails if spaceId is 0', () => {
221
- const model = new Note();
222
- model.spaceId = 0;
223
- expect(model.validate()).toBe(false);
224
- });
225
-
226
- test('validate fails if not new and id <= 0', () => {
227
- const model = new Note().clean();
228
- model.id = 0;
229
- model.spaceId = 123;
230
- expect(model.validate()).toBe(false);
231
- });
232
-
233
- test('validate throws error if arg set to true', () => {
234
- const model = new Note();
235
- model.spaceId = 0;
236
- expect(() => model.validate(true)).toThrowError();
237
- });
238
-
239
- test('validate calls validate on ownTag', () => {
240
- const note = new Note().setOwnTag('asdf');
241
- note.spaceId = 123;
242
- expect(note.validate()).toBe(true);
243
- note.ownTag.clean();
244
- expect(note.validate()).toBe(false);
245
- });
246
-
247
- test('validate calls validate on each added tag', () => {
248
- const note = new Note();
249
- note.spaceId = 123;
250
- const nt = note.addTag(newCleanTag());
251
- expect(note.validate()).toBe(true);
252
- nt.tagId = 0;
253
- expect(note.validate()).toBe(false);
254
- });
255
-
256
- test('validate calls validate on each added attr', () => {
257
- const note = new Note();
258
- note.spaceId = 123;
259
- const na = note.addAttr(newCleanAttr());
260
- expect(note.validate()).toBe(true);
261
- na.attrId = 0;
262
- expect(note.validate()).toBe(false);
263
- });
264
-
265
-
266
- test('addTag adds new NoteTag object', () => {
267
- const tag = newCleanTag();
268
- const note = new Note();
269
-
270
- note.addTag(tag);
271
-
272
- expect(note.tags.length).toBe(1);
273
- expect(note.tags[0].note).toBe(note);
274
- expect(note.tags[0].tag).toBe(tag);
275
- });
276
-
277
- test('addTag returns existing NoteTag object if trying to add duplicate tag', () => {
278
- const tag = newCleanTag();
279
- const note = new Note();
280
- note.addTag(tag);
281
-
282
- note.addTag(tag);
283
-
284
- expect(note.tags.length).toBe(1);
285
- expect(note.tags[0].note).toBe(note);
286
- expect(note.tags[0].tag).toBe(tag);
287
- });
288
-
289
- test('addTag undeletes existing NoteTag if trying to add duplicate tag', () => {
290
- const tag = newCleanTag();
291
- const note = new Note();
292
- const nt = note.addTag(tag);
293
- nt.delete();
294
-
295
- note.addTag(tag);
296
-
297
- expect(note.tags.length).toBe(1);
298
- expect(nt.isDirty).toBe(true);
299
- });
300
-
301
- test('addTag throws error if trying to add deleted tag', () => {
302
- const tag = newCleanTag().delete();
303
- const note = new Note();
304
- expect(() => note.addTag(tag)).toThrowError();
305
- });
306
-
307
- test('addTag prevents note from adding its own tag', () => {
308
- const note = new Note();
309
- note.id = 123;
310
- note.setOwnTag('test');
311
-
312
- expect(() => note.addTag(note.ownTag)).toThrowError();
313
- });
314
-
315
- test('addTag prevents note from adding tag that hasnt been saved yet', () => {
316
- const note = new Note();
317
- expect(() => note.addTag(new Tag())).toThrowError();
318
- });
319
-
320
- test('removeTag removes newly added tag from note', () => {
321
- const tag = newCleanTag();
322
- const note = new Note();
323
- note.addTag(tag);
324
-
325
- note.removeTag(tag);
326
-
327
- expect(note.tags.length).toBe(0);
328
- });
329
-
330
- test('removeTag marks existing tag on note as deleted', () => {
331
- const tag = newCleanTag();
332
- const note = new Note();
333
- note.addTag(tag).clean();
334
-
335
- note.removeTag(tag);
336
-
337
- expect(note.tags.length).toBe(1);
338
- expect(note.tags[0].isDeleted).toBe(true);
339
- });
340
-
341
-
342
- test('addAttr adds new NoteAttr object', () => {
343
- const attr = newCleanAttr();
344
- const note = new Note();
345
-
346
- note.addAttr(attr);
347
-
348
- expect(note.attrs.length).toBe(1);
349
- expect(note.attrs[0].note).toBe(note);
350
- expect(note.attrs[0].attr).toBe(attr);
351
- });
352
-
353
- test('addAttr returns existing NoteAttr object if trying to add duplicate attr', () => {
354
- const attr = newCleanAttr();
355
- const note = new Note();
356
- note.addAttr(attr);
357
-
358
- note.addAttr(attr);
359
-
360
- expect(note.attrs.length).toBe(1);
361
- expect(note.attrs[0].note).toBe(note);
362
- expect(note.attrs[0].attr).toBe(attr);
363
- });
364
-
365
- test('addAttr undeletes existing NoteAttr if trying to add duplicate tag', () => {
366
- const attr = newCleanAttr();
367
- const note = new Note();
368
- const na = note.addAttr(attr);
369
- na.delete();
370
-
371
- note.addAttr(attr);
372
-
373
- expect(note.attrs.length).toBe(1);
374
- expect(na.isDirty).toBe(true);
375
- });
376
-
377
- test('addAttr throws error if trying to add deleted attr', () => {
378
- const attr = newCleanAttr().delete();
379
- const note = new Note();
380
- expect(() => note.addAttr(attr)).toThrowError();
381
- });
382
-
383
- test('addAttr prevents note from adding attr that hasnt been saved yet', () => {
384
- const note = new Note();
385
- expect(() => note.addAttr(new Attr())).toThrowError();
386
- });
387
-
388
- test('removeAttr removes newly added attr from note', () => {
389
- const attr = newCleanAttr();
390
- const note = new Note();
391
- note.addAttr(attr);
392
-
393
- note.removeAttr(attr);
394
-
395
- expect(note.attrs.length).toBe(0);
396
- });
397
-
398
- test('removeAttr marks existing attr on note as deleted', () => {
399
- const attr = newCleanAttr();
400
- const note = new Note();
401
- note.addAttr(attr).clean();
402
-
403
- note.removeAttr(attr);
404
-
405
- expect(note.attrs.length).toBe(1);
406
- expect(note.attrs[0].isDeleted).toBe(true);
407
- });