notu 0.4.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/notu.mjs +125 -34
- package/dist/notu.umd.js +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/models/Note.d.ts +0 -4
- package/dist/types/services/CachedClient.d.ts +25 -0
- package/dist/types/services/HttpClient.d.ts +5 -3
- package/package.json +1 -1
- package/dist/types/Environment.d.ts +0 -17
package/dist/notu.mjs
CHANGED
|
@@ -133,40 +133,130 @@ class Attr extends ModelWithState {
|
|
|
133
133
|
return output.type = json.type, output.spaceId = json.spaceId, output.id = json.id, output.state = json.state, output;
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
class
|
|
137
|
-
constructor(
|
|
138
|
-
__publicField(this, "
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
this
|
|
136
|
+
class CachedClient {
|
|
137
|
+
constructor(internalClient) {
|
|
138
|
+
__publicField(this, "_internalClient");
|
|
139
|
+
//Caches
|
|
140
|
+
__publicField(this, "_spaces", null);
|
|
141
|
+
__publicField(this, "_attrs", null);
|
|
142
|
+
__publicField(this, "_tags", null);
|
|
143
|
+
this._internalClient = internalClient;
|
|
144
|
+
}
|
|
145
|
+
_linkTagsToSpaces() {
|
|
146
|
+
for (const tag of this._tags.values()) {
|
|
147
|
+
const space = this._spaces.get(tag.spaceId);
|
|
148
|
+
space && (tag.space = space);
|
|
149
|
+
}
|
|
143
150
|
}
|
|
144
|
-
|
|
145
|
-
|
|
151
|
+
_linkAttrsToSpaces() {
|
|
152
|
+
for (const attr of this._attrs.values()) {
|
|
153
|
+
const space = this._spaces.get(attr.spaceId);
|
|
154
|
+
space && (attr.space = space);
|
|
155
|
+
}
|
|
146
156
|
}
|
|
147
|
-
|
|
148
|
-
|
|
157
|
+
/////////////////////////////////////
|
|
158
|
+
// NotuClient implementation start //
|
|
159
|
+
/////////////////////////////////////
|
|
160
|
+
async login(username, password) {
|
|
161
|
+
return await this._internalClient.login(username, password);
|
|
149
162
|
}
|
|
150
|
-
async
|
|
151
|
-
|
|
163
|
+
async getSpaces() {
|
|
164
|
+
if (this._spaces == null) {
|
|
165
|
+
const spaces = await this._internalClient.getSpaces();
|
|
166
|
+
this._spaces = /* @__PURE__ */ new Map();
|
|
167
|
+
for (const space of spaces)
|
|
168
|
+
this._spaces.set(space.id, space);
|
|
169
|
+
this._tags != null && this._linkTagsToSpaces(), this._attrs != null && this._linkAttrsToSpaces();
|
|
170
|
+
}
|
|
171
|
+
return [...this._spaces.values()];
|
|
152
172
|
}
|
|
153
173
|
async saveSpace(space) {
|
|
154
|
-
|
|
174
|
+
const saveResult = await this._internalClient.saveSpace(space);
|
|
175
|
+
return this._spaces != null && this._spaces.set(saveResult.id, saveResult), saveResult;
|
|
176
|
+
}
|
|
177
|
+
async getAttrs(spaceId) {
|
|
178
|
+
if (this._attrs == null) {
|
|
179
|
+
const attrs = await this._internalClient.getAttrs(spaceId);
|
|
180
|
+
this._attrs = /* @__PURE__ */ new Map();
|
|
181
|
+
for (const attr of attrs)
|
|
182
|
+
this._attrs.set(attr.id, attr);
|
|
183
|
+
this._spaces != null && this._linkAttrsToSpaces();
|
|
184
|
+
}
|
|
185
|
+
return [...this._attrs.values()];
|
|
186
|
+
}
|
|
187
|
+
async saveAttr(attr) {
|
|
188
|
+
const saveResult = await this._internalClient.saveAttr(attr);
|
|
189
|
+
return this._attrs != null && this._attrs.set(saveResult.id, saveResult), saveResult;
|
|
190
|
+
}
|
|
191
|
+
async getTags() {
|
|
192
|
+
if (this._tags == null) {
|
|
193
|
+
const tags = await this._internalClient.getTags();
|
|
194
|
+
this._tags = /* @__PURE__ */ new Map();
|
|
195
|
+
for (const tag of tags)
|
|
196
|
+
this._tags.set(tag.id, tag);
|
|
197
|
+
this._spaces != null && this._linkTagsToSpaces();
|
|
198
|
+
}
|
|
199
|
+
return [...this._tags.values()];
|
|
155
200
|
}
|
|
156
201
|
async getNotes(query, spaceId) {
|
|
157
|
-
|
|
202
|
+
const results = await this._internalClient.getNotes(query, spaceId);
|
|
203
|
+
if (this._spaces != null)
|
|
204
|
+
for (const note of results) {
|
|
205
|
+
const space = this._spaces.get(note.spaceId);
|
|
206
|
+
space && (note.space = space);
|
|
207
|
+
}
|
|
208
|
+
if (this._attrs != null)
|
|
209
|
+
for (const note of results)
|
|
210
|
+
for (const na of note.attrs) {
|
|
211
|
+
const attr = this._attrs.get(na.attrId);
|
|
212
|
+
attr && (na.attr = attr);
|
|
213
|
+
}
|
|
214
|
+
if (this._tags != null)
|
|
215
|
+
for (const note of results) {
|
|
216
|
+
for (const nt of note.tags) {
|
|
217
|
+
const tag = this._tags.get(nt.tagId);
|
|
218
|
+
tag && (nt.tag = tag);
|
|
219
|
+
}
|
|
220
|
+
for (const na of note.attrs.filter((x) => x.tagId != null)) {
|
|
221
|
+
const tag = this._tags.get(na.tagId);
|
|
222
|
+
tag && (na.tag = tag);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return results;
|
|
158
226
|
}
|
|
159
227
|
async getNoteCount(query, spaceId) {
|
|
160
|
-
return await this.
|
|
161
|
-
}
|
|
162
|
-
async saveNote(note) {
|
|
163
|
-
return (await this.client.saveNotes([note]))[0];
|
|
228
|
+
return await this._internalClient.getNoteCount(query, spaceId);
|
|
164
229
|
}
|
|
165
230
|
async saveNotes(notes) {
|
|
166
|
-
|
|
231
|
+
const saveResults = await this._internalClient.saveNotes(notes);
|
|
232
|
+
if (this._tags != null)
|
|
233
|
+
for (const note of saveResults.filter((x) => !!x.ownTag))
|
|
234
|
+
this._tags.set(note.ownTag.id, note.ownTag);
|
|
235
|
+
return saveResults;
|
|
167
236
|
}
|
|
168
237
|
async customJob(name, data) {
|
|
169
|
-
return await this.
|
|
238
|
+
return await this._internalClient.customJob(name, data);
|
|
239
|
+
}
|
|
240
|
+
///////////////////////////////////
|
|
241
|
+
// NotuClient implementation end //
|
|
242
|
+
///////////////////////////////////
|
|
243
|
+
//Synchronous cache methods
|
|
244
|
+
//These are introduced to make it far easier to lookup the cached values
|
|
245
|
+
//Especially in React where async is kind of a pain
|
|
246
|
+
//Make sure this method has been called before any of the other methods in this section
|
|
247
|
+
async cacheAll() {
|
|
248
|
+
await this.getSpaces();
|
|
249
|
+
const tagsPromise = this.getTags(), attrsPromise = this.getAttrs(0);
|
|
250
|
+
await Promise.all([tagsPromise, attrsPromise]);
|
|
251
|
+
}
|
|
252
|
+
get spaces() {
|
|
253
|
+
return [...this._spaces.values()];
|
|
254
|
+
}
|
|
255
|
+
get tags() {
|
|
256
|
+
return [...this._tags.values()];
|
|
257
|
+
}
|
|
258
|
+
get attrs() {
|
|
259
|
+
return [...this._attrs.values()];
|
|
170
260
|
}
|
|
171
261
|
}
|
|
172
262
|
class Space extends ModelWithState {
|
|
@@ -253,9 +343,9 @@ class HttpClient {
|
|
|
253
343
|
);
|
|
254
344
|
return Space.fromJSON(await result.json());
|
|
255
345
|
}
|
|
256
|
-
async getAttrs() {
|
|
346
|
+
async getAttrs(spaceId = 0) {
|
|
257
347
|
return (await (await this._fetch(
|
|
258
|
-
this.url +
|
|
348
|
+
this.url + `/attrs?space=${spaceId}`,
|
|
259
349
|
{
|
|
260
350
|
method: "GET",
|
|
261
351
|
headers: { Authorization: "Bearer " + this.token }
|
|
@@ -273,6 +363,15 @@ class HttpClient {
|
|
|
273
363
|
);
|
|
274
364
|
return Attr.fromJSON(await result.json());
|
|
275
365
|
}
|
|
366
|
+
async getTags() {
|
|
367
|
+
return (await (await this._fetch(
|
|
368
|
+
this.url + "/tags",
|
|
369
|
+
{
|
|
370
|
+
method: "GET",
|
|
371
|
+
headers: { Authorization: "Bearer " + this.token }
|
|
372
|
+
}
|
|
373
|
+
)).json()).map((x) => Tag.fromJSON(x));
|
|
374
|
+
}
|
|
276
375
|
async getNotes(query, spaceId) {
|
|
277
376
|
return (await (await this._fetch(
|
|
278
377
|
this.url + `/notes?space=${spaceId}&query=${encodeURIComponent(query)}`,
|
|
@@ -543,7 +642,6 @@ class Note extends ModelWithState {
|
|
|
543
642
|
__publicField(this, "_id", 0);
|
|
544
643
|
__publicField(this, "_date", /* @__PURE__ */ new Date());
|
|
545
644
|
__publicField(this, "_text", "");
|
|
546
|
-
__publicField(this, "_archived", !1);
|
|
547
645
|
__publicField(this, "_spaceId", 0);
|
|
548
646
|
__publicField(this, "_space", null);
|
|
549
647
|
__publicField(this, "_ownTag", null);
|
|
@@ -572,12 +670,6 @@ class Note extends ModelWithState {
|
|
|
572
670
|
set text(value) {
|
|
573
671
|
value !== this._text && (this._text = value, this.isClean && this.dirty());
|
|
574
672
|
}
|
|
575
|
-
get archived() {
|
|
576
|
-
return this._archived;
|
|
577
|
-
}
|
|
578
|
-
set archived(value) {
|
|
579
|
-
value !== this._archived && (this._archived = value, this.isClean && this.dirty());
|
|
580
|
-
}
|
|
581
673
|
get spaceId() {
|
|
582
674
|
return this._spaceId;
|
|
583
675
|
}
|
|
@@ -646,7 +738,7 @@ class Note extends ModelWithState {
|
|
|
646
738
|
}
|
|
647
739
|
duplicate() {
|
|
648
740
|
const output = new Note();
|
|
649
|
-
return output.id = this.id, output.date = this.date, output.text = this.text, output.
|
|
741
|
+
return output.id = this.id, output.date = this.date, output.text = this.text, output.space = this.space, output.state = this.state, output;
|
|
650
742
|
}
|
|
651
743
|
toJSON() {
|
|
652
744
|
return {
|
|
@@ -654,7 +746,6 @@ class Note extends ModelWithState {
|
|
|
654
746
|
id: this.id,
|
|
655
747
|
date: this.date,
|
|
656
748
|
text: this.text,
|
|
657
|
-
archived: this.archived,
|
|
658
749
|
spaceId: this.spaceId,
|
|
659
750
|
ownTag: this.ownTag,
|
|
660
751
|
tags: this.tags,
|
|
@@ -663,7 +754,7 @@ class Note extends ModelWithState {
|
|
|
663
754
|
}
|
|
664
755
|
static fromJSON(json) {
|
|
665
756
|
const output = new Note(json.text);
|
|
666
|
-
return output.id = json.id, output.date = new Date(json.date), output.
|
|
757
|
+
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;
|
|
667
758
|
}
|
|
668
759
|
validate(throwError = !1) {
|
|
669
760
|
let output = null;
|
|
@@ -762,7 +853,7 @@ function identifyAttrs(query, parsedQuery) {
|
|
|
762
853
|
}
|
|
763
854
|
export {
|
|
764
855
|
Attr,
|
|
765
|
-
|
|
856
|
+
CachedClient,
|
|
766
857
|
HttpClient,
|
|
767
858
|
Note,
|
|
768
859
|
NoteAttr,
|
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 Environment{constructor(client){__publicField(this,"_client",null);__publicField(this,"_spaces",[]);if(!client)throw Error("Client must be set on Environment constructor");this._client=client}get client(){return this._client}get spaces(){return this._spaces}async loadSpaces(){return this._spaces=await this.client.getSpaces(),this.spaces}async saveSpace(space){return await this.client.saveSpace(space)}async getNotes(query,spaceId){return await this.client.getNotes(query,spaceId)}async getNoteCount(query,spaceId){return await this.client.getNoteCount(query,spaceId)}async saveNote(note){return(await this.client.saveNotes([note]))[0]}async saveNotes(notes){return await this.client.saveNotes(notes)}async customJob(name,data){return await this.client.customJob(name,data)}}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(){return(await(await this._fetch(this.url+"/attrs",{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 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,"_archived",!1);__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 archived(){return this._archived}set archived(value){value!==this._archived&&(this._archived=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.archived=this.archived,output.space=this.space,output.state=this.state,output}toJSON(){return{state:this.state,id:this.id,date:this.date,text:this.text,archived:this.archived,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.archived=json.archived,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.Environment=Environment,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,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){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(){await this.getSpaces();const tagsPromise=this.getTags(),attrsPromise=this.getAttrs(0);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"})});
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Attr from './models/Attr';
|
|
2
|
-
import
|
|
2
|
+
import { CachedClient } from './services/CachedClient';
|
|
3
3
|
import HttpClient from './services/HttpClient';
|
|
4
4
|
import Note from './models/Note';
|
|
5
5
|
import NoteAttr from './models/NoteAttr';
|
|
@@ -7,4 +7,4 @@ import NoteTag from './models/NoteTag';
|
|
|
7
7
|
import parseQuery, { ParsedQuery, ParsedTag, ParsedAttr } from './services/QueryParser';
|
|
8
8
|
import Space from './models/Space';
|
|
9
9
|
import Tag from './models/Tag';
|
|
10
|
-
export { Attr,
|
|
10
|
+
export { Attr, CachedClient, HttpClient, Note, NoteAttr, NoteTag, parseQuery, ParsedQuery, ParsedTag, ParsedAttr, Space, Tag };
|
|
@@ -16,9 +16,6 @@ export default class Note extends ModelWithState<Note> {
|
|
|
16
16
|
private _text;
|
|
17
17
|
get text(): string;
|
|
18
18
|
set text(value: string);
|
|
19
|
-
private _archived;
|
|
20
|
-
get archived(): boolean;
|
|
21
|
-
set archived(value: boolean);
|
|
22
19
|
private _spaceId;
|
|
23
20
|
get spaceId(): number;
|
|
24
21
|
set spaceId(value: number);
|
|
@@ -44,7 +41,6 @@ export default class Note extends ModelWithState<Note> {
|
|
|
44
41
|
id: number;
|
|
45
42
|
date: Date;
|
|
46
43
|
text: string;
|
|
47
|
-
archived: boolean;
|
|
48
44
|
spaceId: number;
|
|
49
45
|
ownTag: Tag;
|
|
50
46
|
tags: NoteTag[];
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Attr, Note, Space, Tag } from '..';
|
|
2
|
+
import { NotuClient, NotuLoginResult } from './HttpClient';
|
|
3
|
+
export declare class CachedClient implements NotuClient {
|
|
4
|
+
private _internalClient;
|
|
5
|
+
constructor(internalClient: NotuClient);
|
|
6
|
+
private _spaces;
|
|
7
|
+
private _attrs;
|
|
8
|
+
private _tags;
|
|
9
|
+
private _linkTagsToSpaces;
|
|
10
|
+
private _linkAttrsToSpaces;
|
|
11
|
+
login(username: string, password: string): Promise<NotuLoginResult>;
|
|
12
|
+
getSpaces(): Promise<Array<Space>>;
|
|
13
|
+
saveSpace(space: Space): Promise<Space>;
|
|
14
|
+
getAttrs(spaceId: number): Promise<Array<Attr>>;
|
|
15
|
+
saveAttr(attr: Attr): Promise<Attr>;
|
|
16
|
+
getTags(): Promise<Array<Tag>>;
|
|
17
|
+
getNotes(query: string, spaceId: number): Promise<Array<Note>>;
|
|
18
|
+
getNoteCount(query: string, spaceId: number): Promise<number>;
|
|
19
|
+
saveNotes(notes: Array<Note>): Promise<Array<Note>>;
|
|
20
|
+
customJob(name: string, data: any): Promise<any>;
|
|
21
|
+
cacheAll(): Promise<void>;
|
|
22
|
+
get spaces(): Array<Space>;
|
|
23
|
+
get tags(): Array<Tag>;
|
|
24
|
+
get attrs(): Array<Attr>;
|
|
25
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Space from "../models/Space";
|
|
2
|
-
import { Note, Attr } from "..";
|
|
2
|
+
import { Note, Attr, Tag } from "..";
|
|
3
3
|
export interface NotuLoginResult {
|
|
4
4
|
success: boolean;
|
|
5
5
|
error: string;
|
|
@@ -9,8 +9,9 @@ export interface NotuClient {
|
|
|
9
9
|
login(username: string, password: string): Promise<NotuLoginResult>;
|
|
10
10
|
getSpaces(): Promise<Array<Space>>;
|
|
11
11
|
saveSpace(space: Space): Promise<Space>;
|
|
12
|
-
getAttrs(): Promise<Array<Attr>>;
|
|
12
|
+
getAttrs(spaceId: number): Promise<Array<Attr>>;
|
|
13
13
|
saveAttr(attr: Attr): Promise<Attr>;
|
|
14
|
+
getTags(): Promise<Array<Tag>>;
|
|
14
15
|
getNotes(query: string, spaceId: number): Promise<Array<Note>>;
|
|
15
16
|
getNoteCount(query: string, spaceId: number): Promise<number>;
|
|
16
17
|
saveNotes(notes: Array<Note>): Promise<Array<Note>>;
|
|
@@ -27,8 +28,9 @@ export default class HttpClient {
|
|
|
27
28
|
login(username: string, password: string): Promise<NotuLoginResult>;
|
|
28
29
|
getSpaces(): Promise<Array<Space>>;
|
|
29
30
|
saveSpace(space: Space): Promise<Space>;
|
|
30
|
-
getAttrs(): Promise<Array<Attr>>;
|
|
31
|
+
getAttrs(spaceId?: number): Promise<Array<Attr>>;
|
|
31
32
|
saveAttr(attr: Attr): Promise<Attr>;
|
|
33
|
+
getTags(): Promise<Array<Tag>>;
|
|
32
34
|
getNotes(query: string, spaceId: number): Promise<Array<Note>>;
|
|
33
35
|
getNoteCount(query: string, spaceId: number): Promise<number>;
|
|
34
36
|
saveNotes(notes: Array<Note>): Promise<Array<Note>>;
|
package/package.json
CHANGED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Note } from '.';
|
|
2
|
-
import Space from './models/Space';
|
|
3
|
-
import { NotuClient } from './services/HttpClient';
|
|
4
|
-
export default class Environment {
|
|
5
|
-
private _client;
|
|
6
|
-
get client(): NotuClient;
|
|
7
|
-
private _spaces;
|
|
8
|
-
get spaces(): Array<Space>;
|
|
9
|
-
constructor(client: NotuClient);
|
|
10
|
-
loadSpaces(): Promise<Array<Space>>;
|
|
11
|
-
saveSpace(space: Space): Promise<Space>;
|
|
12
|
-
getNotes(query: string, spaceId: number): Promise<Array<Note>>;
|
|
13
|
-
getNoteCount(query: string, spaceId: number): Promise<number>;
|
|
14
|
-
saveNote(note: Note): Promise<Note>;
|
|
15
|
-
saveNotes(notes: Array<Note>): Promise<Array<Note>>;
|
|
16
|
-
customJob(name: string, data: any): Promise<any>;
|
|
17
|
-
}
|