From 12611fb01b3f18d75e7389d5f8f5a415ac624aef Mon Sep 17 00:00:00 2001 From: Aleksejs Kovalovs Date: Wed, 14 May 2025 05:41:01 +0300 Subject: [PATCH] Fix Google contacts letter cases, removed main.js from manifest, registered event for interval sync, Vault.getFileByPath and Vault.getFolderByPath used instead of getAbstractFileByPath, MetadataCache.getFileCache used instead of vault.read and parsing frontmatter, processFrontMatter used instead of manual file parse and update, add AbstractInputSuggest for folder setting, fixed minAppVersion, settings rearranged with new Auth heading --- README.md | 8 +- docs/assets/highlight.css | 49 - docs/assets/main.js | 8 +- docs/assets/navigation.js | 2 +- docs/assets/search.js | 2 +- .../classes/auth_AuthManager.AuthManager.html | 12 +- ...e_ContactNoteWriter.ContactNoteWriter.html | 66 +- .../core_FolderSuggest.FolderSuggest.html | 19 + docs/classes/core_Formatter.Formatter.html | 22 +- ...ContactsService.GoogleContactsService.html | 8 +- docs/classes/i18n_translator.Translator.html | 8 +- docs/classes/main.default.html | 30 +- ...plugin_settings.ContactSyncSettingTab.html | 10 +- ...vices_MetadataService.MetadataService.html | 14 + .../services_VaultService.VaultService.html | 22 +- .../functions/auth_getAuthUrl.getAuthUrl.html | 2 +- docs/functions/i18n_translator.t.html | 2 +- ...sInFolder.getAllMarkdownFilesInFolder.html | 2 +- docs/index.html | 2 +- docs/interfaces/types_Contact.Birthday.html | 8 +- .../types_Contact.ContactGroupMembership.html | 8 +- .../types_Contact.GoogleContact.html | 20 +- .../types_Contact.GoogleContactGroup.html | 8 +- docs/interfaces/types_Contact.Membership.html | 8 +- ...s_ContactNoteConfig.ContactNoteConfig.html | 6 + .../types_Settings.ContactSyncSettings.html | 30 +- docs/modules/core_FolderSuggest.html | 1 + docs/modules/services_MetadataService.html | 1 + docs/modules/types_ContactNoteConfig.html | 1 + docs/variables/config.DEFAULT_SETTINGS.html | 2 +- docs/variables/config.LINK_TO_MANUAL.html | 2 +- docs/variables/config.URI_OATUH_REDIRECT.html | 2 +- docs/variables/config.URL_CONTACT_GROUPS.html | 2 +- docs/variables/config.URL_OAUTH_AUTH.html | 2 +- docs/variables/config.URL_OAUTH_SCOPE.html | 2 +- docs/variables/config.URL_OAUTH_TOKEN.html | 2 +- docs/variables/config.URL_PEOPLE_API.html | 2 +- docs/variables/config.URL_PEOPLE_BASE.html | 2 +- .../config.URL_PEOPLE_CONNECTIONS.html | 2 +- docs/variables/i18n_translations.en.html | 6 +- docs/variables/i18n_translations.lv.html | 6 +- docs/variables/i18n_translations.ru.html | 6 +- .../variables/i18n_translator.translator.html | 2 +- manifest.json | 7 +- package-lock.json | 1336 ++++++++++++++--- package.json | 2 +- .../obsidian_contact_sync_plugin_note.png | Bin 35913 -> 33470 bytes .../obsidian_contact_sync_plugin_settings.png | Bin 42993 -> 44669 bytes src/__mocks__/obsidian.ts | 29 +- src/__tests__/core/ContactNoteWriter.test.ts | 153 +- .../core/ContactNoteWriterProcess.test.ts | 101 +- src/auth/AuthManager.ts | 2 +- src/core/ContactNoteWriter.ts | 312 ++-- src/core/FolderSuggest.ts | 83 + src/core/GoogleContactsService.ts | 2 +- src/i18n/translations.ts | 32 +- src/main.ts | 50 +- src/plugin/settings.ts | 139 +- src/services/MetadataService.ts | 39 + src/services/VaultService.ts | 36 +- src/types/Contact.ts | 6 +- src/types/ContactNoteConfig.ts | 7 + src/types/Settings.ts | 4 +- 63 files changed, 1869 insertions(+), 890 deletions(-) create mode 100644 docs/classes/core_FolderSuggest.FolderSuggest.html create mode 100644 docs/classes/services_MetadataService.MetadataService.html create mode 100644 docs/interfaces/types_ContactNoteConfig.ContactNoteConfig.html create mode 100644 docs/modules/core_FolderSuggest.html create mode 100644 docs/modules/services_MetadataService.html create mode 100644 docs/modules/types_ContactNoteConfig.html create mode 100644 src/core/FolderSuggest.ts create mode 100644 src/services/MetadataService.ts create mode 100644 src/types/ContactNoteConfig.ts diff --git a/README.md b/README.md index 710f1c8..398987b 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,19 @@ # 🧩 Google Contacts Sync -Synchronize your Google Contacts directly into Obsidian! +Synchronize your Google contacts directly into Obsidian! Each contact becomes a separate note with YAML frontmatter for metadata and free-form text for your notes. --- ## ⚙️ Features -- 🔄 Synchronize Google Contacts into your Obsidian vault +- 🔄 Synchronize Google contacts into your Obsidian vault - 🗂 Configurable folder for storing contact notes - ✏️ Customizable note template (under the metadata block) -- 🏷 Filter by Google Contact label (e.g. only sync contacts tagged with `obsidian`) +- 🏷 Filter by Google contact label (e.g. only sync contacts tagged with `obsidian`) - 📛 Filename prefix support (e.g. `p Ivan Ivanov.md`) @@ -94,7 +94,7 @@ The plugin will automatically save the access and refresh tokens. 1. Open the command palette (Ctrl+P or Cmd+P) -2. Run the command: Sync Google Contacts +2. Run the command: Sync Google contacts ## 🔁 Sync Algorithm diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css index 8756492..5674cf3 100644 --- a/docs/assets/highlight.css +++ b/docs/assets/highlight.css @@ -1,71 +1,22 @@ :root { - --light-hl-0: #0000FF; - --dark-hl-0: #569CD6; - --light-hl-1: #000000; - --dark-hl-1: #D4D4D4; - --light-hl-2: #0070C1; - --dark-hl-2: #4FC1FF; - --light-hl-3: #AF00DB; - --dark-hl-3: #C586C0; - --light-hl-4: #795E26; - --dark-hl-4: #DCDCAA; - --light-hl-5: #001080; - --dark-hl-5: #9CDCFE; - --light-hl-6: #008000; - --dark-hl-6: #6A9955; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @media (prefers-color-scheme: light) { :root { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); --code-background: var(--light-code-background); } } @media (prefers-color-scheme: dark) { :root { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); --code-background: var(--dark-code-background); } } :root[data-theme='light'] { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); --code-background: var(--light-code-background); } :root[data-theme='dark'] { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); --code-background: var(--dark-code-background); } -.hl-0 { color: var(--hl-0); } -.hl-1 { color: var(--hl-1); } -.hl-2 { color: var(--hl-2); } -.hl-3 { color: var(--hl-3); } -.hl-4 { color: var(--hl-4); } -.hl-5 { color: var(--hl-5); } -.hl-6 { color: var(--hl-6); } pre, code { background: var(--code-background); } diff --git a/docs/assets/main.js b/docs/assets/main.js index 3effabb..19bbb7a 100644 --- a/docs/assets/main.js +++ b/docs/assets/main.js @@ -1,9 +1,9 @@ "use strict"; window.translations={"copy":"Copy","copied":"Copied!","normally_hidden":"This member is normally hidden due to your filter settings.","hierarchy_expand":"Expand","hierarchy_collapse":"Collapse","folder":"Folder","search_index_not_available":"The search index is not available","search_no_results_found_for_0":"No results found for {0}","kind_1":"Project","kind_2":"Module","kind_4":"Namespace","kind_8":"Enumeration","kind_16":"Enumeration Member","kind_32":"Variable","kind_64":"Function","kind_128":"Class","kind_256":"Interface","kind_512":"Constructor","kind_1024":"Property","kind_2048":"Method","kind_4096":"Call Signature","kind_8192":"Index Signature","kind_16384":"Constructor Signature","kind_32768":"Parameter","kind_65536":"Type Literal","kind_131072":"Type Parameter","kind_262144":"Accessor","kind_524288":"Get Signature","kind_1048576":"Set Signature","kind_2097152":"Type Alias","kind_4194304":"Reference","kind_8388608":"Document"}; -"use strict";(()=>{var Je=Object.create;var he=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Ge=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Ye=Object.prototype.hasOwnProperty;var Ze=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var et=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ge(e))!Ye.call(t,i)&&i!==n&&he(t,i,{get:()=>e[i],enumerable:!(r=Ke(e,i))||r.enumerable});return t};var tt=(t,e,n)=>(n=t!=null?Je(Xe(t)):{},et(e||!t||!t.__esModule?he(n,"default",{value:t,enumerable:!0}):n,t));var ye=Ze((me,ge)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,l],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. -`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(oc?d+=2:a==c&&(n+=r[l+1]*i[d+1],l+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}if(s.str.length==0&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),f=s.str.charAt(1),p;f in s.node.edges?p=s.node.edges[f]:(p=new t.TokenSet,s.node.edges[f]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),c=0;c1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof me=="object"?ge.exports=n():e.lunr=n()}(this,function(){return t})})()});var O,G={getItem(){return null},setItem(){}},K;try{K=localStorage,O=K}catch{K=G,O=G}var S={getItem:t=>O.getItem(t),setItem:(t,e)=>O.setItem(t,e),disableWritingLocalStorage(){O=G},disable(){localStorage.clear(),O=G},enable(){O=K}};window.TypeDoc||={disableWritingLocalStorage(){S.disableWritingLocalStorage()},disableLocalStorage:()=>{S.disable()},enableLocalStorage:()=>{S.enable()}};window.translations||={copy:"Copy",copied:"Copied!",normally_hidden:"This member is normally hidden due to your filter settings.",hierarchy_expand:"Expand",hierarchy_collapse:"Collapse",search_index_not_available:"The search index is not available",search_no_results_found_for_0:"No results found for {0}",folder:"Folder",kind_1:"Project",kind_2:"Module",kind_4:"Namespace",kind_8:"Enumeration",kind_16:"Enumeration Member",kind_32:"Variable",kind_64:"Function",kind_128:"Class",kind_256:"Interface",kind_512:"Constructor",kind_1024:"Property",kind_2048:"Method",kind_4096:"Call Signature",kind_8192:"Index Signature",kind_16384:"Constructor Signature",kind_32768:"Parameter",kind_65536:"Type Literal",kind_131072:"Type Parameter",kind_262144:"Accessor",kind_524288:"Get Signature",kind_1048576:"Set Signature",kind_2097152:"Type Alias",kind_4194304:"Reference",kind_8388608:"Document"};var pe=[];function Y(t,e){pe.push({selector:e,constructor:t})}var X=class{alwaysVisibleMember=null;constructor(){this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){pe.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!nt(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function nt(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var fe=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var Ie=tt(ye(),1);async function R(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0)),r=new Blob([e]).stream().pipeThrough(new DecompressionStream("deflate")),i=await new Response(r).text();return JSON.parse(i)}var Z="closing",ae="tsd-overlay";function rt(){let t=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.body.style.overflow="hidden",document.body.style.paddingRight=`${t}px`}function it(){document.body.style.removeProperty("overflow"),document.body.style.removeProperty("padding-right")}function xe(t,e){t.addEventListener("animationend",()=>{t.classList.contains(Z)&&(t.classList.remove(Z),document.getElementById(ae)?.remove(),t.close(),it())}),t.addEventListener("cancel",n=>{n.preventDefault(),ve(t)}),e?.closeOnClick&&document.addEventListener("click",n=>{t.open&&!t.contains(n.target)&&ve(t)},!0)}function Ee(t){if(t.open)return;let e=document.createElement("div");e.id=ae,document.body.appendChild(e),t.showModal(),rt()}function ve(t){if(!t.open)return;document.getElementById(ae)?.classList.add(Z),t.classList.add(Z)}var I=class{el;app;constructor(e){this.el=e.el,this.app=e.app}};var be=document.head.appendChild(document.createElement("style"));be.dataset.for="filters";var le={};function we(t){for(let e of t.split(/\s+/))if(le.hasOwnProperty(e)&&!le[e])return!0;return!1}var ee=class extends I{key;value;constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),be.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } -`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=S.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){S.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),le[`tsd-is-${this.el.name}`]=this.value,this.app.filterChanged(),this.app.updateIndexVisibility()}};var Le=0;async function Se(t,e){if(!window.searchData)return;let n=await R(window.searchData);t.data=n,t.index=Ie.Index.load(n.index),e.innerHTML=""}function _e(){let t=document.getElementById("tsd-search-trigger"),e=document.getElementById("tsd-search"),n=document.getElementById("tsd-search-input"),r=document.getElementById("tsd-search-results"),i=document.getElementById("tsd-search-script"),s=document.getElementById("tsd-search-status");if(!(t&&e&&n&&r&&i&&s))throw new Error("Search controls missing");let o={base:document.documentElement.dataset.base};o.base.endsWith("/")||(o.base+="/"),i.addEventListener("error",()=>{let a=window.translations.search_index_not_available;Pe(s,a)}),i.addEventListener("load",()=>{Se(o,s)}),Se(o,s),st({trigger:t,searchEl:e,results:r,field:n,status:s},o)}function st(t,e){let{field:n,results:r,searchEl:i,status:s,trigger:o}=t;xe(i,{closeOnClick:!0});function a(){Ee(i),n.setSelectionRange(0,n.value.length)}o.addEventListener("click",a),n.addEventListener("input",fe(()=>{ot(r,n,s,e)},200)),n.addEventListener("keydown",l=>{if(r.childElementCount===0||l.ctrlKey||l.metaKey||l.altKey)return;let d=n.getAttribute("aria-activedescendant"),f=d?document.getElementById(d):null;if(f){let p=!1,v=!1;switch(l.key){case"Home":case"End":case"ArrowLeft":case"ArrowRight":v=!0;break;case"ArrowDown":case"ArrowUp":p=l.shiftKey;break}(p||v)&&ke(n)}if(!l.shiftKey)switch(l.key){case"Enter":f?.querySelector("a")?.click();break;case"ArrowUp":Te(r,n,f,-1),l.preventDefault();break;case"ArrowDown":Te(r,n,f,1),l.preventDefault();break}});function c(){ke(n)}n.addEventListener("change",c),n.addEventListener("blur",c),n.addEventListener("click",c),document.body.addEventListener("keydown",l=>{if(l.altKey||l.metaKey||l.shiftKey)return;let d=l.ctrlKey&&l.key==="k",f=!l.ctrlKey&&!ct()&&l.key==="/";(d||f)&&(l.preventDefault(),a())})}function ot(t,e,n,r){if(!r.index||!r.data)return;t.innerHTML="",n.innerHTML="",Le+=1;let i=e.value.trim(),s;if(i){let a=i.split(" ").map(c=>c.length?`*${c}*`:"").join(" ");s=r.index.search(a).filter(({ref:c})=>{let l=r.data.rows[Number(c)].classes;return!l||!we(l)})}else s=[];if(s.length===0&&i){let a=window.translations.search_no_results_found_for_0.replace("{0}",` "${te(i)}" `);Pe(n,a);return}for(let a=0;ac.score-a.score);let o=Math.min(10,s.length);for(let a=0;a`,f=Ce(c.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(f+=` (score: ${s[a].score.toFixed(2)})`),c.parent&&(f=` - ${Ce(c.parent,i)}.${f}`);let p=document.createElement("li");p.id=`tsd-search:${Le}-${a}`,p.role="option",p.ariaSelected="false",p.classList.value=c.classes??"";let v=document.createElement("a");v.tabIndex=-1,v.href=r.base+c.url,v.innerHTML=d+`${f}`,p.append(v),t.appendChild(p)}}function Te(t,e,n,r){let i;if(r===1?i=n?.nextElementSibling||t.firstElementChild:i=n?.previousElementSibling||t.lastElementChild,i!==n){if(!i||i.role!=="option"){console.error("Option missing");return}i.ariaSelected="true",i.scrollIntoView({behavior:"smooth",block:"nearest"}),e.setAttribute("aria-activedescendant",i.id),n?.setAttribute("aria-selected","false")}}function ke(t){let e=t.getAttribute("aria-activedescendant");(e?document.getElementById(e):null)?.setAttribute("aria-selected","false"),t.setAttribute("aria-activedescendant","")}function Ce(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(te(t.substring(s,o)),`${te(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(te(t.substring(s))),i.join("")}var at={"&":"&","<":"<",">":">","'":"'",'"':"""};function te(t){return t.replace(/[&<>"'"]/g,e=>at[e])}function Pe(t,e){t.innerHTML=e?`
${e}
`:""}var lt=["button","checkbox","file","hidden","image","radio","range","reset","submit"];function ct(){let t=document.activeElement;return t?t.isContentEditable||t.tagName==="TEXTAREA"||t.tagName==="SEARCH"?!0:t.tagName==="INPUT"&&!lt.includes(t.type):!1}var D="mousedown",Oe="mousemove",$="mouseup",ne={x:0,y:0},Qe=!1,ce=!1,ut=!1,F=!1,Me=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(Me?"is-mobile":"not-mobile");Me&&"ontouchstart"in document.documentElement&&(ut=!0,D="touchstart",Oe="touchmove",$="touchend");document.addEventListener(D,t=>{ce=!0,F=!1;let e=D=="touchstart"?t.targetTouches[0]:t;ne.y=e.pageY||0,ne.x=e.pageX||0});document.addEventListener(Oe,t=>{if(ce&&!F){let e=D=="touchstart"?t.targetTouches[0]:t,n=ne.x-(e.pageX||0),r=ne.y-(e.pageY||0);F=Math.sqrt(n*n+r*r)>10}});document.addEventListener($,()=>{ce=!1});document.addEventListener("click",t=>{Qe&&(t.preventDefault(),t.stopImmediatePropagation(),Qe=!1)});var re=class extends I{active;className;constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener($,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(D,n=>this.onDocumentPointerDown(n)),document.addEventListener($,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){F||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!F&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var ue=new Map,de=class{open;accordions=[];key;constructor(e,n){this.key=e,this.open=n}add(e){this.accordions.push(e),e.open=this.open,e.addEventListener("toggle",()=>{this.toggle(e.open)})}toggle(e){for(let n of this.accordions)n.open=e;S.setItem(this.key,e.toString())}},ie=class extends I{constructor(e){super(e);let n=this.el.querySelector("summary"),r=n.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)});let i=`tsd-accordion-${n.dataset.key??n.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`,s;if(ue.has(i))s=ue.get(i);else{let o=S.getItem(i),a=o?o==="true":this.el.open;s=new de(i,a),ue.set(i,s)}s.add(this.el)}};function He(t){let e=S.getItem("tsd-theme")||"os";t.value=e,Ae(e),t.addEventListener("change",()=>{S.setItem("tsd-theme",t.value),Ae(t.value)})}function Ae(t){document.documentElement.dataset.theme=t}var se;function Fe(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Re),Re())}async function Re(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let e=await R(window.navigationData);se=document.documentElement.dataset.base,se.endsWith("/")||(se+="/"),t.innerHTML="";for(let n of e)Ne(n,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Ne(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',De(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let c=a.appendChild(document.createElement("ul"));c.className="tsd-nested-navigation";for(let l of t.children)Ne(l,c,i)}else De(t,r,t.class)}function De(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));if(r.href=se+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&(r.classList.add("current"),r.ariaCurrent="page"),t.kind){let i=window.translations[`kind_${t.kind}`].replaceAll('"',""");r.innerHTML=``}r.appendChild(document.createElement("span")).textContent=t.text}else{let r=e.appendChild(document.createElement("span")),i=window.translations.folder.replaceAll('"',""");r.innerHTML=``,r.appendChild(document.createElement("span")).textContent=t.text}}var oe=document.documentElement.dataset.base;oe.endsWith("/")||(oe+="/");function Ve(){document.querySelector(".tsd-full-hierarchy")?dt():document.querySelector(".tsd-hierarchy")&&ht()}function dt(){document.addEventListener("click",r=>{let i=r.target;for(;i.parentElement&&i.parentElement.tagName!="LI";)i=i.parentElement;i.dataset.dropdown&&(i.dataset.dropdown=String(i.dataset.dropdown!=="true"))});let t=new Map,e=new Set;for(let r of document.querySelectorAll(".tsd-full-hierarchy [data-refl]")){let i=r.querySelector("ul");t.has(r.dataset.refl)?e.add(r.dataset.refl):i&&t.set(r.dataset.refl,i)}for(let r of e)n(r);function n(r){let i=t.get(r).cloneNode(!0);i.querySelectorAll("[id]").forEach(s=>{s.removeAttribute("id")}),i.querySelectorAll("[data-dropdown]").forEach(s=>{s.dataset.dropdown="false"});for(let s of document.querySelectorAll(`[data-refl="${r}"]`)){let o=mt(),a=s.querySelector("ul");s.insertBefore(o,a),o.dataset.dropdown=String(!!a),a||s.appendChild(i.cloneNode(!0))}}}function ht(){let t=document.getElementById("tsd-hierarchy-script");t&&(t.addEventListener("load",Be),Be())}async function Be(){let t=document.querySelector(".tsd-panel.tsd-hierarchy:has(h4 a)");if(!t||!window.hierarchyData)return;let e=+t.dataset.refl,n=await R(window.hierarchyData),r=t.querySelector("ul"),i=document.createElement("ul");if(i.classList.add("tsd-hierarchy"),pt(i,n,e),r.querySelectorAll("li").length==i.querySelectorAll("li").length)return;let s=document.createElement("span");s.classList.add("tsd-hierarchy-toggle"),s.textContent=window.translations.hierarchy_expand,t.querySelector("h4 a")?.insertAdjacentElement("afterend",s),s.insertAdjacentText("beforebegin",", "),s.addEventListener("click",()=>{s.textContent===window.translations.hierarchy_expand?(r.insertAdjacentElement("afterend",i),r.remove(),s.textContent=window.translations.hierarchy_collapse):(i.insertAdjacentElement("afterend",r),i.remove(),s.textContent=window.translations.hierarchy_expand)})}function pt(t,e,n){let r=e.roots.filter(i=>ft(e,i,n));for(let i of r)t.appendChild($e(e,i,n))}function $e(t,e,n,r=new Set){if(r.has(e))return;r.add(e);let i=t.reflections[e],s=document.createElement("li");if(s.classList.add("tsd-hierarchy-item"),e===n){let o=s.appendChild(document.createElement("span"));o.textContent=i.name,o.classList.add("tsd-hierarchy-target")}else{for(let a of i.uniqueNameParents||[]){let c=t.reflections[a],l=s.appendChild(document.createElement("a"));l.textContent=c.name,l.href=oe+c.url,l.className=c.class+" tsd-signature-type",s.append(document.createTextNode("."))}let o=s.appendChild(document.createElement("a"));o.textContent=t.reflections[e].name,o.href=oe+i.url,o.className=i.class+" tsd-signature-type"}if(i.children){let o=s.appendChild(document.createElement("ul"));o.classList.add("tsd-hierarchy");for(let a of i.children){let c=$e(t,a,n,r);c&&o.appendChild(c)}}return r.delete(e),s}function ft(t,e,n){if(e===n)return!0;let r=new Set,i=[t.reflections[e]];for(;i.length;){let s=i.pop();if(!r.has(s)){r.add(s);for(let o of s.children||[]){if(o===n)return!0;i.push(t.reflections[o])}}}return!1}function mt(){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");return t.setAttribute("width","20"),t.setAttribute("height","20"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.innerHTML='',t}Y(re,"a[data-toggle]");Y(ie,".tsd-accordion");Y(ee,".tsd-filter-item input[type=checkbox]");var je=document.getElementById("tsd-theme");je&&He(je);var gt=new X;Object.defineProperty(window,"app",{value:gt});_e();Fe();Ve();"virtualKeyboard"in navigator&&(navigator.virtualKeyboard.overlaysContent=!0);})(); +"use strict";(()=>{var Ke=Object.create;var he=Object.defineProperty;var Ge=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Ye=Object.prototype.hasOwnProperty;var et=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var tt=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ze(e))!Ye.call(t,i)&&i!==n&&he(t,i,{get:()=>e[i],enumerable:!(r=Ge(e,i))||r.enumerable});return t};var nt=(t,e,n)=>(n=t!=null?Ke(Xe(t)):{},tt(e||!t||!t.__esModule?he(n,"default",{value:t,enumerable:!0}):n,t));var ye=et((me,ge)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,l],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(oc?d+=2:a==c&&(n+=r[l+1]*i[d+1],l+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}if(s.str.length==0&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),f=s.str.charAt(1),p;f in s.node.edges?p=s.node.edges[f]:(p=new t.TokenSet,s.node.edges[f]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),c=0;c1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof me=="object"?ge.exports=n():e.lunr=n()}(this,function(){return t})})()});var M,G={getItem(){return null},setItem(){}},K;try{K=localStorage,M=K}catch{K=G,M=G}var S={getItem:t=>M.getItem(t),setItem:(t,e)=>M.setItem(t,e),disableWritingLocalStorage(){M=G},disable(){localStorage.clear(),M=G},enable(){M=K}};window.TypeDoc||={disableWritingLocalStorage(){S.disableWritingLocalStorage()},disableLocalStorage:()=>{S.disable()},enableLocalStorage:()=>{S.enable()}};window.translations||={copy:"Copy",copied:"Copied!",normally_hidden:"This member is normally hidden due to your filter settings.",hierarchy_expand:"Expand",hierarchy_collapse:"Collapse",search_index_not_available:"The search index is not available",search_no_results_found_for_0:"No results found for {0}",folder:"Folder",kind_1:"Project",kind_2:"Module",kind_4:"Namespace",kind_8:"Enumeration",kind_16:"Enumeration Member",kind_32:"Variable",kind_64:"Function",kind_128:"Class",kind_256:"Interface",kind_512:"Constructor",kind_1024:"Property",kind_2048:"Method",kind_4096:"Call Signature",kind_8192:"Index Signature",kind_16384:"Constructor Signature",kind_32768:"Parameter",kind_65536:"Type Literal",kind_131072:"Type Parameter",kind_262144:"Accessor",kind_524288:"Get Signature",kind_1048576:"Set Signature",kind_2097152:"Type Alias",kind_4194304:"Reference",kind_8388608:"Document"};var pe=[];function X(t,e){pe.push({selector:e,constructor:t})}var Z=class{alwaysVisibleMember=null;constructor(){this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){pe.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!rt(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function rt(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var fe=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var Ie=nt(ye(),1);async function R(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0)),r=new Blob([e]).stream().pipeThrough(new DecompressionStream("deflate")),i=await new Response(r).text();return JSON.parse(i)}var Y="closing",ae="tsd-overlay";function it(){let t=Math.abs(window.innerWidth-document.documentElement.clientWidth);document.body.style.overflow="hidden",document.body.style.paddingRight=`${t}px`}function st(){document.body.style.removeProperty("overflow"),document.body.style.removeProperty("padding-right")}function xe(t,e){t.addEventListener("animationend",()=>{t.classList.contains(Y)&&(t.classList.remove(Y),document.getElementById(ae)?.remove(),t.close(),st())}),t.addEventListener("cancel",n=>{n.preventDefault(),ve(t)}),e?.closeOnClick&&document.addEventListener("click",n=>{t.open&&!t.contains(n.target)&&ve(t)},!0)}function Ee(t){if(t.open)return;let e=document.createElement("div");e.id=ae,document.body.appendChild(e),t.showModal(),it()}function ve(t){if(!t.open)return;document.getElementById(ae)?.classList.add(Y),t.classList.add(Y)}var I=class{el;app;constructor(e){this.el=e.el,this.app=e.app}};var be=document.head.appendChild(document.createElement("style"));be.dataset.for="filters";var le={};function we(t){for(let e of t.split(/\s+/))if(le.hasOwnProperty(e)&&!le[e])return!0;return!1}var ee=class extends I{key;value;constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),be.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } +`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=S.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){S.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),le[`tsd-is-${this.el.name}`]=this.value,this.app.filterChanged(),this.app.updateIndexVisibility()}};var Le=0;async function Se(t,e){if(!window.searchData)return;let n=await R(window.searchData);t.data=n,t.index=Ie.Index.load(n.index),e.innerHTML=""}function _e(){let t=document.getElementById("tsd-search-trigger"),e=document.getElementById("tsd-search"),n=document.getElementById("tsd-search-input"),r=document.getElementById("tsd-search-results"),i=document.getElementById("tsd-search-script"),s=document.getElementById("tsd-search-status");if(!(t&&e&&n&&r&&i&&s))throw new Error("Search controls missing");let o={base:document.documentElement.dataset.base};o.base.endsWith("/")||(o.base+="/"),i.addEventListener("error",()=>{let a=window.translations.search_index_not_available;Pe(s,a)}),i.addEventListener("load",()=>{Se(o,s)}),Se(o,s),ot({trigger:t,searchEl:e,results:r,field:n,status:s},o)}function ot(t,e){let{field:n,results:r,searchEl:i,status:s,trigger:o}=t;xe(i,{closeOnClick:!0});function a(){Ee(i),n.setSelectionRange(0,n.value.length)}o.addEventListener("click",a),n.addEventListener("input",fe(()=>{at(r,n,s,e)},200)),n.addEventListener("keydown",l=>{if(r.childElementCount===0||l.ctrlKey||l.metaKey||l.altKey)return;let d=n.getAttribute("aria-activedescendant"),f=d?document.getElementById(d):null;if(f){let p=!1,v=!1;switch(l.key){case"Home":case"End":case"ArrowLeft":case"ArrowRight":v=!0;break;case"ArrowDown":case"ArrowUp":p=l.shiftKey;break}(p||v)&&ke(n)}if(!l.shiftKey)switch(l.key){case"Enter":f?.querySelector("a")?.click();break;case"ArrowUp":Te(r,n,f,-1),l.preventDefault();break;case"ArrowDown":Te(r,n,f,1),l.preventDefault();break}});function c(){ke(n)}n.addEventListener("change",c),n.addEventListener("blur",c),n.addEventListener("click",c),document.body.addEventListener("keydown",l=>{if(l.altKey||l.metaKey||l.shiftKey)return;let d=l.ctrlKey&&l.key==="k",f=!l.ctrlKey&&!ut()&&l.key==="/";(d||f)&&(l.preventDefault(),a())})}function at(t,e,n,r){if(!r.index||!r.data)return;t.innerHTML="",n.innerHTML="",Le+=1;let i=e.value.trim(),s;if(i){let a=i.split(" ").map(c=>c.length?`*${c}*`:"").join(" ");s=r.index.search(a).filter(({ref:c})=>{let l=r.data.rows[Number(c)].classes;return!l||!we(l)})}else s=[];if(s.length===0&&i){let a=window.translations.search_no_results_found_for_0.replace("{0}",` "${te(i)}" `);Pe(n,a);return}for(let a=0;ac.score-a.score);let o=Math.min(10,s.length);for(let a=0;a`,f=Ce(c.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(f+=` (score: ${s[a].score.toFixed(2)})`),c.parent&&(f=` + ${Ce(c.parent,i)}.${f}`);let p=document.createElement("li");p.id=`tsd-search:${Le}-${a}`,p.role="option",p.ariaSelected="false",p.classList.value=c.classes??"";let v=document.createElement("a");v.tabIndex=-1,v.href=r.base+c.url,v.innerHTML=d+`${f}`,p.append(v),t.appendChild(p)}}function Te(t,e,n,r){let i;if(r===1?i=n?.nextElementSibling||t.firstElementChild:i=n?.previousElementSibling||t.lastElementChild,i!==n){if(!i||i.role!=="option"){console.error("Option missing");return}i.ariaSelected="true",i.scrollIntoView({behavior:"smooth",block:"nearest"}),e.setAttribute("aria-activedescendant",i.id),n?.setAttribute("aria-selected","false")}}function ke(t){let e=t.getAttribute("aria-activedescendant");(e?document.getElementById(e):null)?.setAttribute("aria-selected","false"),t.setAttribute("aria-activedescendant","")}function Ce(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(te(t.substring(s,o)),`${te(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(te(t.substring(s))),i.join("")}var lt={"&":"&","<":"<",">":">","'":"'",'"':"""};function te(t){return t.replace(/[&<>"'"]/g,e=>lt[e])}function Pe(t,e){t.innerHTML=e?`
${e}
`:""}var ct=["button","checkbox","file","hidden","image","radio","range","reset","submit"];function ut(){let t=document.activeElement;return t?t.isContentEditable||t.tagName==="TEXTAREA"||t.tagName==="SEARCH"?!0:t.tagName==="INPUT"&&!ct.includes(t.type):!1}var D="mousedown",Me="mousemove",$="mouseup",ne={x:0,y:0},Qe=!1,ce=!1,dt=!1,F=!1,Oe=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(Oe?"is-mobile":"not-mobile");Oe&&"ontouchstart"in document.documentElement&&(dt=!0,D="touchstart",Me="touchmove",$="touchend");document.addEventListener(D,t=>{ce=!0,F=!1;let e=D=="touchstart"?t.targetTouches[0]:t;ne.y=e.pageY||0,ne.x=e.pageX||0});document.addEventListener(Me,t=>{if(ce&&!F){let e=D=="touchstart"?t.targetTouches[0]:t,n=ne.x-(e.pageX||0),r=ne.y-(e.pageY||0);F=Math.sqrt(n*n+r*r)>10}});document.addEventListener($,()=>{ce=!1});document.addEventListener("click",t=>{Qe&&(t.preventDefault(),t.stopImmediatePropagation(),Qe=!1)});var re=class extends I{active;className;constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener($,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(D,n=>this.onDocumentPointerDown(n)),document.addEventListener($,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){F||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!F&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var ue=new Map,de=class{open;accordions=[];key;constructor(e,n){this.key=e,this.open=n}add(e){this.accordions.push(e),e.open=this.open,e.addEventListener("toggle",()=>{this.toggle(e.open)})}toggle(e){for(let n of this.accordions)n.open=e;S.setItem(this.key,e.toString())}},ie=class extends I{constructor(e){super(e);let n=this.el.querySelector("summary"),r=n.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)});let i=`tsd-accordion-${n.dataset.key??n.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`,s;if(ue.has(i))s=ue.get(i);else{let o=S.getItem(i),a=o?o==="true":this.el.open;s=new de(i,a),ue.set(i,s)}s.add(this.el)}};function He(t){let e=S.getItem("tsd-theme")||"os";t.value=e,Ae(e),t.addEventListener("change",()=>{S.setItem("tsd-theme",t.value),Ae(t.value)})}function Ae(t){document.documentElement.dataset.theme=t}var se;function Ne(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Re),Re())}async function Re(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let e=await R(window.navigationData);se=document.documentElement.dataset.base,se.endsWith("/")||(se+="/"),t.innerHTML="";for(let n of e)Be(n,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Be(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',De(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let c=a.appendChild(document.createElement("ul"));c.className="tsd-nested-navigation";for(let l of t.children)Be(l,c,i)}else De(t,r,t.class)}function De(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));if(r.href=se+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&(r.classList.add("current"),r.ariaCurrent="page"),t.kind){let i=window.translations[`kind_${t.kind}`].replaceAll('"',""");r.innerHTML=``}r.appendChild(Fe(t.text,document.createElement("span")))}else{let r=e.appendChild(document.createElement("span")),i=window.translations.folder.replaceAll('"',""");r.innerHTML=``,r.appendChild(Fe(t.text,document.createElement("span")))}}function Fe(t,e){let n=t.split(/(?<=[^A-Z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[_-])(?=[^_-])/);for(let r=0;r{let i=r.target;for(;i.parentElement&&i.parentElement.tagName!="LI";)i=i.parentElement;i.dataset.dropdown&&(i.dataset.dropdown=String(i.dataset.dropdown!=="true"))});let t=new Map,e=new Set;for(let r of document.querySelectorAll(".tsd-full-hierarchy [data-refl]")){let i=r.querySelector("ul");t.has(r.dataset.refl)?e.add(r.dataset.refl):i&&t.set(r.dataset.refl,i)}for(let r of e)n(r);function n(r){let i=t.get(r).cloneNode(!0);i.querySelectorAll("[id]").forEach(s=>{s.removeAttribute("id")}),i.querySelectorAll("[data-dropdown]").forEach(s=>{s.dataset.dropdown="false"});for(let s of document.querySelectorAll(`[data-refl="${r}"]`)){let o=gt(),a=s.querySelector("ul");s.insertBefore(o,a),o.dataset.dropdown=String(!!a),a||s.appendChild(i.cloneNode(!0))}}}function pt(){let t=document.getElementById("tsd-hierarchy-script");t&&(t.addEventListener("load",Ve),Ve())}async function Ve(){let t=document.querySelector(".tsd-panel.tsd-hierarchy:has(h4 a)");if(!t||!window.hierarchyData)return;let e=+t.dataset.refl,n=await R(window.hierarchyData),r=t.querySelector("ul"),i=document.createElement("ul");if(i.classList.add("tsd-hierarchy"),ft(i,n,e),r.querySelectorAll("li").length==i.querySelectorAll("li").length)return;let s=document.createElement("span");s.classList.add("tsd-hierarchy-toggle"),s.textContent=window.translations.hierarchy_expand,t.querySelector("h4 a")?.insertAdjacentElement("afterend",s),s.insertAdjacentText("beforebegin",", "),s.addEventListener("click",()=>{s.textContent===window.translations.hierarchy_expand?(r.insertAdjacentElement("afterend",i),r.remove(),s.textContent=window.translations.hierarchy_collapse):(i.insertAdjacentElement("afterend",r),i.remove(),s.textContent=window.translations.hierarchy_expand)})}function ft(t,e,n){let r=e.roots.filter(i=>mt(e,i,n));for(let i of r)t.appendChild(je(e,i,n))}function je(t,e,n,r=new Set){if(r.has(e))return;r.add(e);let i=t.reflections[e],s=document.createElement("li");if(s.classList.add("tsd-hierarchy-item"),e===n){let o=s.appendChild(document.createElement("span"));o.textContent=i.name,o.classList.add("tsd-hierarchy-target")}else{for(let a of i.uniqueNameParents||[]){let c=t.reflections[a],l=s.appendChild(document.createElement("a"));l.textContent=c.name,l.href=oe+c.url,l.className=c.class+" tsd-signature-type",s.append(document.createTextNode("."))}let o=s.appendChild(document.createElement("a"));o.textContent=t.reflections[e].name,o.href=oe+i.url,o.className=i.class+" tsd-signature-type"}if(i.children){let o=s.appendChild(document.createElement("ul"));o.classList.add("tsd-hierarchy");for(let a of i.children){let c=je(t,a,n,r);c&&o.appendChild(c)}}return r.delete(e),s}function mt(t,e,n){if(e===n)return!0;let r=new Set,i=[t.reflections[e]];for(;i.length;){let s=i.pop();if(!r.has(s)){r.add(s);for(let o of s.children||[]){if(o===n)return!0;i.push(t.reflections[o])}}}return!1}function gt(){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");return t.setAttribute("width","20"),t.setAttribute("height","20"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.innerHTML='',t}X(re,"a[data-toggle]");X(ie,".tsd-accordion");X(ee,".tsd-filter-item input[type=checkbox]");var qe=document.getElementById("tsd-theme");qe&&He(qe);var yt=new Z;Object.defineProperty(window,"app",{value:yt});_e();Ne();$e();"virtualKeyboard"in navigator&&(navigator.virtualKeyboard.overlaysContent=!0);})(); /*! Bundled license information: lunr/lunr.js: diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js index 3240ef7..271ebaf 100644 --- a/docs/assets/navigation.js +++ b/docs/assets/navigation.js @@ -1 +1 @@ -window.navigationData = "eJyll01vozAQhv8L56hRu7tVlRulJEVNIAqwe6gqywUnWHVMZEx2q1X/+woo5cMfONpLDuGdZ94ZPAM8/7U4+sOthQVLnlkzK8kwSRmi1uL565Jd8mwDKTwgZs2sE+SZtbCOeVoSVMyrONBTXGX8SKyZ9YZpai1uLiAmBBaFjKikX9/cfbx8zL6wB8QrbcyIwmcnMLIp4+1LmnCcU5Gogt9+/3gZ2ExyuscH0WLzv5GzB3dpx+sIhG4Uef4q7GBnyDB87eHG0iH/203P2Nrzn0AUgI3tx/ZawxwKNcR454HAjuJHsHMfvJ3rRBqqKNaS18AJ/Mh2IrDaBfFW1wNRPEEO7Dh6BNXPBLUTGhFDJ9i6RshaacSMgifXN2LWygnm1g22axfYW28C2QnNiPd2OFV5T2nGdALfd53IC/ypuy8GCBmGI8qQYhs6OeUw4X7O0S+GuWwnVtFA0BkNtobe7kcFfSLfeFcuc3aEXG3/67qRbQltYLejKbhje6s8PxD0WVMRInbGCVJYlWqNbE9kGZQgz2KQuymtXxy+vqOK08UZpAWB9RNGLLcKBH2JUZWIyoZDZCGqmTpyNoOQswbCSjMIK7XT2WpzyeEdwHKz0xtJeO29H/MiBbq6y3qHioJzdqWyO+gdl72DCKSJV48jxFTsWfWvUaNStIcl4WKXasLnVf1gn0h5wHReIM4xPUjOeCMAreCSrRm+0yRs4iL4Kroco6VhevtFM+HF/GdVqnIvtTLQlxmVIue2Fci56iRj+/z9hAr9g00spg5qnzhGRdxjxrMUvncsTDlie5gIuFY64v647bn+1K5YXp426PiKWJHhkwFcHqhLNdjnBhkGemNwbehSeh2kS3FRa3Tt6J+YUDmoDS/8vzktNFZD9ZyO09Wm+7ZLjkkxrz7JCNlA9pbmv+kSE1R4dJmTVPbaU4cATYjxN+Nkym6BTyc1NtQs+3/Y7HH8" \ No newline at end of file +window.navigationData = "eJylmE1vozAQhv8L56hVu7tVlRulNEVNIApk91BVlgsOWHVMZEx2q1X/+woI4cMfONpLDvDOM++M8WDy+tfi6A+35hYseWbNrDjDJGGIWvPX8y275NkKUpgiZs2sA+SZNbf2eVISVFxXcaCnuMr4nlgz6wPTxJrfXkCMCSwKGVFJv7m9/3r7mp2xKeKVdsuIwmcnMLIp4+1KGnOcU5Gogt99/3ob2IxzusOpaLG5buTs0X2yt8sIhG4Uef4i7GBHyDB87+HG0iH/223P2NLzX0AUgJXtb+2lhjkUaojbjQcCO9o+g4376G1cJ9JQRbGWvARO4Ee2E4HFJtiudT0QxRPkwN5Gz6D6maB2QiNi6ARr1whZK42YUfDi+kbMWjnBXLvBeukCe+1NIDuhGfHBDqcq7ynNmE7g+64TeYE/tfpigJBhuEUZUkxDJ6ccxtzPOfrFMJfNxCoaCDqjja2ht/NRQZ/IN56VTzlJEAvLNEUFV5Qw0BjZV1AH1odUTQ7RMttDru74+b6hVYE2stnSFNyxvUWepwSdlqEIETviGCmsSrVGtieyDEqQZzHI3ZTWLw7f3FPFhuAM0oLA+qUollsFgr7EqEpEZftZZCGqGRTkaAYhRw2ElWYQVmoHSqvNJQ/vAJabPb2RhNeu/ZgXKdDVKusdKgrO2ZXK7qB3XHZsEkgTp6U9xFTsWXXVqFEJ2sGSSGZRTTjd1W/sAylTTK8LxDmmqeQZbwSgFVwy6MNPGodNXATfRZdjtDRMb79odnih2L4rxGECOVQOrDYejJRGZSrpbYFKujbbuMaf1SpOV9CXGdmXcwXvA646iThW+edBuTCnpRbLqYPaE4BRGQ+Y8SyBnx0LU47YDsYCrpWOuD/ueq5P2gXLy8MK7d8RKzJ8MIDLA3WpBi8rgwwDvTG4NnQpvQ7SpbioNbp2vIm9r455juI7cgDuhJeeP8d4lfVehqmco1pC5URtEoT/N1ALjfdQPVDH6WrTfdslx6S4rj73CVlB9pHkv+kTJqjwaHOaFeupQ4AmxPj/iMmU3Zt2Oqmxoeat/A/BoEeX" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js index 738e312..d93b3e9 100644 --- a/docs/assets/search.js +++ b/docs/assets/search.js @@ -1 +1 @@ -window.searchData = "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"; \ No newline at end of file +window.searchData = "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"; \ No newline at end of file diff --git a/docs/classes/auth_AuthManager.AuthManager.html b/docs/classes/auth_AuthManager.AuthManager.html index 36a72e0..8543b60 100644 --- a/docs/classes/auth_AuthManager.AuthManager.html +++ b/docs/classes/auth_AuthManager.AuthManager.html @@ -1,17 +1,17 @@ -AuthManager | Documentation
Documentation
    Preparing search index...

    Manages OAuth2 authentication for accessing the Google Contacts API. +AuthManager | Documentation

    Documentation
      Preparing search index...

      Manages OAuth2 authentication for accessing the Google contacts API. Handles exchanging authorization codes, refreshing access tokens, and providing updated credentials.

      -
      Index

      Constructors

      Index

      Constructors

      Methods

      • Ensures the access token is valid and refreshes it if expired.

        +

      Returns AuthManager

      Methods

      • Ensures the access token is valid and refreshes it if expired.

        Returns Promise<string>

        A promise that resolves to a valid access token.

        -
      • Exchanges an authorization code for access and refresh tokens.

        +
      • Exchanges an authorization code for access and refresh tokens.

        Parameters

        • code: string

          The authorization code received from the OAuth flow.

        Returns Promise<void>

        A promise that resolves when tokens have been successfully obtained.

        -
      +
      diff --git a/docs/classes/core_ContactNoteWriter.ContactNoteWriter.html b/docs/classes/core_ContactNoteWriter.ContactNoteWriter.html index ef7ff3b..19f0535 100644 --- a/docs/classes/core_ContactNoteWriter.ContactNoteWriter.html +++ b/docs/classes/core_ContactNoteWriter.ContactNoteWriter.html @@ -1,52 +1,36 @@ ContactNoteWriter | Documentation
      Documentation
        Preparing search index...

        Responsible for creating and updating contact notes in the vault. Handles writing new notes and updating existing ones based on contact metadata.

        -
        Index

        Constructors

        Properties

        Index

        Constructors

        Properties

        formatter: Formatter = ...

        The Formatter instance used for formatting contact data into frontmatter.

        +

        Constructors

        • Creates an instance of ContactNoteWriter.

          +

          Parameters

          • vault: Vault

            The Obsidian Vault instance to operate on.

            +
          • metadataCache: MetadataCache

            The Obsidian MetadataCache instance to operate on.

            +
          • fileManager: FileManager

            The Obsidian FileManager instance to operate on.

            +

          Returns ContactNoteWriter

        Properties

        fileManager: FileManager

        The FileManager instance used for file operations.

        +

        This protected property is used to manage file operations in the Obsidian vault.

        +
        formatter: Formatter = ...

        The Formatter instance used for formatting contact data into frontmatter.

        This protected property is used to format contact data into a suitable format for Obsidian frontmatter.

        -
        vaultService: VaultService

        The VaultService instance used for vault operations.

        +
        metadataCache: MetadataCache

        The MetadataCache instance used for managing file metadata.

        +

        This protected property is used to manage file metadata in the Obsidian vault.

        +
        vaultService: VaultService

        The VaultService instance used for vault operations.

        This protected property is used to encapsulate file and folder operations to facilitate testing and decouple from direct API usage.

        -

        Methods

        • Generates a YAML frontmatter block string from the provided fields.

          -

          Parameters

          • fields: Record<string, string | string[]>

            A record of key-value pairs to include in the frontmatter.

            -

          Returns string

          A string representing the full frontmatter block with proper formatting.

          -

        Methods

        • Checks if a Google contact has the specified sync label.

          Parameters

          • contact: GoogleContact

            The Google contact to check.

          • syncLabel: string

            The label to check for.

          • labelMap: Record<string, string>

            A mapping of label names to their corresponding group IDs.

          Returns boolean

          True if the contact has the label, false otherwise.

          -
        • Returns a function that modifies the frontmatter of a note with new contact data.

          -

          Parameters

          • frontmatterLines: Record<string, string>

            The new contact data to inject into the frontmatter.

            -

          Returns (data: string) => string

          A function that takes the note content and returns the modified content.

          -
        • Scans an array of files, reads their content, and checks if the file's frontmatter contains an id field. -If an id field is found, it adds the id as a key and the corresponding file (TFile) as the value to a mapping object.

          -

          This method uses Obsidian's vaultService.readFile() to read file content and parseYaml() to safely parse the YAML frontmatter. -It ensures that only files with valid id fields in their frontmatter are added to the mapping.

          -

          Parameters

          • files: TFile[]

            An array of TFile objects representing the files to be scanned.

            -
          • propertyPrefix: string

            A string that may be used as a prefix for the id field in frontmatter.

            -

          Returns Promise<Record<string, TFile>>

          A promise that resolves to a record object where keys are the id values found in the frontmatter, -and values are the corresponding TFile objects.

          -
          const idFileMapping = await this.scanFiles(files);
          console.log(idFileMapping); // { "123": file1, "456": file2, ... } -
          - -
        • Updates the YAML frontmatter of a note with new contact fields, merging with existing values.

          -

          Parameters

          • content: string

            Original markdown note content.

            -
          • newContactFields: Record<string, string | string[]>

            Contact data to inject into the frontmatter.

            -

          Returns string

          Updated markdown content.

          -
        • Creates or updates markdown notes for each contact based on the provided contact data.

          -

          Parameters

          • prefix: string

            Prefix to use for note filenames.

            -
          • propertyPrefix: string

            Prefix to use for frontmatter properties.

            -
          • syncLabel: string

            Label used to determine which contacts to sync.

            -
          • labelMap: Record<string, string>

            Mapping of label names to Google Contact group resource names.

            -
          • contacts: GoogleContact[]

            List of Google contacts to sync into notes.

            -
          • folderPath: string

            Target folder path where notes should be stored.

            -
          • noteBody: string

            The body template to insert below the frontmatter in each note.

            -

          Returns Promise<void>

        +
        • Scans the provided files for frontmatter properties matching the specified prefix.

          +

          Parameters

          • files: TFile[]

            The list of TFile objects to scan.

            +
          • propertyPrefix: string

            The prefix to use for identifying frontmatter properties.

            +

          Returns Promise<Record<string, TFile>>

          A mapping of property values to TFile objects.

          +
        • Writes notes for the provided contacts based on the specified configuration.

          +

          Parameters

          • config: ContactNoteConfig

            The configuration for writing contact notes.

            +
          • labelMap: Record<string, string>

            A mapping of label names to their corresponding group IDs.

            +
          • contacts: GoogleContact[]

            The list of Google contacts to write notes for.

            +

          Returns Promise<void>

        diff --git a/docs/classes/core_FolderSuggest.FolderSuggest.html b/docs/classes/core_FolderSuggest.FolderSuggest.html new file mode 100644 index 0000000..14556ab --- /dev/null +++ b/docs/classes/core_FolderSuggest.FolderSuggest.html @@ -0,0 +1,19 @@ +FolderSuggest | Documentation
        Documentation
          Preparing search index...

          FolderSuggest class for providing folder suggestions in Obsidian. +This class extends AbstractInputSuggest to create a custom suggestion provider +for folder paths in the Obsidian vault.

          +

          Hierarchy

          • AbstractInputSuggest<TFolder>
            • FolderSuggest
          Index

          Constructors

          • Constructs a FolderSuggest instance.

            +

            Parameters

            • app: App

              The Obsidian app instance.

              +
            • inputEl: HTMLInputElement

              The input element to attach the suggestions to.

              +

            Returns FolderSuggest

          Methods

          • Returns the folder suggestions based on the input query.

            +

            Parameters

            • query: string

              The input query to filter folder suggestions.

              +

            Returns TFolder[]

            An array of TFolder objects that match the query.

            +
          • Renders the suggestion element for a folder.

            +

            Parameters

            • folder: TFolder

              The TFolder object to render.

              +
            • el: HTMLElement

              The HTML element to render the suggestion into.

              +

            Returns void

          • Handles the selection of a folder suggestion.

            +

            Parameters

            • folder: TFolder

              The selected TFolder object.

              +

            Returns void

          diff --git a/docs/classes/core_Formatter.Formatter.html b/docs/classes/core_Formatter.Formatter.html index 4a4718a..32d793e 100644 --- a/docs/classes/core_Formatter.Formatter.html +++ b/docs/classes/core_Formatter.Formatter.html @@ -1,5 +1,5 @@ Formatter | Documentation
          Documentation
            Preparing search index...

            Formatter class for transforming Google contact data into a format suitable for Obsidian frontmatter.

            -
            Index

            Constructors

            Index

            Constructors

            Methods

            addAddressFields addBioField addBirthdayFields @@ -15,47 +15,47 @@ Handles multiple addresses and appends a suffix to each additional field.

            Parameters

            • frontmatterLines: Record<string, string>

              The object representing the frontmatter fields to update.

            • contact: GoogleContact

              The Google contact containing address information.

            • propertyPrefix: string

              The prefix to prepend to the field name.

              -

            Returns void

            • Adds the biography field(s) from the contact to the frontmatter lines.

              +

            Returns void

            • Adds the biography field(s) from the contact to the frontmatter lines.

              Parameters

              • frontmatterLines: Record<string, string>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing biography information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

                -

              Returns void

            • Adds birthday field(s) from the contact to the frontmatter lines. +

            Returns void

            • Adds birthday field(s) from the contact to the frontmatter lines. Handles multiple birthdays and appends a suffix to each additional field.

              Parameters

              • frontmatterLines: Record<string, string>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing birthday information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

                -

              Returns void

            • Adds extracted contact field values to frontmatter with proper formatting.

              +

            Returns void

            • Adds extracted contact field values to frontmatter with proper formatting.

              Type Parameters

              • T extends { [key: string]: unknown }

              Parameters

              • frontmatter: Record<string, string>

                Frontmatter object to modify.

              • contact: undefined | T[]

                Contact array from which to extract values.

              • keyName: string

                Field key (e.g., "email", "phone").

              • propertyPrefix: string

                Prefix to apply to each field name in frontmatter.

              • valueExtractor: (item: T) => undefined | string

                Function to extract a string value from each item.

                -

              Returns void

            • Adds the email field(s) from the contact to the frontmatter lines.

              +

            Returns void

            • Adds the email field(s) from the contact to the frontmatter lines.

              Parameters

              • frontmatterLines: Record<string, string>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing email information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

                -

              Returns void

            • Adds job title field(s) from the contact to the frontmatter lines. +

            Returns void

            • Adds job title field(s) from the contact to the frontmatter lines. Handles multiple job titles and appends a suffix to each additional field.

              Parameters

              • frontmatterLines: Record<string, string>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing job title information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

                -

              Returns void

            • Adds labels from the contact to the frontmatter lines. +

            Returns void

            • Adds labels from the contact to the frontmatter lines. Handles multiple labels and appends a suffix to each additional field.

              Parameters

              • frontmatterLines: Record<string, string | string[]>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing label information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

              • labelMap: Record<string, string>

                A mapping of label IDs to their corresponding names.

                -

              Returns void

            • Adds the name field from the contact to the frontmatter lines.

              +

            Returns void

            • Adds the name field from the contact to the frontmatter lines.

              Parameters

              • frontmatterLines: Record<string, string>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing name information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

                -

              Returns void

            • Adds organization field(s) from the contact to the frontmatter lines. +

            Returns void

            • Adds organization field(s) from the contact to the frontmatter lines. Handles multiple organizations and appends a suffix to each additional field.

              Parameters

              • frontmatterLines: Record<string, string>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing organization information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

                -

              Returns void

            • Adds the phone field(s) from the contact to the frontmatter lines.

              +

            Returns void

            • Adds the phone field(s) from the contact to the frontmatter lines.

              Parameters

              • frontmatterLines: Record<string, string>

                The object representing the frontmatter fields to update.

              • contact: GoogleContact

                The Google contact containing phone number information.

              • propertyPrefix: string

                The prefix to prepend to the field name.

                -

              Returns void

            +

            Returns void

            diff --git a/docs/classes/core_GoogleContactsService.GoogleContactsService.html b/docs/classes/core_GoogleContactsService.GoogleContactsService.html index 4f49686..6151dcd 100644 --- a/docs/classes/core_GoogleContactsService.GoogleContactsService.html +++ b/docs/classes/core_GoogleContactsService.GoogleContactsService.html @@ -1,14 +1,14 @@ -GoogleContactsService | Documentation
            Documentation
              Preparing search index...

              Core service responsible for interacting with Google Contacts and Contact Groups APIs.

              +GoogleContactsService | Documentation
              Documentation
                Preparing search index...

                Core service responsible for interacting with Google contacts and Contact Groups APIs.

                Encapsulates logic for fetching, processing, and transforming Google contact data. Designed to be used by higher-level plugin components to separate external API concerns from application and Obsidian-specific logic.

                -
                Index

                Constructors

                Index

                Constructors

                Methods

                • Fetches contact groups and returns a mapping of lowercase group name → group ID.

                  +
                • Fetches contact groups and returns a mapping of lowercase group name → group ID.

                  Parameters

                  • token: string

                    OAuth access token.

                  Returns Promise<Record<string, string>>

                  Record mapping lowercase group names to their resource IDs.

                  -
                +
                diff --git a/docs/classes/i18n_translator.Translator.html b/docs/classes/i18n_translator.Translator.html index 460eb5e..ebeb299 100644 --- a/docs/classes/i18n_translator.Translator.html +++ b/docs/classes/i18n_translator.Translator.html @@ -1,11 +1,11 @@ Translator | Documentation
                Documentation
                  Preparing search index...

                  Translator handles language selection and translation fallback.

                  -
                  Index

                  Constructors

                  Index

                  Constructors

                  Methods

                  Constructors

                  Methods

                  • Sets the active language (e.g. 'ru' or 'en').

                    -

                    Parameters

                    • language: string

                    Returns void

                  • Translates a key using the selected language. +

                  Constructors

                  Methods

                  • Sets the active language (e.g. 'ru' or 'en').

                    +

                    Parameters

                    • language: string

                    Returns void

                  • Translates a key using the selected language. Falls back to English if key is missing. Returns the key itself if translation is not found at all.

                    Parameters

                    • key: string

                      The translation key.

                    Returns string

                    The translated string.

                    -
                  +
                  diff --git a/docs/classes/main.default.html b/docs/classes/main.default.html index 07cede3..08748b2 100644 --- a/docs/classes/main.default.html +++ b/docs/classes/main.default.html @@ -1,5 +1,5 @@ -default | Documentation
                  Documentation
                    Preparing search index...

                    Class default

                    Obsidian plugin for synchronizing contacts from Google Contacts into markdown notes.

                    -

                    Hierarchy

                    • Plugin
                      • default
                    Index

                    Constructors

                    constructor +default | Documentation
                    Documentation
                      Preparing search index...

                      Class default

                      Obsidian plugin for synchronizing contacts from Google contacts into markdown notes.

                      +

                      Hierarchy

                      • Plugin
                        • default
                      Index

                      Constructors

                      • Parameters

                        • app: App
                        • manifest: PluginManifest

                        Returns default

                      Properties

                      auth: null | AuthManager = null

                      Manages OAuth token exchange and refresh

                      -
                      googleService: null | GoogleContactsService = null

                      Service layer handling communication with the Google Contacts API. +

                      googleService: null | GoogleContactsService = null

                      Service layer handling communication with the Google contacts API. Used to fetch contacts and groups, separate from Obsidian-specific logic.

                      -
                      noteWriter: null | ContactNoteWriter = null

                      Handles writing contact notes to the vault

                      -
                      settings: ContactSyncSettings = DEFAULT_SETTINGS

                      Plugin settings loaded from user config

                      -

                      Methods

                      • Loads plugin settings from disk, applying defaults as needed.

                        -

                        Returns Promise<void>

                      • Called when the plugin is loaded by Obsidian.

                        -

                        Returns Promise<void>

                      • Override this to unload your component

                        -

                        Returns Promise<void>

                      • Saves current plugin settings to disk.

                        -

                        Returns Promise<void>

                      • Sets up automatic periodic syncing using setInterval based on plugin settings.

                        -

                        Returns void

                      • Determines whether syncing should be triggered based on the last sync time and interval.

                        +
                      noteWriter: null | ContactNoteWriter = null

                      Handles writing contact notes to the vault

                      +
                      settings: ContactSyncSettings = DEFAULT_SETTINGS

                      Plugin settings loaded from user config

                      +

                      Methods

                      • Loads plugin settings from disk, applying defaults as needed.

                        +

                        Returns Promise<void>

                      • Called when the plugin is loaded by Obsidian.

                        +

                        Returns Promise<void>

                      • Override this to unload your component

                        +

                        Returns Promise<void>

                      • Saves current plugin settings to disk.

                        +

                        Returns Promise<void>

                      • Sets up automatic periodic syncing using setInterval based on plugin settings.

                        +

                        Returns void

                      • Determines whether syncing should be triggered based on the last sync time and interval.

                        Returns boolean

                        True if sync should be triggered now, false otherwise.

                        -
                      • Performs the contact synchronization process: fetching, processing, and saving contact notes.

                        -

                        Returns Promise<void>

                      • Updates the plugin settings with the latest authentication tokens from the AuthManager +

                      • Performs the contact synchronization process: fetching, processing, and saving contact notes.

                        +

                        Returns Promise<void>

                      • Updates the plugin settings with the latest authentication tokens from the AuthManager and persists them to the plugin storage.

                        -

                        Returns Promise<void>

                      • Updates the last synchronization timestamp and saves the updated plugin settings. +

                        Returns Promise<void>

                      • Updates the last synchronization timestamp and saves the updated plugin settings. This should be called after a successful sync to persist the last sync time.

                        -

                        Returns Promise<void>

                      +

                      Returns Promise<void>

                      diff --git a/docs/classes/plugin_settings.ContactSyncSettingTab.html b/docs/classes/plugin_settings.ContactSyncSettingTab.html index 8afd4ea..acf387f 100644 --- a/docs/classes/plugin_settings.ContactSyncSettingTab.html +++ b/docs/classes/plugin_settings.ContactSyncSettingTab.html @@ -1,11 +1,11 @@ -ContactSyncSettingTab | Documentation
                      Documentation
                        Preparing search index...

                        Class ContactSyncSettingTab

                        Settings tab for the Google Contacts Sync plugin. +ContactSyncSettingTab | Documentation

                        Documentation
                          Preparing search index...

                          Class ContactSyncSettingTab

                          Settings tab for the Google contacts sync plugin. Allows the user to configure plugin options through the Obsidian settings UI.

                          -

                          Hierarchy

                          • PluginSettingTab
                            • ContactSyncSettingTab
                          Index

                          Constructors

                          Hierarchy

                          • PluginSettingTab
                            • ContactSyncSettingTab
                          Index

                          Constructors

                          Properties

                          Methods

                          Constructors

                          Properties

                          plugin: default

                          Reference to the main plugin instance

                          -

                          Methods

                          • Renders the plugin's settings UI in Obsidian's settings panel.

                            -

                            Returns void

                          +

                          Returns ContactSyncSettingTab

                          Properties

                          plugin: default

                          Reference to the main plugin instance

                          +

                          Methods

                          • Renders the plugin's settings UI in Obsidian's settings panel.

                            +

                            Returns void

                          diff --git a/docs/classes/services_MetadataService.MetadataService.html b/docs/classes/services_MetadataService.MetadataService.html new file mode 100644 index 0000000..dfc7c9c --- /dev/null +++ b/docs/classes/services_MetadataService.MetadataService.html @@ -0,0 +1,14 @@ +MetadataService | Documentation
                          Documentation
                            Preparing search index...

                            Service class for managing metadata in Obsidian files. +Encapsulates metadata operations to facilitate testing and decouple from direct API usage.

                            +
                            Index

                            Constructors

                            Methods

                            Constructors

                            • Creates an instance of MetadataService.

                              +

                              Parameters

                              • metadataCache: MetadataCache

                                The Obsidian MetadataCache instance to operate on.

                                +

                              Returns MetadataService

                            Methods

                            • Retrieves the YAML frontmatter from a file.

                              +

                              Parameters

                              • file: TFile

                                The TFile to retrieve YAML frontmatter from.

                                +

                              Returns null | CachedMetadata

                              The YAML frontmatter as a string, or null if not found.

                              +
                            • Retrieves the frontmatter metadata from a file.

                              +

                              Parameters

                              • file: TFile

                                The TFile to retrieve frontmatter from.

                                +

                              Returns undefined | Record<string, string | string[]>

                              The frontmatter as a record of key-value pairs, or undefined if not found.

                              +
                            diff --git a/docs/classes/services_VaultService.VaultService.html b/docs/classes/services_VaultService.VaultService.html index 57d0158..60ef148 100644 --- a/docs/classes/services_VaultService.VaultService.html +++ b/docs/classes/services_VaultService.VaultService.html @@ -1,28 +1,22 @@ VaultService | Documentation
                            Documentation
                              Preparing search index...

                              Service class for interacting with the Obsidian Vault. Encapsulates file and folder operations to facilitate testing and decouple from direct API usage.

                              -
                              Index

                              Constructors

                              Index

                              Constructors

                              Methods

                              • Creates a new file with the given content.

                                +

                              Returns VaultService

                              Methods

                              • Creates a new file with the given content.

                                Parameters

                                • filePath: string

                                  The path for the new file.

                                • content: string

                                  The initial content of the file.

                                  -

                                Returns Promise<void>

                              • Ensures that a folder exists at the given path, creating it if necessary.

                                +

                              Returns Promise<TFile>

                              The created TFile.

                              +
                              • Ensures that a folder exists at the given path, creating it if necessary.

                                Parameters

                                • folderPath: string

                                  The path of the folder to create.

                                  -

                                Returns Promise<void>

                              • Retrieves a file from the vault by its path.

                                +

                              Returns Promise<void>

                              • Retrieves a file from the vault by its path.

                                Parameters

                                • filePath: string

                                  The path of the file to retrieve.

                                  -

                                Returns null | TFile

                                The TFile if found, or null.

                                -
                              • Retrieves a folder from the vault by its path.

                                +

                              Returns Promise<null | TFile>

                              The TFile if found, or null.

                              +
                              • Retrieves a folder from the vault by its path.

                                Parameters

                                • folderPath: string

                                  The path of the folder to retrieve.

                                Returns null | TFolder

                                The TFolder if found, or null.

                                -
                              • Modifies an existing file with new content.

                                -

                                Parameters

                                • file: TFile

                                  The file to modify.

                                  -
                                • modify: (data: string) => string

                                Returns Promise<void>

                              • Reads the content of a file.

                                -

                                Parameters

                                • file: TFile

                                  The file to read.

                                  -

                                Returns Promise<string>

                                The file content as a string.

                                -
                              +
                              diff --git a/docs/functions/auth_getAuthUrl.getAuthUrl.html b/docs/functions/auth_getAuthUrl.getAuthUrl.html index 7040fca..20f760e 100644 --- a/docs/functions/auth_getAuthUrl.getAuthUrl.html +++ b/docs/functions/auth_getAuthUrl.getAuthUrl.html @@ -1,4 +1,4 @@ getAuthUrl | Documentation
                              Documentation
                                Preparing search index...

                                Function getAuthUrl

                                • Generates the Google OAuth2 authorization URL for user authentication.

                                  Parameters

                                  • clientId: string

                                    The OAuth2 client ID provided by Google.

                                  Returns string

                                  A complete URL string that initiates the OAuth2 authorization flow.

                                  -
                                +
                                diff --git a/docs/functions/i18n_translator.t.html b/docs/functions/i18n_translator.t.html index f44def1..992b3ed 100644 --- a/docs/functions/i18n_translator.t.html +++ b/docs/functions/i18n_translator.t.html @@ -1,4 +1,4 @@ t | Documentation
                                Documentation
                                  Preparing search index...
                                  • Global translation function.

                                    Parameters

                                    • key: string

                                      The translation key.

                                    Returns string

                                    The translated string.

                                    -
                                  +
                                  diff --git a/docs/functions/utils_getAllMarkdownFilesInFolder.getAllMarkdownFilesInFolder.html b/docs/functions/utils_getAllMarkdownFilesInFolder.getAllMarkdownFilesInFolder.html index 73c7ab9..6a01236 100644 --- a/docs/functions/utils_getAllMarkdownFilesInFolder.getAllMarkdownFilesInFolder.html +++ b/docs/functions/utils_getAllMarkdownFilesInFolder.getAllMarkdownFilesInFolder.html @@ -1,4 +1,4 @@ getAllMarkdownFilesInFolder | Documentation
                                  Documentation
                                    Preparing search index...
                                    • Recursively retrieves all markdown files in the specified folder.

                                      Parameters

                                      • folder: TFolder

                                        The root folder to search within.

                                      Returns TFile[]

                                      An array of markdown files.

                                      -
                                    +
                                    diff --git a/docs/index.html b/docs/index.html index 6311a72..7a484e3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1 +1 @@ -Documentation
                                    Documentation
                                      Preparing search index...
                                      +Documentation
                                      Documentation
                                        Preparing search index...
                                        diff --git a/docs/interfaces/types_Contact.Birthday.html b/docs/interfaces/types_Contact.Birthday.html index fde48c2..05afae7 100644 --- a/docs/interfaces/types_Contact.Birthday.html +++ b/docs/interfaces/types_Contact.Birthday.html @@ -1,8 +1,8 @@ Birthday | Documentation
                                        Documentation
                                          Preparing search index...

                                          Interface Birthday

                                          Represents a contact's birthday, including optional structured date and metadata.

                                          -
                                          interface Birthday {
                                              date?: { day?: number; year?: number; month?: number };
                                              metadata?: Record<string, unknown>;
                                              text?: string;
                                          }
                                          Index

                                          Properties

                                          interface Birthday {
                                              date?: { day?: number; year?: number; month?: number };
                                              metadata?: Record<string, unknown>;
                                              text?: string;
                                          }
                                          Index

                                          Properties

                                          Properties

                                          date?: { day?: number; year?: number; month?: number }

                                          Structured date object (year, month, day)

                                          -
                                          metadata?: Record<string, unknown>

                                          Additional metadata about the birthday

                                          -
                                          text?: string

                                          Free-form birthday string if structured date is unavailable

                                          -
                                          +
                                          metadata?: Record<string, unknown>

                                          Additional metadata about the birthday

                                          +
                                          text?: string

                                          Free-form birthday string if structured date is unavailable

                                          +
                                          diff --git a/docs/interfaces/types_Contact.ContactGroupMembership.html b/docs/interfaces/types_Contact.ContactGroupMembership.html index a9e304b..0ce6ec7 100644 --- a/docs/interfaces/types_Contact.ContactGroupMembership.html +++ b/docs/interfaces/types_Contact.ContactGroupMembership.html @@ -1,6 +1,6 @@ -ContactGroupMembership | Documentation
                                          Documentation
                                            Preparing search index...

                                            Interface ContactGroupMembership

                                            Represents a membership in a Google Contact Group.

                                            -
                                            interface ContactGroupMembership {
                                                contactGroupId: string;
                                                contactGroupResourceName?: string;
                                            }
                                            Index

                                            Properties

                                            contactGroupId +ContactGroupMembership | Documentation
                                            Documentation
                                              Preparing search index...

                                              Interface ContactGroupMembership

                                              Represents a membership in a Google contact Group.

                                              +
                                              interface ContactGroupMembership {
                                                  contactGroupId: string;
                                                  contactGroupResourceName?: string;
                                              }
                                              Index

                                              Properties

                                              contactGroupId: string

                                              Identifier of the contact group (e.g., "abc123")

                                              -
                                              contactGroupResourceName?: string

                                              Optional full resource name of the contact group (e.g., "contactGroups/family")

                                              -
                                              +
                                              contactGroupResourceName?: string

                                              Optional full resource name of the contact group (e.g., "contactGroups/family")

                                              +
                                              diff --git a/docs/interfaces/types_Contact.GoogleContact.html b/docs/interfaces/types_Contact.GoogleContact.html index d06a12d..4ea94bd 100644 --- a/docs/interfaces/types_Contact.GoogleContact.html +++ b/docs/interfaces/types_Contact.GoogleContact.html @@ -1,5 +1,5 @@ -GoogleContact | Documentation
                                              Documentation
                                                Preparing search index...

                                                Interface GoogleContact

                                                Represents a single contact retrieved from Google Contacts API.

                                                -
                                                interface GoogleContact {
                                                    addresses?: {
                                                        city: string;
                                                        country: string;
                                                        countryCode: string;
                                                        extendedAddress: string;
                                                        formattedType: string;
                                                        formattedValue: string;
                                                        postalCode: string;
                                                        streetAddress: string;
                                                        type: string;
                                                    }[];
                                                    biographies?: { value: string }[];
                                                    birthdays?: Birthday[];
                                                    emailAddresses?: { value: string }[];
                                                    memberships?: Membership[];
                                                    names?: { displayName: string }[];
                                                    organizations?: { name: string; title: string }[];
                                                    phoneNumbers?: { value: string }[];
                                                    resourceName: string;
                                                }
                                                Index

                                                Properties

                                                addresses? +GoogleContact | Documentation
                                                Documentation
                                                  Preparing search index...

                                                  Interface GoogleContact

                                                  Represents a single contact retrieved from Google contacts API.

                                                  +
                                                  interface GoogleContact {
                                                      addresses?: {
                                                          city: string;
                                                          country: string;
                                                          countryCode: string;
                                                          extendedAddress: string;
                                                          formattedType: string;
                                                          formattedValue: string;
                                                          postalCode: string;
                                                          streetAddress: string;
                                                          type: string;
                                                      }[];
                                                      biographies?: { value: string }[];
                                                      birthdays?: Birthday[];
                                                      emailAddresses?: { value: string }[];
                                                      memberships?: Membership[];
                                                      names?: { displayName: string }[];
                                                      organizations?: { name: string; title: string }[];
                                                      phoneNumbers?: { value: string }[];
                                                      resourceName: string;
                                                  }
                                                  Index

                                                  Properties

                                                  addresses?: {
                                                      city: string;
                                                      country: string;
                                                      countryCode: string;
                                                      extendedAddress: string;
                                                      formattedType: string;
                                                      formattedValue: string;
                                                      postalCode: string;
                                                      streetAddress: string;
                                                      type: string;
                                                  }[]

                                                  Array of address objects associated with the contact

                                                  -
                                                  biographies?: { value: string }[]

                                                  Array of biographies objects associated with the contact

                                                  -
                                                  birthdays?: Birthday[]

                                                  Array of birthday objects associated with the contact

                                                  -
                                                  emailAddresses?: { value: string }[]

                                                  Array of email address objects

                                                  -
                                                  memberships?: Membership[]

                                                  Array of group/domain memberships associated with the contact

                                                  -
                                                  names?: { displayName: string }[]

                                                  Array of name objects (usually contains a displayName)

                                                  -
                                                  organizations?: { name: string; title: string }[]
                                                  phoneNumbers?: { value: string }[]

                                                  Array of phone number objects

                                                  -
                                                  resourceName: string

                                                  Unique resource identifier for the contact (e.g., "people/c123...")

                                                  -
                                                  +
                                                  biographies?: { value: string }[]

                                                  Array of biographies objects associated with the contact

                                                  +
                                                  birthdays?: Birthday[]

                                                  Array of birthday objects associated with the contact

                                                  +
                                                  emailAddresses?: { value: string }[]

                                                  Array of email address objects

                                                  +
                                                  memberships?: Membership[]

                                                  Array of group/domain memberships associated with the contact

                                                  +
                                                  names?: { displayName: string }[]

                                                  Array of name objects (usually contains a displayName)

                                                  +
                                                  organizations?: { name: string; title: string }[]
                                                  phoneNumbers?: { value: string }[]

                                                  Array of phone number objects

                                                  +
                                                  resourceName: string

                                                  Unique resource identifier for the contact (e.g., "people/c123...")

                                                  +
                                                  diff --git a/docs/interfaces/types_Contact.GoogleContactGroup.html b/docs/interfaces/types_Contact.GoogleContactGroup.html index 53ff104..7a0b541 100644 --- a/docs/interfaces/types_Contact.GoogleContactGroup.html +++ b/docs/interfaces/types_Contact.GoogleContactGroup.html @@ -1,6 +1,6 @@ -GoogleContactGroup | Documentation
                                                  Documentation
                                                    Preparing search index...

                                                    Interface GoogleContactGroup

                                                    Represents a contact group fetched from Google Contacts API.

                                                    -
                                                    interface GoogleContactGroup {
                                                        name: string;
                                                        resourceName: string;
                                                    }
                                                    Index

                                                    Properties

                                                    name +GoogleContactGroup | Documentation
                                                    Documentation
                                                      Preparing search index...

                                                      Interface GoogleContactGroup

                                                      Represents a contact group fetched from Google contacts API.

                                                      +
                                                      interface GoogleContactGroup {
                                                          name: string;
                                                          resourceName: string;
                                                      }
                                                      Index

                                                      Properties

                                                      Properties

                                                      name: string

                                                      Human-readable name of the group (e.g., "Friends")

                                                      -
                                                      resourceName: string

                                                      Full resource name of the group (e.g., "contactGroups/friends")

                                                      -
                                                      +
                                                      resourceName: string

                                                      Full resource name of the group (e.g., "contactGroups/friends")

                                                      +
                                                      diff --git a/docs/interfaces/types_Contact.Membership.html b/docs/interfaces/types_Contact.Membership.html index 69b48f9..ca42bbd 100644 --- a/docs/interfaces/types_Contact.Membership.html +++ b/docs/interfaces/types_Contact.Membership.html @@ -1,8 +1,8 @@ Membership | Documentation
                                                      Documentation
                                                        Preparing search index...

                                                        Interface Membership

                                                        Represents a contact's membership in various domains or groups.

                                                        -
                                                        interface Membership {
                                                            contactGroupMembership?: ContactGroupMembership;
                                                            domainMembership?: Record<string, unknown>;
                                                            metadata?: Record<string, unknown>;
                                                        }
                                                        Index

                                                        Properties

                                                        interface Membership {
                                                            contactGroupMembership?: ContactGroupMembership;
                                                            domainMembership?: Record<string, unknown>;
                                                            metadata?: Record<string, unknown>;
                                                        }
                                                        Index

                                                        Properties

                                                        contactGroupMembership?: ContactGroupMembership

                                                        Membership in a specific contact group

                                                        -
                                                        domainMembership?: Record<string, unknown>

                                                        Optional domain membership data

                                                        -
                                                        metadata?: Record<string, unknown>

                                                        Optional metadata associated with the membership

                                                        -
                                                        +
                                                        domainMembership?: Record<string, unknown>

                                                        Optional domain membership data

                                                        +
                                                        metadata?: Record<string, unknown>

                                                        Optional metadata associated with the membership

                                                        +
                                                        diff --git a/docs/interfaces/types_ContactNoteConfig.ContactNoteConfig.html b/docs/interfaces/types_ContactNoteConfig.ContactNoteConfig.html new file mode 100644 index 0000000..3b8e638 --- /dev/null +++ b/docs/interfaces/types_ContactNoteConfig.ContactNoteConfig.html @@ -0,0 +1,6 @@ +ContactNoteConfig | Documentation
                                                        Documentation
                                                          Preparing search index...

                                                          Interface ContactNoteConfig

                                                          interface ContactNoteConfig {
                                                              folderPath: string;
                                                              noteBody: string;
                                                              prefix: string;
                                                              propertyPrefix: string;
                                                              syncLabel: string;
                                                          }
                                                          Index

                                                          Properties

                                                          folderPath: string
                                                          noteBody: string
                                                          prefix: string
                                                          propertyPrefix: string
                                                          syncLabel: string
                                                          diff --git a/docs/interfaces/types_Settings.ContactSyncSettings.html b/docs/interfaces/types_Settings.ContactSyncSettings.html index e89c5c1..def6dc9 100644 --- a/docs/interfaces/types_Settings.ContactSyncSettings.html +++ b/docs/interfaces/types_Settings.ContactSyncSettings.html @@ -1,5 +1,5 @@ -ContactSyncSettings | Documentation
                                                          Documentation
                                                            Preparing search index...

                                                            Interface ContactSyncSettings

                                                            Configuration options for Google Contacts synchronization.

                                                            -
                                                            interface ContactSyncSettings {
                                                                accessToken: string;
                                                                clientId: string;
                                                                clientSecret: string;
                                                                contactsFolder: string;
                                                                fileNamePrefix: string;
                                                                lastSyncTime?: string;
                                                                noteTemplate: string;
                                                                propertyNamePrefix: string;
                                                                refreshToken: string;
                                                                syncIntervalMinutes: number;
                                                                syncLabel: string;
                                                                syncOnStartup: boolean;
                                                                tokenExpiresAt: number;
                                                            }
                                                            Index

                                                            Properties

                                                            accessToken +ContactSyncSettings | Documentation
                                                            Documentation
                                                              Preparing search index...

                                                              Interface ContactSyncSettings

                                                              Configuration options for Google contacts synchronization.

                                                              +
                                                              interface ContactSyncSettings {
                                                                  accessToken: string;
                                                                  clientId: string;
                                                                  clientSecret: string;
                                                                  contactsFolder: string;
                                                                  fileNamePrefix: string;
                                                                  lastSyncTime?: string;
                                                                  noteTemplate: string;
                                                                  propertyNamePrefix: string;
                                                                  refreshToken: string;
                                                                  syncIntervalMinutes: number;
                                                                  syncLabel: string;
                                                                  syncOnStartup: boolean;
                                                                  tokenExpiresAt: number;
                                                              }
                                                              Index

                                                              Properties

                                                              accessToken: string

                                                              OAuth access token used to authorize API requests

                                                              -
                                                              clientId: string

                                                              OAuth client ID from Google Developer Console

                                                              -
                                                              clientSecret: string

                                                              OAuth client secret from Google Developer Console

                                                              -
                                                              contactsFolder: string

                                                              Path to the folder where contact notes will be stored

                                                              -
                                                              fileNamePrefix: string

                                                              Prefix used in contact note filenames

                                                              -
                                                              lastSyncTime?: string

                                                              ISO timestamp string of the last sync (optional)

                                                              -
                                                              noteTemplate: string

                                                              Template content for each contact note

                                                              -
                                                              propertyNamePrefix: string

                                                              Prefix used for frontmatter keys in contact notes

                                                              -
                                                              refreshToken: string

                                                              OAuth refresh token to obtain a new access token

                                                              -
                                                              syncIntervalMinutes: number

                                                              Interval (in minutes) for auto-sync

                                                              -
                                                              syncLabel: string

                                                              Name of the contact group to sync from Google Contacts

                                                              -
                                                              syncOnStartup: boolean

                                                              Whether to trigger sync automatically when Obsidian starts

                                                              -
                                                              tokenExpiresAt: number

                                                              Timestamp (in ms) when the access token will expire

                                                              -
                                                              +
                                                              clientId: string

                                                              OAuth client ID from Google Developer Console

                                                              +
                                                              clientSecret: string

                                                              OAuth client secret from Google Developer Console

                                                              +
                                                              contactsFolder: string

                                                              Path to the folder where contact notes will be stored

                                                              +
                                                              fileNamePrefix: string

                                                              Prefix used in contact note filenames

                                                              +
                                                              lastSyncTime?: string

                                                              ISO timestamp string of the last sync (optional)

                                                              +
                                                              noteTemplate: string

                                                              Template content for each contact note

                                                              +
                                                              propertyNamePrefix: string

                                                              Prefix used for frontmatter keys in contact notes

                                                              +
                                                              refreshToken: string

                                                              OAuth refresh token to obtain a new access token

                                                              +
                                                              syncIntervalMinutes: number

                                                              Interval (in minutes) for auto-sync

                                                              +
                                                              syncLabel: string

                                                              Name of the contact group to sync from Google contacts

                                                              +
                                                              syncOnStartup: boolean

                                                              Whether to trigger sync automatically when Obsidian starts

                                                              +
                                                              tokenExpiresAt: number

                                                              Timestamp (in ms) when the access token will expire

                                                              +
                                                              diff --git a/docs/modules/core_FolderSuggest.html b/docs/modules/core_FolderSuggest.html new file mode 100644 index 0000000..aee0bda --- /dev/null +++ b/docs/modules/core_FolderSuggest.html @@ -0,0 +1 @@ +core/FolderSuggest | Documentation
                                                              Documentation
                                                                Preparing search index...

                                                                Module core/FolderSuggest

                                                                Classes

                                                                FolderSuggest
                                                                diff --git a/docs/modules/services_MetadataService.html b/docs/modules/services_MetadataService.html new file mode 100644 index 0000000..eaca1b6 --- /dev/null +++ b/docs/modules/services_MetadataService.html @@ -0,0 +1 @@ +services/MetadataService | Documentation
                                                                Documentation
                                                                  Preparing search index...

                                                                  Module services/MetadataService

                                                                  Classes

                                                                  MetadataService
                                                                  diff --git a/docs/modules/types_ContactNoteConfig.html b/docs/modules/types_ContactNoteConfig.html new file mode 100644 index 0000000..cf18d61 --- /dev/null +++ b/docs/modules/types_ContactNoteConfig.html @@ -0,0 +1 @@ +types/ContactNoteConfig | Documentation
                                                                  Documentation
                                                                    Preparing search index...

                                                                    Module types/ContactNoteConfig

                                                                    Interfaces

                                                                    ContactNoteConfig
                                                                    diff --git a/docs/variables/config.DEFAULT_SETTINGS.html b/docs/variables/config.DEFAULT_SETTINGS.html index e27cc8e..4327b07 100644 --- a/docs/variables/config.DEFAULT_SETTINGS.html +++ b/docs/variables/config.DEFAULT_SETTINGS.html @@ -1,2 +1,2 @@ DEFAULT_SETTINGS | Documentation
                                                                    Documentation
                                                                      Preparing search index...

                                                                      Variable DEFAULT_SETTINGSConst

                                                                      DEFAULT_SETTINGS: {
                                                                          accessToken: string;
                                                                          clientId: string;
                                                                          clientSecret: string;
                                                                          contactsFolder: string;
                                                                          fileNamePrefix: string;
                                                                          noteTemplate: string;
                                                                          propertyNamePrefix: string;
                                                                          refreshToken: string;
                                                                          syncIntervalMinutes: number;
                                                                          syncLabel: string;
                                                                          syncOnStartup: boolean;
                                                                          tokenExpiresAt: number;
                                                                      } = ...

                                                                      Plugin default settings

                                                                      -

                                                                      Type declaration

                                                                      • accessToken: string
                                                                      • clientId: string
                                                                      • clientSecret: string
                                                                      • contactsFolder: string
                                                                      • fileNamePrefix: string
                                                                      • noteTemplate: string
                                                                      • propertyNamePrefix: string
                                                                      • refreshToken: string
                                                                      • syncIntervalMinutes: number
                                                                      • syncLabel: string
                                                                      • syncOnStartup: boolean
                                                                      • tokenExpiresAt: number
                                                                      +

                                                                      Type declaration

                                                                      • accessToken: string
                                                                      • clientId: string
                                                                      • clientSecret: string
                                                                      • contactsFolder: string
                                                                      • fileNamePrefix: string
                                                                      • noteTemplate: string
                                                                      • propertyNamePrefix: string
                                                                      • refreshToken: string
                                                                      • syncIntervalMinutes: number
                                                                      • syncLabel: string
                                                                      • syncOnStartup: boolean
                                                                      • tokenExpiresAt: number
                                                                      diff --git a/docs/variables/config.LINK_TO_MANUAL.html b/docs/variables/config.LINK_TO_MANUAL.html index 704eea4..abcaac4 100644 --- a/docs/variables/config.LINK_TO_MANUAL.html +++ b/docs/variables/config.LINK_TO_MANUAL.html @@ -1,2 +1,2 @@ LINK_TO_MANUAL | Documentation
                                                                      Documentation
                                                                        Preparing search index...

                                                                        Variable LINK_TO_MANUALConst

                                                                        LINK_TO_MANUAL: "https://github.com/YukiGasai/obsidian-google-calendar/blob/1.10.16/documentation/content/Install.pdf" = 'https://github.com/YukiGasai/obsidian-google-calendar/blob/1.10.16/documentation/content/Install.pdf'

                                                                        External links

                                                                        -
                                                                        +
                                                                        diff --git a/docs/variables/config.URI_OATUH_REDIRECT.html b/docs/variables/config.URI_OATUH_REDIRECT.html index 43dadba..e46fecf 100644 --- a/docs/variables/config.URI_OATUH_REDIRECT.html +++ b/docs/variables/config.URI_OATUH_REDIRECT.html @@ -1,2 +1,2 @@ URI_OATUH_REDIRECT | Documentation
                                                                        Documentation
                                                                          Preparing search index...

                                                                          Variable URI_OATUH_REDIRECTConst

                                                                          URI_OATUH_REDIRECT: "urn:ietf:wg:oauth:2.0:oob" = 'urn:ietf:wg:oauth:2.0:oob'

                                                                          OAuth2 defaults

                                                                          -
                                                                          +
                                                                          diff --git a/docs/variables/config.URL_CONTACT_GROUPS.html b/docs/variables/config.URL_CONTACT_GROUPS.html index ad01f77..ecaf61a 100644 --- a/docs/variables/config.URL_CONTACT_GROUPS.html +++ b/docs/variables/config.URL_CONTACT_GROUPS.html @@ -1 +1 @@ -URL_CONTACT_GROUPS | Documentation
                                                                          Documentation
                                                                            Preparing search index...

                                                                            Variable URL_CONTACT_GROUPSConst

                                                                            URL_CONTACT_GROUPS: "https://people.googleapis.com/v1/contactGroups" = ...
                                                                            +URL_CONTACT_GROUPS | Documentation
                                                                            Documentation
                                                                              Preparing search index...

                                                                              Variable URL_CONTACT_GROUPSConst

                                                                              URL_CONTACT_GROUPS: "https://people.googleapis.com/v1/contactGroups" = ...
                                                                              diff --git a/docs/variables/config.URL_OAUTH_AUTH.html b/docs/variables/config.URL_OAUTH_AUTH.html index 6861aad..ee4c8b1 100644 --- a/docs/variables/config.URL_OAUTH_AUTH.html +++ b/docs/variables/config.URL_OAUTH_AUTH.html @@ -1,2 +1,2 @@ URL_OAUTH_AUTH | Documentation
                                                                              Documentation
                                                                                Preparing search index...

                                                                                Variable URL_OAUTH_AUTHConst

                                                                                URL_OAUTH_AUTH: "https://accounts.google.com/o/oauth2/v2/auth" = 'https://accounts.google.com/o/oauth2/v2/auth'

                                                                                OAuth2 endpoints

                                                                                -
                                                                                +
                                                                                diff --git a/docs/variables/config.URL_OAUTH_SCOPE.html b/docs/variables/config.URL_OAUTH_SCOPE.html index 3609b2c..cea5ec8 100644 --- a/docs/variables/config.URL_OAUTH_SCOPE.html +++ b/docs/variables/config.URL_OAUTH_SCOPE.html @@ -1 +1 @@ -URL_OAUTH_SCOPE | Documentation
                                                                                Documentation
                                                                                  Preparing search index...

                                                                                  Variable URL_OAUTH_SCOPEConst

                                                                                  URL_OAUTH_SCOPE: "https://www.googleapis.com/auth/contacts.readonly" = 'https://www.googleapis.com/auth/contacts.readonly'
                                                                                  +URL_OAUTH_SCOPE | Documentation
                                                                                  Documentation
                                                                                    Preparing search index...

                                                                                    Variable URL_OAUTH_SCOPEConst

                                                                                    URL_OAUTH_SCOPE: "https://www.googleapis.com/auth/contacts.readonly" = 'https://www.googleapis.com/auth/contacts.readonly'
                                                                                    diff --git a/docs/variables/config.URL_OAUTH_TOKEN.html b/docs/variables/config.URL_OAUTH_TOKEN.html index 17abc05..7f40e91 100644 --- a/docs/variables/config.URL_OAUTH_TOKEN.html +++ b/docs/variables/config.URL_OAUTH_TOKEN.html @@ -1 +1 @@ -URL_OAUTH_TOKEN | Documentation
                                                                                    Documentation
                                                                                      Preparing search index...

                                                                                      Variable URL_OAUTH_TOKENConst

                                                                                      URL_OAUTH_TOKEN: "https://oauth2.googleapis.com/token" = 'https://oauth2.googleapis.com/token'
                                                                                      +URL_OAUTH_TOKEN | Documentation
                                                                                      Documentation
                                                                                        Preparing search index...

                                                                                        Variable URL_OAUTH_TOKENConst

                                                                                        URL_OAUTH_TOKEN: "https://oauth2.googleapis.com/token" = 'https://oauth2.googleapis.com/token'
                                                                                        diff --git a/docs/variables/config.URL_PEOPLE_API.html b/docs/variables/config.URL_PEOPLE_API.html index 4ed2e07..c2b450d 100644 --- a/docs/variables/config.URL_PEOPLE_API.html +++ b/docs/variables/config.URL_PEOPLE_API.html @@ -1 +1 @@ -URL_PEOPLE_API | Documentation
                                                                                        Documentation
                                                                                          Preparing search index...

                                                                                          Variable URL_PEOPLE_APIConst

                                                                                          URL_PEOPLE_API: "https://people.googleapis.com/v1/people/me/connections?personFields=names,emailAddresses,phoneNumbers,birthdays,memberships,metadata,addresses,biographies,organizations&pageSize=2000" = ...
                                                                                          +URL_PEOPLE_API | Documentation
                                                                                          Documentation
                                                                                            Preparing search index...

                                                                                            Variable URL_PEOPLE_APIConst

                                                                                            URL_PEOPLE_API: "https://people.googleapis.com/v1/people/me/connections?personFields=names,emailAddresses,phoneNumbers,birthdays,memberships,metadata,addresses,biographies,organizations&pageSize=2000" = ...
                                                                                            diff --git a/docs/variables/config.URL_PEOPLE_BASE.html b/docs/variables/config.URL_PEOPLE_BASE.html index 96ee68f..65f74dc 100644 --- a/docs/variables/config.URL_PEOPLE_BASE.html +++ b/docs/variables/config.URL_PEOPLE_BASE.html @@ -1,2 +1,2 @@ URL_PEOPLE_BASE | Documentation
                                                                                            Documentation
                                                                                              Preparing search index...

                                                                                              Variable URL_PEOPLE_BASEConst

                                                                                              URL_PEOPLE_BASE: "https://people.googleapis.com/v1" = 'https://people.googleapis.com/v1'

                                                                                              Google People API endpoints

                                                                                              -
                                                                                              +
                                                                                              diff --git a/docs/variables/config.URL_PEOPLE_CONNECTIONS.html b/docs/variables/config.URL_PEOPLE_CONNECTIONS.html index 9889aec..792ffa4 100644 --- a/docs/variables/config.URL_PEOPLE_CONNECTIONS.html +++ b/docs/variables/config.URL_PEOPLE_CONNECTIONS.html @@ -1 +1 @@ -URL_PEOPLE_CONNECTIONS | Documentation
                                                                                              Documentation
                                                                                                Preparing search index...

                                                                                                Variable URL_PEOPLE_CONNECTIONSConst

                                                                                                URL_PEOPLE_CONNECTIONS: "https://people.googleapis.com/v1/people/me/connections" = ...
                                                                                                +URL_PEOPLE_CONNECTIONS | Documentation
                                                                                                Documentation
                                                                                                  Preparing search index...

                                                                                                  Variable URL_PEOPLE_CONNECTIONSConst

                                                                                                  URL_PEOPLE_CONNECTIONS: "https://people.googleapis.com/v1/people/me/connections" = ...
                                                                                                  diff --git a/docs/variables/i18n_translations.en.html b/docs/variables/i18n_translations.en.html index daf0f86..6a4a3f1 100644 --- a/docs/variables/i18n_translations.en.html +++ b/docs/variables/i18n_translations.en.html @@ -1,4 +1,4 @@ -en | Documentation
                                                                                                  Documentation
                                                                                                    Preparing search index...

                                                                                                    Variable enConst

                                                                                                    en: {
                                                                                                        "Authorization code": string;
                                                                                                        "Auto sync period": string;
                                                                                                        "Automatically sync contacts when the plugin is loaded.": string;
                                                                                                        "Client ID and Secret required.": string;
                                                                                                        "Contacts folder": string;
                                                                                                        "e.g. # Notes\n\nWrite something here...": string;
                                                                                                        "e.g. 1440": string;
                                                                                                        "e.g. Contacts": string;
                                                                                                        "e.g. obsidian": string;
                                                                                                        "e.g. p ": string;
                                                                                                        "e.g. s_": string;
                                                                                                        "Enter your client ID": string;
                                                                                                        "Enter your client secret": string;
                                                                                                        "Fallback to English": string;
                                                                                                        "File name prefix": string;
                                                                                                        "Google client ID": string;
                                                                                                        "Google client secret": string;
                                                                                                        "Here is the manual about creating your own client:": string;
                                                                                                        "If not empty, then only contacts with this label will synced": string;
                                                                                                        "Label to sync": string;
                                                                                                        Login: string;
                                                                                                        "Login with Google": string;
                                                                                                        manual: string;
                                                                                                        "Note template": string;
                                                                                                        "Open google's OAuth page in your browser": string;
                                                                                                        "Paste code here": string;
                                                                                                        "Paste the code from Google after login": string;
                                                                                                        "Period in minutes. If 0, then never. 1 day = 1440": string;
                                                                                                        "Please enter your Client ID first.": string;
                                                                                                        "Prefix to add to the beginning of each contact file name": string;
                                                                                                        "Prefix to add to the beginning of each contact property name": string;
                                                                                                        "Property name prefix": string;
                                                                                                        "Sync on startup": string;
                                                                                                        "Template to insert below the metadata block for new contact notes": string;
                                                                                                        "Tokens saved!": string;
                                                                                                        "Vault folder where contact notes will be stored": string;
                                                                                                    } = ...

                                                                                                    Language dictionaries for English translations.

                                                                                                    -

                                                                                                    Type declaration

                                                                                                    • Authorization code: string
                                                                                                    • Auto sync period: string
                                                                                                    • Automatically sync contacts when the plugin is loaded.: string
                                                                                                    • Client ID and Secret required.: string
                                                                                                    • Contacts folder: string
                                                                                                    • e.g. # Notes +en | Documentation
                                                                                                      Documentation
                                                                                                        Preparing search index...

                                                                                                        Variable enConst

                                                                                                        en: {
                                                                                                            "Authorization code": string;
                                                                                                            "Auto sync period": string;
                                                                                                            "Automatically sync contacts when the plugin is loaded.": string;
                                                                                                            "Client ID and secret required.": string;
                                                                                                            "Contacts folder": string;
                                                                                                            "e.g. # Notes\n\nWrite something here...": string;
                                                                                                            "e.g. 1440": string;
                                                                                                            "e.g. Contacts": string;
                                                                                                            "e.g. obsidian": string;
                                                                                                            "e.g. p ": string;
                                                                                                            "e.g. s_": string;
                                                                                                            "Enter your client ID": string;
                                                                                                            "Enter your client secret": string;
                                                                                                            "Failed to obtain access token. Please re-authenticate.": string;
                                                                                                            "Fallback to English": string;
                                                                                                            "File name prefix": string;
                                                                                                            "Google auth": string;
                                                                                                            "Google client ID": string;
                                                                                                            "Google client secret": string;
                                                                                                            "Google contacts synced!": string;
                                                                                                            "Here is the manual about creating your own client:": string;
                                                                                                            "If not empty, then only contacts with this label will synced": string;
                                                                                                            "Label to sync": string;
                                                                                                            Login: string;
                                                                                                            "Login with Google": string;
                                                                                                            manual: string;
                                                                                                            "Note template": string;
                                                                                                            "Open Google's auth page in your browser": string;
                                                                                                            "Paste code here": string;
                                                                                                            "Paste the code from Google after login": string;
                                                                                                            "Period in minutes. If 0, then never. 1 day = 1440": string;
                                                                                                            "Please enter your client ID first.": string;
                                                                                                            "Prefix to add to the beginning of each contact file name": string;
                                                                                                            "Prefix to add to the beginning of each contact property name": string;
                                                                                                            "Property name prefix": string;
                                                                                                            "Sync on startup": string;
                                                                                                            "Template to insert below the metadata block for new contact notes": string;
                                                                                                            "Tokens saved!": string;
                                                                                                            "Vault folder where contact notes will be stored": string;
                                                                                                        } = ...

                                                                                                        Language dictionaries for English translations.

                                                                                                        +

                                                                                                        Type declaration

                                                                                                        • Authorization code: string
                                                                                                        • Auto sync period: string
                                                                                                        • Automatically sync contacts when the plugin is loaded.: string
                                                                                                        • Client ID and secret required.: string
                                                                                                        • Contacts folder: string
                                                                                                        • e.g. # Notes -Write something here...: string
                                                                                                        • e.g. 1440: string
                                                                                                        • e.g. Contacts: string
                                                                                                        • e.g. obsidian: string
                                                                                                        • e.g. p : string
                                                                                                        • e.g. s_: string
                                                                                                        • Enter your client ID: string
                                                                                                        • Enter your client secret: string
                                                                                                        • Fallback to English: string
                                                                                                        • File name prefix: string
                                                                                                        • Google client ID: string
                                                                                                        • Google client secret: string
                                                                                                        • Here is the manual about creating your own client:: string
                                                                                                        • If not empty, then only contacts with this label will synced: string
                                                                                                        • Label to sync: string
                                                                                                        • Login: string
                                                                                                        • Login with Google: string
                                                                                                        • manual: string
                                                                                                        • Note template: string
                                                                                                        • Open google's OAuth page in your browser: string
                                                                                                        • Paste code here: string
                                                                                                        • Paste the code from Google after login: string
                                                                                                        • Period in minutes. If 0, then never. 1 day = 1440: string
                                                                                                        • Please enter your Client ID first.: string
                                                                                                        • Prefix to add to the beginning of each contact file name: string
                                                                                                        • Prefix to add to the beginning of each contact property name: string
                                                                                                        • Property name prefix: string
                                                                                                        • Sync on startup: string
                                                                                                        • Template to insert below the metadata block for new contact notes: string
                                                                                                        • Tokens saved!: string
                                                                                                        • Vault folder where contact notes will be stored: string
                                                                                                        +Write something here...
                                                                                                        : string
                                                                                                      • e.g. 1440: string
                                                                                                      • e.g. Contacts: string
                                                                                                      • e.g. obsidian: string
                                                                                                      • e.g. p : string
                                                                                                      • e.g. s_: string
                                                                                                      • Enter your client ID: string
                                                                                                      • Enter your client secret: string
                                                                                                      • Failed to obtain access token. Please re-authenticate.: string
                                                                                                      • Fallback to English: string
                                                                                                      • File name prefix: string
                                                                                                      • Google auth: string
                                                                                                      • Google client ID: string
                                                                                                      • Google client secret: string
                                                                                                      • Google contacts synced!: string
                                                                                                      • Here is the manual about creating your own client:: string
                                                                                                      • If not empty, then only contacts with this label will synced: string
                                                                                                      • Label to sync: string
                                                                                                      • Login: string
                                                                                                      • Login with Google: string
                                                                                                      • manual: string
                                                                                                      • Note template: string
                                                                                                      • Open Google's auth page in your browser: string
                                                                                                      • Paste code here: string
                                                                                                      • Paste the code from Google after login: string
                                                                                                      • Period in minutes. If 0, then never. 1 day = 1440: string
                                                                                                      • Please enter your client ID first.: string
                                                                                                      • Prefix to add to the beginning of each contact file name: string
                                                                                                      • Prefix to add to the beginning of each contact property name: string
                                                                                                      • Property name prefix: string
                                                                                                      • Sync on startup: string
                                                                                                      • Template to insert below the metadata block for new contact notes: string
                                                                                                      • Tokens saved!: string
                                                                                                      • Vault folder where contact notes will be stored: string
                                                                                                      diff --git a/docs/variables/i18n_translations.lv.html b/docs/variables/i18n_translations.lv.html index 7f8e8c7..6442ce9 100644 --- a/docs/variables/i18n_translations.lv.html +++ b/docs/variables/i18n_translations.lv.html @@ -1,4 +1,4 @@ -lv | Documentation
                                                                                                      Documentation
                                                                                                        Preparing search index...

                                                                                                        Variable lvConst

                                                                                                        lv: {
                                                                                                            "Authorization code": string;
                                                                                                            "Auto sync period": string;
                                                                                                            "Automatically sync contacts when the plugin is loaded.": string;
                                                                                                            "Client ID and Secret required.": string;
                                                                                                            "Contacts folder": string;
                                                                                                            "e.g. # Notes\n\nWrite something here...": string;
                                                                                                            "e.g. 1440": string;
                                                                                                            "e.g. Contacts": string;
                                                                                                            "e.g. obsidian": string;
                                                                                                            "e.g. p ": string;
                                                                                                            "e.g. s_": string;
                                                                                                            "Enter your client ID": string;
                                                                                                            "Enter your client secret": string;
                                                                                                            "File name prefix": string;
                                                                                                            "Google client ID": string;
                                                                                                            "Google client secret": string;
                                                                                                            "Here is the manual about creating your own client:": string;
                                                                                                            "If not empty, then only contacts with this label will synced": string;
                                                                                                            "Label to sync": string;
                                                                                                            Login: string;
                                                                                                            "Login with Google": string;
                                                                                                            manual: string;
                                                                                                            "Note template": string;
                                                                                                            "Open google's OAuth page in your browser": string;
                                                                                                            "Paste code here": string;
                                                                                                            "Paste the code from Google after login": string;
                                                                                                            "Period in minutes. If 0, then never. 1 day = 1440": string;
                                                                                                            "Please enter your Client ID first.": string;
                                                                                                            "Prefix to add to the beginning of each contact file name": string;
                                                                                                            "Prefix to add to the beginning of each contact property name": string;
                                                                                                            "Property name prefix": string;
                                                                                                            "Sync on startup": string;
                                                                                                            "Template to insert below the metadata block for new contact notes": string;
                                                                                                            "Tokens saved!": string;
                                                                                                            "Vault folder where contact notes will be stored": string;
                                                                                                        } = ...

                                                                                                        Language dictionaries for Latvian translations.

                                                                                                        -

                                                                                                        Type declaration

                                                                                                        • Authorization code: string
                                                                                                        • Auto sync period: string
                                                                                                        • Automatically sync contacts when the plugin is loaded.: string
                                                                                                        • Client ID and Secret required.: string
                                                                                                        • Contacts folder: string
                                                                                                        • e.g. # Notes +lv | Documentation
                                                                                                          Documentation
                                                                                                            Preparing search index...

                                                                                                            Variable lvConst

                                                                                                            lv: {
                                                                                                                "Authorization code": string;
                                                                                                                "Auto sync period": string;
                                                                                                                "Automatically sync contacts when the plugin is loaded.": string;
                                                                                                                "Client ID and secret required.": string;
                                                                                                                "Contacts folder": string;
                                                                                                                "e.g. # Notes\n\nWrite something here...": string;
                                                                                                                "e.g. 1440": string;
                                                                                                                "e.g. Contacts": string;
                                                                                                                "e.g. obsidian": string;
                                                                                                                "e.g. p ": string;
                                                                                                                "e.g. s_": string;
                                                                                                                "Enter your client ID": string;
                                                                                                                "Enter your client secret": string;
                                                                                                                "Failed to obtain access token. Please re-authenticate.": string;
                                                                                                                "File name prefix": string;
                                                                                                                "Google auth": string;
                                                                                                                "Google client ID": string;
                                                                                                                "Google client secret": string;
                                                                                                                "Google contacts synced!": string;
                                                                                                                "Here is the manual about creating your own client:": string;
                                                                                                                "If not empty, then only contacts with this label will synced": string;
                                                                                                                "Label to sync": string;
                                                                                                                Login: string;
                                                                                                                "Login with Google": string;
                                                                                                                manual: string;
                                                                                                                "Note template": string;
                                                                                                                "Open Google's auth page in your browser": string;
                                                                                                                "Paste code here": string;
                                                                                                                "Paste the code from Google after login": string;
                                                                                                                "Period in minutes. If 0, then never. 1 day = 1440": string;
                                                                                                                "Please enter your client ID first.": string;
                                                                                                                "Prefix to add to the beginning of each contact file name": string;
                                                                                                                "Prefix to add to the beginning of each contact property name": string;
                                                                                                                "Property name prefix": string;
                                                                                                                "Sync on startup": string;
                                                                                                                "Template to insert below the metadata block for new contact notes": string;
                                                                                                                "Tokens saved!": string;
                                                                                                                "Vault folder where contact notes will be stored": string;
                                                                                                            } = ...

                                                                                                            Language dictionaries for Latvian translations.

                                                                                                            +

                                                                                                            Type declaration

                                                                                                            • Authorization code: string
                                                                                                            • Auto sync period: string
                                                                                                            • Automatically sync contacts when the plugin is loaded.: string
                                                                                                            • Client ID and secret required.: string
                                                                                                            • Contacts folder: string
                                                                                                            • e.g. # Notes -Write something here...: string
                                                                                                            • e.g. 1440: string
                                                                                                            • e.g. Contacts: string
                                                                                                            • e.g. obsidian: string
                                                                                                            • e.g. p : string
                                                                                                            • e.g. s_: string
                                                                                                            • Enter your client ID: string
                                                                                                            • Enter your client secret: string
                                                                                                            • File name prefix: string
                                                                                                            • Google client ID: string
                                                                                                            • Google client secret: string
                                                                                                            • Here is the manual about creating your own client:: string
                                                                                                            • If not empty, then only contacts with this label will synced: string
                                                                                                            • Label to sync: string
                                                                                                            • Login: string
                                                                                                            • Login with Google: string
                                                                                                            • manual: string
                                                                                                            • Note template: string
                                                                                                            • Open google's OAuth page in your browser: string
                                                                                                            • Paste code here: string
                                                                                                            • Paste the code from Google after login: string
                                                                                                            • Period in minutes. If 0, then never. 1 day = 1440: string
                                                                                                            • Please enter your Client ID first.: string
                                                                                                            • Prefix to add to the beginning of each contact file name: string
                                                                                                            • Prefix to add to the beginning of each contact property name: string
                                                                                                            • Property name prefix: string
                                                                                                            • Sync on startup: string
                                                                                                            • Template to insert below the metadata block for new contact notes: string
                                                                                                            • Tokens saved!: string
                                                                                                            • Vault folder where contact notes will be stored: string
                                                                                                            +Write something here...
                                                                                                            : string
                                                                                                          • e.g. 1440: string
                                                                                                          • e.g. Contacts: string
                                                                                                          • e.g. obsidian: string
                                                                                                          • e.g. p : string
                                                                                                          • e.g. s_: string
                                                                                                          • Enter your client ID: string
                                                                                                          • Enter your client secret: string
                                                                                                          • Failed to obtain access token. Please re-authenticate.: string
                                                                                                          • File name prefix: string
                                                                                                          • Google auth: string
                                                                                                          • Google client ID: string
                                                                                                          • Google client secret: string
                                                                                                          • Google contacts synced!: string
                                                                                                          • Here is the manual about creating your own client:: string
                                                                                                          • If not empty, then only contacts with this label will synced: string
                                                                                                          • Label to sync: string
                                                                                                          • Login: string
                                                                                                          • Login with Google: string
                                                                                                          • manual: string
                                                                                                          • Note template: string
                                                                                                          • Open Google's auth page in your browser: string
                                                                                                          • Paste code here: string
                                                                                                          • Paste the code from Google after login: string
                                                                                                          • Period in minutes. If 0, then never. 1 day = 1440: string
                                                                                                          • Please enter your client ID first.: string
                                                                                                          • Prefix to add to the beginning of each contact file name: string
                                                                                                          • Prefix to add to the beginning of each contact property name: string
                                                                                                          • Property name prefix: string
                                                                                                          • Sync on startup: string
                                                                                                          • Template to insert below the metadata block for new contact notes: string
                                                                                                          • Tokens saved!: string
                                                                                                          • Vault folder where contact notes will be stored: string
                                                                                                          diff --git a/docs/variables/i18n_translations.ru.html b/docs/variables/i18n_translations.ru.html index c7fdf42..be38259 100644 --- a/docs/variables/i18n_translations.ru.html +++ b/docs/variables/i18n_translations.ru.html @@ -1,4 +1,4 @@ -ru | Documentation
                                                                                                          Documentation
                                                                                                            Preparing search index...

                                                                                                            Variable ruConst

                                                                                                            ru: {
                                                                                                                "Authorization code": string;
                                                                                                                "Auto sync period": string;
                                                                                                                "Automatically sync contacts when the plugin is loaded.": string;
                                                                                                                "Client ID and Secret required.": string;
                                                                                                                "Contacts folder": string;
                                                                                                                "e.g. # Notes\n\nWrite something here...": string;
                                                                                                                "e.g. 1440": string;
                                                                                                                "e.g. Contacts": string;
                                                                                                                "e.g. obsidian": string;
                                                                                                                "e.g. p ": string;
                                                                                                                "e.g. s_": string;
                                                                                                                "Enter your client ID": string;
                                                                                                                "Enter your client secret": string;
                                                                                                                "File name prefix": string;
                                                                                                                "Google client ID": string;
                                                                                                                "Google client secret": string;
                                                                                                                "Here is the manual about creating your own client:": string;
                                                                                                                "If not empty, then only contacts with this label will synced": string;
                                                                                                                "Label to sync": string;
                                                                                                                Login: string;
                                                                                                                "Login with Google": string;
                                                                                                                manual: string;
                                                                                                                "Note template": string;
                                                                                                                "Open google's OAuth page in your browser": string;
                                                                                                                "Paste code here": string;
                                                                                                                "Paste the code from Google after login": string;
                                                                                                                "Period in minutes. If 0, then never. 1 day = 1440": string;
                                                                                                                "Please enter your Client ID first.": string;
                                                                                                                "Prefix to add to the beginning of each contact file name": string;
                                                                                                                "Prefix to add to the beginning of each contact property name": string;
                                                                                                                "Property name prefix": string;
                                                                                                                "Sync on startup": string;
                                                                                                                "Template to insert below the metadata block for new contact notes": string;
                                                                                                                "Tokens saved!": string;
                                                                                                                "Vault folder where contact notes will be stored": string;
                                                                                                            } = ...

                                                                                                            Language dictionaries for Russian translations.

                                                                                                            -

                                                                                                            Type declaration

                                                                                                            • Authorization code: string
                                                                                                            • Auto sync period: string
                                                                                                            • Automatically sync contacts when the plugin is loaded.: string
                                                                                                            • Client ID and Secret required.: string
                                                                                                            • Contacts folder: string
                                                                                                            • e.g. # Notes +ru | Documentation
                                                                                                              Documentation
                                                                                                                Preparing search index...

                                                                                                                Variable ruConst

                                                                                                                ru: {
                                                                                                                    "Authorization code": string;
                                                                                                                    "Auto sync period": string;
                                                                                                                    "Automatically sync contacts when the plugin is loaded.": string;
                                                                                                                    "Client ID and secret required.": string;
                                                                                                                    "Contacts folder": string;
                                                                                                                    "e.g. # Notes\n\nWrite something here...": string;
                                                                                                                    "e.g. 1440": string;
                                                                                                                    "e.g. Contacts": string;
                                                                                                                    "e.g. obsidian": string;
                                                                                                                    "e.g. p ": string;
                                                                                                                    "e.g. s_": string;
                                                                                                                    "Enter your client ID": string;
                                                                                                                    "Enter your client secret": string;
                                                                                                                    "Failed to obtain access token. Please re-authenticate.": string;
                                                                                                                    "File name prefix": string;
                                                                                                                    "Google auth": string;
                                                                                                                    "Google client ID": string;
                                                                                                                    "Google client secret": string;
                                                                                                                    "Google contacts synced!": string;
                                                                                                                    "Here is the manual about creating your own client:": string;
                                                                                                                    "If not empty, then only contacts with this label will synced": string;
                                                                                                                    "Label to sync": string;
                                                                                                                    Login: string;
                                                                                                                    "Login with Google": string;
                                                                                                                    manual: string;
                                                                                                                    "Note template": string;
                                                                                                                    "Open Google's auth page in your browser": string;
                                                                                                                    "Paste code here": string;
                                                                                                                    "Paste the code from Google after login": string;
                                                                                                                    "Period in minutes. If 0, then never. 1 day = 1440": string;
                                                                                                                    "Please enter your client ID first.": string;
                                                                                                                    "Prefix to add to the beginning of each contact file name": string;
                                                                                                                    "Prefix to add to the beginning of each contact property name": string;
                                                                                                                    "Property name prefix": string;
                                                                                                                    "Sync on startup": string;
                                                                                                                    "Template to insert below the metadata block for new contact notes": string;
                                                                                                                    "Tokens saved!": string;
                                                                                                                    "Vault folder where contact notes will be stored": string;
                                                                                                                } = ...

                                                                                                                Language dictionaries for Russian translations.

                                                                                                                +

                                                                                                                Type declaration

                                                                                                                • Authorization code: string
                                                                                                                • Auto sync period: string
                                                                                                                • Automatically sync contacts when the plugin is loaded.: string
                                                                                                                • Client ID and secret required.: string
                                                                                                                • Contacts folder: string
                                                                                                                • e.g. # Notes -Write something here...: string
                                                                                                                • e.g. 1440: string
                                                                                                                • e.g. Contacts: string
                                                                                                                • e.g. obsidian: string
                                                                                                                • e.g. p : string
                                                                                                                • e.g. s_: string
                                                                                                                • Enter your client ID: string
                                                                                                                • Enter your client secret: string
                                                                                                                • File name prefix: string
                                                                                                                • Google client ID: string
                                                                                                                • Google client secret: string
                                                                                                                • Here is the manual about creating your own client:: string
                                                                                                                • If not empty, then only contacts with this label will synced: string
                                                                                                                • Label to sync: string
                                                                                                                • Login: string
                                                                                                                • Login with Google: string
                                                                                                                • manual: string
                                                                                                                • Note template: string
                                                                                                                • Open google's OAuth page in your browser: string
                                                                                                                • Paste code here: string
                                                                                                                • Paste the code from Google after login: string
                                                                                                                • Period in minutes. If 0, then never. 1 day = 1440: string
                                                                                                                • Please enter your Client ID first.: string
                                                                                                                • Prefix to add to the beginning of each contact file name: string
                                                                                                                • Prefix to add to the beginning of each contact property name: string
                                                                                                                • Property name prefix: string
                                                                                                                • Sync on startup: string
                                                                                                                • Template to insert below the metadata block for new contact notes: string
                                                                                                                • Tokens saved!: string
                                                                                                                • Vault folder where contact notes will be stored: string
                                                                                                                +Write something here...
                                                                                                                : string
                                                                                                              • e.g. 1440: string
                                                                                                              • e.g. Contacts: string
                                                                                                              • e.g. obsidian: string
                                                                                                              • e.g. p : string
                                                                                                              • e.g. s_: string
                                                                                                              • Enter your client ID: string
                                                                                                              • Enter your client secret: string
                                                                                                              • Failed to obtain access token. Please re-authenticate.: string
                                                                                                              • File name prefix: string
                                                                                                              • Google auth: string
                                                                                                              • Google client ID: string
                                                                                                              • Google client secret: string
                                                                                                              • Google contacts synced!: string
                                                                                                              • Here is the manual about creating your own client:: string
                                                                                                              • If not empty, then only contacts with this label will synced: string
                                                                                                              • Label to sync: string
                                                                                                              • Login: string
                                                                                                              • Login with Google: string
                                                                                                              • manual: string
                                                                                                              • Note template: string
                                                                                                              • Open Google's auth page in your browser: string
                                                                                                              • Paste code here: string
                                                                                                              • Paste the code from Google after login: string
                                                                                                              • Period in minutes. If 0, then never. 1 day = 1440: string
                                                                                                              • Please enter your client ID first.: string
                                                                                                              • Prefix to add to the beginning of each contact file name: string
                                                                                                              • Prefix to add to the beginning of each contact property name: string
                                                                                                              • Property name prefix: string
                                                                                                              • Sync on startup: string
                                                                                                              • Template to insert below the metadata block for new contact notes: string
                                                                                                              • Tokens saved!: string
                                                                                                              • Vault folder where contact notes will be stored: string
                                                                                                              diff --git a/docs/variables/i18n_translator.translator.html b/docs/variables/i18n_translator.translator.html index aaba967..b1dcac6 100644 --- a/docs/variables/i18n_translator.translator.html +++ b/docs/variables/i18n_translator.translator.html @@ -1 +1 @@ -translator | Documentation
                                                                                                              Documentation
                                                                                                                Preparing search index...

                                                                                                                Variable translatorConst

                                                                                                                translator: Translator = ...
                                                                                                                +translator | Documentation
                                                                                                                Documentation
                                                                                                                  Preparing search index...

                                                                                                                  Variable translatorConst

                                                                                                                  translator: Translator = ...
                                                                                                                  diff --git a/manifest.json b/manifest.json index 115954f..c45720c 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,10 @@ { "id": "google-contacts", "name": "Google Contacts", - "version": "0.1.10", - "minAppVersion": "0.12.0", - "description": "Synchronize your Google Contacts with separate contact-notes", + "version": "0.1.11", + "minAppVersion": "1.8.0", + "description": "Synchronize your Google contacts with separate contact-notes", "author": "aleksejs1", "authorUrl": "kovalovs.lv", - "main": "main.js", "isDesktopOnly": true } diff --git a/package-lock.json b/package-lock.json index 6159749..daec3d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "google-contacts", - "version": "0.1.10", + "version": "0.1.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "google-contacts", - "version": "0.1.10", + "version": "0.1.11", "license": "ISC", "dependencies": { "ts-node": "^10.9.2", @@ -61,9 +61,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.1.tgz", - "integrity": "sha512-Q+E+rd/yBzNQhXkG+zQnF58e4zoZfBedaxwzPmicKsiK3nt8iJYrSrDbjwFFDGC4f+rPafqRaPH6TsDoSvMf7A==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", + "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -125,12 +125,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.1.tgz", - "integrity": "sha512-2YaDd/Rd9E598B5+WIc8wJPmWETiiJXFYVE60oX8FDohv7rAUU3CQj+A1MgeEmcsk2+dQuEjIe/GDvig0SqL4g==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.27.1", + "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -229,9 +229,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.1.tgz", - "integrity": "sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "dev": true, "dependencies": { "@babel/types": "^7.27.1" @@ -466,13 +466,13 @@ } }, "node_modules/@babel/template": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.1.tgz", - "integrity": "sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.1", + "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" }, "engines": { @@ -536,9 +536,9 @@ } }, "node_modules/@codemirror/view": { - "version": "6.36.6", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.6.tgz", - "integrity": "sha512-uxugGLet+Nzp0Jcit8Hn3LypM8ioMLKTsdf8FRoT3HWvZtb9GhaWMe0Cc15rz90Ljab4YFJiAulmIVB74OY0IQ==", + "version": "6.36.8", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.8.tgz", + "integrity": "sha512-yoRo4f+FdnD01fFt4XpfpMCcCAo9QvZOtbrXExn4SqzH32YC6LgzqxfLZw/r6Ge65xyY03mK/UfUqrVw1gFiFg==", "dev": true, "peer": true, "dependencies": { @@ -568,9 +568,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", - "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -631,9 +631,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz", - "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", + "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -684,6 +684,15 @@ "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -697,9 +706,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.25.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.1.tgz", - "integrity": "sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==", + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.26.0.tgz", + "integrity": "sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -728,15 +737,15 @@ } }, "node_modules/@gerrit0/mini-shiki": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.3.0.tgz", - "integrity": "sha512-frvArO0+s5Viq68uSod5SieLPVM2cLpXoQ1e07lURwgADXpL/MOypM7jPz9otks0g2DIe2YedDAeVrDyYJZRxA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.4.0.tgz", + "integrity": "sha512-48lKoQegmfJ0iyR/jRz5OrYOSM3WewG9YWCPqUvYFEC54shQO8RsAaspaK/2PRHVVnjekRqfAFvq8pwCpIo5ig==", "dev": true, "dependencies": { - "@shikijs/engine-oniguruma": "^3.3.0", - "@shikijs/langs": "^3.3.0", - "@shikijs/themes": "^3.3.0", - "@shikijs/types": "^3.3.0", + "@shikijs/engine-oniguruma": "^3.4.0", + "@shikijs/langs": "^3.4.0", + "@shikijs/themes": "^3.4.0", + "@shikijs/types": "^3.4.0", "@shikijs/vscode-textmate": "^10.0.2" } }, @@ -789,9 +798,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", - "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "engines": { "node": ">=18.18" @@ -1240,6 +1249,27 @@ "dev": true, "peer": true }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.2.tgz", + "integrity": "sha512-H9vwztj5OAqHg9GockCQC06k1natgcxWQSRpQcPJf6i5+MWBzfKkRtxGbjQf0X2ihii0ffLZCRGbYV2f2bjNCQ==", + "dev": true, + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1348,9 +1378,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz", - "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", + "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==", "cpu": [ "arm" ], @@ -1361,9 +1391,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz", - "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz", + "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==", "cpu": [ "arm64" ], @@ -1374,9 +1404,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz", - "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz", + "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==", "cpu": [ "arm64" ], @@ -1387,9 +1417,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz", - "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", + "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", "cpu": [ "x64" ], @@ -1400,9 +1430,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz", - "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz", + "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==", "cpu": [ "arm64" ], @@ -1413,9 +1443,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz", - "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz", + "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==", "cpu": [ "x64" ], @@ -1426,9 +1456,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz", - "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz", + "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==", "cpu": [ "arm" ], @@ -1439,9 +1469,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz", - "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz", + "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==", "cpu": [ "arm" ], @@ -1452,9 +1482,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz", - "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", + "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", "cpu": [ "arm64" ], @@ -1465,9 +1495,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz", - "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", + "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", "cpu": [ "arm64" ], @@ -1478,9 +1508,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz", - "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz", + "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==", "cpu": [ "loong64" ], @@ -1491,9 +1521,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz", - "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz", + "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==", "cpu": [ "ppc64" ], @@ -1504,9 +1534,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz", - "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz", + "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==", "cpu": [ "riscv64" ], @@ -1517,9 +1547,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz", - "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz", + "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==", "cpu": [ "riscv64" ], @@ -1530,9 +1560,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz", - "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz", + "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==", "cpu": [ "s390x" ], @@ -1543,9 +1573,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz", - "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", + "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", "cpu": [ "x64" ], @@ -1556,9 +1586,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz", - "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", + "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", "cpu": [ "x64" ], @@ -1569,9 +1599,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz", - "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz", + "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==", "cpu": [ "arm64" ], @@ -1582,9 +1612,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz", - "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz", + "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==", "cpu": [ "ia32" ], @@ -1595,9 +1625,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz", - "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", + "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", "cpu": [ "x64" ], @@ -1608,37 +1638,37 @@ ] }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.3.0.tgz", - "integrity": "sha512-l0vIw+GxeNU7uGnsu6B+Crpeqf+WTQ2Va71cHb5ZYWEVEPdfYwY5kXwYqRJwHrxz9WH+pjSpXQz+TJgAsrkA5A==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.4.0.tgz", + "integrity": "sha512-zwcWlZ4OQuJ/+1t32ClTtyTU1AiDkK1lhtviRWoq/hFqPjCNyLj22bIg9rB7BfoZKOEOfrsGz7No33BPCf+WlQ==", "dev": true, "dependencies": { - "@shikijs/types": "3.3.0", + "@shikijs/types": "3.4.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.3.0.tgz", - "integrity": "sha512-zt6Kf/7XpBQKSI9eqku+arLkAcDQ3NHJO6zFjiChI8w0Oz6Jjjay7pToottjQGjSDCFk++R85643WbyINcuL+g==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.4.0.tgz", + "integrity": "sha512-bQkR+8LllaM2duU9BBRQU0GqFTx7TuF5kKlw/7uiGKoK140n1xlLAwCgXwSxAjJ7Htk9tXTFwnnsJTCU5nDPXQ==", "dev": true, "dependencies": { - "@shikijs/types": "3.3.0" + "@shikijs/types": "3.4.0" } }, "node_modules/@shikijs/themes": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.3.0.tgz", - "integrity": "sha512-tXeCvLXBnqq34B0YZUEaAD1lD4lmN6TOHAhnHacj4Owh7Ptb/rf5XCDeROZt2rEOk5yuka3OOW2zLqClV7/SOg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.4.0.tgz", + "integrity": "sha512-YPP4PKNFcFGLxItpbU0ZW1Osyuk8AyZ24YEFaq04CFsuCbcqydMvMUTi40V2dkc0qs1U2uZFrnU6s5zI6IH+uA==", "dev": true, "dependencies": { - "@shikijs/types": "3.3.0" + "@shikijs/types": "3.4.0" } }, "node_modules/@shikijs/types": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.3.0.tgz", - "integrity": "sha512-KPCGnHG6k06QG/2pnYGbFtFvpVJmC3uIpXrAiPrawETifujPBv0Se2oUxm5qYgjCvGJS9InKvjytOdN+bGuX+Q==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.4.0.tgz", + "integrity": "sha512-EUT/0lGiE//7j5N/yTMNMT3eCWNcHJLrRKxT0NDXWIfdfSmFJKfPX7nMmRBrQnWboAzIsUziCThrYMMhjbMS1A==", "dev": true, "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -1810,9 +1840,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", - "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", + "version": "22.15.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.17.tgz", + "integrity": "sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==", "dependencies": { "undici-types": "~6.21.0" } @@ -1860,20 +1890,20 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz", - "integrity": "sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", + "integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.31.1", - "@typescript-eslint/type-utils": "8.31.1", - "@typescript-eslint/utils": "8.31.1", - "@typescript-eslint/visitor-keys": "8.31.1", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/type-utils": "8.32.1", + "@typescript-eslint/utils": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1889,15 +1919,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.1.tgz", - "integrity": "sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", + "integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.31.1", - "@typescript-eslint/types": "8.31.1", - "@typescript-eslint/typescript-estree": "8.31.1", - "@typescript-eslint/visitor-keys": "8.31.1", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4" }, "engines": { @@ -1913,13 +1943,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz", - "integrity": "sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", + "integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.31.1", - "@typescript-eslint/visitor-keys": "8.31.1" + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1930,15 +1960,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz", - "integrity": "sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", + "integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "8.31.1", - "@typescript-eslint/utils": "8.31.1", + "@typescript-eslint/typescript-estree": "8.32.1", + "@typescript-eslint/utils": "8.32.1", "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1953,9 +1983,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.1.tgz", - "integrity": "sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", + "integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1966,19 +1996,19 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz", - "integrity": "sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", + "integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.31.1", - "@typescript-eslint/visitor-keys": "8.31.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/visitor-keys": "8.32.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1992,15 +2022,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.1.tgz", - "integrity": "sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", + "integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.31.1", - "@typescript-eslint/types": "8.31.1", - "@typescript-eslint/typescript-estree": "8.31.1" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.32.1", + "@typescript-eslint/types": "8.32.1", + "@typescript-eslint/typescript-estree": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2015,12 +2045,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz", - "integrity": "sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", + "integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "8.31.1", + "@typescript-eslint/types": "8.32.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -2043,6 +2073,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", @@ -2296,6 +2339,26 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dev": true, + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -2318,9 +2381,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", "dev": true, "funding": [ { @@ -2337,10 +2400,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -2376,6 +2439,44 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2395,9 +2496,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001716", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001716.tgz", - "integrity": "sha512-49/c1+x3Kwz7ZIWt+4DvK3aMJy9oYXXG6/97JKsnjdCk/6n9vVyWL8NAwVt95Lwt9eigI10Hl782kDfZUUlRXw==", + "version": "1.0.30001718", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", + "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", "dev": true, "funding": [ { @@ -2606,12 +2707,64 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -2653,9 +2806,9 @@ } }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "dependencies": { "ms": "^2.1.3" @@ -2670,9 +2823,9 @@ } }, "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -2698,6 +2851,15 @@ "node": ">=0.10.0" } }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -2724,6 +2886,26 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -2740,9 +2922,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.148", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.148.tgz", - "integrity": "sha512-8uc1QXwwqayD4mblcsQYZqoi+cOc97A2XmKSBOIRbEAvbp6vrqmSYs4dHD2qVygUgn7Mi0qdKgPaJ9WC8cv63A==", + "version": "1.5.152", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.152.tgz", + "integrity": "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==", "dev": true }, "node_modules/emittery": { @@ -2763,6 +2945,15 @@ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -2796,6 +2987,36 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2805,6 +3026,12 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2818,9 +3045,9 @@ } }, "node_modules/eslint": { - "version": "9.25.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.1.tgz", - "integrity": "sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==", + "version": "9.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.26.0.tgz", + "integrity": "sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -2829,11 +3056,12 @@ "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.13.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.25.1", + "@eslint/js": "9.26.0", "@eslint/plugin-kit": "^0.2.8", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", + "@modelcontextprotocol/sdk": "^1.8.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -2857,7 +3085,8 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3" + "optionator": "^0.9.3", + "zod": "^3.24.2" }, "bin": { "eslint": "bin/eslint.js" @@ -2878,13 +3107,16 @@ } }, "node_modules/eslint-config-prettier": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz", - "integrity": "sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", + "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, "peerDependencies": { "eslint": ">=7.0.0" } @@ -2939,6 +3171,15 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3041,12 +3282,42 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "dev": true, + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", + "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", + "dev": true, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3095,6 +3366,63 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dev": true, + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": "^4.11 || 5 || ^5.0.0-beta.1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3204,6 +3532,23 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dev": true, + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3239,6 +3584,24 @@ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3298,6 +3661,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -3307,6 +3694,19 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -3386,6 +3786,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -3407,6 +3819,18 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -3425,6 +3849,22 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3449,10 +3889,22 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", + "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", "dev": true, "engines": { "node": ">= 4" @@ -3519,6 +3971,15 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -3597,6 +4058,12 @@ "node": ">=0.12.0" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4422,9 +4889,9 @@ } }, "node_modules/lint-staged": { - "version": "15.5.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.1.tgz", - "integrity": "sha512-6m7u8mue4Xn6wK6gZvSCQwBvMBR36xfY24nF5bMTf2MHDYG6S3yhJuOgdYVw99hsjyDt2d4z168b3naI8+NWtQ==", + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", "dev": true, "dependencies": { "chalk": "^5.4.1", @@ -4595,9 +5062,9 @@ } }, "node_modules/listr2": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.2.tgz", - "integrity": "sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", "dev": true, "dependencies": { "cli-truncate": "^4.0.0", @@ -4803,12 +5270,42 @@ "markdown-it": "bin/markdown-it.mjs" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/mdurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -4849,6 +5346,27 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -4906,6 +5424,15 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -4939,6 +5466,27 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/obsidian": { "version": "1.8.7", "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.8.7.tgz", @@ -4953,6 +5501,18 @@ "@codemirror/view": "^6.0.0" } }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5063,6 +5623,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5096,6 +5665,15 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5135,6 +5713,15 @@ "node": ">= 6" } }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "dev": true, + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -5262,6 +5849,19 @@ "node": ">= 6" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -5296,6 +5896,21 @@ } ] }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5316,6 +5931,30 @@ } ] }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -5450,9 +6089,9 @@ "dev": true }, "node_modules/rollup": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", - "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz", + "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==", "dev": true, "dependencies": { "@types/estree": "1.0.7" @@ -5465,29 +6104,45 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.40.1", - "@rollup/rollup-android-arm64": "4.40.1", - "@rollup/rollup-darwin-arm64": "4.40.1", - "@rollup/rollup-darwin-x64": "4.40.1", - "@rollup/rollup-freebsd-arm64": "4.40.1", - "@rollup/rollup-freebsd-x64": "4.40.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.40.1", - "@rollup/rollup-linux-arm-musleabihf": "4.40.1", - "@rollup/rollup-linux-arm64-gnu": "4.40.1", - "@rollup/rollup-linux-arm64-musl": "4.40.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.40.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1", - "@rollup/rollup-linux-riscv64-gnu": "4.40.1", - "@rollup/rollup-linux-riscv64-musl": "4.40.1", - "@rollup/rollup-linux-s390x-gnu": "4.40.1", - "@rollup/rollup-linux-x64-gnu": "4.40.1", - "@rollup/rollup-linux-x64-musl": "4.40.1", - "@rollup/rollup-win32-arm64-msvc": "4.40.1", - "@rollup/rollup-win32-ia32-msvc": "4.40.1", - "@rollup/rollup-win32-x64-msvc": "4.40.1", + "@rollup/rollup-android-arm-eabi": "4.40.2", + "@rollup/rollup-android-arm64": "4.40.2", + "@rollup/rollup-darwin-arm64": "4.40.2", + "@rollup/rollup-darwin-x64": "4.40.2", + "@rollup/rollup-freebsd-arm64": "4.40.2", + "@rollup/rollup-freebsd-x64": "4.40.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.2", + "@rollup/rollup-linux-arm-musleabihf": "4.40.2", + "@rollup/rollup-linux-arm64-gnu": "4.40.2", + "@rollup/rollup-linux-arm64-musl": "4.40.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-musl": "4.40.2", + "@rollup/rollup-linux-s390x-gnu": "4.40.2", + "@rollup/rollup-linux-x64-gnu": "4.40.2", + "@rollup/rollup-linux-x64-musl": "4.40.2", + "@rollup/rollup-win32-arm64-msvc": "4.40.2", + "@rollup/rollup-win32-ia32-msvc": "4.40.2", + "@rollup/rollup-win32-x64-msvc": "4.40.2", "fsevents": "~2.3.2" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5511,10 +6166,36 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "bin": { "semver": "bin/semver.js" @@ -5523,6 +6204,49 @@ "node": ">=10" } }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dev": true, + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5544,6 +6268,78 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -5639,6 +6435,15 @@ "node": ">=8" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -5832,6 +6637,15 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -5894,9 +6708,9 @@ } }, "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.40.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.1.tgz", - "integrity": "sha512-9YvLNnORDpI+vghLU/Nf+zSv0kL47KbVJ1o3sKgoTefl6i+zebxbiDQWoe/oWWqPhIgQdRZRT1KA9sCPL810SA==", + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "engines": { "node": ">=16" @@ -5985,10 +6799,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typedoc": { - "version": "0.28.3", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.3.tgz", - "integrity": "sha512-5svOCTfXvVSh6zbZKSQluZhR8yN2tKpTeHZxlmWpE6N5vc3R8k/jhg9nnD6n5tN9/ObuQTojkONrOxFdUFUG9w==", + "version": "0.28.4", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.4.tgz", + "integrity": "sha512-xKvKpIywE1rnqqLgjkoq0F3wOqYaKO9nV6YkkSat6IxOWacUCc/7Es0hR3OPmkIqkPoEn7U3x+sYdG72rstZQA==", "dev": true, "dependencies": { "@gerrit0/mini-shiki": "^3.2.2", @@ -6021,14 +6849,14 @@ } }, "node_modules/typescript-eslint": { - "version": "8.31.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.1.tgz", - "integrity": "sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA==", + "version": "8.32.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz", + "integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "8.31.1", - "@typescript-eslint/parser": "8.31.1", - "@typescript-eslint/utils": "8.31.1" + "@typescript-eslint/eslint-plugin": "8.32.1", + "@typescript-eslint/parser": "8.32.1", + "@typescript-eslint/utils": "8.32.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6053,6 +6881,15 @@ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -6111,6 +6948,15 @@ "node": ">=10.12.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", @@ -6328,6 +7174,24 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.24.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", + "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.5", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", + "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", + "dev": true, + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/package.json b/package.json index 00ab8e7..e2ce66c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "google-contacts", - "version": "0.1.10", + "version": "0.1.11", "description": "", "main": "rollup.config.js", "type": "module", diff --git a/resources/obsidian_contact_sync_plugin_note.png b/resources/obsidian_contact_sync_plugin_note.png index 69ad27634756fd3c4cfe2ebd60b35b12cffa741d..a2402b2dd507156e18c24558e15a394d5cb5bad4 100644 GIT binary patch literal 33470 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

                                                                                                                  qV}6GQbkoA;jxG^O`_ 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

                                                                                                                  z)=qxDg|1h$SVlp<**GsESIE19l(5elBj7}$(!N>^dI_BslAfW z1yRn2L;HJ1-5}oB@#$I<-m94 z8Y0eVj?mw4D82x8|1K8-A0_HJO8SG?@F6;XG_{KndV?8uZ=b|-y|1arO$NIzU1)x&dPv+mE7lUrcTD=`pJ$Y#hoonLzz;SWBW(Tk_nz(WrsdH@ql zdsw!9F`eIUsw<7mEZ)W4F0D{Thx+x$Jg9R39N)cJOm38NC zFMEE9xR`b20(}K0TuSiK)5AW^=*hI3eAZ?YCvnbbF9!}g`?a-LfQ*>ut-aubWDKuTLH`goOOHP@HFWzIBwm>d4xZjGc?&E{m$EhRp|6zT{} zTlz76yGXlgPV>(YQbpB(2e_)s=K-7(@*639@#`L?VelO>j6&w>fzo^2lA79q!9At& zc;9q+NN*kX&E)J7`oz~)gf3`p>4Y6xUiOxh<&87h2g?ec|Lx)^6F<6E*{Oa3u^D|-d0RaL^KAdU}9|#b4foRRgBw5tZHHT zYxS1v#x;6IBz7$l1&j9fUS9`oQ+X#nQw_)xWaIn0cd3J1rP;mcUCi7Te8FLR`9$!! z3nz6KZ41e2O)sTTZ1MzmIC_Gu!!I?#sYcKWa zZ3P+4ycOA_Z+M^H)oyy)(|fyj#*e>c6q1ej%LZ=F4}X(ql#;__4JxEsus!G_svujg z=dr#OpK>0u7P*{>_T3(eBFNeO=lQLn`{fNDHZxyDGBLkz_del?7!5~eEj;I#N%im zx6T5(YHkX1u)Mzk5TiLA%(zOX#PW7U{B`f8s20h| zcT63{h%in9rww`m%Ar^}9Ys)h6%HvQ_rj)D#KQ2RE9+}&3U0w!m@@GNPY%$m;Ez{z z2;J(L>~h_d6w#~3!^_HY-Fj!;I*h8ODpqHJn{(Tb0C;^;v)ptxpRVIhEKL}!G-cgv zKb^*`-QWTOJX@K>poK~h5wWl?IM*XTW&#P_RerfH@jgo01**SYpTk66(^m-DlbV!@ zZ%*32eNV1*$Jcbvp0=_W8mf(abispj$ob93> z7w?8QexLTyb_C0-3B;r>OUJ$lf6Bh$^f69Lww#zAIg!b14kE84?_g2&vy}z9Be5T? z0)xaMAA#9u9`5f1m3F_1A{J*&2$9?f$Jx855du`pm{)1nO7W@7T@u!|YB}zRnv~DW z{-~ILIE&7~7dPH?c~>VLhObJ-eT{^}Ag%{SVl50x29jJT??d^WceVNw-C(<#^oOkHW{|Ti;1EALs!PUI`%WCl zkR_?$Crf*{i1}EC;*I{Xw2FKHF5RIxzs{l(xJDm2B5XuKpI~hIor8vimc6(-jpJOa zZ0K=p8n;O)W4;c17&!A(&KE9aCWaJJz?H^jq9M(~WxL3j*(fDkrCUY~G+-dD2H02$ zx4m_-@Sfz>mtRt-|?B;Fc{cDm= zt1Mq^e?UX@161`SnBeR@xO?I7dYRgzeoM|q^;w+Dk>m$0AN7E6E?1?aO=U1}G^dW= zpl%ep89^oUalhs1?-q=VbBQ@F9uRiQM)dSIBH-Z!*nk(|<&G?G{|JA4#RUF?nQrz3 z$z`kGJV7Sqx1$cYj^9y$aGl)wg*9mfBBy6~@nfS7`yXWxo}CwIy#4wS7!|vjq~mB- zl^g7MJ0M!?mcQOm=F+$S46$H^EBe!{%qBWiC-sBDSU>Ns^IUpHRu_$NV;R{&8XWd( z2bj`yXm=a?;}Zu!NpHTr9-^GY|5^orwPsECum{ zll4zxEO4rqfE~a`@I2hLOuB5;#M=7THF4PY7`cZ2%)0||G0@_uGNAiyMSoHTFe$4* z!|!4j$LD~Ub`z6sFutP?83tTEYO9E>Pr#r8xlRO>GhC(kavzB|*wdWpc(Gcw^W zF|r0}Kmw>i(g2C_QQ(5|{|n>?8~CyA;j;-wWo0&e6_oiq6DmN9$q`XrUjNenunPM%0Q+Sbx4*g=ie_GW#% z3ajt`Z+~|D?a!rkbtCY|spol4ofcPxJ5825CR}BqS<(w*<`vVpw-3F5jgDo%Gy8E< zN7ZiXFhL2zTB)O_$u8<3vv8dz%V9Pfx^gKvA;!^ehB^!&E6t(~M@k(SVUI=^d#Hmw zoHI8Uk6`pE;r%p@140W(HbDB&?YDgfZj^toQM=zWdL*H9YgA@;5>hQ7)qi0$n zQL9e;!+NP>6FZH@k8@zq-9rh@j>hwri;Ja=?wIQ4BzI{SsM9%gB43Y@9E_Adb@X*N zO3{f=D;4*GP^T57A$D@zVNLl@osOh#)=YdOVrJbBi!d#&3UqTGx*MxA=Ss%HS2Ds>E7V3DB? zjO6y&LmeUjp$@up9eF!2q|~7^SRxi?X+v$OWj2dC&^M?~5QPR*F_++UpX{ZM+{d$q zbLTF`i7vby&!P^{hQN)EpV&JLG9njZ0F%vW-&OZk7nESHUPcjvYDg-f>RJ?DtgYtn zLCc>z3;jKlFpaG3$!aN`H+0}lUKn(c3Cyl|uDSwY5c1@LQoMEk$+BeBk9V}^2j3;{ z&0tAhj>Xn4DCH{AMz1XF>00(h30ux_#mZyzpVFR=DlMRn!4B`R{!`~~`d_^&2X}5m zuH+*MhuVR0zVo`KC(WCR}rpp$t;f;V? z#fo&&yI9_sXRves{(tIpEPvSlU|PPou+(8X^t*&fPccaO=&pd4Wmw+S;a(+PqJHEL zW`j=wCpafR>_uijPdj@)Pv|HE$PUqBP<{REo@lz7!+mCExq;>@yFjgS8ndKm>74aiwQyu0#JSb@tHt2stiqowz-xMdRRe4zN)_d1KR)nTDNKWZ22 z%4%V5-{we|P;QoiASwy_wU)ao%Pm|;8ew{iwY|!gC!uAgJ z6iuQeJ-T6CEu#)DC{ZyHfm z1jpPNeyEYA4O_)JS5-yI)IqmXr_S4fQ3o>Wm{zY<@0hc3a-QxzM6Ah%zY^ixyeRz} z5%nAB$64?2&ZxsO>X>`b%X?bN74GU}L&I{)pIvC0!c5XTjf zeF3X^g!3W76*FMKW*D*AMn&P+MLxlkT_$ZpnluRt3WAN0uh1$F=zlLUXl3>t;tNBJ1365o@s{kE|-H0|_fDNDU%5O*#xi4RBNrA_#DNXleSw5s4LW-3>oR?-<3BrHjCEU z7Gu}-sUN!a=5RP{Hk*Sp;yx8ZwQ#>!tyT*zi^XEOT;lw5S}nKR@bw?8wvA=?`CriX z(-sTw_r1jIKBD>}o;LLvCHO z=Hdm5nPs(K>wevpU9P1ZO0imKz!>_z>*#o7Ze^{2I94?if$2zTl8}4*!X$G$*Wf)!MK{C@;gCif+ie#p6Aoo=;hog_tVKGIJ#HG>X&bC-t3V# zqSh*w0uOj#l$1~60sTH@BKIKPI01z@ALw+#daCvM5>ruefJFEqkM1UwFR!G`CM*}) z6k}kba&!+dBCGMr^)s7@*fSE*fzgSmh=pn6!x~dXeq*@p@h?o2Xxdc__Y3a9JwQ{o R!B_wQ002ovPDHLkV1m{eVzK}L diff --git a/resources/obsidian_contact_sync_plugin_settings.png b/resources/obsidian_contact_sync_plugin_settings.png index 9fbd876fbaa8c4ec4ba39143cb39bac86479ba6e..b7e17ef023624282474abcd3eee484bf9545a00a 100644 GIT binary patch literal 44669 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

                                                                                                                • 15{7u?jT@I@}F0O(RS21|3Cl#f1~mL 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 Din*|F literal 42993 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 = new Map(); + setFileCache(file: TFile, cache: unknown) { + this.fileCacheMap.set(file.path, cache); + } + getFileCache(file: TFile): unknown { + return this.fileCacheMap.get(file.path); + } + getFirstLinkpathDest() { + return null; // Mock implementation + } + getCache() { + return {}; // Mock implementation + } + fileToLinktext() { + return ''; // Mock implementation + } + resolvedLinks = {}; + unresolvedLinks = {}; + on() {} + off() {} + offref() {} + trigger() {} + tryTrigger() {} +} diff --git a/src/__tests__/core/ContactNoteWriter.test.ts b/src/__tests__/core/ContactNoteWriter.test.ts index 3b922ac..43715e1 100644 --- a/src/__tests__/core/ContactNoteWriter.test.ts +++ b/src/__tests__/core/ContactNoteWriter.test.ts @@ -1,6 +1,8 @@ +import { MockMetadataCache } from 'src/__mocks__/obsidian'; import { ContactNoteWriter } from '../../core/ContactNoteWriter'; -import { Vault, TFile, FileStats } from 'obsidian'; +import { Vault, TFile, FileStats, MetadataCache, FileManager } from 'obsidian'; import { GoogleContact } from 'src/types/Contact'; +import { ContactNoteConfig } from 'src/types/ContactNoteConfig'; import { getAllMarkdownFilesInFolder } from 'src/utils/getAllMarkdownFilesInFolder'; jest.mock('obsidian', () => { @@ -25,6 +27,7 @@ jest.mock('obsidian', () => { read: jest.fn(), process: jest.fn(), getFileByPath: jest.fn(), + getFolderByPath: jest.fn(), })), TFolder: class MockTFolder { static [Symbol.hasInstance](instance: unknown) { @@ -54,10 +57,25 @@ jest.mock('src/utils/getAllMarkdownFilesInFolder', () => ({ describe('ContactNoteWriter', () => { let contactNoteWriter: ContactNoteWriter; let vault: Vault; + let metadataCache: MetadataCache; + let fileManager: FileManager; beforeEach(() => { vault = new Vault() as unknown as Vault; - contactNoteWriter = new ContactNoteWriter(vault); + metadataCache = new MockMetadataCache() as unknown as MetadataCache; + metadataCache.getFileCache = jest.fn(); + fileManager = { + create: jest.fn(), + createFolder: jest.fn().mockResolvedValue(undefined), + getAbstractFileByPath: jest.fn(), + getFileByPath: jest.fn(), + processFrontMatter: jest.fn(), + } as unknown as FileManager; + contactNoteWriter = new ContactNoteWriter( + vault, + metadataCache, + fileManager + ); }); describe('writeNotesForContacts', () => { @@ -74,24 +92,28 @@ describe('ContactNoteWriter', () => { const mockFolder = { path: 'path/to/folder', __isMockTFolder: true }; - (vault.getAbstractFileByPath as jest.Mock).mockReturnValue(mockFolder); + (vault.getFolderByPath as jest.Mock).mockReturnValue(mockFolder); (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([]); (vault.create as jest.Mock).mockResolvedValue(undefined); (vault.getFileByPath as jest.Mock).mockResolvedValue(null); + const config: ContactNoteConfig = { + prefix: 'prefix-', + propertyPrefix: 'propertyPrefix-', + syncLabel: '', + folderPath: 'path/to/folder', + noteBody: mockNoteBody, + }; + await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - '', + config, mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody + mockContacts ); expect(vault.create).toHaveBeenCalledWith( 'path/to/folder/prefix-Alice Smith.md', - expect.stringContaining('---') + expect.stringContaining(mockNoteBody) ); }); @@ -115,24 +137,28 @@ describe('ContactNoteWriter', () => { const mockNoteBody = 'This is a note body'; const mockFolder = { path: 'path/to/folder', __isMockTFolder: true }; - (vault.getAbstractFileByPath as jest.Mock).mockReturnValue(mockFolder); + (vault.getFolderByPath as jest.Mock).mockReturnValue(mockFolder); (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([]); (vault.create as jest.Mock).mockResolvedValue(undefined); (vault.getFileByPath as jest.Mock).mockResolvedValue(null); + const config: ContactNoteConfig = { + prefix: 'prefix-', + propertyPrefix: 'propertyPrefix-', + syncLabel: 'family', + folderPath: 'path/to/folder', + noteBody: mockNoteBody, + }; + await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - 'family', + config, mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody + mockContacts ); expect(vault.create).toHaveBeenCalledWith( 'path/to/folder/prefix-Alice Smith.md', - expect.stringContaining('---') + expect.stringContaining(mockNoteBody) ); }); @@ -155,24 +181,28 @@ describe('ContactNoteWriter', () => { const mockNoteBody = 'This is a note body'; const mockFolder = { path: 'path/to/folder', __isMockTFolder: true }; - (vault.getAbstractFileByPath as jest.Mock).mockReturnValue(mockFolder); + (vault.getFolderByPath as jest.Mock).mockReturnValue(mockFolder); (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([]); (vault.create as jest.Mock).mockResolvedValue(undefined); (vault.getFileByPath as jest.Mock).mockResolvedValue(null); + const config: ContactNoteConfig = { + prefix: 'prefix-', + propertyPrefix: 'propertyPrefix-', + syncLabel: 'family', + folderPath: 'path/to/folder', + noteBody: mockNoteBody, + }; + await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - 'family', + config, mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody + mockContacts ); expect(vault.create).toHaveBeenCalledWith( 'path/to/folder/prefix-123.md', - expect.stringContaining('---') + expect.stringContaining(mockNoteBody) ); }); @@ -189,19 +219,23 @@ describe('ContactNoteWriter', () => { const mockFolder = { path: 'path/to/folder', __isMockTFolder: true }; // Mock methods - (vault.getAbstractFileByPath as jest.Mock).mockReturnValue(mockFolder); + (vault.getFolderByPath as jest.Mock).mockReturnValue(mockFolder); (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([]); (vault.create as jest.Mock).mockResolvedValue(undefined); (vault.getFileByPath as jest.Mock).mockResolvedValue(null); + const config: ContactNoteConfig = { + prefix: 'prefix-', + propertyPrefix: 'propertyPrefix-', + syncLabel: '', + folderPath: 'path/to/folder', + noteBody: mockNoteBody, + }; + await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - '', + config, mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody + mockContacts ); expect(vault.create).not.toHaveBeenCalled(); @@ -221,51 +255,23 @@ describe('ContactNoteWriter', () => { const mockFolder = { path: 'path/to/folder', __isMockTFolder: true }; // Mock methods - (vault.getAbstractFileByPath as jest.Mock).mockReturnValue(mockFolder); + (vault.getFolderByPath as jest.Mock).mockReturnValue(mockFolder); (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([]); (vault.create as jest.Mock).mockResolvedValue(undefined); (vault.getFileByPath as jest.Mock).mockResolvedValue(null); - await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - 'work', // Not matching syncLabel - mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody - ); - - expect(vault.create).not.toHaveBeenCalled(); - }); - - it('should not create or update notes in case of wrong folder', async () => { - const mockContacts: GoogleContact[] = [ - { - resourceName: 'people/123', - names: [{ displayName: 'Alice Smith' }], - emailAddresses: [{ value: 'alice@example.com' }], - }, - ]; - const mockLabelMap = { family: 'group1' }; - const mockNoteBody = 'This is a note body'; - - const mockFolder = {}; - - // Mock methods - (vault.getAbstractFileByPath as jest.Mock).mockReturnValue(mockFolder); - (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([]); - (vault.create as jest.Mock).mockResolvedValue(undefined); - (vault.getFileByPath as jest.Mock).mockResolvedValue(null); + const config: ContactNoteConfig = { + prefix: 'prefix-', + propertyPrefix: 'propertyPrefix-', + syncLabel: 'work', // Not matching syncLabel + folderPath: 'path/to/folder', + noteBody: mockNoteBody, + }; await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - '', + config, mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody + mockContacts ); expect(vault.create).not.toHaveBeenCalled(); @@ -290,6 +296,11 @@ describe('ContactNoteWriter', () => { // Mock methods (vault.read as jest.Mock).mockResolvedValue(mockFrontmatter); + (metadataCache.getFileCache as jest.Mock).mockReturnValue({ + frontmatter: { + 'propertyPrefix-id': '123', + }, + }); const result = await contactNoteWriter['scanFiles']( mockFiles, diff --git a/src/__tests__/core/ContactNoteWriterProcess.test.ts b/src/__tests__/core/ContactNoteWriterProcess.test.ts index ec4b183..acd8819 100644 --- a/src/__tests__/core/ContactNoteWriterProcess.test.ts +++ b/src/__tests__/core/ContactNoteWriterProcess.test.ts @@ -1,6 +1,8 @@ +import { MockMetadataCache } from 'src/__mocks__/obsidian'; import { ContactNoteWriter } from '../../core/ContactNoteWriter'; -import { Vault } from 'obsidian'; +import { FileManager, MetadataCache, Vault } from 'obsidian'; import { GoogleContact } from 'src/types/Contact'; +import { ContactNoteConfig } from 'src/types/ContactNoteConfig'; import { getAllMarkdownFilesInFolder } from 'src/utils/getAllMarkdownFilesInFolder'; jest.mock('obsidian', () => { @@ -25,6 +27,7 @@ jest.mock('obsidian', () => { read: jest.fn(), process: jest.fn(), getFileByPath: jest.fn(), + getFolderByPath: jest.fn(), })), TFolder: class MockTFolder { static [Symbol.hasInstance](instance: unknown) { @@ -54,10 +57,26 @@ jest.mock('src/utils/getAllMarkdownFilesInFolder', () => ({ describe('ContactNoteWriterUpdate', () => { let contactNoteWriter: ContactNoteWriter; let vault: Vault; + let metadataCache: MetadataCache; + let fileManager: FileManager; beforeEach(() => { vault = new Vault() as unknown as Vault; - contactNoteWriter = new ContactNoteWriter(vault); + // metadataCache = new MetadataCache(); + metadataCache = new MockMetadataCache() as unknown as MetadataCache; + fileManager = { + create: jest.fn(), + createFolder: jest.fn(), + getAbstractFileByPath: jest.fn(), + getFileByPath: jest.fn(), + process: jest.fn(), + processFrontMatter: jest.fn(), + } as unknown as FileManager; + contactNoteWriter = new ContactNoteWriter( + vault, + metadataCache, + fileManager + ); }); describe('writeNotesForContacts', () => { @@ -80,22 +99,26 @@ describe('ContactNoteWriterUpdate', () => { '---\npropertyPrefix-id: 123\n---\nBody content'; // Mock methods - (vault.getAbstractFileByPath as jest.Mock).mockReturnValue(mockFile); + (vault.getFileByPath as jest.Mock).mockReturnValue(mockFile); + (vault.getFolderByPath as jest.Mock).mockReturnValue(mockFile); (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([mockFile]); (vault.read as jest.Mock).mockResolvedValue(mockExistingContent); - (vault.process as jest.Mock).mockResolvedValue(undefined); + + const config: ContactNoteConfig = { + folderPath: 'path/to/folder', + prefix: 'prefix-', + propertyPrefix: 'propertyPrefix-', + syncLabel: '', + noteBody: mockNoteBody, + }; await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - '', + config, mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody + mockContacts ); - expect(vault.process).toHaveBeenCalledTimes(1); + expect(fileManager.processFrontMatter).toHaveBeenCalledTimes(1); }); it('should update an existing note without id, begins with ---, but not yaml', async () => { @@ -117,56 +140,26 @@ describe('ContactNoteWriterUpdate', () => { const mockExistingContent = '---\nBody content'; // Mock methods - (vault.getAbstractFileByPath as jest.Mock) - .mockReturnValueOnce(mockFolder) - .mockReturnValueOnce(mockFile); + (vault.getFileByPath as jest.Mock).mockReturnValue(mockFile); + (vault.getFolderByPath as jest.Mock).mockReturnValue(mockFolder); (getAllMarkdownFilesInFolder as jest.Mock).mockReturnValue([mockFile]); (vault.read as jest.Mock).mockResolvedValue(mockExistingContent); - (vault.process as jest.Mock).mockResolvedValue(undefined); + + const config: ContactNoteConfig = { + folderPath: 'path/to/folder', + prefix: 'prefix-', + propertyPrefix: 'propertyPrefix-', + syncLabel: '', + noteBody: mockNoteBody, + }; await contactNoteWriter.writeNotesForContacts( - 'prefix-', - 'propertyPrefix-', - '', + config, mockLabelMap, - mockContacts, - 'path/to/folder', - mockNoteBody + mockContacts ); - expect(vault.process).toHaveBeenCalledTimes(1); - }); - - it('should add block with yaml', async () => { - expect( - contactNoteWriter.updateFrontmatterWithContactData('test', { aa: 'bb' }) - ).toBe('---\naa: bb\n---\n\ntest'); - }); - - it('should update block with yaml', async () => { - expect( - contactNoteWriter.updateFrontmatterWithContactData( - '---\naa: bb\n---\n\ntest', - { cc: 'dd' } - ) - ).toBe('---\npropertyPrefix-id: 123\ncc: dd\n---\n\ntest'); - }); - - it('should update block with separator', async () => { - expect( - contactNoteWriter.updateFrontmatterWithContactData('---\ntest', { - aa: 'bb', - }) - ).toBe('---\naa: bb\n---\n\n---\ntest'); - }); - - it('should update existed yaml', async () => { - expect( - contactNoteWriter.updateFrontmatterWithContactData( - '---\npropertyPrefix-id: 1\n---\n\ntest', - { 'propertyPrefix-id': '123' } - ) - ).toBe('---\npropertyPrefix-id: 123\n---\n\ntest'); + expect(fileManager.processFrontMatter).toHaveBeenCalledTimes(1); }); }); }); diff --git a/src/auth/AuthManager.ts b/src/auth/AuthManager.ts index 2197426..a408719 100644 --- a/src/auth/AuthManager.ts +++ b/src/auth/AuthManager.ts @@ -3,7 +3,7 @@ import { requestUrl } from 'obsidian'; import { URL_OAUTH_TOKEN, URI_OATUH_REDIRECT } from '../config'; /** - * Manages OAuth2 authentication for accessing the Google Contacts API. + * Manages OAuth2 authentication for accessing the Google contacts API. * Handles exchanging authorization codes, refreshing access tokens, * and providing updated credentials. */ diff --git a/src/core/ContactNoteWriter.ts b/src/core/ContactNoteWriter.ts index 4f9e9e5..9ba0627 100644 --- a/src/core/ContactNoteWriter.ts +++ b/src/core/ContactNoteWriter.ts @@ -1,7 +1,7 @@ import { + FileManager, + MetadataCache, normalizePath, - parseYaml, - stringifyYaml, TFile, Vault, } from 'obsidian'; @@ -9,6 +9,7 @@ import { GoogleContact } from 'src/types/Contact'; import { getAllMarkdownFilesInFolder } from 'src/utils/getAllMarkdownFilesInFolder'; import { Formatter } from './Formatter'; import { VaultService } from 'src/services/VaultService'; +import { ContactNoteConfig } from 'src/types/ContactNoteConfig'; /** * Responsible for creating and updating contact notes in the vault. @@ -30,128 +31,176 @@ export class ContactNoteWriter { protected vaultService: VaultService; /** - * Creates an instance of the ContactNoteWriter class. + * The MetadataCache instance used for managing file metadata. * - * @param vault - The Obsidian Vault instance where the contact notes are stored. + * This protected property is used to manage file metadata in the Obsidian vault. */ - constructor(vault: Vault) { + protected metadataCache: MetadataCache; + + /** + * The FileManager instance used for file operations. + * + * This protected property is used to manage file operations in the Obsidian vault. + */ + protected fileManager: FileManager; + + /** + * Creates an instance of ContactNoteWriter. + * + * @param vault - The Obsidian Vault instance to operate on. + * @param metadataCache - The Obsidian MetadataCache instance to operate on. + * @param fileManager - The Obsidian FileManager instance to operate on. + */ + constructor( + vault: Vault, + metadataCache: MetadataCache, + fileManager: FileManager + ) { this.vaultService = new VaultService(vault); + this.metadataCache = metadataCache; + this.fileManager = fileManager; } /** - * Creates or updates markdown notes for each contact based on the provided contact data. + * Writes notes for the provided contacts based on the specified configuration. * - * @param prefix - Prefix to use for note filenames. - * @param propertyPrefix - Prefix to use for frontmatter properties. - * @param syncLabel - Label used to determine which contacts to sync. - * @param labelMap - Mapping of label names to Google Contact group resource names. - * @param contacts - List of Google contacts to sync into notes. - * @param folderPath - Target folder path where notes should be stored. - * @param noteBody - The body template to insert below the frontmatter in each note. + * @param config - The configuration for writing contact notes. + * @param labelMap - A mapping of label names to their corresponding group IDs. + * @param contacts - The list of Google contacts to write notes for. */ async writeNotesForContacts( - prefix: string, - propertyPrefix: string, - syncLabel: string, + config: ContactNoteConfig, labelMap: Record, - contacts: GoogleContact[], - folderPath: string, - noteBody: string + contacts: GoogleContact[] ): Promise { - await this.vaultService.createFolderIfNotExists(folderPath); + await this.vaultService.createFolderIfNotExists(config.folderPath); - const folder = this.vaultService.getFolderByPath(folderPath); + const folder = this.vaultService.getFolderByPath(config.folderPath); if (!folder) return; const files = getAllMarkdownFilesInFolder(folder); - const filesIdMapping = await this.scanFiles(files, propertyPrefix); + const filesIdMapping = await this.scanFiles(files, config.propertyPrefix); const invertedLabelMap: Record = Object.fromEntries( Object.entries(labelMap).map((a) => a.reverse()) ); for (const contact of contacts) { - if (!this.hasSyncLabel(contact, syncLabel, labelMap)) continue; + if (!this.hasSyncLabel(contact, config.syncLabel, labelMap)) continue; - const id = contact.resourceName.split('/').pop(); - const syncedAt = new Date().toISOString(); - const frontmatterLines: Record = { - [`${propertyPrefix}id`]: String(id), - [`${propertyPrefix}synced`]: String(syncedAt), - }; + const id = this.getContactId(contact); + if (!id) continue; - this.formatter.addNameField(frontmatterLines, contact, propertyPrefix); - this.formatter.addEmailField(frontmatterLines, contact, propertyPrefix); - this.formatter.addPhoneField(frontmatterLines, contact, propertyPrefix); - this.formatter.addAddressFields( - frontmatterLines, + const filename = this.getFilename( contact, - propertyPrefix - ); - this.formatter.addBioField(frontmatterLines, contact, propertyPrefix); - this.formatter.addOrganizationFields( - frontmatterLines, - contact, - propertyPrefix - ); - this.formatter.addJobTitleFields( - frontmatterLines, - contact, - propertyPrefix - ); - this.formatter.addBirthdayFields( - frontmatterLines, - contact, - propertyPrefix - ); - this.formatter.addLabels( - frontmatterLines, - contact, - propertyPrefix, - invertedLabelMap + id, + config.folderPath, + config.prefix ); + if (!filename) continue; - const existingFile: TFile | null = filesIdMapping[String(id)] || null; - - if (existingFile) { - await this.vaultService.modifyFile( - existingFile, - this.modifyNote(frontmatterLines) - ); - } else { - const name = - contact.names?.[0]?.displayName || - String(contact.resourceName.split('/').pop()); - if (!name) continue; - const safeName = name.replace(/[\\/:*?"<>|]/g, '_'); - const filename = normalizePath(`${folderPath}/${prefix}${safeName}.md`); - const file = this.vaultService.getFileByPath(filename); - if (file instanceof TFile) { - await this.vaultService.modifyFile( - file, - this.modifyNote(frontmatterLines) - ); - } else { - const initialText = - this.generateFrontmatterBlock(frontmatterLines) + noteBody; - await this.vaultService.createFile(filename, initialText); - } - } + await this.fileManager.processFrontMatter( + filesIdMapping[id] || + (await this.vaultService.getFileByPath(filename)) || + (await this.vaultService.createFile(filename, config.noteBody)), + this.processFrontMatter( + this.generateFrontmatterLines( + config.propertyPrefix, + contact, + invertedLabelMap + ) + ) + ); } } /** - * Returns a function that modifies the frontmatter of a note with new contact data. + * Generates a filename for the contact note based on the contact's display name and ID. * - * @param frontmatterLines - The new contact data to inject into the frontmatter. - * @returns A function that takes the note content and returns the modified content. + * @param contact - The Google contact to generate a filename for. + * @param id - The contact ID. + * @param folderPath - The folder path where the note will be stored. + * @param prefix - The prefix to use for the filename. + * @returns The generated filename, or null if the name is not available. */ - modifyNote( + private getFilename( + contact: GoogleContact, + id: string, + folderPath: string, + prefix: string + ): string | null { + const name = contact.names?.[0]?.displayName || id; + if (!name) return null; + const safeName = name.replace(/[\\/:*?"<>|]/g, '_'); + const filename = normalizePath(`${folderPath}/${prefix}${safeName}.md`); + return filename; + } + + /** + * Processes the frontmatter lines and updates the frontmatter of the given file. + * + * @param frontmatterLines - The frontmatter lines to process. + * @returns A function that takes a frontmatter object and updates it with the provided lines. + */ + private processFrontMatter( frontmatterLines: Record - ): (data: string) => string { - return (data: string): string => { - return this.updateFrontmatterWithContactData(data, frontmatterLines); + ): (frontmatter: Record) => void { + return (frontmatter: Record) => { + for (const key in frontmatterLines) { + frontmatter[key] = frontmatterLines[key]; + } }; } + /** + * Extracts the contact ID from a Google contact object. + * + * @param contact - The Google contact to extract the ID from. + * @returns The extracted contact ID, or null if not found. + */ + private getContactId(contact: GoogleContact): string | null { + if (!contact.resourceName) return null; + return contact.resourceName.split('/').pop() || null; + } + + /** + * Generates frontmatter lines for a contact based on the provided property prefix and contact data. + * + * @param propertyPrefix - The prefix to use for frontmatter properties. + * @param contact - The Google contact to generate frontmatter for. + * @param invertedLabelMap - A mapping of label names to their corresponding group IDs. + * @returns A record of frontmatter properties and their values. + */ + private generateFrontmatterLines( + propertyPrefix: string, + contact: GoogleContact, + invertedLabelMap: Record + ): Record { + const frontmatterLines: Record = { + [`${propertyPrefix}id`]: String(this.getContactId(contact)), + [`${propertyPrefix}synced`]: String(new Date().toISOString()), + }; + + this.formatter.addNameField(frontmatterLines, contact, propertyPrefix); + this.formatter.addEmailField(frontmatterLines, contact, propertyPrefix); + this.formatter.addPhoneField(frontmatterLines, contact, propertyPrefix); + this.formatter.addAddressFields(frontmatterLines, contact, propertyPrefix); + this.formatter.addBioField(frontmatterLines, contact, propertyPrefix); + this.formatter.addOrganizationFields( + frontmatterLines, + contact, + propertyPrefix + ); + this.formatter.addJobTitleFields(frontmatterLines, contact, propertyPrefix); + this.formatter.addBirthdayFields(frontmatterLines, contact, propertyPrefix); + this.formatter.addLabels( + frontmatterLines, + contact, + propertyPrefix, + invertedLabelMap + ); + + return frontmatterLines; + } + /** * Checks if a Google contact has the specified sync label. * @@ -174,20 +223,11 @@ export class ContactNoteWriter { } /** - * Scans an array of files, reads their content, and checks if the file's frontmatter contains an `id` field. - * If an `id` field is found, it adds the `id` as a key and the corresponding file (`TFile`) as the value to a mapping object. + * Scans the provided files for frontmatter properties matching the specified prefix. * - * This method uses Obsidian's `vaultService.readFile()` to read file content and `parseYaml()` to safely parse the YAML frontmatter. - * It ensures that only files with valid `id` fields in their frontmatter are added to the mapping. - * - * @param files An array of `TFile` objects representing the files to be scanned. - * @param propertyPrefix A string that may be used as a prefix for the `id` field in frontmatter. - * @returns A promise that resolves to a record object where keys are the `id` values found in the frontmatter, - * and values are the corresponding `TFile` objects. - * - * @example - * const idFileMapping = await this.scanFiles(files); - * console.log(idFileMapping); // { "123": file1, "456": file2, ... } + * @param files - The list of TFile objects to scan. + * @param propertyPrefix - The prefix to use for identifying frontmatter properties. + * @returns A mapping of property values to TFile objects. */ protected async scanFiles( files: TFile[], @@ -196,71 +236,13 @@ export class ContactNoteWriter { const idToFileMapping: Record = {}; for (const file of files) { - const content = await this.vaultService.readFile(file); - - const match = content.match(/^---\n([\s\S]+?)\n---/); - if (match && match[1]) { - const frontmatter = parseYaml(match[1]); - - const idFieldName = `${propertyPrefix}id`; - if (frontmatter && frontmatter[idFieldName]) { - idToFileMapping[frontmatter[idFieldName]] = file; - } + const frontmatter = this.metadataCache.getFileCache(file)?.frontmatter; + const idFieldName = `${propertyPrefix}id`; + if (frontmatter && frontmatter[idFieldName]) { + idToFileMapping[frontmatter[idFieldName]] = file; } } return idToFileMapping; } - - /** - * Updates the YAML frontmatter of a note with new contact fields, merging with existing values. - * @param content Original markdown note content. - * @param newContactFields Contact data to inject into the frontmatter. - * @returns Updated markdown content. - */ - updateFrontmatterWithContactData( - content: string, - newContactFields: Record - ): string { - if (!content.startsWith('---')) { - return this.generateFrontmatterBlock(newContactFields) + content; - } - - const parts = content.split('---'); - if (parts.length < 3) { - return this.generateFrontmatterBlock(newContactFields) + content; - } - - const originalYaml = parts[1]; - const body = parts.slice(2).join('---').trim(); - - const parsed = parseYaml(originalYaml) as Record; - - for (const key of Object.keys(parsed)) { - if (key in newContactFields) { - parsed[key] = newContactFields[key]; - delete newContactFields[key]; - } - } - - const updated = { - ...parsed, - ...newContactFields, - }; - - return this.generateFrontmatterBlock(updated) + body; - } - - /** - * Generates a YAML frontmatter block string from the provided fields. - * - * @param fields - A record of key-value pairs to include in the frontmatter. - * @returns A string representing the full frontmatter block with proper formatting. - */ - protected generateFrontmatterBlock( - fields: Record - ): string { - const yaml = stringifyYaml(fields); - return `---\n${yaml}---\n\n`; - } } diff --git a/src/core/FolderSuggest.ts b/src/core/FolderSuggest.ts new file mode 100644 index 0000000..7433d95 --- /dev/null +++ b/src/core/FolderSuggest.ts @@ -0,0 +1,83 @@ +import { TFolder, App, AbstractInputSuggest } from 'obsidian'; + +/** + * FolderSuggest class for providing folder suggestions in Obsidian. + * This class extends AbstractInputSuggest to create a custom suggestion provider + * for folder paths in the Obsidian vault. + */ +export class FolderSuggest extends AbstractInputSuggest { + /** + * The list of folders in the vault. + */ + private folders: TFolder[]; + + /** + * The input element to attach the suggestions to. + */ + private inputEl: HTMLInputElement; + + /** + * Constructs a FolderSuggest instance. + * + * @param app - The Obsidian app instance. + * @param inputEl - The input element to attach the suggestions to. + */ + constructor(app: App, inputEl: HTMLInputElement) { + super(app, inputEl); + this.folders = this.getAllFolders(); + this.inputEl = inputEl; + } + + /** + * Returns the folder suggestions based on the input query. + * + * @param query - The input query to filter folder suggestions. + * @returns An array of TFolder objects that match the query. + */ + getSuggestions(query: string): TFolder[] { + return this.folders.filter((folder) => + folder.path.toLowerCase().includes(query.toLowerCase()) + ); + } + + /** + * Renders the suggestion element for a folder. + * + * @param folder - The TFolder object to render. + * @param el - The HTML element to render the suggestion into. + */ + renderSuggestion(folder: TFolder, el: HTMLElement): void { + el.setText(folder.path); + } + + /** + * Handles the selection of a folder suggestion. + * + * @param folder - The selected TFolder object. + */ + selectSuggestion(folder: TFolder): void { + this.inputEl.value = folder.path; + this.inputEl.trigger('input'); + } + + /** + * Retrieves all folders in the vault. + * + * @returns An array of TFolder objects representing all folders in the vault. + */ + private getAllFolders(): TFolder[] { + const folders: TFolder[] = []; + + const walk = (folder: TFolder) => { + folders.push(folder); + for (const child of folder.children) { + if (child instanceof TFolder) { + walk(child); + } + } + }; + + walk(this.app.vault.getRoot()); + return folders; + } +} diff --git a/src/core/GoogleContactsService.ts b/src/core/GoogleContactsService.ts index f18a111..e9364c7 100644 --- a/src/core/GoogleContactsService.ts +++ b/src/core/GoogleContactsService.ts @@ -3,7 +3,7 @@ import { URL_CONTACT_GROUPS, URL_PEOPLE_API } from '../config'; import type { GoogleContact, GoogleContactGroup } from '../types/Contact'; /** - * Core service responsible for interacting with Google Contacts and Contact Groups APIs. + * Core service responsible for interacting with Google contacts and Contact Groups APIs. * * Encapsulates logic for fetching, processing, and transforming Google contact data. * Designed to be used by higher-level plugin components to separate external API concerns diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts index 73d698b..fcc6c83 100644 --- a/src/i18n/translations.ts +++ b/src/i18n/translations.ts @@ -10,16 +10,16 @@ export const ru = { 'Google client secret': 'Секрет клиента Google', 'Enter your client secret': 'Введите ваш секрет клиента', 'Login with Google': 'Войти через Google', - "Open google's OAuth page in your browser": + "Open Google's auth page in your browser": 'Откройте страницу авторизации Google в вашем браузере', Login: 'Вход', - 'Please enter your Client ID first.': + 'Please enter your client ID first.': 'Пожалуйста, сначала введите ID клиента.', 'Authorization code': 'Код авторизации', 'Paste the code from Google after login': 'Вставьте код, полученный после входа в Google', 'Paste code here': 'Вставьте код сюда', - 'Client ID and Secret required.': 'Требуются ID клиента и секрет.', + 'Client ID and secret required.': 'Требуются ID клиента и секрет.', 'Tokens saved!': 'Токены сохранены!', 'Contacts folder': 'Папка с контактами', 'Vault folder where contact notes will be stored': @@ -49,6 +49,10 @@ export const ru = { 'Automatically sync contacts when the plugin is loaded.': 'Автоматически синхронизировать контакты при загрузке плагина.', 'e.g. s_': 'например, s_', + 'Google auth': 'Google авторизация', + 'Google contacts synced!': 'Google контакты синхронизированы!', + 'Failed to obtain access token. Please re-authenticate.': + 'Не удалось получить токен доступа. Пожалуйста, повторите аутентификацию.', }; /** @@ -63,15 +67,15 @@ export const lv = { 'Google client secret': 'Google klienta slepenais atslēga', 'Enter your client secret': 'Ievadiet savu slepeno atslēgu', 'Login with Google': 'Pieslēgties ar Google', - "Open google's OAuth page in your browser": + "Open Google's auth page in your browser": 'Atveriet Google OAuth lapu pārlūkprogrammā', Login: 'Pieteikties', - 'Please enter your Client ID first.': 'Lūdzu, vispirms ievadiet klienta ID.', + 'Please enter your client ID first.': 'Lūdzu, vispirms ievadiet klienta ID.', 'Authorization code': 'Autorizācijas kods', 'Paste the code from Google after login': 'Ielīmējiet kodu no Google pēc pieteikšanās', 'Paste code here': 'Ielīmējiet kodu šeit', - 'Client ID and Secret required.': + 'Client ID and secret required.': 'Nepieciešams klienta ID un slepenais atslēga.', 'Tokens saved!': 'Žetoni saglabāti!', 'Contacts folder': 'Kontaktpersonu mape', @@ -102,6 +106,10 @@ export const lv = { 'Automatically sync contacts when the plugin is loaded.': 'Automātiski sinhronizēt kontaktus, kad spraudnis tiek ielādēts.', 'e.g. s_': 'piem., s_', + 'Google auth': 'Google autentifikācija', + 'Google contacts synced!': 'Google kontakti sinhronizēti!', + 'Failed to obtain access token. Please re-authenticate.': + 'Neizdevās iegūt piekļuves tokenu. Lūdzu, atkārtoti autentificējieties.', }; /** @@ -116,15 +124,15 @@ export const en = { 'Google client secret': 'Google client secret', 'Enter your client secret': 'Enter your client secret', 'Login with Google': 'Login with Google', - "Open google's OAuth page in your browser": - "Open google's OAuth page in your browser", + "Open Google's auth page in your browser": + "Open Google's auth page in your browser", Login: 'Login', - 'Please enter your Client ID first.': 'Please enter your Client ID first.', + 'Please enter your client ID first.': 'Please enter your client ID first.', 'Authorization code': 'Authorization code', 'Paste the code from Google after login': 'Paste the code from Google after login', 'Paste code here': 'Paste code here', - 'Client ID and Secret required.': 'Client ID and Secret required.', + 'Client ID and secret required.': 'Client ID and secret required.', 'Tokens saved!': 'Tokens saved!', 'Contacts folder': 'Contacts folder', 'Vault folder where contact notes will be stored': @@ -155,4 +163,8 @@ export const en = { 'Automatically sync contacts when the plugin is loaded.', 'Fallback to English': 'Fallback to English', 'e.g. s_': 'e.g. s_', + 'Google auth': 'Google auth', + 'Google contacts synced!': 'Google contacts synced!', + 'Failed to obtain access token. Please re-authenticate.': + 'Failed to obtain access token. Please re-authenticate.', }; diff --git a/src/main.ts b/src/main.ts index 6d574c6..95cf48c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,9 +5,11 @@ import { Plugin, Notice } from 'obsidian'; import { AuthManager } from './auth/AuthManager'; import { GoogleContactsService } from './core/GoogleContactsService'; import { ContactNoteWriter } from './core/ContactNoteWriter'; +import { ContactNoteConfig } from './types/ContactNoteConfig'; +import { t } from './i18n/translator'; /** - * Obsidian plugin for synchronizing contacts from Google Contacts into markdown notes. + * Obsidian plugin for synchronizing contacts from Google contacts into markdown notes. */ export default class GoogleContactsSyncPlugin extends Plugin { /** Plugin settings loaded from user config */ @@ -17,7 +19,7 @@ export default class GoogleContactsSyncPlugin extends Plugin { auth: AuthManager | null = null; /** - * Service layer handling communication with the Google Contacts API. + * Service layer handling communication with the Google contacts API. * Used to fetch contacts and groups, separate from Obsidian-specific logic. */ googleService: GoogleContactsService | null = null; @@ -42,7 +44,11 @@ export default class GoogleContactsSyncPlugin extends Plugin { this.auth = new AuthManager(this.settings); this.addSettingTab(new ContactSyncSettingTab(this.app, this)); this.googleService = new GoogleContactsService(); - this.noteWriter = new ContactNoteWriter(this.app.vault); + this.noteWriter = new ContactNoteWriter( + this.app.vault, + this.app.metadataCache, + this.app.fileManager + ); if (this.settings.syncOnStartup || this.shouldSyncNow()) { this.syncContacts(); @@ -64,13 +70,15 @@ export default class GoogleContactsSyncPlugin extends Plugin { const interval = this.settings.syncIntervalMinutes; if (interval > 0) { - this.syncIntervalId = window.setInterval( - () => { - if (this.shouldSyncNow()) { - this.syncContacts(); - } - }, - interval * 60 * 1000 + this.registerInterval( + window.setInterval( + () => { + if (this.shouldSyncNow()) { + this.syncContacts(); + } + }, + interval * 60 * 1000 + ) ); } } @@ -100,7 +108,7 @@ export default class GoogleContactsSyncPlugin extends Plugin { const token = await this.auth?.ensureValidToken(); if (!token) { - new Notice('Failed to obtain access token. Please re-authenticate.'); + new Notice(t('Failed to obtain access token. Please re-authenticate.')); return; } this.updateAuthSettings(); @@ -109,17 +117,17 @@ export default class GoogleContactsSyncPlugin extends Plugin { const contacts = (await this.googleService?.fetchGoogleContacts(token)) || []; - this.noteWriter?.writeNotesForContacts( - this.settings.fileNamePrefix || '', - this.settings.propertyNamePrefix || '', - this.settings.syncLabel, - labelMap, - contacts, - this.settings.contactsFolder, - this.settings.noteTemplate || '# Notes\n' - ); + const config: ContactNoteConfig = { + folderPath: this.settings.contactsFolder, + prefix: this.settings.fileNamePrefix || '', + propertyPrefix: this.settings.propertyNamePrefix || '', + syncLabel: this.settings.syncLabel, + noteBody: this.settings.noteTemplate || '# Notes\n', + }; - new Notice('Google Contacts synced!'); + this.noteWriter?.writeNotesForContacts(config, labelMap, contacts); + + new Notice(t('Google contacts synced!')); } /** diff --git a/src/plugin/settings.ts b/src/plugin/settings.ts index 6c43e35..14ccfa8 100644 --- a/src/plugin/settings.ts +++ b/src/plugin/settings.ts @@ -3,9 +3,10 @@ import { LINK_TO_MANUAL } from '../config'; import { getAuthUrl } from '../auth/getAuthUrl'; import GoogleContactsSyncPlugin from '../main'; import { t } from '../i18n/translator'; +import { FolderSuggest } from 'src/core/FolderSuggest'; /** - * Settings tab for the Google Contacts Sync plugin. + * Settings tab for the Google contacts sync plugin. * Allows the user to configure plugin options through the Obsidian settings UI. */ export class ContactSyncSettingTab extends PluginSettingTab { @@ -39,80 +40,22 @@ export class ContactSyncSettingTab extends PluginSettingTab { }) ); - new Setting(containerEl) - .setName(t('Google client ID')) - .setDesc(manual) - .addText((text) => - text - .setPlaceholder(t('Enter your client ID')) - .setValue(this.plugin.settings.clientId) - .onChange(async (value) => { - this.plugin.settings.clientId = value; - await this.plugin.saveSettings(); - }) - ); - - new Setting(containerEl) - .setName(t('Google client secret')) - .addText((text) => - text - .setPlaceholder(t('Enter your client secret')) - .setValue(this.plugin.settings.clientSecret) - .onChange(async (value) => { - this.plugin.settings.clientSecret = value; - await this.plugin.saveSettings(); - }) - ); - - new Setting(containerEl) - .setName(t('Login with Google')) - .setDesc(t("Open google's OAuth page in your browser")) - .addButton((btn) => - btn.setButtonText(t('Login')).onClick(() => { - if (!this.plugin.settings.clientId) { - new Notice(t('Please enter your Client ID first.')); - return; - } - window.open(getAuthUrl(this.plugin.settings.clientId), '_blank'); - }) - ); - - new Setting(containerEl) - .setName(t('Authorization code')) - .setDesc(t('Paste the code from Google after login')) - .addText((text) => - text.setPlaceholder(t('Paste code here')).onChange(async (code) => { - if ( - !this.plugin.settings.clientId || - !this.plugin.settings.clientSecret || - !this.plugin.auth - ) { - new Notice(t('Client ID and Secret required.')); - return; - } - - this.plugin.auth.exchangeCode(code); - Object.assign( - this.plugin.settings, - this.plugin.auth.getSettingsUpdate() - ); - await this.plugin.saveSettings(); - new Notice(t('Tokens saved!')); - }) - ); - new Setting(containerEl) .setName(t('Contacts folder')) .setDesc(t('Vault folder where contact notes will be stored')) - .addText((text) => + .addText((text) => { text .setPlaceholder(t('e.g. Contacts')) .setValue(this.plugin.settings.contactsFolder) .onChange(async (value) => { this.plugin.settings.contactsFolder = value.trim() || 'Contacts'; await this.plugin.saveSettings(); - }) - ); + }); + + new FolderSuggest(this.app, text.inputEl); + + return text; + }); new Setting(containerEl) .setName(t('Note template')) @@ -203,5 +146,69 @@ export class ContactSyncSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); }) ); + + new Setting(containerEl).setName(t('Google auth')).setHeading(); + + new Setting(containerEl) + .setName(t('Google client ID')) + .setDesc(manual) + .addText((text) => + text + .setPlaceholder(t('Enter your client ID')) + .setValue(this.plugin.settings.clientId) + .onChange(async (value) => { + this.plugin.settings.clientId = value; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName(t('Google client secret')) + .addText((text) => + text + .setPlaceholder(t('Enter your client secret')) + .setValue(this.plugin.settings.clientSecret) + .onChange(async (value) => { + this.plugin.settings.clientSecret = value; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName(t('Login with Google')) + .setDesc(t("Open Google's auth page in your browser")) + .addButton((btn) => + btn.setButtonText(t('Login')).onClick(() => { + if (!this.plugin.settings.clientId) { + new Notice(t('Please enter your client ID first.')); + return; + } + window.open(getAuthUrl(this.plugin.settings.clientId), '_blank'); + }) + ); + + new Setting(containerEl) + .setName(t('Authorization code')) + .setDesc(t('Paste the code from Google after login')) + .addText((text) => + text.setPlaceholder(t('Paste code here')).onChange(async (code) => { + if ( + !this.plugin.settings.clientId || + !this.plugin.settings.clientSecret || + !this.plugin.auth + ) { + new Notice(t('Client ID and secret required.')); + return; + } + + this.plugin.auth.exchangeCode(code); + Object.assign( + this.plugin.settings, + this.plugin.auth.getSettingsUpdate() + ); + await this.plugin.saveSettings(); + new Notice(t('Tokens saved!')); + }) + ); } } diff --git a/src/services/MetadataService.ts b/src/services/MetadataService.ts new file mode 100644 index 0000000..892697c --- /dev/null +++ b/src/services/MetadataService.ts @@ -0,0 +1,39 @@ +import { TFile, CachedMetadata, MetadataCache } from 'obsidian'; + +/** + * Service class for managing metadata in Obsidian files. + * Encapsulates metadata operations to facilitate testing and decouple from direct API usage. + */ +export class MetadataService { + private metadataCache: MetadataCache; + + /** + * Creates an instance of MetadataService. + * + * @param metadataCache - The Obsidian MetadataCache instance to operate on. + */ + constructor(metadataCache: MetadataCache) { + this.metadataCache = metadataCache; + } + + /** + * Retrieves the frontmatter metadata from a file. + * + * @param file - The TFile to retrieve frontmatter from. + * @returns The frontmatter as a record of key-value pairs, or undefined if not found. + */ + getFrontmatter(file: TFile): Record | undefined { + const cache = this.metadataCache.getFileCache(file); + return cache?.frontmatter; + } + + /** + * Retrieves the YAML frontmatter from a file. + * + * @param file - The TFile to retrieve YAML frontmatter from. + * @returns The YAML frontmatter as a string, or null if not found. + */ + getFileCache(file: TFile): CachedMetadata | null { + return this.metadataCache.getFileCache(file); + } +} diff --git a/src/services/VaultService.ts b/src/services/VaultService.ts index b736829..ee5af72 100644 --- a/src/services/VaultService.ts +++ b/src/services/VaultService.ts @@ -37,9 +37,8 @@ export class VaultService { * @param filePath - The path of the file to retrieve. * @returns The TFile if found, or null. */ - getFileByPath(filePath: string): TFile | null { - const file = this.vault.getAbstractFileByPath(filePath); - return file instanceof TFile ? file : null; + async getFileByPath(filePath: string): Promise { + return this.vault.getFileByPath(filePath); } /** @@ -49,31 +48,7 @@ export class VaultService { * @returns The TFolder if found, or null. */ getFolderByPath(folderPath: string): TFolder | null { - const folder = this.vault.getAbstractFileByPath(folderPath); - return folder instanceof TFolder ? folder : null; - } - - /** - * Reads the content of a file. - * - * @param file - The file to read. - * @returns The file content as a string. - */ - async readFile(file: TFile): Promise { - return this.vault.read(file); - } - - /** - * Modifies an existing file with new content. - * - * @param file - The file to modify. - * @param content - The new content to write. - */ - async modifyFile( - file: TFile, - modify: (data: string) => string - ): Promise { - await this.vault.process(file, modify); + return this.vault.getFolderByPath(folderPath); } /** @@ -81,9 +56,10 @@ export class VaultService { * * @param filePath - The path for the new file. * @param content - The initial content of the file. + * @returns The created TFile. */ - async createFile(filePath: string, content: string): Promise { + async createFile(filePath: string, content: string): Promise { const normalizedPath = normalizePath(filePath); - await this.vault.create(normalizedPath, content); + return await this.vault.create(normalizedPath, content); } } diff --git a/src/types/Contact.ts b/src/types/Contact.ts index e93dc00..63c1c9e 100644 --- a/src/types/Contact.ts +++ b/src/types/Contact.ts @@ -1,5 +1,5 @@ /** - * Represents a single contact retrieved from Google Contacts API. + * Represents a single contact retrieved from Google contacts API. */ export interface GoogleContact { /** Unique resource identifier for the contact (e.g., "people/c123...") */ @@ -61,7 +61,7 @@ export interface Birthday { } /** - * Represents a membership in a Google Contact Group. + * Represents a membership in a Google contact Group. */ export interface ContactGroupMembership { /** Identifier of the contact group (e.g., "abc123") */ @@ -86,7 +86,7 @@ export interface Membership { } /** - * Represents a contact group fetched from Google Contacts API. + * Represents a contact group fetched from Google contacts API. */ export interface GoogleContactGroup { /** Human-readable name of the group (e.g., "Friends") */ diff --git a/src/types/ContactNoteConfig.ts b/src/types/ContactNoteConfig.ts new file mode 100644 index 0000000..be4c50f --- /dev/null +++ b/src/types/ContactNoteConfig.ts @@ -0,0 +1,7 @@ +export interface ContactNoteConfig { + prefix: string; + propertyPrefix: string; + syncLabel: string; + folderPath: string; + noteBody: string; +} diff --git a/src/types/Settings.ts b/src/types/Settings.ts index 41c44cf..9778960 100644 --- a/src/types/Settings.ts +++ b/src/types/Settings.ts @@ -1,5 +1,5 @@ /** - * Configuration options for Google Contacts synchronization. + * Configuration options for Google contacts synchronization. */ export interface ContactSyncSettings { /** OAuth client ID from Google Developer Console */ @@ -29,7 +29,7 @@ export interface ContactSyncSettings { /** Prefix used for frontmatter keys in contact notes */ propertyNamePrefix: string; - /** Name of the contact group to sync from Google Contacts */ + /** Name of the contact group to sync from Google contacts */ syncLabel: string; /** Interval (in minutes) for auto-sync */