notu 0.5.1 → 0.5.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/dist/notu.mjs +70 -27
- package/dist/notu.umd.js +1 -1
- package/dist/types/TestHelpers.d.ts +1 -1
- package/dist/types/models/Note.d.ts +2 -1
- package/dist/types/models/Tag.d.ts +10 -1
- package/package.json +1 -1
package/dist/notu.mjs
CHANGED
|
@@ -99,7 +99,7 @@ class Attr extends ModelWithState {
|
|
|
99
99
|
}
|
|
100
100
|
duplicate() {
|
|
101
101
|
const output = new Attr();
|
|
102
|
-
return output.id = this.id, output.name = this.name, output.type = this.type, output.space = this.space, output;
|
|
102
|
+
return output.id = this.id, output.name = this.name, output.type = this.type, this.space ? output.space = this.space : output.spaceId = this.spaceId, output.state = this.state, output;
|
|
103
103
|
}
|
|
104
104
|
validate(throwError = !1) {
|
|
105
105
|
let output = null;
|
|
@@ -481,7 +481,7 @@ class NoteAttr extends ModelWithState {
|
|
|
481
481
|
}
|
|
482
482
|
duplicate() {
|
|
483
483
|
const output = new NoteAttr();
|
|
484
|
-
return output.noteId = this.noteId, output.
|
|
484
|
+
return output.noteId = this.noteId, this.attr ? output.attr = this.attr : output.attrId = this.attrId, this.tag ? output.tag = this.tag : output.tagId = this.tagId, output.value = this.value, output.state = this.state, output;
|
|
485
485
|
}
|
|
486
486
|
validate(throwError = !1) {
|
|
487
487
|
let output = null;
|
|
@@ -539,7 +539,7 @@ class NoteTag extends ModelWithState {
|
|
|
539
539
|
this._tag = value, this.tagId = (value == null ? void 0 : value.id) ?? 0;
|
|
540
540
|
}
|
|
541
541
|
get attrs() {
|
|
542
|
-
return this.note.attrs.filter((x) => x.tagId == this.tagId);
|
|
542
|
+
return this.note ? this.note.attrs.filter((x) => x.tagId == this.tagId) : [];
|
|
543
543
|
}
|
|
544
544
|
addAttr(attr) {
|
|
545
545
|
if (!this.note)
|
|
@@ -549,7 +549,7 @@ class NoteTag extends ModelWithState {
|
|
|
549
549
|
}
|
|
550
550
|
duplicate() {
|
|
551
551
|
const output = new NoteTag();
|
|
552
|
-
return output.noteId = this.noteId, output.tagId = this.tagId, output;
|
|
552
|
+
return output.noteId = this.noteId, this.tag ? output.tag = this.tag : output.tagId = this.tagId, output;
|
|
553
553
|
}
|
|
554
554
|
validate(throwError = !1) {
|
|
555
555
|
let output = null;
|
|
@@ -570,14 +570,15 @@ class NoteTag extends ModelWithState {
|
|
|
570
570
|
}
|
|
571
571
|
}
|
|
572
572
|
class Tag extends ModelWithState {
|
|
573
|
-
constructor(name = ""
|
|
573
|
+
constructor(name = "") {
|
|
574
574
|
super();
|
|
575
575
|
__publicField(this, "_id", 0);
|
|
576
576
|
__publicField(this, "_spaceId", 0);
|
|
577
577
|
__publicField(this, "_space", null);
|
|
578
578
|
__publicField(this, "_name", "");
|
|
579
579
|
__publicField(this, "_color", null);
|
|
580
|
-
this
|
|
580
|
+
__publicField(this, "_isPublic", !0);
|
|
581
|
+
this._name = name;
|
|
581
582
|
}
|
|
582
583
|
get id() {
|
|
583
584
|
return this._id;
|
|
@@ -588,17 +589,18 @@ class Tag extends ModelWithState {
|
|
|
588
589
|
get spaceId() {
|
|
589
590
|
return this._spaceId;
|
|
590
591
|
}
|
|
592
|
+
set spaceId(value) {
|
|
593
|
+
var _a;
|
|
594
|
+
value !== this._spaceId && (this._spaceId = value, value !== ((_a = this.space) == null ? void 0 : _a.id) && (this._space = null), this.isClean && this.dirty());
|
|
595
|
+
}
|
|
591
596
|
get space() {
|
|
592
597
|
return this._space;
|
|
593
598
|
}
|
|
594
599
|
set space(value) {
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
if (value.id !== this.spaceId)
|
|
600
|
-
throw Error("Attempted to set space on Tag where spaceId doesnt match");
|
|
601
|
-
this._space = value;
|
|
600
|
+
this._space = value, this.spaceId = (value == null ? void 0 : value.id) ?? 0;
|
|
601
|
+
}
|
|
602
|
+
in(space) {
|
|
603
|
+
return typeof space == "number" ? this.spaceId = space : this.space = space, this;
|
|
602
604
|
}
|
|
603
605
|
get name() {
|
|
604
606
|
return this._name;
|
|
@@ -606,15 +608,30 @@ class Tag extends ModelWithState {
|
|
|
606
608
|
set name(value) {
|
|
607
609
|
value !== this._name && (this._name = value, this.isClean && this.dirty());
|
|
608
610
|
}
|
|
611
|
+
getQualifiedName(contextSpaceId) {
|
|
612
|
+
return contextSpaceId == this.spaceId ? this.name : `${this.space.name}.${this.name}`;
|
|
613
|
+
}
|
|
609
614
|
get color() {
|
|
610
615
|
return this._color;
|
|
611
616
|
}
|
|
612
617
|
set color(value) {
|
|
613
618
|
value !== this._color && (this._color = value, this.isClean && this.dirty());
|
|
614
619
|
}
|
|
620
|
+
get isPublic() {
|
|
621
|
+
return this._isPublic;
|
|
622
|
+
}
|
|
623
|
+
set isPublic(value) {
|
|
624
|
+
value !== this._isPublic && (this._isPublic = value, this.isClean && this.dirty());
|
|
625
|
+
}
|
|
626
|
+
asPublic() {
|
|
627
|
+
return this.isPublic = !0, this;
|
|
628
|
+
}
|
|
629
|
+
asPrivate() {
|
|
630
|
+
return this.isPublic = !1, this;
|
|
631
|
+
}
|
|
615
632
|
duplicate() {
|
|
616
|
-
const output = new Tag(this.name
|
|
617
|
-
return output.id = this.id, output.state = this.state, output.color = this.color, output.space = this.space, output;
|
|
633
|
+
const output = new Tag(this.name);
|
|
634
|
+
return output.id = this.id, output.state = this.state, output.color = this.color, output.space = this.space, output.isPublic = this.isPublic, output;
|
|
618
635
|
}
|
|
619
636
|
validate(throwError = !1) {
|
|
620
637
|
let output = null;
|
|
@@ -632,12 +649,13 @@ class Tag extends ModelWithState {
|
|
|
632
649
|
id: this.id,
|
|
633
650
|
name: this.name,
|
|
634
651
|
spaceId: this.spaceId,
|
|
635
|
-
color: this.color
|
|
652
|
+
color: this.color,
|
|
653
|
+
isPublic: this.isPublic
|
|
636
654
|
};
|
|
637
655
|
}
|
|
638
656
|
static fromJSON(json) {
|
|
639
|
-
const output = new Tag(json.name
|
|
640
|
-
return output.id = json.id, output.color = json.color, output.state = json.state, output;
|
|
657
|
+
const output = new Tag(json.name);
|
|
658
|
+
return output.id = json.id, output.spaceId = json.spaceId, output.color = json.color, output.state = json.state, output.isPublic = json.isPublic, output;
|
|
641
659
|
}
|
|
642
660
|
}
|
|
643
661
|
class Note extends ModelWithState {
|
|
@@ -679,7 +697,7 @@ class Note extends ModelWithState {
|
|
|
679
697
|
}
|
|
680
698
|
set spaceId(value) {
|
|
681
699
|
var _a;
|
|
682
|
-
value !== this._spaceId && (this._spaceId = value, value !== ((_a = this.space) == null ? void 0 : _a.id) && (this._space = null), this.isClean && this.dirty());
|
|
700
|
+
value !== this._spaceId && (this._spaceId = value, value !== ((_a = this.space) == null ? void 0 : _a.id) && (this._space = null), this.isClean && this.dirty(), this._setOwnTagSpace());
|
|
683
701
|
}
|
|
684
702
|
get space() {
|
|
685
703
|
return this._space;
|
|
@@ -695,7 +713,7 @@ class Note extends ModelWithState {
|
|
|
695
713
|
}
|
|
696
714
|
setOwnTag(tag) {
|
|
697
715
|
if (typeof tag == "string")
|
|
698
|
-
this.ownTag == null && (this._ownTag = new Tag()), this.ownTag.name = tag, this.ownTag.id = this.id;
|
|
716
|
+
this.ownTag == null && (this._ownTag = new Tag()), this.ownTag.name = tag, this.ownTag.id = this.id, this._setOwnTagSpace();
|
|
699
717
|
else {
|
|
700
718
|
if (this.ownTag)
|
|
701
719
|
throw new Error("Note has already had its tag set. If you would like to change the tag name, call setTag with just a string specifying the new tag name.");
|
|
@@ -708,6 +726,9 @@ class Note extends ModelWithState {
|
|
|
708
726
|
removeOwnTag() {
|
|
709
727
|
this.ownTag && (this.ownTag.isNew ? this._ownTag = null : this.ownTag.delete());
|
|
710
728
|
}
|
|
729
|
+
_setOwnTagSpace() {
|
|
730
|
+
this.ownTag && (this.space ? this.ownTag.space = this.space : this.ownTag.spaceId = this.spaceId);
|
|
731
|
+
}
|
|
711
732
|
get tags() {
|
|
712
733
|
return this._tags;
|
|
713
734
|
}
|
|
@@ -718,12 +739,19 @@ class Note extends ModelWithState {
|
|
|
718
739
|
throw Error("Cannot add a tag that hasn't yet been saved to a note");
|
|
719
740
|
if (tag.id == this.id)
|
|
720
741
|
throw Error("Note cannot add its own tag as a linked tag");
|
|
742
|
+
if (!tag.isPublic && tag.spaceId != this.spaceId)
|
|
743
|
+
throw Error("Cannot add a private tag from another space");
|
|
721
744
|
let nt = this.tags.find((x) => x.tagId == tag.id);
|
|
722
745
|
return nt ? (nt.isDeleted && nt.dirty(), nt) : (nt = new NoteTag(), nt.note = this, nt.tag = tag, this._tags.push(nt), nt);
|
|
723
746
|
}
|
|
724
747
|
removeTag(tag) {
|
|
725
748
|
const nt = this.tags.find((x) => x.tagId == tag.id);
|
|
726
|
-
|
|
749
|
+
if (!nt)
|
|
750
|
+
return this;
|
|
751
|
+
nt.isNew ? this._tags = this._tags.filter((x) => x !== nt) : nt.delete();
|
|
752
|
+
for (const na of this.attrs.filter((x) => !x.isDeleted && x.tagId == tag.id))
|
|
753
|
+
this.removeAttr(na.attr, na.tag);
|
|
754
|
+
return this;
|
|
727
755
|
}
|
|
728
756
|
get attrs() {
|
|
729
757
|
return this._attrs;
|
|
@@ -733,16 +761,22 @@ class Note extends ModelWithState {
|
|
|
733
761
|
throw Error("Cannot add an attribute marked as deleted to a note");
|
|
734
762
|
if (attr.isNew)
|
|
735
763
|
throw Error("Cannot add an attribute that hasn't yet been saved to a note");
|
|
736
|
-
|
|
737
|
-
return
|
|
764
|
+
const na = new NoteAttr(this, attr);
|
|
765
|
+
return this._attrs.push(na), na;
|
|
738
766
|
}
|
|
739
|
-
removeAttr(attr) {
|
|
740
|
-
const na = this.attrs.find((x) => x.attrId == attr.id);
|
|
767
|
+
removeAttr(attr, tag = null) {
|
|
768
|
+
const na = this.attrs.find((x) => x.attrId == attr.id && x.tagId == (tag == null ? void 0 : tag.id));
|
|
741
769
|
return na ? (na.isNew ? this._attrs = this._attrs.filter((x) => x !== na) : na.delete(), this) : this;
|
|
742
770
|
}
|
|
743
771
|
duplicate() {
|
|
744
772
|
const output = new Note();
|
|
745
|
-
return output.id = this.id, output.date = this.date, output.text = this.text, output.space = this.space
|
|
773
|
+
return output.id = this.id, output.date = this.date, output.text = this.text, this.space ? output.space = this.space : output.spaceId = this.spaceId, output._tags = this.tags.map((x) => {
|
|
774
|
+
const ntCopy = x.duplicate();
|
|
775
|
+
return ntCopy.note = output, ntCopy;
|
|
776
|
+
}), output._attrs = this.attrs.map((x) => {
|
|
777
|
+
const naCopy = x.duplicate();
|
|
778
|
+
return naCopy.note = output, naCopy;
|
|
779
|
+
}), this.ownTag && output.setOwnTag(this.ownTag.duplicate()), output.state = this.state, output;
|
|
746
780
|
}
|
|
747
781
|
toJSON() {
|
|
748
782
|
return {
|
|
@@ -762,7 +796,16 @@ class Note extends ModelWithState {
|
|
|
762
796
|
}
|
|
763
797
|
validate(throwError = !1) {
|
|
764
798
|
let output = null;
|
|
765
|
-
|
|
799
|
+
this.spaceId <= 0 ? output = "Note spaceId must be greater than zero." : !this.isNew && this.id <= 0 ? output = "Note id must be greater than zero if in non-new state." : this.ownTag && this.ownTag.spaceId != this.spaceId && (output = "Note cannot belong to a different space than its own tag");
|
|
800
|
+
const survivingAttrs = this.attrs.filter((x) => !x.isDeleted);
|
|
801
|
+
for (let i = 0; i < survivingAttrs.length; i++) {
|
|
802
|
+
const na = survivingAttrs[i];
|
|
803
|
+
for (let j = i + 1; j < survivingAttrs.length; j++) {
|
|
804
|
+
const na2 = survivingAttrs[j];
|
|
805
|
+
na.attrId == na2.attrId && na.tagId == na2.tagId && (output = `Attr '${na.attr.name}' is duplicated.`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
if (throwError && output != null)
|
|
766
809
|
throw Error(output);
|
|
767
810
|
if (this.ownTag && !this.ownTag.validate(throwError))
|
|
768
811
|
return !1;
|
package/dist/notu.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(global,factory){typeof exports=="object"&&typeof module<"u"?factory(exports):typeof define=="function"&&define.amd?define(["exports"],factory):(global=typeof globalThis<"u"?globalThis:global||self,factory(global.notu={}))})(this,function(exports2){"use strict";var __defProp=Object.defineProperty;var __defNormalProp=(obj,key,value)=>key in obj?__defProp(obj,key,{enumerable:!0,configurable:!0,writable:!0,value}):obj[key]=value;var __publicField=(obj,key,value)=>(__defNormalProp(obj,typeof key!="symbol"?key+"":key,value),value);class ModelWithState{constructor(){__publicField(this,"state","NEW")}new(){return this.state="NEW",this}clean(){return this.state="CLEAN",this}dirty(){return this.state="DIRTY",this}delete(){return this.state="DELETED",this}get isNew(){return this.state=="NEW"}get isClean(){return this.state=="CLEAN"}get isDirty(){return this.state=="DIRTY"}get isDeleted(){return this.state=="DELETED"}validate(throwError=!1){return!0}}class Attr extends ModelWithState{constructor(name){super();__publicField(this,"id",0);__publicField(this,"_name","");__publicField(this,"_type","TEXT");__publicField(this,"_spaceId",0);__publicField(this,"_space",null);name&&(this.name=name)}get name(){return this._name}set name(value){value!==this._name&&(this._name=value,this.isClean&&this.dirty())}get type(){return this._type}set type(value){if(!this.isNew)throw Error("Cannot change an attribute's type once it has been created.");this._type=value}get isText(){return this.type=="TEXT"}get isNumber(){return this.type=="NUMBER"}get isBoolean(){return this.type=="BOOLEAN"}get isDate(){return this.type=="DATE"}asText(){return this.type="TEXT",this}asNumber(){return this.type="NUMBER",this}asBoolean(){return this.type="BOOLEAN",this}asDate(){return this.type="DATE",this}get spaceId(){return this._spaceId}set spaceId(value){var _a;value!==this._spaceId&&(this._spaceId=value,value!==((_a=this.space)==null?void 0:_a.id)&&(this._space=null),this.isClean&&this.dirty())}get space(){return this._space}set space(value){this._space=value,this.spaceId=(value==null?void 0:value.id)??0}in(space){return typeof space=="number"?this.spaceId=space:this.space=space,this}duplicate(){const output=new Attr;return output.id=this.id,output.name=this.name,output.type=this.type,output.space=this.space,output}validate(throwError=!1){let output=null;if(this.spaceId<=0?output="Note spaceId must be greater than zero.":!this.isNew&&this.id<=0&&(output="Attr id must be greater than zero if in non-new state."),throwError&&output!=null)throw Error(output);return output==null}get defaultValue(){switch(this.type){case"TEXT":return"";case"NUMBER":return 0;case"BOOLEAN":return!1;case"DATE":return new Date}}toJSON(){return{state:this.state,id:this.id,name:this.name,type:this.type,spaceId:this.spaceId}}static fromJSON(json){const output=new Attr(json.name);return output.type=json.type,output.spaceId=json.spaceId,output.id=json.id,output.state=json.state,output}}class CachedClient{constructor(internalClient){__publicField(this,"_internalClient");__publicField(this,"_spaces",null);__publicField(this,"_attrs",null);__publicField(this,"_tags",null);this._internalClient=internalClient}_linkTagsToSpaces(){for(const tag of this._tags.values()){const space=this._spaces.get(tag.spaceId);space&&(tag.space=space)}}_linkAttrsToSpaces(){for(const attr of this._attrs.values()){const space=this._spaces.get(attr.spaceId);space&&(attr.space=space)}}async login(username,password){return await this._internalClient.login(username,password)}async getSpaces(){if(this._spaces==null){const spaces=await this._internalClient.getSpaces();this._spaces=new Map;for(const space of spaces)this._spaces.set(space.id,space);this._tags!=null&&this._linkTagsToSpaces(),this._attrs!=null&&this._linkAttrsToSpaces()}return[...this._spaces.values()]}async saveSpace(space){const saveResult=await this._internalClient.saveSpace(space);return this._spaces!=null&&this._spaces.set(saveResult.id,saveResult),saveResult}async getAttrs(spaceId){if(this._attrs==null){const attrs=await this._internalClient.getAttrs(spaceId);this._attrs=new Map;for(const attr of attrs)this._attrs.set(attr.id,attr);this._spaces!=null&&this._linkAttrsToSpaces()}return[...this._attrs.values()]}async saveAttr(attr){const saveResult=await this._internalClient.saveAttr(attr);return this._attrs!=null&&this._attrs.set(saveResult.id,saveResult),saveResult}async getTags(){if(this._tags==null){const tags=await this._internalClient.getTags();this._tags=new Map;for(const tag of tags)this._tags.set(tag.id,tag);this._spaces!=null&&this._linkTagsToSpaces()}return[...this._tags.values()]}async getNotes(query,spaceId){const results=await this._internalClient.getNotes(query,spaceId);if(this._spaces!=null)for(const note of results){const space=this._spaces.get(note.spaceId);space&&(note.space=space)}if(this._attrs!=null)for(const note of results)for(const na of note.attrs){const attr=this._attrs.get(na.attrId);attr&&(na.attr=attr)}if(this._tags!=null)for(const note of results){{const tag=this._tags.get(note.id);tag&¬e.setOwnTag(tag)}for(const nt of note.tags){const tag=this._tags.get(nt.tagId);tag&&(nt.tag=tag)}for(const na of note.attrs.filter(x=>x.tagId!=null)){const tag=this._tags.get(na.tagId);tag&&(na.tag=tag)}}return results}async getNoteCount(query,spaceId){return await this._internalClient.getNoteCount(query,spaceId)}async saveNotes(notes){const saveResults=await this._internalClient.saveNotes(notes);if(this._tags!=null)for(const note of saveResults.filter(x=>!!x.ownTag))this._tags.set(note.ownTag.id,note.ownTag);return saveResults}async customJob(name,data){return await this._internalClient.customJob(name,data)}async cacheAll(spaceId=0){await this.getSpaces();const tagsPromise=this.getTags(),attrsPromise=this.getAttrs(spaceId);await Promise.all([tagsPromise,attrsPromise])}get spaces(){return[...this._spaces.values()]}get tags(){return[...this._tags.values()]}get attrs(){return[...this._attrs.values()]}}class Space extends ModelWithState{constructor(name=""){super();__publicField(this,"id",0);__publicField(this,"_name","");this._name=name}get name(){return this._name}set name(value){value!==this._name&&(this._name=value,this.isClean&&this.dirty())}duplicate(){const output=new Space;return output.id=this.id,output.name=this.name,output.state=this.state,output}validate(throwError=!1){let output=null;if(!this.isNew&&this.id<=0&&(output="Space id must be greater than zero if in non-new state."),throwError&&output!=null)throw Error(output);return output==null}toJSON(){return{state:this.state,id:this.id,name:this.name}}static fromJSON(json){const output=new Space(json.name);return output.id=json.id,output.state=json.state,output}}class HttpClient{constructor(url,fetchMethod=null){__publicField(this,"_url",null);__publicField(this,"_token",null);__publicField(this,"_fetch");if(!url)throw Error("Endpoint URL must be passed in to NotuClient constructor");url.endsWith("/")&&(url=url.substring(0,url.length-1)),this._url=url,this._fetch=fetchMethod??window.fetch.bind(window)}get url(){return this._url}get token(){return this._token}set token(value){this._token=value}async login(username,password){const result=await this._fetch(this.url+"/login",{method:"POST",body:JSON.stringify({username,password})});return result.body!=null?(this._token=(await result.json()).token,{success:!0,error:null,token:this._token}):{success:!1,error:"Invalid username & password.",token:null}}async getSpaces(){return(await(await this._fetch(this.url+"/spaces",{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Space.fromJSON(x))}async saveSpace(space){const result=await this._fetch(this.url+"/spaces",{method:"POST",body:JSON.stringify(space),headers:{Authorization:"Bearer "+this.token}});return Space.fromJSON(await result.json())}async getAttrs(spaceId=0){return(await(await this._fetch(this.url+`/attrs?space=${spaceId}`,{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Attr.fromJSON(x))}async saveAttr(attr){const result=await this._fetch(this.url+"/attrs",{method:"POST",body:JSON.stringify(attr),headers:{Authorization:"Bearer "+this.token}});return Attr.fromJSON(await result.json())}async getTags(){return(await(await this._fetch(this.url+"/tags",{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Tag.fromJSON(x))}async getNotes(query,spaceId){return(await(await this._fetch(this.url+`/notes?space=${spaceId}&query=${encodeURIComponent(query)}`,{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Note.fromJSON(x))}async getNoteCount(query,spaceId){return(await(await this._fetch(this.url+`/notes?count=true&space=${spaceId}&query=${encodeURIComponent(query)}`,{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).count}async saveNotes(notes){return(await(await this._fetch(this.url+"/notes",{method:"POST",body:JSON.stringify(notes),headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Note.fromJSON(x))}async customJob(name,data){return await(await this._fetch(this.url+"customjob",{method:"POST",body:JSON.stringify({name,data}),headers:{Authorization:"Bearer "+this.token}})).json()}}class NoteAttr extends ModelWithState{constructor(note,attr,value){super();__publicField(this,"_noteId",0);__publicField(this,"_note",null);__publicField(this,"_attrId",0);__publicField(this,"_attr",null);__publicField(this,"_value",null);__publicField(this,"_tagId",null);__publicField(this,"_tag",null);note!=null&¬e!=null&&(typeof note=="number"?this.noteId=note:this.note=note),attr!=null&&attr!=null&&(typeof attr=="number"?this.attrId=attr:this.attr=attr),value!=null&&value!=null&&(this.value=value)}get noteId(){return this._noteId}set noteId(value){var _a;value!==this._noteId&&(this._noteId=value,value!==((_a=this.note)==null?void 0:_a.id)&&(this._note=null),this.isClean&&this.dirty())}get note(){return this._note}set note(value){this._note=value,this.noteId=(value==null?void 0:value.id)??0}get attrId(){return this._attrId}set attrId(value){var _a;value!==this._attrId&&(this._attrId=value,value!==((_a=this.attr)==null?void 0:_a.id)&&(this._attr=null),this.isClean&&this.dirty())}get attr(){return this._attr}set attr(newAttr){const oldAttr=this._attr;this._attr=newAttr,newAttr?(!oldAttr||newAttr.type!=oldAttr.type)&&(this.value=newAttr.defaultValue):this.value=null,this.attrId=(newAttr==null?void 0:newAttr.id)??0}get value(){return this._value}set value(newVal){newVal!=this._value&&(this._value=newVal,this.isClean&&this.dirty())}withValue(value){return this.value=value,this}get tagId(){return this._tagId}set tagId(value){var _a;value!==this._tagId&&(this._tagId=value,value!==((_a=this.tag)==null?void 0:_a.id)&&(this._tag=null),this.isClean&&this.dirty())}get tag(){return this._tag}set tag(value){this._tag=value,this.tagId=(value==null?void 0:value.id)??null}onTag(tag){return typeof tag=="number"?this.tagId=tag:this.tag=tag,this}duplicate(){const output=new NoteAttr;return output.noteId=this.noteId,output.note=this.note,output.attrId=this.attrId,output.attr=this.attr,output.tagId=this.tagId,output.tag=this.tag,output.value=this.value,output}validate(throwError=!1){let output=null;if(this.noteId<=0&&!this.isNew?output="NoteAttr noteId must be greater than zero":this.attrId<=0&&(output="NoteAttr attrId must be greater than zero"),throwError&&output!=null)throw Error(output);return output==null}toJSON(){return{state:this.state,noteId:this.noteId,attrId:this.attrId,tagId:this.tagId,value:this.value}}static fromJSON(json){const output=new NoteAttr(json.noteId,json.attrId,json.value);return output.tagId=json.tagId,output.state=json.state,output}}class NoteTag extends ModelWithState{constructor(note,tag){super();__publicField(this,"_noteId",0);__publicField(this,"_note",null);__publicField(this,"_tagId",0);__publicField(this,"_tag",null);note!=null&¬e!=null&&(typeof note=="number"?this.noteId=note:this.note=note),tag!=null&&tag!=null&&(typeof tag=="number"?this.tagId=tag:this.tag=tag)}get noteId(){return this._noteId}set noteId(value){var _a;value!==this._noteId&&(this._noteId=value,value!==((_a=this.note)==null?void 0:_a.id)&&(this._note=null),this.isClean&&this.dirty())}get note(){return this._note}set note(value){this._note=value,this.noteId=(value==null?void 0:value.id)??0}get tagId(){return this._tagId}set tagId(value){var _a;value!==this._tagId&&(this._tagId=value,value!==((_a=this.tag)==null?void 0:_a.id)&&(this._tag=null),this.isClean&&this.dirty())}get tag(){return this._tag}set tag(value){this._tag=value,this.tagId=(value==null?void 0:value.id)??0}get attrs(){return this.note.attrs.filter(x=>x.tagId==this.tagId)}addAttr(attr){if(!this.note)throw new Error("Cannot call addAttr on NoteTag where note property has not been set");const na=this.note.addAttr(attr);return na.tag=this.tag,na}duplicate(){const output=new NoteTag;return output.noteId=this.noteId,output.tagId=this.tagId,output}validate(throwError=!1){let output=null;if(this.noteId<=0&&!this.isNew?output="NoteTag noteId must be greater than zero":this.tagId<=0?output="NoteTag tagId must be greater than zero":this.noteId==this.tagId&&(output="NoteTag cannot link a note to its own tag"),throwError&&output!=null)throw Error(output);return output==null}toJSON(){return{state:this.state,noteId:this.noteId,tagId:this.tagId}}static fromJSON(json){const output=new NoteTag(json.noteId,json.tagId);return output.state=json.state,output}}class Tag extends ModelWithState{constructor(name="",spaceId=0){super();__publicField(this,"_id",0);__publicField(this,"_spaceId",0);__publicField(this,"_space",null);__publicField(this,"_name","");__publicField(this,"_color",null);this._name=name,this._spaceId=spaceId}get id(){return this._id}set id(value){value!==this._id&&(this._id=value,this.isClean&&this.dirty())}get spaceId(){return this._spaceId}get space(){return this._space}set space(value){if(value===null){this._space=null;return}if(value.id!==this.spaceId)throw Error("Attempted to set space on Tag where spaceId doesnt match");this._space=value}get name(){return this._name}set name(value){value!==this._name&&(this._name=value,this.isClean&&this.dirty())}get color(){return this._color}set color(value){value!==this._color&&(this._color=value,this.isClean&&this.dirty())}duplicate(){const output=new Tag(this.name,this.spaceId);return output.id=this.id,output.state=this.state,output.color=this.color,output.space=this.space,output}validate(throwError=!1){let output=null;if(!this.isNew&&this.id<=0?output="Tag id must be greater than zero if in non-new state.":!this.name||!/^[a-zA-Z][a-zA-Z0-9 ]*[a-zA-Z0-9]?$/.test(this.name)?output="Tag name is invalid, must only contain letters, numbers, and spaces, starting with a letter":this.color&&!/^#?[A-z0-9]{6}$/.test(this.color)&&(output="Tag color is invalid, must be a 6 character hexadecimal."),throwError&&output!=null)throw Error(output);return output==null}getColorInt(){let hex=this.color;return hex?(hex.startsWith("#")&&(hex=hex.substring(1)),parseInt(hex,16)):null}toJSON(){return{state:this.state,id:this.id,name:this.name,spaceId:this.spaceId,color:this.color}}static fromJSON(json){const output=new Tag(json.name,json.spaceId);return output.id=json.id,output.color=json.color,output.state=json.state,output}}class Note extends ModelWithState{constructor(text){super();__publicField(this,"_id",0);__publicField(this,"_date",new Date);__publicField(this,"_text","");__publicField(this,"_spaceId",0);__publicField(this,"_space",null);__publicField(this,"_ownTag",null);__publicField(this,"_tags",[]);__publicField(this,"_attrs",[]);text&&(this.text=text)}get id(){return this._id}set id(value){this._id=value,this.ownTag&&(this.ownTag.id=value)}get date(){return this._date}set date(value){value!==this._date&&(this._date=value,this.isClean&&this.dirty())}at(value){return this.date=value,this}get text(){return this._text}set text(value){value!==this._text&&(this._text=value,this.isClean&&this.dirty())}get spaceId(){return this._spaceId}set spaceId(value){var _a;value!==this._spaceId&&(this._spaceId=value,value!==((_a=this.space)==null?void 0:_a.id)&&(this._space=null),this.isClean&&this.dirty())}get space(){return this._space}set space(value){this._space=value,this.spaceId=(value==null?void 0:value.id)??0}in(space){return typeof space=="number"?this.spaceId=space:this.space=space,this}get ownTag(){return this._ownTag}setOwnTag(tag){if(typeof tag=="string")this.ownTag==null&&(this._ownTag=new Tag),this.ownTag.name=tag,this.ownTag.id=this.id;else{if(this.ownTag)throw new Error("Note has already had its tag set. If you would like to change the tag name, call setTag with just a string specifying the new tag name.");if(tag.id!=0&&tag.id!=this.id)throw new Error("Attempted to set tag to note with non-matching ID. Added tag id must either match the note id, which indicates that the tag has already been added to the note. Otherwise the tag id must be zero, indicating that the tag still needs to be added.");this._ownTag=tag}return this}removeOwnTag(){this.ownTag&&(this.ownTag.isNew?this._ownTag=null:this.ownTag.delete())}get tags(){return this._tags}addTag(tag){if(tag.isDeleted)throw Error("Cannot add a tag marked as deleted to a note");if(tag.isNew)throw Error("Cannot add a tag that hasn't yet been saved to a note");if(tag.id==this.id)throw Error("Note cannot add its own tag as a linked tag");let nt=this.tags.find(x=>x.tagId==tag.id);return nt?(nt.isDeleted&&nt.dirty(),nt):(nt=new NoteTag,nt.note=this,nt.tag=tag,this._tags.push(nt),nt)}removeTag(tag){const nt=this.tags.find(x=>x.tagId==tag.id);return nt?(nt.isNew?this._tags=this._tags.filter(x=>x!==nt):nt.delete(),this):this}get attrs(){return this._attrs}addAttr(attr){if(attr.isDeleted)throw Error("Cannot add an attribute marked as deleted to a note");if(attr.isNew)throw Error("Cannot add an attribute that hasn't yet been saved to a note");let na=this.attrs.find(x=>x.attrId==attr.id);return na?(na.isDeleted&&na.dirty(),na):(na=new NoteAttr,na.note=this,na.attr=attr,this._attrs.push(na),na)}removeAttr(attr){const na=this.attrs.find(x=>x.attrId==attr.id);return na?(na.isNew?this._attrs=this._attrs.filter(x=>x!==na):na.delete(),this):this}duplicate(){const output=new Note;return output.id=this.id,output.date=this.date,output.text=this.text,output.space=this.space,output.state=this.state,output}toJSON(){return{state:this.state,id:this.id,date:this.date,text:this.text,spaceId:this.spaceId,ownTag:this.ownTag,tags:this.tags,attrs:this.attrs}}static fromJSON(json){const output=new Note(json.text);return output.id=json.id,output.date=new Date(json.date),output.spaceId=json.spaceId,json.ownTag&&output.setOwnTag(Tag.fromJSON(json.ownTag)),json.tags&&(output._tags=json.tags.map(x=>NoteTag.fromJSON(x))),json.attrs&&(output._attrs=json.attrs.map(x=>NoteAttr.fromJSON(x))),output.state=json.state,output}validate(throwError=!1){let output=null;if(this.spaceId<=0?output="Note spaceId must be greater than zero.":!this.isNew&&this.id<=0&&(output="Note id must be greater than zero if in non-new state."),throwError&&output!=null)throw Error(output);if(this.ownTag&&!this.ownTag.validate(throwError))return!1;for(const nt of this.tags)if(!nt.validate(throwError))return!1;for(const na of this.attrs)if(!na.validate(throwError))return!1;return output==null}}class ParsedQuery{constructor(){__publicField(this,"where",null);__publicField(this,"order",null);__publicField(this,"tags",[]);__publicField(this,"attrs",[])}}class ParsedTag{constructor(){__publicField(this,"space",null);__publicField(this,"name",null);__publicField(this,"searchDepth",0);__publicField(this,"strictSearchDepth",!0);__publicField(this,"includeOwner",!1)}}class ParsedAttr{constructor(){__publicField(this,"name",null);__publicField(this,"exists",!1);__publicField(this,"tagNameFilters",null)}}function parseQuery(query){const output=splitQuery(query);return output.where=identifyTags(output.where,output),output.order=identifyTags(output.order,output),output.where=identifyAttrs(output.where,output),output.order=identifyAttrs(output.order,output),output}function splitQuery(query){query=" "+query+" ";const output=new ParsedQuery,orderByIndex=query.toUpperCase().indexOf(" ORDER BY ");return orderByIndex<0?output.where=query.trim():(output.where=query.substring(0,orderByIndex).trim(),output.order=query.substring(orderByIndex+10).trim()),output.where==""&&(output.where=null),output}function identifyTags(query,parsedQuery){const regexes=[/(#+\??~?|~)([\w\d]+\.)?([\w\d]+)/,/(#+\??~?|~)\[([\w\d\s]+\.)?([\w\d\s]+)\]/];for(const regex of regexes)for(;;){const match=regex.exec(query);if(!match)break;const hashPrefix=match[1],parsedTag=new ParsedTag;parsedTag.space=match[2]?match[2].substring(0,match[2].length-1):null,parsedTag.name=match[3],parsedTag.includeOwner=hashPrefix.includes("~"),parsedTag.searchDepth=(hashPrefix.match(/#/g)||[]).length,parsedTag.strictSearchDepth=!hashPrefix.includes("?");const fullMatch=match[0],matchStart=query.indexOf(fullMatch),matchEnd=matchStart+fullMatch.length;query=query.substring(0,matchStart)+`{tag${parsedQuery.tags.length}}`+query.substring(matchEnd),parsedQuery.tags.push(parsedTag)}return query}function identifyAttrs(query,parsedQuery){const regexes=[/@([\w\d]+)/,/@\[([\w\d\s]+)\]/];for(const regex of regexes)for(;;){const match=regex.exec(query);if(!match)break;const parsedAttr=new ParsedAttr;parsedAttr.name=match[1];const matchStart=query.indexOf(match[0]);let matchEnd=matchStart+match[0].length;if(query.substring(matchEnd,matchEnd+9)==".Exists()"&&(parsedAttr.exists=!0,matchEnd+=9),query.substring(matchEnd,matchEnd+4)==".On("){let tagFilterStart=matchEnd+4;if(matchEnd=query.indexOf(")",tagFilterStart),matchEnd<0)throw Error("Unclosed bracket detected");let tagNameFilters=query.substring(tagFilterStart,matchEnd).split("|");const dummyParsedQuery=new ParsedQuery;for(let tagNameFilter of tagNameFilters)tagNameFilter.startsWith("~")||(tagNameFilter="~"+tagNameFilter),identifyTags(tagNameFilter,dummyParsedQuery);parsedAttr.tagNameFilters=dummyParsedQuery.tags,matchEnd++}query=query.substring(0,matchStart)+`{attr${parsedQuery.attrs.length}}`+query.substring(matchEnd),parsedQuery.attrs.push(parsedAttr)}return query}exports2.Attr=Attr,exports2.CachedClient=CachedClient,exports2.HttpClient=HttpClient,exports2.Note=Note,exports2.NoteAttr=NoteAttr,exports2.NoteTag=NoteTag,exports2.ParsedAttr=ParsedAttr,exports2.ParsedQuery=ParsedQuery,exports2.ParsedTag=ParsedTag,exports2.Space=Space,exports2.Tag=Tag,exports2.parseQuery=parseQuery,Object.defineProperty(exports2,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(global,factory){typeof exports=="object"&&typeof module<"u"?factory(exports):typeof define=="function"&&define.amd?define(["exports"],factory):(global=typeof globalThis<"u"?globalThis:global||self,factory(global.notu={}))})(this,function(exports2){"use strict";var __defProp=Object.defineProperty;var __defNormalProp=(obj,key,value)=>key in obj?__defProp(obj,key,{enumerable:!0,configurable:!0,writable:!0,value}):obj[key]=value;var __publicField=(obj,key,value)=>(__defNormalProp(obj,typeof key!="symbol"?key+"":key,value),value);class ModelWithState{constructor(){__publicField(this,"state","NEW")}new(){return this.state="NEW",this}clean(){return this.state="CLEAN",this}dirty(){return this.state="DIRTY",this}delete(){return this.state="DELETED",this}get isNew(){return this.state=="NEW"}get isClean(){return this.state=="CLEAN"}get isDirty(){return this.state=="DIRTY"}get isDeleted(){return this.state=="DELETED"}validate(throwError=!1){return!0}}class Attr extends ModelWithState{constructor(name){super();__publicField(this,"id",0);__publicField(this,"_name","");__publicField(this,"_type","TEXT");__publicField(this,"_spaceId",0);__publicField(this,"_space",null);name&&(this.name=name)}get name(){return this._name}set name(value){value!==this._name&&(this._name=value,this.isClean&&this.dirty())}get type(){return this._type}set type(value){if(!this.isNew)throw Error("Cannot change an attribute's type once it has been created.");this._type=value}get isText(){return this.type=="TEXT"}get isNumber(){return this.type=="NUMBER"}get isBoolean(){return this.type=="BOOLEAN"}get isDate(){return this.type=="DATE"}asText(){return this.type="TEXT",this}asNumber(){return this.type="NUMBER",this}asBoolean(){return this.type="BOOLEAN",this}asDate(){return this.type="DATE",this}get spaceId(){return this._spaceId}set spaceId(value){var _a;value!==this._spaceId&&(this._spaceId=value,value!==((_a=this.space)==null?void 0:_a.id)&&(this._space=null),this.isClean&&this.dirty())}get space(){return this._space}set space(value){this._space=value,this.spaceId=(value==null?void 0:value.id)??0}in(space){return typeof space=="number"?this.spaceId=space:this.space=space,this}duplicate(){const output=new Attr;return output.id=this.id,output.name=this.name,output.type=this.type,this.space?output.space=this.space:output.spaceId=this.spaceId,output.state=this.state,output}validate(throwError=!1){let output=null;if(this.spaceId<=0?output="Note spaceId must be greater than zero.":!this.isNew&&this.id<=0&&(output="Attr id must be greater than zero if in non-new state."),throwError&&output!=null)throw Error(output);return output==null}get defaultValue(){switch(this.type){case"TEXT":return"";case"NUMBER":return 0;case"BOOLEAN":return!1;case"DATE":return new Date}}toJSON(){return{state:this.state,id:this.id,name:this.name,type:this.type,spaceId:this.spaceId}}static fromJSON(json){const output=new Attr(json.name);return output.type=json.type,output.spaceId=json.spaceId,output.id=json.id,output.state=json.state,output}}class CachedClient{constructor(internalClient){__publicField(this,"_internalClient");__publicField(this,"_spaces",null);__publicField(this,"_attrs",null);__publicField(this,"_tags",null);this._internalClient=internalClient}_linkTagsToSpaces(){for(const tag of this._tags.values()){const space=this._spaces.get(tag.spaceId);space&&(tag.space=space)}}_linkAttrsToSpaces(){for(const attr of this._attrs.values()){const space=this._spaces.get(attr.spaceId);space&&(attr.space=space)}}async login(username,password){return await this._internalClient.login(username,password)}async getSpaces(){if(this._spaces==null){const spaces=await this._internalClient.getSpaces();this._spaces=new Map;for(const space of spaces)this._spaces.set(space.id,space);this._tags!=null&&this._linkTagsToSpaces(),this._attrs!=null&&this._linkAttrsToSpaces()}return[...this._spaces.values()]}async saveSpace(space){const saveResult=await this._internalClient.saveSpace(space);return this._spaces!=null&&this._spaces.set(saveResult.id,saveResult),saveResult}async getAttrs(spaceId){if(this._attrs==null){const attrs=await this._internalClient.getAttrs(spaceId);this._attrs=new Map;for(const attr of attrs)this._attrs.set(attr.id,attr);this._spaces!=null&&this._linkAttrsToSpaces()}return[...this._attrs.values()]}async saveAttr(attr){const saveResult=await this._internalClient.saveAttr(attr);return this._attrs!=null&&this._attrs.set(saveResult.id,saveResult),saveResult}async getTags(){if(this._tags==null){const tags=await this._internalClient.getTags();this._tags=new Map;for(const tag of tags)this._tags.set(tag.id,tag);this._spaces!=null&&this._linkTagsToSpaces()}return[...this._tags.values()]}async getNotes(query,spaceId){const results=await this._internalClient.getNotes(query,spaceId);if(this._spaces!=null)for(const note of results){const space=this._spaces.get(note.spaceId);space&&(note.space=space)}if(this._attrs!=null)for(const note of results)for(const na of note.attrs){const attr=this._attrs.get(na.attrId);attr&&(na.attr=attr)}if(this._tags!=null)for(const note of results){{const tag=this._tags.get(note.id);tag&¬e.setOwnTag(tag)}for(const nt of note.tags){const tag=this._tags.get(nt.tagId);tag&&(nt.tag=tag)}for(const na of note.attrs.filter(x=>x.tagId!=null)){const tag=this._tags.get(na.tagId);tag&&(na.tag=tag)}}return results}async getNoteCount(query,spaceId){return await this._internalClient.getNoteCount(query,spaceId)}async saveNotes(notes){const saveResults=await this._internalClient.saveNotes(notes);if(this._tags!=null)for(const note of saveResults.filter(x=>!!x.ownTag))this._tags.set(note.ownTag.id,note.ownTag);return saveResults}async customJob(name,data){return await this._internalClient.customJob(name,data)}async cacheAll(spaceId=0){await this.getSpaces();const tagsPromise=this.getTags(),attrsPromise=this.getAttrs(spaceId);await Promise.all([tagsPromise,attrsPromise])}get spaces(){return[...this._spaces.values()]}get tags(){return[...this._tags.values()]}get attrs(){return[...this._attrs.values()]}}class Space extends ModelWithState{constructor(name=""){super();__publicField(this,"id",0);__publicField(this,"_name","");this._name=name}get name(){return this._name}set name(value){value!==this._name&&(this._name=value,this.isClean&&this.dirty())}duplicate(){const output=new Space;return output.id=this.id,output.name=this.name,output.state=this.state,output}validate(throwError=!1){let output=null;if(!this.isNew&&this.id<=0&&(output="Space id must be greater than zero if in non-new state."),throwError&&output!=null)throw Error(output);return output==null}toJSON(){return{state:this.state,id:this.id,name:this.name}}static fromJSON(json){const output=new Space(json.name);return output.id=json.id,output.state=json.state,output}}class HttpClient{constructor(url,fetchMethod=null){__publicField(this,"_url",null);__publicField(this,"_token",null);__publicField(this,"_fetch");if(!url)throw Error("Endpoint URL must be passed in to NotuClient constructor");url.endsWith("/")&&(url=url.substring(0,url.length-1)),this._url=url,this._fetch=fetchMethod??window.fetch.bind(window)}get url(){return this._url}get token(){return this._token}set token(value){this._token=value}async login(username,password){const result=await this._fetch(this.url+"/login",{method:"POST",body:JSON.stringify({username,password})});return result.body!=null?(this._token=(await result.json()).token,{success:!0,error:null,token:this._token}):{success:!1,error:"Invalid username & password.",token:null}}async getSpaces(){return(await(await this._fetch(this.url+"/spaces",{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Space.fromJSON(x))}async saveSpace(space){const result=await this._fetch(this.url+"/spaces",{method:"POST",body:JSON.stringify(space),headers:{Authorization:"Bearer "+this.token}});return Space.fromJSON(await result.json())}async getAttrs(spaceId=0){return(await(await this._fetch(this.url+`/attrs?space=${spaceId}`,{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Attr.fromJSON(x))}async saveAttr(attr){const result=await this._fetch(this.url+"/attrs",{method:"POST",body:JSON.stringify(attr),headers:{Authorization:"Bearer "+this.token}});return Attr.fromJSON(await result.json())}async getTags(){return(await(await this._fetch(this.url+"/tags",{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Tag.fromJSON(x))}async getNotes(query,spaceId){return(await(await this._fetch(this.url+`/notes?space=${spaceId}&query=${encodeURIComponent(query)}`,{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Note.fromJSON(x))}async getNoteCount(query,spaceId){return(await(await this._fetch(this.url+`/notes?count=true&space=${spaceId}&query=${encodeURIComponent(query)}`,{method:"GET",headers:{Authorization:"Bearer "+this.token}})).json()).count}async saveNotes(notes){return(await(await this._fetch(this.url+"/notes",{method:"POST",body:JSON.stringify(notes),headers:{Authorization:"Bearer "+this.token}})).json()).map(x=>Note.fromJSON(x))}async customJob(name,data){return await(await this._fetch(this.url+"customjob",{method:"POST",body:JSON.stringify({name,data}),headers:{Authorization:"Bearer "+this.token}})).json()}}class NoteAttr extends ModelWithState{constructor(note,attr,value){super();__publicField(this,"_noteId",0);__publicField(this,"_note",null);__publicField(this,"_attrId",0);__publicField(this,"_attr",null);__publicField(this,"_value",null);__publicField(this,"_tagId",null);__publicField(this,"_tag",null);note!=null&¬e!=null&&(typeof note=="number"?this.noteId=note:this.note=note),attr!=null&&attr!=null&&(typeof attr=="number"?this.attrId=attr:this.attr=attr),value!=null&&value!=null&&(this.value=value)}get noteId(){return this._noteId}set noteId(value){var _a;value!==this._noteId&&(this._noteId=value,value!==((_a=this.note)==null?void 0:_a.id)&&(this._note=null),this.isClean&&this.dirty())}get note(){return this._note}set note(value){this._note=value,this.noteId=(value==null?void 0:value.id)??0}get attrId(){return this._attrId}set attrId(value){var _a;value!==this._attrId&&(this._attrId=value,value!==((_a=this.attr)==null?void 0:_a.id)&&(this._attr=null),this.isClean&&this.dirty())}get attr(){return this._attr}set attr(newAttr){const oldAttr=this._attr;this._attr=newAttr,newAttr?(!oldAttr||newAttr.type!=oldAttr.type)&&(this.value=newAttr.defaultValue):this.value=null,this.attrId=(newAttr==null?void 0:newAttr.id)??0}get value(){return this._value}set value(newVal){newVal!=this._value&&(this._value=newVal,this.isClean&&this.dirty())}withValue(value){return this.value=value,this}get tagId(){return this._tagId}set tagId(value){var _a;value!==this._tagId&&(this._tagId=value,value!==((_a=this.tag)==null?void 0:_a.id)&&(this._tag=null),this.isClean&&this.dirty())}get tag(){return this._tag}set tag(value){this._tag=value,this.tagId=(value==null?void 0:value.id)??null}onTag(tag){return typeof tag=="number"?this.tagId=tag:this.tag=tag,this}duplicate(){const output=new NoteAttr;return output.noteId=this.noteId,this.attr?output.attr=this.attr:output.attrId=this.attrId,this.tag?output.tag=this.tag:output.tagId=this.tagId,output.value=this.value,output.state=this.state,output}validate(throwError=!1){let output=null;if(this.noteId<=0&&!this.isNew?output="NoteAttr noteId must be greater than zero":this.attrId<=0&&(output="NoteAttr attrId must be greater than zero"),throwError&&output!=null)throw Error(output);return output==null}toJSON(){return{state:this.state,noteId:this.noteId,attrId:this.attrId,tagId:this.tagId,value:this.value}}static fromJSON(json){const output=new NoteAttr(json.noteId,json.attrId,json.value);return output.tagId=json.tagId,output.state=json.state,output}}class NoteTag extends ModelWithState{constructor(note,tag){super();__publicField(this,"_noteId",0);__publicField(this,"_note",null);__publicField(this,"_tagId",0);__publicField(this,"_tag",null);note!=null&¬e!=null&&(typeof note=="number"?this.noteId=note:this.note=note),tag!=null&&tag!=null&&(typeof tag=="number"?this.tagId=tag:this.tag=tag)}get noteId(){return this._noteId}set noteId(value){var _a;value!==this._noteId&&(this._noteId=value,value!==((_a=this.note)==null?void 0:_a.id)&&(this._note=null),this.isClean&&this.dirty())}get note(){return this._note}set note(value){this._note=value,this.noteId=(value==null?void 0:value.id)??0}get tagId(){return this._tagId}set tagId(value){var _a;value!==this._tagId&&(this._tagId=value,value!==((_a=this.tag)==null?void 0:_a.id)&&(this._tag=null),this.isClean&&this.dirty())}get tag(){return this._tag}set tag(value){this._tag=value,this.tagId=(value==null?void 0:value.id)??0}get attrs(){return this.note?this.note.attrs.filter(x=>x.tagId==this.tagId):[]}addAttr(attr){if(!this.note)throw new Error("Cannot call addAttr on NoteTag where note property has not been set");const na=this.note.addAttr(attr);return na.tag=this.tag,na}duplicate(){const output=new NoteTag;return output.noteId=this.noteId,this.tag?output.tag=this.tag:output.tagId=this.tagId,output}validate(throwError=!1){let output=null;if(this.noteId<=0&&!this.isNew?output="NoteTag noteId must be greater than zero":this.tagId<=0?output="NoteTag tagId must be greater than zero":this.noteId==this.tagId&&(output="NoteTag cannot link a note to its own tag"),throwError&&output!=null)throw Error(output);return output==null}toJSON(){return{state:this.state,noteId:this.noteId,tagId:this.tagId}}static fromJSON(json){const output=new NoteTag(json.noteId,json.tagId);return output.state=json.state,output}}class Tag extends ModelWithState{constructor(name=""){super();__publicField(this,"_id",0);__publicField(this,"_spaceId",0);__publicField(this,"_space",null);__publicField(this,"_name","");__publicField(this,"_color",null);__publicField(this,"_isPublic",!0);this._name=name}get id(){return this._id}set id(value){value!==this._id&&(this._id=value,this.isClean&&this.dirty())}get spaceId(){return this._spaceId}set spaceId(value){var _a;value!==this._spaceId&&(this._spaceId=value,value!==((_a=this.space)==null?void 0:_a.id)&&(this._space=null),this.isClean&&this.dirty())}get space(){return this._space}set space(value){this._space=value,this.spaceId=(value==null?void 0:value.id)??0}in(space){return typeof space=="number"?this.spaceId=space:this.space=space,this}get name(){return this._name}set name(value){value!==this._name&&(this._name=value,this.isClean&&this.dirty())}getQualifiedName(contextSpaceId){return contextSpaceId==this.spaceId?this.name:`${this.space.name}.${this.name}`}get color(){return this._color}set color(value){value!==this._color&&(this._color=value,this.isClean&&this.dirty())}get isPublic(){return this._isPublic}set isPublic(value){value!==this._isPublic&&(this._isPublic=value,this.isClean&&this.dirty())}asPublic(){return this.isPublic=!0,this}asPrivate(){return this.isPublic=!1,this}duplicate(){const output=new Tag(this.name);return output.id=this.id,output.state=this.state,output.color=this.color,output.space=this.space,output.isPublic=this.isPublic,output}validate(throwError=!1){let output=null;if(!this.isNew&&this.id<=0?output="Tag id must be greater than zero if in non-new state.":!this.name||!/^[a-zA-Z][a-zA-Z0-9 ]*[a-zA-Z0-9]?$/.test(this.name)?output="Tag name is invalid, must only contain letters, numbers, and spaces, starting with a letter":this.color&&!/^#?[A-z0-9]{6}$/.test(this.color)&&(output="Tag color is invalid, must be a 6 character hexadecimal."),throwError&&output!=null)throw Error(output);return output==null}getColorInt(){let hex=this.color;return hex?(hex.startsWith("#")&&(hex=hex.substring(1)),parseInt(hex,16)):null}toJSON(){return{state:this.state,id:this.id,name:this.name,spaceId:this.spaceId,color:this.color,isPublic:this.isPublic}}static fromJSON(json){const output=new Tag(json.name);return output.id=json.id,output.spaceId=json.spaceId,output.color=json.color,output.state=json.state,output.isPublic=json.isPublic,output}}class Note extends ModelWithState{constructor(text){super();__publicField(this,"_id",0);__publicField(this,"_date",new Date);__publicField(this,"_text","");__publicField(this,"_spaceId",0);__publicField(this,"_space",null);__publicField(this,"_ownTag",null);__publicField(this,"_tags",[]);__publicField(this,"_attrs",[]);text&&(this.text=text)}get id(){return this._id}set id(value){this._id=value,this.ownTag&&(this.ownTag.id=value)}get date(){return this._date}set date(value){value!==this._date&&(this._date=value,this.isClean&&this.dirty())}at(value){return this.date=value,this}get text(){return this._text}set text(value){value!==this._text&&(this._text=value,this.isClean&&this.dirty())}get spaceId(){return this._spaceId}set spaceId(value){var _a;value!==this._spaceId&&(this._spaceId=value,value!==((_a=this.space)==null?void 0:_a.id)&&(this._space=null),this.isClean&&this.dirty(),this._setOwnTagSpace())}get space(){return this._space}set space(value){this._space=value,this.spaceId=(value==null?void 0:value.id)??0}in(space){return typeof space=="number"?this.spaceId=space:this.space=space,this}get ownTag(){return this._ownTag}setOwnTag(tag){if(typeof tag=="string")this.ownTag==null&&(this._ownTag=new Tag),this.ownTag.name=tag,this.ownTag.id=this.id,this._setOwnTagSpace();else{if(this.ownTag)throw new Error("Note has already had its tag set. If you would like to change the tag name, call setTag with just a string specifying the new tag name.");if(tag.id!=0&&tag.id!=this.id)throw new Error("Attempted to set tag to note with non-matching ID. Added tag id must either match the note id, which indicates that the tag has already been added to the note. Otherwise the tag id must be zero, indicating that the tag still needs to be added.");this._ownTag=tag}return this}removeOwnTag(){this.ownTag&&(this.ownTag.isNew?this._ownTag=null:this.ownTag.delete())}_setOwnTagSpace(){this.ownTag&&(this.space?this.ownTag.space=this.space:this.ownTag.spaceId=this.spaceId)}get tags(){return this._tags}addTag(tag){if(tag.isDeleted)throw Error("Cannot add a tag marked as deleted to a note");if(tag.isNew)throw Error("Cannot add a tag that hasn't yet been saved to a note");if(tag.id==this.id)throw Error("Note cannot add its own tag as a linked tag");if(!tag.isPublic&&tag.spaceId!=this.spaceId)throw Error("Cannot add a private tag from another space");let nt=this.tags.find(x=>x.tagId==tag.id);return nt?(nt.isDeleted&&nt.dirty(),nt):(nt=new NoteTag,nt.note=this,nt.tag=tag,this._tags.push(nt),nt)}removeTag(tag){const nt=this.tags.find(x=>x.tagId==tag.id);if(!nt)return this;nt.isNew?this._tags=this._tags.filter(x=>x!==nt):nt.delete();for(const na of this.attrs.filter(x=>!x.isDeleted&&x.tagId==tag.id))this.removeAttr(na.attr,na.tag);return this}get attrs(){return this._attrs}addAttr(attr){if(attr.isDeleted)throw Error("Cannot add an attribute marked as deleted to a note");if(attr.isNew)throw Error("Cannot add an attribute that hasn't yet been saved to a note");const na=new NoteAttr(this,attr);return this._attrs.push(na),na}removeAttr(attr,tag=null){const na=this.attrs.find(x=>x.attrId==attr.id&&x.tagId==(tag==null?void 0:tag.id));return na?(na.isNew?this._attrs=this._attrs.filter(x=>x!==na):na.delete(),this):this}duplicate(){const output=new Note;return output.id=this.id,output.date=this.date,output.text=this.text,this.space?output.space=this.space:output.spaceId=this.spaceId,output._tags=this.tags.map(x=>{const ntCopy=x.duplicate();return ntCopy.note=output,ntCopy}),output._attrs=this.attrs.map(x=>{const naCopy=x.duplicate();return naCopy.note=output,naCopy}),this.ownTag&&output.setOwnTag(this.ownTag.duplicate()),output.state=this.state,output}toJSON(){return{state:this.state,id:this.id,date:this.date,text:this.text,spaceId:this.spaceId,ownTag:this.ownTag,tags:this.tags,attrs:this.attrs}}static fromJSON(json){const output=new Note(json.text);return output.id=json.id,output.date=new Date(json.date),output.spaceId=json.spaceId,json.ownTag&&output.setOwnTag(Tag.fromJSON(json.ownTag)),json.tags&&(output._tags=json.tags.map(x=>NoteTag.fromJSON(x))),json.attrs&&(output._attrs=json.attrs.map(x=>NoteAttr.fromJSON(x))),output.state=json.state,output}validate(throwError=!1){let output=null;this.spaceId<=0?output="Note spaceId must be greater than zero.":!this.isNew&&this.id<=0?output="Note id must be greater than zero if in non-new state.":this.ownTag&&this.ownTag.spaceId!=this.spaceId&&(output="Note cannot belong to a different space than its own tag");const survivingAttrs=this.attrs.filter(x=>!x.isDeleted);for(let i=0;i<survivingAttrs.length;i++){const na=survivingAttrs[i];for(let j=i+1;j<survivingAttrs.length;j++){const na2=survivingAttrs[j];na.attrId==na2.attrId&&na.tagId==na2.tagId&&(output=`Attr '${na.attr.name}' is duplicated.`)}}if(throwError&&output!=null)throw Error(output);if(this.ownTag&&!this.ownTag.validate(throwError))return!1;for(const nt of this.tags)if(!nt.validate(throwError))return!1;for(const na of this.attrs)if(!na.validate(throwError))return!1;return output==null}}class ParsedQuery{constructor(){__publicField(this,"where",null);__publicField(this,"order",null);__publicField(this,"tags",[]);__publicField(this,"attrs",[])}}class ParsedTag{constructor(){__publicField(this,"space",null);__publicField(this,"name",null);__publicField(this,"searchDepth",0);__publicField(this,"strictSearchDepth",!0);__publicField(this,"includeOwner",!1)}}class ParsedAttr{constructor(){__publicField(this,"name",null);__publicField(this,"exists",!1);__publicField(this,"tagNameFilters",null)}}function parseQuery(query){const output=splitQuery(query);return output.where=identifyTags(output.where,output),output.order=identifyTags(output.order,output),output.where=identifyAttrs(output.where,output),output.order=identifyAttrs(output.order,output),output}function splitQuery(query){query=" "+query+" ";const output=new ParsedQuery,orderByIndex=query.toUpperCase().indexOf(" ORDER BY ");return orderByIndex<0?output.where=query.trim():(output.where=query.substring(0,orderByIndex).trim(),output.order=query.substring(orderByIndex+10).trim()),output.where==""&&(output.where=null),output}function identifyTags(query,parsedQuery){const regexes=[/(#+\??~?|~)([\w\d]+\.)?([\w\d]+)/,/(#+\??~?|~)\[([\w\d\s]+\.)?([\w\d\s]+)\]/];for(const regex of regexes)for(;;){const match=regex.exec(query);if(!match)break;const hashPrefix=match[1],parsedTag=new ParsedTag;parsedTag.space=match[2]?match[2].substring(0,match[2].length-1):null,parsedTag.name=match[3],parsedTag.includeOwner=hashPrefix.includes("~"),parsedTag.searchDepth=(hashPrefix.match(/#/g)||[]).length,parsedTag.strictSearchDepth=!hashPrefix.includes("?");const fullMatch=match[0],matchStart=query.indexOf(fullMatch),matchEnd=matchStart+fullMatch.length;query=query.substring(0,matchStart)+`{tag${parsedQuery.tags.length}}`+query.substring(matchEnd),parsedQuery.tags.push(parsedTag)}return query}function identifyAttrs(query,parsedQuery){const regexes=[/@([\w\d]+)/,/@\[([\w\d\s]+)\]/];for(const regex of regexes)for(;;){const match=regex.exec(query);if(!match)break;const parsedAttr=new ParsedAttr;parsedAttr.name=match[1];const matchStart=query.indexOf(match[0]);let matchEnd=matchStart+match[0].length;if(query.substring(matchEnd,matchEnd+9)==".Exists()"&&(parsedAttr.exists=!0,matchEnd+=9),query.substring(matchEnd,matchEnd+4)==".On("){let tagFilterStart=matchEnd+4;if(matchEnd=query.indexOf(")",tagFilterStart),matchEnd<0)throw Error("Unclosed bracket detected");let tagNameFilters=query.substring(tagFilterStart,matchEnd).split("|");const dummyParsedQuery=new ParsedQuery;for(let tagNameFilter of tagNameFilters)tagNameFilter.startsWith("~")||(tagNameFilter="~"+tagNameFilter),identifyTags(tagNameFilter,dummyParsedQuery);parsedAttr.tagNameFilters=dummyParsedQuery.tags,matchEnd++}query=query.substring(0,matchStart)+`{attr${parsedQuery.attrs.length}}`+query.substring(matchEnd),parsedQuery.attrs.push(parsedAttr)}return query}exports2.Attr=Attr,exports2.CachedClient=CachedClient,exports2.HttpClient=HttpClient,exports2.Note=Note,exports2.NoteAttr=NoteAttr,exports2.NoteTag=NoteTag,exports2.ParsedAttr=ParsedAttr,exports2.ParsedQuery=ParsedQuery,exports2.ParsedTag=ParsedTag,exports2.Space=Space,exports2.Tag=Tag,exports2.parseQuery=parseQuery,Object.defineProperty(exports2,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -2,4 +2,4 @@ import { Attr, Note, Space, Tag } from ".";
|
|
|
2
2
|
export declare function newNote(text?: string, id?: number): Note;
|
|
3
3
|
export declare function newSpace(name?: string, id?: number): Space;
|
|
4
4
|
export declare function newAttr(name?: string, id?: number): Attr;
|
|
5
|
-
export declare function newTag(name?: string,
|
|
5
|
+
export declare function newTag(name?: string, id?: number): Tag;
|
|
@@ -27,6 +27,7 @@ export default class Note extends ModelWithState<Note> {
|
|
|
27
27
|
get ownTag(): Tag;
|
|
28
28
|
setOwnTag(tag: string | Tag): Note;
|
|
29
29
|
removeOwnTag(): Note;
|
|
30
|
+
private _setOwnTagSpace;
|
|
30
31
|
private _tags;
|
|
31
32
|
get tags(): Array<NoteTag>;
|
|
32
33
|
addTag(tag: Tag): NoteTag;
|
|
@@ -34,7 +35,7 @@ export default class Note extends ModelWithState<Note> {
|
|
|
34
35
|
private _attrs;
|
|
35
36
|
get attrs(): Array<NoteAttr>;
|
|
36
37
|
addAttr(attr: Attr): NoteAttr;
|
|
37
|
-
removeAttr(attr: Attr): Note;
|
|
38
|
+
removeAttr(attr: Attr, tag?: Tag): Note;
|
|
38
39
|
duplicate(): Note;
|
|
39
40
|
toJSON(): {
|
|
40
41
|
state: "NEW" | "CLEAN" | "DIRTY" | "DELETED";
|
|
@@ -6,16 +6,24 @@ export default class Tag extends ModelWithState<Tag> {
|
|
|
6
6
|
set id(value: number);
|
|
7
7
|
private _spaceId;
|
|
8
8
|
get spaceId(): number;
|
|
9
|
+
set spaceId(value: number);
|
|
9
10
|
private _space;
|
|
10
11
|
get space(): Space;
|
|
11
12
|
set space(value: Space);
|
|
13
|
+
in(space: number | Space): Tag;
|
|
12
14
|
private _name;
|
|
13
15
|
get name(): string;
|
|
14
16
|
set name(value: string);
|
|
17
|
+
getQualifiedName(contextSpaceId: number): string;
|
|
15
18
|
private _color;
|
|
16
19
|
get color(): string;
|
|
17
20
|
set color(value: string);
|
|
18
|
-
|
|
21
|
+
private _isPublic;
|
|
22
|
+
get isPublic(): boolean;
|
|
23
|
+
set isPublic(value: boolean);
|
|
24
|
+
asPublic(): Tag;
|
|
25
|
+
asPrivate(): Tag;
|
|
26
|
+
constructor(name?: string);
|
|
19
27
|
duplicate(): Tag;
|
|
20
28
|
validate(throwError?: boolean): boolean;
|
|
21
29
|
getColorInt(): number;
|
|
@@ -25,6 +33,7 @@ export default class Tag extends ModelWithState<Tag> {
|
|
|
25
33
|
name: string;
|
|
26
34
|
spaceId: number;
|
|
27
35
|
color: string;
|
|
36
|
+
isPublic: boolean;
|
|
28
37
|
};
|
|
29
38
|
static fromJSON(json: any): Tag;
|
|
30
39
|
}
|