mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	separate DB connection for each transaction (just for the record, will be reverted probably)
This commit is contained in:
		
							parent
							
								
									4d95eb0762
								
							
						
					
					
						commit
						fd764f6163
					
				
							
								
								
									
										342
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										342
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -7382,9 +7382,9 @@
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "sqlite": {
 | 
			
		||||
      "version": "2.8.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-2.8.0.tgz",
 | 
			
		||||
      "integrity": "sha1-rLbRhppSQcVwFsiGBuygCfDzG5A=",
 | 
			
		||||
      "version": "2.9.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/sqlite/-/sqlite-2.9.0.tgz",
 | 
			
		||||
      "integrity": "sha1-M/A8ZG6g96XVBuZFoZucU1Ldn6Q=",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "sqlite3": "3.1.13"
 | 
			
		||||
      }
 | 
			
		||||
@ -7400,13 +7400,11 @@
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "abbrev": {
 | 
			
		||||
          "version": "1.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "ajv": {
 | 
			
		||||
          "version": "4.11.8",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
 | 
			
		||||
          "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "co": "4.6.0",
 | 
			
		||||
            "json-stable-stringify": "1.0.1"
 | 
			
		||||
@ -7414,18 +7412,15 @@
 | 
			
		||||
        },
 | 
			
		||||
        "ansi-regex": {
 | 
			
		||||
          "version": "2.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
 | 
			
		||||
          "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "aproba": {
 | 
			
		||||
          "version": "1.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
 | 
			
		||||
          "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "are-we-there-yet": {
 | 
			
		||||
          "version": "1.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz",
 | 
			
		||||
          "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "delegates": "1.0.0",
 | 
			
		||||
            "readable-stream": "2.3.3"
 | 
			
		||||
@ -7433,38 +7428,31 @@
 | 
			
		||||
        },
 | 
			
		||||
        "asn1": {
 | 
			
		||||
          "version": "0.2.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
 | 
			
		||||
          "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "assert-plus": {
 | 
			
		||||
          "version": "0.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
 | 
			
		||||
          "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "asynckit": {
 | 
			
		||||
          "version": "0.4.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 | 
			
		||||
          "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "aws-sign2": {
 | 
			
		||||
          "version": "0.6.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
 | 
			
		||||
          "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "aws4": {
 | 
			
		||||
          "version": "1.6.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
 | 
			
		||||
          "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "balanced-match": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "bcrypt-pbkdf": {
 | 
			
		||||
          "version": "1.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "tweetnacl": "0.14.5"
 | 
			
		||||
@ -7472,24 +7460,21 @@
 | 
			
		||||
        },
 | 
			
		||||
        "block-stream": {
 | 
			
		||||
          "version": "0.0.9",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
 | 
			
		||||
          "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "inherits": "2.0.3"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "boom": {
 | 
			
		||||
          "version": "2.10.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
 | 
			
		||||
          "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "hoek": "2.16.3"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "brace-expansion": {
 | 
			
		||||
          "version": "1.1.8",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
 | 
			
		||||
          "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "balanced-match": "1.0.0",
 | 
			
		||||
            "concat-map": "0.0.1"
 | 
			
		||||
@ -7497,92 +7482,77 @@
 | 
			
		||||
        },
 | 
			
		||||
        "caseless": {
 | 
			
		||||
          "version": "0.12.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
 | 
			
		||||
          "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "co": {
 | 
			
		||||
          "version": "4.6.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
 | 
			
		||||
          "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "code-point-at": {
 | 
			
		||||
          "version": "1.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
 | 
			
		||||
          "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "combined-stream": {
 | 
			
		||||
          "version": "1.0.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
 | 
			
		||||
          "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "delayed-stream": "1.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "concat-map": {
 | 
			
		||||
          "version": "0.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "console-control-strings": {
 | 
			
		||||
          "version": "1.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
 | 
			
		||||
          "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "core-util-is": {
 | 
			
		||||
          "version": "1.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "cryptiles": {
 | 
			
		||||
          "version": "2.0.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
 | 
			
		||||
          "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "boom": "2.10.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "dashdash": {
 | 
			
		||||
          "version": "1.14.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
 | 
			
		||||
          "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "assert-plus": "1.0.0"
 | 
			
		||||
          },
 | 
			
		||||
          "dependencies": {
 | 
			
		||||
            "assert-plus": {
 | 
			
		||||
              "version": "1.0.0",
 | 
			
		||||
              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 | 
			
		||||
              "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
 | 
			
		||||
              "bundled": true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "debug": {
 | 
			
		||||
          "version": "2.6.9",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
 | 
			
		||||
          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ms": "2.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "deep-extend": {
 | 
			
		||||
          "version": "0.4.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
 | 
			
		||||
          "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "delayed-stream": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "delegates": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "ecc-jsbn": {
 | 
			
		||||
          "version": "0.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
 | 
			
		||||
          "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "jsbn": "0.1.1"
 | 
			
		||||
@ -7590,23 +7560,19 @@
 | 
			
		||||
        },
 | 
			
		||||
        "extend": {
 | 
			
		||||
          "version": "3.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "extsprintf": {
 | 
			
		||||
          "version": "1.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
 | 
			
		||||
          "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "forever-agent": {
 | 
			
		||||
          "version": "0.6.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
 | 
			
		||||
          "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "form-data": {
 | 
			
		||||
          "version": "2.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
 | 
			
		||||
          "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "asynckit": "0.4.0",
 | 
			
		||||
            "combined-stream": "1.0.5",
 | 
			
		||||
@ -7615,13 +7581,11 @@
 | 
			
		||||
        },
 | 
			
		||||
        "fs.realpath": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "fstream": {
 | 
			
		||||
          "version": "1.0.11",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
 | 
			
		||||
          "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "graceful-fs": "4.1.11",
 | 
			
		||||
            "inherits": "2.0.3",
 | 
			
		||||
@ -7631,8 +7595,7 @@
 | 
			
		||||
        },
 | 
			
		||||
        "fstream-ignore": {
 | 
			
		||||
          "version": "1.0.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz",
 | 
			
		||||
          "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "fstream": "1.0.11",
 | 
			
		||||
            "inherits": "2.0.3",
 | 
			
		||||
@ -7641,8 +7604,7 @@
 | 
			
		||||
        },
 | 
			
		||||
        "gauge": {
 | 
			
		||||
          "version": "2.7.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
 | 
			
		||||
          "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "aproba": "1.2.0",
 | 
			
		||||
            "console-control-strings": "1.1.0",
 | 
			
		||||
@ -7656,23 +7618,20 @@
 | 
			
		||||
        },
 | 
			
		||||
        "getpass": {
 | 
			
		||||
          "version": "0.1.7",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
 | 
			
		||||
          "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "assert-plus": "1.0.0"
 | 
			
		||||
          },
 | 
			
		||||
          "dependencies": {
 | 
			
		||||
            "assert-plus": {
 | 
			
		||||
              "version": "1.0.0",
 | 
			
		||||
              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 | 
			
		||||
              "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
 | 
			
		||||
              "bundled": true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "glob": {
 | 
			
		||||
          "version": "7.1.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
 | 
			
		||||
          "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "fs.realpath": "1.0.0",
 | 
			
		||||
            "inflight": "1.0.6",
 | 
			
		||||
@ -7684,18 +7643,15 @@
 | 
			
		||||
        },
 | 
			
		||||
        "graceful-fs": {
 | 
			
		||||
          "version": "4.1.11",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
 | 
			
		||||
          "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "har-schema": {
 | 
			
		||||
          "version": "1.0.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
 | 
			
		||||
          "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "har-validator": {
 | 
			
		||||
          "version": "4.2.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
 | 
			
		||||
          "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ajv": "4.11.8",
 | 
			
		||||
            "har-schema": "1.0.5"
 | 
			
		||||
@ -7703,13 +7659,11 @@
 | 
			
		||||
        },
 | 
			
		||||
        "has-unicode": {
 | 
			
		||||
          "version": "2.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "hawk": {
 | 
			
		||||
          "version": "3.1.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
 | 
			
		||||
          "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "boom": "2.10.1",
 | 
			
		||||
            "cryptiles": "2.0.5",
 | 
			
		||||
@ -7719,13 +7673,11 @@
 | 
			
		||||
        },
 | 
			
		||||
        "hoek": {
 | 
			
		||||
          "version": "2.16.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
 | 
			
		||||
          "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "http-signature": {
 | 
			
		||||
          "version": "1.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
 | 
			
		||||
          "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "assert-plus": "0.2.0",
 | 
			
		||||
            "jsprim": "1.4.1",
 | 
			
		||||
@ -7734,8 +7686,7 @@
 | 
			
		||||
        },
 | 
			
		||||
        "inflight": {
 | 
			
		||||
          "version": "1.0.6",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
 | 
			
		||||
          "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "once": "1.4.0",
 | 
			
		||||
            "wrappy": "1.0.2"
 | 
			
		||||
@ -7743,70 +7694,58 @@
 | 
			
		||||
        },
 | 
			
		||||
        "inherits": {
 | 
			
		||||
          "version": "2.0.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
 | 
			
		||||
          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "ini": {
 | 
			
		||||
          "version": "1.3.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
 | 
			
		||||
          "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "is-fullwidth-code-point": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "number-is-nan": "1.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "is-typedarray": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "isarray": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "isstream": {
 | 
			
		||||
          "version": "0.1.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
 | 
			
		||||
          "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "jsbn": {
 | 
			
		||||
          "version": "0.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
 | 
			
		||||
          "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "json-schema": {
 | 
			
		||||
          "version": "0.2.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
 | 
			
		||||
          "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "json-stable-stringify": {
 | 
			
		||||
          "version": "1.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "jsonify": "0.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "json-stringify-safe": {
 | 
			
		||||
          "version": "5.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "jsonify": {
 | 
			
		||||
          "version": "0.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "jsprim": {
 | 
			
		||||
          "version": "1.4.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
 | 
			
		||||
          "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "assert-plus": "1.0.0",
 | 
			
		||||
            "extsprintf": "1.3.0",
 | 
			
		||||
@ -7816,54 +7755,46 @@
 | 
			
		||||
          "dependencies": {
 | 
			
		||||
            "assert-plus": {
 | 
			
		||||
              "version": "1.0.0",
 | 
			
		||||
              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 | 
			
		||||
              "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
 | 
			
		||||
              "bundled": true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "mime-db": {
 | 
			
		||||
          "version": "1.30.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
 | 
			
		||||
          "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "mime-types": {
 | 
			
		||||
          "version": "2.1.17",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
 | 
			
		||||
          "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "mime-db": "1.30.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "minimatch": {
 | 
			
		||||
          "version": "3.0.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 | 
			
		||||
          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "brace-expansion": "1.1.8"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "minimist": {
 | 
			
		||||
          "version": "0.0.8",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
 | 
			
		||||
          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "mkdirp": {
 | 
			
		||||
          "version": "0.5.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
 | 
			
		||||
          "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "minimist": "0.0.8"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "ms": {
 | 
			
		||||
          "version": "2.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "node-pre-gyp": {
 | 
			
		||||
          "version": "0.6.38",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.38.tgz",
 | 
			
		||||
          "integrity": "sha1-6Sog+DQWQVu0CG9tH7eLPac9ET0=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "hawk": "3.1.3",
 | 
			
		||||
            "mkdirp": "0.5.1",
 | 
			
		||||
@ -7879,8 +7810,7 @@
 | 
			
		||||
        },
 | 
			
		||||
        "nopt": {
 | 
			
		||||
          "version": "4.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "abbrev": "1.1.1",
 | 
			
		||||
            "osenv": "0.1.4"
 | 
			
		||||
@ -7888,8 +7818,7 @@
 | 
			
		||||
        },
 | 
			
		||||
        "npmlog": {
 | 
			
		||||
          "version": "4.1.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
 | 
			
		||||
          "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "are-we-there-yet": "1.1.4",
 | 
			
		||||
            "console-control-strings": "1.1.0",
 | 
			
		||||
@ -7899,41 +7828,34 @@
 | 
			
		||||
        },
 | 
			
		||||
        "number-is-nan": {
 | 
			
		||||
          "version": "1.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "oauth-sign": {
 | 
			
		||||
          "version": "0.8.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
 | 
			
		||||
          "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "object-assign": {
 | 
			
		||||
          "version": "4.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
 | 
			
		||||
          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "once": {
 | 
			
		||||
          "version": "1.4.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 | 
			
		||||
          "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "wrappy": "1.0.2"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "os-homedir": {
 | 
			
		||||
          "version": "1.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "os-tmpdir": {
 | 
			
		||||
          "version": "1.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "osenv": {
 | 
			
		||||
          "version": "0.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
 | 
			
		||||
          "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "os-homedir": "1.0.2",
 | 
			
		||||
            "os-tmpdir": "1.0.2"
 | 
			
		||||
@ -7941,33 +7863,27 @@
 | 
			
		||||
        },
 | 
			
		||||
        "path-is-absolute": {
 | 
			
		||||
          "version": "1.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "performance-now": {
 | 
			
		||||
          "version": "0.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
 | 
			
		||||
          "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "process-nextick-args": {
 | 
			
		||||
          "version": "1.0.7",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
 | 
			
		||||
          "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "punycode": {
 | 
			
		||||
          "version": "1.4.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
 | 
			
		||||
          "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "qs": {
 | 
			
		||||
          "version": "6.4.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
 | 
			
		||||
          "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "rc": {
 | 
			
		||||
          "version": "1.2.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz",
 | 
			
		||||
          "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "deep-extend": "0.4.2",
 | 
			
		||||
            "ini": "1.3.4",
 | 
			
		||||
@ -7977,15 +7893,13 @@
 | 
			
		||||
          "dependencies": {
 | 
			
		||||
            "minimist": {
 | 
			
		||||
              "version": "1.2.0",
 | 
			
		||||
              "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 | 
			
		||||
              "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
 | 
			
		||||
              "bundled": true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "readable-stream": {
 | 
			
		||||
          "version": "2.3.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
 | 
			
		||||
          "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "core-util-is": "1.0.2",
 | 
			
		||||
            "inherits": "2.0.3",
 | 
			
		||||
@ -7998,8 +7912,7 @@
 | 
			
		||||
        },
 | 
			
		||||
        "request": {
 | 
			
		||||
          "version": "2.81.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
 | 
			
		||||
          "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "aws-sign2": "0.6.0",
 | 
			
		||||
            "aws4": "1.6.0",
 | 
			
		||||
@ -8027,44 +7940,37 @@
 | 
			
		||||
        },
 | 
			
		||||
        "rimraf": {
 | 
			
		||||
          "version": "2.6.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
 | 
			
		||||
          "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "glob": "7.1.2"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "safe-buffer": {
 | 
			
		||||
          "version": "5.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "semver": {
 | 
			
		||||
          "version": "5.4.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
 | 
			
		||||
          "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "set-blocking": {
 | 
			
		||||
          "version": "2.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "signal-exit": {
 | 
			
		||||
          "version": "3.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "sntp": {
 | 
			
		||||
          "version": "1.0.9",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
 | 
			
		||||
          "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "hoek": "2.16.3"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "sshpk": {
 | 
			
		||||
          "version": "1.13.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
 | 
			
		||||
          "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "asn1": "0.2.3",
 | 
			
		||||
            "assert-plus": "1.0.0",
 | 
			
		||||
@ -8078,15 +7984,13 @@
 | 
			
		||||
          "dependencies": {
 | 
			
		||||
            "assert-plus": {
 | 
			
		||||
              "version": "1.0.0",
 | 
			
		||||
              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 | 
			
		||||
              "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
 | 
			
		||||
              "bundled": true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "string-width": {
 | 
			
		||||
          "version": "1.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "code-point-at": "1.1.0",
 | 
			
		||||
            "is-fullwidth-code-point": "1.0.0",
 | 
			
		||||
@ -8095,34 +7999,29 @@
 | 
			
		||||
        },
 | 
			
		||||
        "string_decoder": {
 | 
			
		||||
          "version": "1.0.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
 | 
			
		||||
          "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "safe-buffer": "5.1.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "stringstream": {
 | 
			
		||||
          "version": "0.0.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
 | 
			
		||||
          "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "strip-ansi": {
 | 
			
		||||
          "version": "3.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ansi-regex": "2.1.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "strip-json-comments": {
 | 
			
		||||
          "version": "2.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
 | 
			
		||||
          "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "tar": {
 | 
			
		||||
          "version": "2.2.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
 | 
			
		||||
          "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "block-stream": "0.0.9",
 | 
			
		||||
            "fstream": "1.0.11",
 | 
			
		||||
@ -8131,8 +8030,7 @@
 | 
			
		||||
        },
 | 
			
		||||
        "tar-pack": {
 | 
			
		||||
          "version": "3.4.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz",
 | 
			
		||||
          "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "debug": "2.6.9",
 | 
			
		||||
            "fstream": "1.0.11",
 | 
			
		||||
@ -8146,45 +8044,38 @@
 | 
			
		||||
        },
 | 
			
		||||
        "tough-cookie": {
 | 
			
		||||
          "version": "2.3.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
 | 
			
		||||
          "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "punycode": "1.4.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "tunnel-agent": {
 | 
			
		||||
          "version": "0.6.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 | 
			
		||||
          "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "safe-buffer": "5.1.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "tweetnacl": {
 | 
			
		||||
          "version": "0.14.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
 | 
			
		||||
          "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "uid-number": {
 | 
			
		||||
          "version": "0.0.6",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
 | 
			
		||||
          "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "util-deprecate": {
 | 
			
		||||
          "version": "1.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "uuid": {
 | 
			
		||||
          "version": "3.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
 | 
			
		||||
          "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        },
 | 
			
		||||
        "verror": {
 | 
			
		||||
          "version": "1.10.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
 | 
			
		||||
          "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "assert-plus": "1.0.0",
 | 
			
		||||
            "core-util-is": "1.0.2",
 | 
			
		||||
@ -8193,23 +8084,20 @@
 | 
			
		||||
          "dependencies": {
 | 
			
		||||
            "assert-plus": {
 | 
			
		||||
              "version": "1.0.0",
 | 
			
		||||
              "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 | 
			
		||||
              "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
 | 
			
		||||
              "bundled": true
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "wide-align": {
 | 
			
		||||
          "version": "1.1.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
 | 
			
		||||
          "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
 | 
			
		||||
          "bundled": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "string-width": "1.0.2"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "wrappy": {
 | 
			
		||||
          "version": "1.0.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
 | 
			
		||||
          "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
 | 
			
		||||
          "bundled": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@
 | 
			
		||||
    "serve-favicon": "~2.4.5",
 | 
			
		||||
    "session-file-store": "^1.1.2",
 | 
			
		||||
    "simple-node-logger": "^0.93.30",
 | 
			
		||||
    "sqlite": "^2.8.0",
 | 
			
		||||
    "sqlite": "^2.9.0",
 | 
			
		||||
    "ws": "^3.3.2"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,9 @@ async function deleteOld() {
 | 
			
		||||
    const cutoffId = await sql.getSingleValue("SELECT id FROM event_log ORDER BY id DESC LIMIT 1000, 1");
 | 
			
		||||
 | 
			
		||||
    if (cutoffId) {
 | 
			
		||||
        await sql.execute("DELETE FROM event_log WHERE id < ?", [cutoffId]);
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await sql.execute(db, "DELETE FROM event_log WHERE id < ?", [cutoffId]);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,10 @@ router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.put('', auth.checkApiAuth, async (req, res, next) => {
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await sql.replace("notes_history", req.body);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await sql.replace(db, "notes_history", req.body);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteHistorySync(req.body.note_history_id);
 | 
			
		||||
        await sync_table.addNoteHistorySync(db, req.body.note_history_id);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send();
 | 
			
		||||
 | 
			
		||||
@ -59,8 +59,8 @@ router.put('/:noteId', async (req, res, next) => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
router.delete('/:noteTreeId', async (req, res, next) => {
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await notes.deleteNote(req.params.noteTreeId);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await notes.deleteNote(db, req.params.noteTreeId);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send({});
 | 
			
		||||
 | 
			
		||||
@ -16,11 +16,11 @@ router.put('/:noteTreeId/moveTo/:parentNoteId', auth.checkApiAuth, async (req, r
 | 
			
		||||
 | 
			
		||||
    const now = utils.nowTimestamp();
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await sql.execute("UPDATE notes_tree SET note_pid = ?, note_pos = ?, date_modified = ? WHERE note_tree_id = ?",
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await sql.execute(db, "UPDATE notes_tree SET note_pid = ?, note_pos = ?, date_modified = ? WHERE note_tree_id = ?",
 | 
			
		||||
            [parentNoteId, newNotePos, now, noteTreeId]);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteTreeSync(noteTreeId);
 | 
			
		||||
        await sync_table.addNoteTreeSync(db, noteTreeId);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send({});
 | 
			
		||||
@ -33,18 +33,18 @@ router.put('/:noteTreeId/moveBefore/:beforeNoteTreeId', async (req, res, next) =
 | 
			
		||||
    const beforeNote = await sql.getSingleResult("SELECT * FROM notes_tree WHERE note_tree_id = ?", [beforeNoteTreeId]);
 | 
			
		||||
 | 
			
		||||
    if (beforeNote) {
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            // we don't change date_modified so other changes are prioritized in case of conflict
 | 
			
		||||
            await sql.execute("UPDATE notes_tree SET note_pos = note_pos + 1 WHERE note_pid = ? AND note_pos >= ? AND is_deleted = 0",
 | 
			
		||||
            await sql.execute(db, "UPDATE notes_tree SET note_pos = note_pos + 1 WHERE note_pid = ? AND note_pos >= ? AND is_deleted = 0",
 | 
			
		||||
                [beforeNote.note_pid, beforeNote.note_pos]);
 | 
			
		||||
 | 
			
		||||
            const now = utils.nowTimestamp();
 | 
			
		||||
 | 
			
		||||
            await sql.execute("UPDATE notes_tree SET note_pid = ?, note_pos = ?, date_modified = ? WHERE note_tree_id = ?",
 | 
			
		||||
            await sql.execute(db, "UPDATE notes_tree SET note_pid = ?, note_pos = ?, date_modified = ? WHERE note_tree_id = ?",
 | 
			
		||||
                [beforeNote.note_pid, beforeNote.note_pos, now, noteTreeId]);
 | 
			
		||||
 | 
			
		||||
            await sync_table.addNoteTreeSync(noteTreeId);
 | 
			
		||||
            await sync_table.addNoteReorderingSync(beforeNote.note_pid);
 | 
			
		||||
            await sync_table.addNoteTreeSync(db, noteTreeId);
 | 
			
		||||
            await sync_table.addNoteReorderingSync(db, beforeNote.note_pid);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        res.send({});
 | 
			
		||||
@ -61,18 +61,18 @@ router.put('/:noteTreeId/moveAfter/:afterNoteTreeId', async (req, res, next) =>
 | 
			
		||||
    const afterNote = await sql.getSingleResult("SELECT * FROM notes_tree WHERE note_tree_id = ?", [afterNoteTreeId]);
 | 
			
		||||
 | 
			
		||||
    if (afterNote) {
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            // we don't change date_modified so other changes are prioritized in case of conflict
 | 
			
		||||
            await sql.execute("UPDATE notes_tree SET note_pos = note_pos + 1 WHERE note_pid = ? AND note_pos > ? AND is_deleted = 0",
 | 
			
		||||
            await sql.execute(db, "UPDATE notes_tree SET note_pos = note_pos + 1 WHERE note_pid = ? AND note_pos > ? AND is_deleted = 0",
 | 
			
		||||
                [afterNote.note_pid, afterNote.note_pos]);
 | 
			
		||||
 | 
			
		||||
            const now = utils.nowTimestamp();
 | 
			
		||||
 | 
			
		||||
            await sql.execute("UPDATE notes_tree SET note_pid = ?, note_pos = ?, date_modified = ? WHERE note_tree_id = ?",
 | 
			
		||||
            await sql.execute(db, "UPDATE notes_tree SET note_pid = ?, note_pos = ?, date_modified = ? WHERE note_tree_id = ?",
 | 
			
		||||
                [afterNote.note_pid, afterNote.note_pos + 1, now, noteTreeId]);
 | 
			
		||||
 | 
			
		||||
            await sync_table.addNoteTreeSync(noteTreeId);
 | 
			
		||||
            await sync_table.addNoteReorderingSync(afterNote.note_pid);
 | 
			
		||||
            await sync_table.addNoteTreeSync(db, noteTreeId);
 | 
			
		||||
            await sync_table.addNoteReorderingSync(db, afterNote.note_pid);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        res.send({});
 | 
			
		||||
@ -105,7 +105,7 @@ router.put('/:childNoteId/cloneTo/:parentNoteId', auth.checkApiAuth, async (req,
 | 
			
		||||
    const maxNotePos = await sql.getSingleValue('SELECT MAX(note_pos) FROM notes_tree WHERE note_pid = ? AND is_deleted = 0', [parentNoteId]);
 | 
			
		||||
    const newNotePos = maxNotePos === null ? 0 : maxNotePos + 1;
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        const noteTree = {
 | 
			
		||||
            'note_tree_id': utils.newNoteTreeId(),
 | 
			
		||||
            'note_id': childNoteId,
 | 
			
		||||
@ -116,9 +116,9 @@ router.put('/:childNoteId/cloneTo/:parentNoteId', auth.checkApiAuth, async (req,
 | 
			
		||||
            'is_deleted': 0
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        await sql.replace("notes_tree", noteTree);
 | 
			
		||||
        await sql.replace(db, "notes_tree", noteTree);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteTreeSync(noteTree.note_tree_id);
 | 
			
		||||
        await sync_table.addNoteTreeSync(db, noteTree.note_tree_id);
 | 
			
		||||
 | 
			
		||||
        res.send({
 | 
			
		||||
            success: true
 | 
			
		||||
@ -152,9 +152,9 @@ router.put('/:noteId/cloneAfter/:afterNoteTreeId', async (req, res, next) => {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        // we don't change date_modified so other changes are prioritized in case of conflict
 | 
			
		||||
        await sql.execute("UPDATE notes_tree SET note_pos = note_pos + 1 WHERE note_pid = ? AND note_pos > ? AND is_deleted = 0",
 | 
			
		||||
        await sql.execute(db, "UPDATE notes_tree SET note_pos = note_pos + 1 WHERE note_pid = ? AND note_pos > ? AND is_deleted = 0",
 | 
			
		||||
            [afterNote.note_pid, afterNote.note_pos]);
 | 
			
		||||
 | 
			
		||||
        const noteTree = {
 | 
			
		||||
@ -167,10 +167,10 @@ router.put('/:noteId/cloneAfter/:afterNoteTreeId', async (req, res, next) => {
 | 
			
		||||
            'is_deleted': 0
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        await sql.replace("notes_tree", noteTree);
 | 
			
		||||
        await sql.replace(db, "notes_tree", noteTree);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteTreeSync(noteTree.note_tree_id);
 | 
			
		||||
        await sync_table.addNoteReorderingSync(afterNote.note_pid);
 | 
			
		||||
        await sync_table.addNoteTreeSync(db, noteTree.note_tree_id);
 | 
			
		||||
        await sync_table.addNoteReorderingSync(db, afterNote.note_pid);
 | 
			
		||||
 | 
			
		||||
        res.send({
 | 
			
		||||
            success: true
 | 
			
		||||
@ -202,8 +202,8 @@ router.put('/:noteTreeId/expanded/:expanded', async (req, res, next) => {
 | 
			
		||||
    const noteTreeId = req.params.noteTreeId;
 | 
			
		||||
    const expanded = req.params.expanded;
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await sql.execute("UPDATE notes_tree SET is_expanded = ? WHERE note_tree_id = ?", [expanded, noteTreeId]);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await sql.execute(db, "UPDATE notes_tree SET is_expanded = ? WHERE note_tree_id = ?", [expanded, noteTreeId]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send({});
 | 
			
		||||
 | 
			
		||||
@ -15,16 +15,16 @@ router.get('', auth.checkApiAuth, async (req, res, next) => {
 | 
			
		||||
router.put('/:notePath', auth.checkApiAuth, async (req, res, next) => {
 | 
			
		||||
    const notePath = req.params.notePath;
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async() => {
 | 
			
		||||
        await sql.replace('recent_notes', {
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await sql.replace(db, 'recent_notes', {
 | 
			
		||||
            note_path: notePath,
 | 
			
		||||
            date_accessed: utils.nowTimestamp(),
 | 
			
		||||
            is_deleted: 0
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await sync_table.addRecentNoteSync(notePath);
 | 
			
		||||
        await sync_table.addRecentNoteSync(db, notePath);
 | 
			
		||||
 | 
			
		||||
        await options.setOption('start_note_tree_id', notePath);
 | 
			
		||||
        await options.setOption(db, 'start_note_tree_id', notePath);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send(await getRecentNotes());
 | 
			
		||||
@ -33,10 +33,10 @@ router.put('/:notePath', auth.checkApiAuth, async (req, res, next) => {
 | 
			
		||||
router.delete('/:notePath', auth.checkApiAuth, async (req, res, next) => {
 | 
			
		||||
    const notePath = req.params.notePath;
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async() => {
 | 
			
		||||
        await sql.execute('UPDATE recent_notes SET is_deleted = 1 WHERE note_path = ?', [notePath]);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await sql.execute(db, 'UPDATE recent_notes SET is_deleted = 1 WHERE note_path = ?', [notePath]);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addRecentNoteSync(notePath);
 | 
			
		||||
        await sync_table.addRecentNoteSync(db, notePath);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send(await getRecentNotes());
 | 
			
		||||
@ -52,7 +52,9 @@ async function deleteOld() {
 | 
			
		||||
    const cutoffDateAccessed = await sql.getSingleValue("SELECT date_accessed FROM recent_notes WHERE is_deleted = 0 ORDER BY date_accessed DESC LIMIT 100, 1");
 | 
			
		||||
 | 
			
		||||
    if (cutoffDateAccessed) {
 | 
			
		||||
        await sql.execute("DELETE FROM recent_notes WHERE date_accessed < ?", [cutoffDateAccessed]);
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await sql.execute(db, "DELETE FROM recent_notes WHERE date_accessed < ?", [cutoffDateAccessed]);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -29,8 +29,8 @@ router.post('/', async (req, res, next) => {
 | 
			
		||||
    if (ALLOWED_OPTIONS.includes(body['name'])) {
 | 
			
		||||
        const optionName = await options.getOption(body['name']);
 | 
			
		||||
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
            await options.setOption(body['name'], body['value']);
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await options.setOption(db, body['name'], body['value']);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        res.send({});
 | 
			
		||||
 | 
			
		||||
@ -41,8 +41,8 @@ router.put('/:noteId/protectSubTree/:isProtected', auth.checkApiAuth, async (req
 | 
			
		||||
    const isProtected = !!parseInt(req.params.isProtected);
 | 
			
		||||
    const dataKey = protected_session.getDataKey(req);
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await notes.protectNoteRecursively(noteId, dataKey, isProtected);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await notes.protectNoteRecursively(db, noteId, dataKey, isProtected);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send({});
 | 
			
		||||
@ -52,10 +52,10 @@ router.put('/:noteTreeId/setPrefix', auth.checkApiAuth, async (req, res, next) =
 | 
			
		||||
    const noteTreeId = req.params.noteTreeId;
 | 
			
		||||
    const prefix = utils.isEmptyOrWhitespace(req.body.prefix) ? null : req.body.prefix;
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await sql.execute("UPDATE notes_tree SET prefix = ?, date_modified = ? WHERE note_tree_id = ?", [prefix, utils.nowTimestamp(), noteTreeId]);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await sql.execute(db, "UPDATE notes_tree SET prefix = ?, date_modified = ? WHERE note_tree_id = ?", [prefix, utils.nowTimestamp(), noteTreeId]);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteTreeSync(noteTreeId);
 | 
			
		||||
        await sync_table.addNoteTreeSync(db, noteTreeId);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    res.send({});
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,9 @@ async function backupNow() {
 | 
			
		||||
 | 
			
		||||
    log.info("Created backup at " + backupFile);
 | 
			
		||||
 | 
			
		||||
    await options.setOption('last_backup_date', now);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await options.setOption(db, 'last_backup_date', now);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function cleanupOldBackups() {
 | 
			
		||||
 | 
			
		||||
@ -17,10 +17,10 @@ async function changePassword(currentPassword, newPassword, req) {
 | 
			
		||||
    const newPasswordVerificationKey = utils.toBase64(await my_scrypt.getVerificationHash(newPassword));
 | 
			
		||||
    const decryptedDataKey = await password_encryption.getDataKey(currentPassword);
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
        await password_encryption.setDataKey(newPassword, decryptedDataKey);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        await password_encryption.setDataKey(db, newPassword, decryptedDataKey);
 | 
			
		||||
 | 
			
		||||
        await options.setOption('password_verification_hash', newPasswordVerificationKey);
 | 
			
		||||
        await options.setOption(db, 'password_verification_hash', newPasswordVerificationKey);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
 | 
			
		||||
@ -2,12 +2,12 @@ const sql = require('./sql');
 | 
			
		||||
const utils = require('./utils');
 | 
			
		||||
const log = require('./log');
 | 
			
		||||
 | 
			
		||||
async function addEvent(comment) {
 | 
			
		||||
    await addNoteEvent(null, comment);
 | 
			
		||||
async function addEvent(db, comment) {
 | 
			
		||||
    await addNoteEvent(db, null, comment);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function addNoteEvent(noteId, comment) {
 | 
			
		||||
    await sql.insert('event_log', {
 | 
			
		||||
async function addNoteEvent(db, noteId, comment) {
 | 
			
		||||
    await sql.insert(db, 'event_log', {
 | 
			
		||||
       note_id : noteId,
 | 
			
		||||
       comment: comment,
 | 
			
		||||
       date_added: utils.nowTimestamp()
 | 
			
		||||
 | 
			
		||||
@ -43,25 +43,25 @@ async function migrate() {
 | 
			
		||||
        try {
 | 
			
		||||
            log.info("Attempting migration to version " + mig.dbVersion);
 | 
			
		||||
 | 
			
		||||
            await sql.doInTransaction(async () => {
 | 
			
		||||
            await sql.doInTransaction(async db => {
 | 
			
		||||
                if (mig.type === 'sql') {
 | 
			
		||||
                    const migrationSql = fs.readFileSync(MIGRATIONS_DIR + "/" + mig.file).toString('utf8');
 | 
			
		||||
 | 
			
		||||
                    console.log("Migration with SQL script: " + migrationSql);
 | 
			
		||||
 | 
			
		||||
                    await sql.executeScript(migrationSql);
 | 
			
		||||
                    await sql.executeScript(db, migrationSql);
 | 
			
		||||
                }
 | 
			
		||||
                else if (mig.type === 'js') {
 | 
			
		||||
                    console.log("Migration with JS module");
 | 
			
		||||
 | 
			
		||||
                    const migrationModule = require("../" + MIGRATIONS_DIR + "/" + mig.file);
 | 
			
		||||
                    await migrationModule();
 | 
			
		||||
                    await migrationModule(db);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    throw new Error("Unknown migration type " + mig.type);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await options.setOption("db_version", mig.dbVersion);
 | 
			
		||||
                await options.setOption(db, "db_version", mig.dbVersion);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            log.info("Migration to version " + mig.dbVersion + " has been successful.");
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ async function createNewNote(parentNoteId, note) {
 | 
			
		||||
 | 
			
		||||
    let newNotePos = 0;
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        if (note.target === 'into') {
 | 
			
		||||
            const maxNotePos = await sql.getSingleValue('SELECT MAX(note_pos) FROM notes_tree WHERE note_pid = ? AND is_deleted = 0', [parentNoteId]);
 | 
			
		||||
 | 
			
		||||
@ -22,19 +22,19 @@ async function createNewNote(parentNoteId, note) {
 | 
			
		||||
 | 
			
		||||
            newNotePos = afterNote.note_pos + 1;
 | 
			
		||||
 | 
			
		||||
            await sql.execute('UPDATE notes_tree SET note_pos = note_pos + 1, date_modified = ? WHERE note_pid = ? AND note_pos > ? AND is_deleted = 0',
 | 
			
		||||
            await sql.execute(db, 'UPDATE notes_tree SET note_pos = note_pos + 1, date_modified = ? WHERE note_pid = ? AND note_pos > ? AND is_deleted = 0',
 | 
			
		||||
                [utils.nowTimestamp(), parentNoteId, afterNote.note_pos]);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            throw new Error('Unknown target: ' + note.target);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteTreeSync(noteTreeId);
 | 
			
		||||
        await sync_table.addNoteSync(noteId);
 | 
			
		||||
        await sync_table.addNoteTreeSync(db, noteTreeId);
 | 
			
		||||
        await sync_table.addNoteSync(db, noteId);
 | 
			
		||||
 | 
			
		||||
        const now = utils.nowTimestamp();
 | 
			
		||||
 | 
			
		||||
        await sql.insert("notes", {
 | 
			
		||||
        await sql.insert(db, "notes", {
 | 
			
		||||
            'note_id': noteId,
 | 
			
		||||
            'note_title': note.note_title,
 | 
			
		||||
            'note_text': '',
 | 
			
		||||
@ -43,7 +43,7 @@ async function createNewNote(parentNoteId, note) {
 | 
			
		||||
            'is_protected': note.is_protected
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await sql.insert("notes_tree", {
 | 
			
		||||
        await sql.insert(db, "notes_tree", {
 | 
			
		||||
            'note_tree_id': noteTreeId,
 | 
			
		||||
            'note_id': noteId,
 | 
			
		||||
            'note_pid': parentNoteId,
 | 
			
		||||
@ -65,10 +65,10 @@ async function encryptNote(note, ctx) {
 | 
			
		||||
    note.detail.note_text = data_encryption.encrypt(ctx.getDataKey(), data_encryption.noteTextIv(note.detail.note_id), note.detail.note_text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function protectNoteRecursively(noteId, dataKey, protect) {
 | 
			
		||||
async function protectNoteRecursively(db, noteId, dataKey, protect) {
 | 
			
		||||
    const note = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [noteId]);
 | 
			
		||||
 | 
			
		||||
    await protectNote(note, dataKey, protect);
 | 
			
		||||
    await protectNote(db, note, dataKey, protect);
 | 
			
		||||
 | 
			
		||||
    const children = await sql.getFlattenedResults("note_id", "SELECT note_id FROM notes_tree WHERE note_pid = ?", [noteId]);
 | 
			
		||||
 | 
			
		||||
@ -77,7 +77,7 @@ async function protectNoteRecursively(noteId, dataKey, protect) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function protectNote(note, dataKey, protect) {
 | 
			
		||||
async function protectNote(db, note, dataKey, protect) {
 | 
			
		||||
    let changed = false;
 | 
			
		||||
 | 
			
		||||
    if (protect && !note.is_protected) {
 | 
			
		||||
@ -98,16 +98,16 @@ async function protectNote(note, dataKey, protect) {
 | 
			
		||||
    if (changed) {
 | 
			
		||||
        console.log("Updating...");
 | 
			
		||||
 | 
			
		||||
        await sql.execute("UPDATE notes SET note_title = ?, note_text = ?, is_protected = ? WHERE note_id = ?",
 | 
			
		||||
        await sql.execute(db, "UPDATE notes SET note_title = ?, note_text = ?, is_protected = ? WHERE note_id = ?",
 | 
			
		||||
            [note.note_title, note.note_text, note.is_protected, note.note_id]);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteSync(note.note_id);
 | 
			
		||||
        await sync_table.addNoteSync(db, note.note_id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await protectNoteHistory(note.note_id, dataKey, protect);
 | 
			
		||||
    await protectNoteHistory(db, note.note_id, dataKey, protect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function protectNoteHistory(noteId, dataKey, protect) {
 | 
			
		||||
async function protectNoteHistory(db, noteId, dataKey, protect) {
 | 
			
		||||
    const historyToChange = await sql.getResults("SELECT * FROM notes_history WHERE note_id = ? AND is_protected != ?", [noteId, protect]);
 | 
			
		||||
 | 
			
		||||
    for (const history of historyToChange) {
 | 
			
		||||
@ -122,10 +122,10 @@ async function protectNoteHistory(noteId, dataKey, protect) {
 | 
			
		||||
            history.is_protected = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await sql.execute("UPDATE notes_history SET note_title = ?, note_text = ?, is_protected = ? WHERE note_history_id = ?",
 | 
			
		||||
        await sql.execute(db, "UPDATE notes_history SET note_title = ?, note_text = ?, is_protected = ? WHERE note_history_id = ?",
 | 
			
		||||
            [history.note_title, history.note_text, history.is_protected, history.note_history_id]);
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteHistorySync(history.note_history_id);
 | 
			
		||||
        await sync_table.addNoteHistorySync(db, history.note_history_id);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -147,11 +147,11 @@ async function updateNote(noteId, newNote, ctx) {
 | 
			
		||||
 | 
			
		||||
    const existingNoteHistoryId = await sql.getSingleValue("SELECT note_history_id FROM notes_history WHERE note_id = ? AND date_modified_from >= ?", [noteId, historyCutoff]);
 | 
			
		||||
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        if (!existingNoteHistoryId) {
 | 
			
		||||
            const newNoteHistoryId = utils.newNoteHistoryId();
 | 
			
		||||
 | 
			
		||||
            await sql.insert('notes_history', {
 | 
			
		||||
            await sql.insert(db, 'notes_history', {
 | 
			
		||||
                note_history_id: newNoteHistoryId,
 | 
			
		||||
                note_id: noteId,
 | 
			
		||||
                note_title: noteTitleForHistory,
 | 
			
		||||
@ -161,53 +161,53 @@ async function updateNote(noteId, newNote, ctx) {
 | 
			
		||||
                date_modified_to: now
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            await sync_table.addNoteHistorySync(newNoteHistoryId);
 | 
			
		||||
            await sync_table.addNoteHistorySync(db, newNoteHistoryId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await protectNoteHistory(noteId, ctx.getDataKeyOrNull(), newNote.detail.is_protected);
 | 
			
		||||
        await protectNoteHistory(db, noteId, ctx.getDataKeyOrNull(), newNote.detail.is_protected);
 | 
			
		||||
 | 
			
		||||
        await sql.execute("UPDATE notes SET note_title = ?, note_text = ?, is_protected = ?, date_modified = ? WHERE note_id = ?", [
 | 
			
		||||
        await sql.execute(db, "UPDATE notes SET note_title = ?, note_text = ?, is_protected = ?, date_modified = ? WHERE note_id = ?", [
 | 
			
		||||
            newNote.detail.note_title,
 | 
			
		||||
            newNote.detail.note_text,
 | 
			
		||||
            newNote.detail.is_protected,
 | 
			
		||||
            now,
 | 
			
		||||
            noteId]);
 | 
			
		||||
 | 
			
		||||
        await sql.remove("images", noteId);
 | 
			
		||||
        await sql.remove(db, "images", noteId);
 | 
			
		||||
 | 
			
		||||
        for (const img of newNote.images) {
 | 
			
		||||
            img.image_data = atob(img.image_data);
 | 
			
		||||
 | 
			
		||||
            await sql.insert("images", img);
 | 
			
		||||
            await sql.insert(db, "images", img);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await sql.remove("links", noteId);
 | 
			
		||||
        await sql.remove(db, "links", noteId);
 | 
			
		||||
 | 
			
		||||
        for (const link in newNote.links) {
 | 
			
		||||
            //await sql.insert("links", link);
 | 
			
		||||
            //await sql.insert(db, "links", link);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteSync(noteId);
 | 
			
		||||
        await sync_table.addNoteSync(db, noteId);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function deleteNote(noteTreeId) {
 | 
			
		||||
async function deleteNote(db, noteTreeId) {
 | 
			
		||||
    const now = utils.nowTimestamp();
 | 
			
		||||
    await sql.execute("UPDATE notes_tree SET is_deleted = 1, date_modified = ? WHERE note_tree_id = ?", [now, noteTreeId]);
 | 
			
		||||
    await sync_table.addNoteTreeSync(noteTreeId);
 | 
			
		||||
    await sql.execute(db, "UPDATE notes_tree SET is_deleted = 1, date_modified = ? WHERE note_tree_id = ?", [now, noteTreeId]);
 | 
			
		||||
    await sync_table.addNoteTreeSync(db, noteTreeId);
 | 
			
		||||
 | 
			
		||||
    const noteId = await sql.getSingleValue("SELECT note_id FROM notes_tree WHERE note_tree_id = ?", [noteTreeId]);
 | 
			
		||||
 | 
			
		||||
    const notDeletedNoteTreesCount = await sql.getSingleValue("SELECT COUNT(*) FROM notes_tree WHERE note_id = ? AND is_deleted = 0", [noteId]);
 | 
			
		||||
 | 
			
		||||
    if (!notDeletedNoteTreesCount) {
 | 
			
		||||
        await sql.execute("UPDATE notes SET is_deleted = 1, date_modified = ? WHERE note_id = ?", [now, noteId]);
 | 
			
		||||
        await sync_table.addNoteSync(noteId);
 | 
			
		||||
        await sql.execute(db, "UPDATE notes SET is_deleted = 1, date_modified = ? WHERE note_id = ?", [now, noteId]);
 | 
			
		||||
        await sync_table.addNoteSync(db, noteId);
 | 
			
		||||
 | 
			
		||||
        const children = await sql.getResults("SELECT note_tree_id FROM notes_tree WHERE note_pid = ? AND is_deleted = 0", [noteId]);
 | 
			
		||||
 | 
			
		||||
        for (const child of children) {
 | 
			
		||||
            await deleteNote(child.note_tree_id);
 | 
			
		||||
            await deleteNote(db, child.note_tree_id);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,38 +15,31 @@ async function getOption(optName) {
 | 
			
		||||
    return row['opt_value'];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function setOptionInTransaction(optName, optValue) {
 | 
			
		||||
    await sql.doInTransaction(async () => setOption(optName, optValue));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function setOption(optName, optValue) {
 | 
			
		||||
async function setOption(db, optName, optValue) {
 | 
			
		||||
    if (SYNCED_OPTIONS.includes(optName)) {
 | 
			
		||||
        await sync_table.addOptionsSync(optName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await setOptionNoSync(optName, optValue);
 | 
			
		||||
    await setOptionNoSync(db, optName, optValue);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function setOptionNoSync(optName, optValue) {
 | 
			
		||||
async function setOptionNoSync(db, optName, optValue) {
 | 
			
		||||
    const now = utils.nowTimestamp();
 | 
			
		||||
 | 
			
		||||
    await sql.execute("UPDATE options SET opt_value = ?, date_modified = ? WHERE opt_name = ?", [optValue, now, optName]);
 | 
			
		||||
    await sql.execute(db, "UPDATE options SET opt_value = ?, date_modified = ? WHERE opt_name = ?", [optValue, now, optName]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sql.dbReady.then(async () => {
 | 
			
		||||
    if (!await getOption('document_id')) {
 | 
			
		||||
        await setOption('document_id', utils.randomSecureToken(16));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!await getOption('document_secret')) {
 | 
			
		||||
        await setOption('document_secret', utils.randomSecureToken(16));
 | 
			
		||||
    if (!await getOption('document_id') || !await getOption('document_secret')) {
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await setOption(db, 'document_id', utils.randomSecureToken(16));
 | 
			
		||||
            await setOption(db, 'document_secret', utils.randomSecureToken(16));
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getOption,
 | 
			
		||||
    setOption,
 | 
			
		||||
    setOptionNoSync,
 | 
			
		||||
    setOptionInTransaction,
 | 
			
		||||
    SYNCED_OPTIONS
 | 
			
		||||
};
 | 
			
		||||
@ -11,18 +11,18 @@ async function verifyPassword(password) {
 | 
			
		||||
    return givenPasswordHash === dbPasswordHash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function setDataKey(password, plainTextDataKey) {
 | 
			
		||||
async function setDataKey(db, password, plainTextDataKey) {
 | 
			
		||||
    const passwordDerivedKey = await my_scrypt.getPasswordDerivedKey(password);
 | 
			
		||||
 | 
			
		||||
    const encryptedDataKeyIv = utils.randomSecureToken(16).slice(0, 16);
 | 
			
		||||
 | 
			
		||||
    await options.setOption('encrypted_data_key_iv', encryptedDataKeyIv);
 | 
			
		||||
    await options.setOption(db, 'encrypted_data_key_iv', encryptedDataKeyIv);
 | 
			
		||||
 | 
			
		||||
    const buffer = Buffer.from(plainTextDataKey);
 | 
			
		||||
 | 
			
		||||
    const newEncryptedDataKey = data_encryption.encrypt(passwordDerivedKey, encryptedDataKeyIv, buffer);
 | 
			
		||||
 | 
			
		||||
    await options.setOption('encrypted_data_key', newEncryptedDataKey);
 | 
			
		||||
    await options.setOption(db, 'encrypted_data_key', newEncryptedDataKey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getDataKey(password) {
 | 
			
		||||
 | 
			
		||||
@ -10,9 +10,11 @@ let allSourceIds = [];
 | 
			
		||||
 | 
			
		||||
sql.dbReady.then(async () => {
 | 
			
		||||
    try {
 | 
			
		||||
        sql.insert("source_ids", {
 | 
			
		||||
            source_id: currentSourceId,
 | 
			
		||||
            date_created: utils.nowTimestamp()
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await sql.insert(db, "source_ids", {
 | 
			
		||||
                source_id: currentSourceId,
 | 
			
		||||
                date_created: utils.nowTimestamp()
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        allSourceIds = await sql.getFlattenedResults("source_id", "SELECT source_id FROM source_ids");
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,16 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
const utils = require('./utils');
 | 
			
		||||
const log = require('./log');
 | 
			
		||||
const dataDir = require('./data_dir');
 | 
			
		||||
const sqlite = require('sqlite');
 | 
			
		||||
 | 
			
		||||
const dbReady = (() => {
 | 
			
		||||
    const db = require('sqlite');
 | 
			
		||||
async function createConnection() {
 | 
			
		||||
    return await sqlite.open(dataDir.DOCUMENT_PATH, {Promise});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    return db.open(dataDir.DOCUMENT_PATH, {Promise}).then(() => db);
 | 
			
		||||
})();
 | 
			
		||||
const dbReady = createConnection();
 | 
			
		||||
 | 
			
		||||
async function insert(table_name, rec, replace = false) {
 | 
			
		||||
async function insert(db, table_name, rec, replace = false) {
 | 
			
		||||
    const keys = Object.keys(rec);
 | 
			
		||||
    if (keys.length === 0) {
 | 
			
		||||
        log.error("Can't insert empty object into table " + table_name);
 | 
			
		||||
@ -22,33 +22,36 @@ async function insert(table_name, rec, replace = false) {
 | 
			
		||||
 | 
			
		||||
    const query = "INSERT " + (replace ? "OR REPLACE" : "") + " INTO " + table_name + "(" + columns + ") VALUES (" + questionMarks + ")";
 | 
			
		||||
 | 
			
		||||
    const res = await execute(query, Object.values(rec));
 | 
			
		||||
    const res = await execute(db, query, Object.values(rec));
 | 
			
		||||
 | 
			
		||||
    return res.lastID;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function replace(table_name, rec) {
 | 
			
		||||
    return await insert(table_name, rec, true);
 | 
			
		||||
async function replace(db, table_name, rec) {
 | 
			
		||||
    return await insert(db, table_name, rec, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function beginTransaction() {
 | 
			
		||||
    return await wrap(async db => db.run("BEGIN"));
 | 
			
		||||
async function beginTransaction(db) {
 | 
			
		||||
    return await wrap(async () => db.run("BEGIN"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function commit() {
 | 
			
		||||
    return await wrap(async db => db.run("COMMIT"));
 | 
			
		||||
async function commit(db) {
 | 
			
		||||
    return await wrap(async () => db.run("COMMIT"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function rollback() {
 | 
			
		||||
    return await wrap(async db => db.run("ROLLBACK"));
 | 
			
		||||
async function rollback(db) {
 | 
			
		||||
    return await wrap(async () => db.run("ROLLBACK"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getSingleResult(query, params = []) {
 | 
			
		||||
    return await wrap(async db => db.get(query, ...params));
 | 
			
		||||
    const db = await dbReady;
 | 
			
		||||
 | 
			
		||||
    return await wrap(async () => db.get(query, ...params));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getSingleResultOrNull(query, params = []) {
 | 
			
		||||
    const all = await wrap(async db => db.all(query, ...params));
 | 
			
		||||
    const db = await dbReady;
 | 
			
		||||
    const all = await wrap(async () => db.all(query, ...params));
 | 
			
		||||
 | 
			
		||||
    return all.length > 0 ? all[0] : null;
 | 
			
		||||
}
 | 
			
		||||
@ -64,7 +67,9 @@ async function getSingleValue(query, params = []) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getResults(query, params = []) {
 | 
			
		||||
    return await wrap(async db => db.all(query, ...params));
 | 
			
		||||
    const db = await dbReady;
 | 
			
		||||
 | 
			
		||||
    return await wrap(async () => db.all(query, ...params));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getMap(query, params = []) {
 | 
			
		||||
@ -91,25 +96,23 @@ async function getFlattenedResults(key, query, params = []) {
 | 
			
		||||
    return list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function execute(query, params = []) {
 | 
			
		||||
    return await wrap(async db => db.run(query, ...params));
 | 
			
		||||
async function execute(db, query, params = []) {
 | 
			
		||||
    return await wrap(async () => db.run(query, ...params));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function executeScript(query) {
 | 
			
		||||
    return await wrap(async db => db.exec(query));
 | 
			
		||||
async function executeScript(db, query) {
 | 
			
		||||
    return await wrap(async () => db.exec(query));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function remove(tableName, noteId) {
 | 
			
		||||
    return await execute("DELETE FROM " + tableName + " WHERE note_id = ?", [noteId]);
 | 
			
		||||
async function remove(db, tableName, noteId) {
 | 
			
		||||
    return await execute(db, "DELETE FROM " + tableName + " WHERE note_id = ?", [noteId]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function wrap(func) {
 | 
			
		||||
    const thisError = new Error();
 | 
			
		||||
 | 
			
		||||
    const db = await dbReady;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        return await func(db);
 | 
			
		||||
        return await func();
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        log.error("Error executing query. Inner exception: " + e.stack + thisError.stack);
 | 
			
		||||
@ -120,19 +123,20 @@ async function wrap(func) {
 | 
			
		||||
 | 
			
		||||
async function doInTransaction(func) {
 | 
			
		||||
    const error = new Error(); // to capture correct stack trace in case of exception
 | 
			
		||||
    const db = await createConnection();
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
 | 
			
		||||
        await beginTransaction();
 | 
			
		||||
        await beginTransaction(db);
 | 
			
		||||
 | 
			
		||||
        await func();
 | 
			
		||||
        await func(db);
 | 
			
		||||
 | 
			
		||||
        await commit();
 | 
			
		||||
        await commit(db);
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        log.error("Error executing transaction, executing rollback. Inner exception: " + e.stack + error.stack);
 | 
			
		||||
 | 
			
		||||
        await rollback();
 | 
			
		||||
        await rollback(db);
 | 
			
		||||
 | 
			
		||||
        throw e;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -149,7 +149,9 @@ async function pullSync(syncContext) {
 | 
			
		||||
            throw new Error("Unrecognized entity type " + sync.entity_name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await options.setOption('last_synced_pull', sync.id);
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await options.setOption(db, 'last_synced_pull', sync.id);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    log.info("Finished pull");
 | 
			
		||||
@ -182,7 +184,9 @@ async function pushSync(syncContext) {
 | 
			
		||||
 | 
			
		||||
        lastSyncedPush = sync.id;
 | 
			
		||||
 | 
			
		||||
        await options.setOption('last_synced_push', lastSyncedPush);
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await options.setOption(db, 'last_synced_push', lastSyncedPush);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -258,10 +262,10 @@ async function checkContentHash(syncContext) {
 | 
			
		||||
    const localContentHash = await content_hash.getContentHash();
 | 
			
		||||
 | 
			
		||||
    if (resp.content_hash === localContentHash) {
 | 
			
		||||
        log.info("Content hash check passed with value: " + localContentHash);
 | 
			
		||||
        log.info("Content hash check PASSED with value: " + localContentHash);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        await event_log.addEvent("Content hash check failed. Local is " + localContentHash + ", remote is " + resp.content_hash);
 | 
			
		||||
        await event_log.addEvent("Content hash check FAILED. Local is " + localContentHash + ", remote is " + resp.content_hash);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,32 +2,32 @@ const sql = require('./sql');
 | 
			
		||||
const source_id = require('./source_id');
 | 
			
		||||
const utils = require('./utils');
 | 
			
		||||
 | 
			
		||||
async function addNoteSync(noteId, sourceId) {
 | 
			
		||||
    await addEntitySync("notes", noteId, sourceId)
 | 
			
		||||
async function addNoteSync(db, noteId, sourceId) {
 | 
			
		||||
    await addEntitySync(db, "notes", noteId, sourceId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function addNoteTreeSync(noteTreeId, sourceId) {
 | 
			
		||||
    await addEntitySync("notes_tree", noteTreeId, sourceId)
 | 
			
		||||
async function addNoteTreeSync(db, noteTreeId, sourceId) {
 | 
			
		||||
    await addEntitySync(db, "notes_tree", noteTreeId, sourceId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function addNoteReorderingSync(parentNoteTreeId, sourceId) {
 | 
			
		||||
    await addEntitySync("notes_reordering", parentNoteTreeId, sourceId)
 | 
			
		||||
async function addNoteReorderingSync(db, parentNoteTreeId, sourceId) {
 | 
			
		||||
    await addEntitySync(db, "notes_reordering", parentNoteTreeId, sourceId)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function addNoteHistorySync(noteHistoryId, sourceId) {
 | 
			
		||||
    await addEntitySync("notes_history", noteHistoryId, sourceId);
 | 
			
		||||
async function addNoteHistorySync(db, noteHistoryId, sourceId) {
 | 
			
		||||
    await addEntitySync(db, "notes_history", noteHistoryId, sourceId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function addOptionsSync(optName, sourceId) {
 | 
			
		||||
    await addEntitySync("options", optName, sourceId);
 | 
			
		||||
async function addOptionsSync(db, optName, sourceId) {
 | 
			
		||||
    await addEntitySync(db, "options", optName, sourceId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function addRecentNoteSync(notePath, sourceId) {
 | 
			
		||||
    await addEntitySync("recent_notes", notePath, sourceId);
 | 
			
		||||
async function addRecentNoteSync(db, notePath, sourceId) {
 | 
			
		||||
    await addEntitySync(db, "recent_notes", notePath, sourceId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function addEntitySync(entityName, entityId, sourceId) {
 | 
			
		||||
    await sql.replace("sync", {
 | 
			
		||||
async function addEntitySync(db, entityName, entityId, sourceId) {
 | 
			
		||||
    await sql.replace(db, "sync", {
 | 
			
		||||
        entity_name: entityName,
 | 
			
		||||
        entity_id: entityId,
 | 
			
		||||
        sync_date: utils.nowTimestamp(),
 | 
			
		||||
 | 
			
		||||
@ -10,71 +10,71 @@ async function updateNote(entity, links, sourceId) {
 | 
			
		||||
    const origNote = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [entity.note_id]);
 | 
			
		||||
 | 
			
		||||
    if (!origNote || origNote.date_modified <= entity.date_modified) {
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
            await sql.replace("notes", entity);
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await sql.replace(db, "notes", entity);
 | 
			
		||||
 | 
			
		||||
            await sql.remove("links", entity.note_id);
 | 
			
		||||
            await sql.remove(db, "links", entity.note_id);
 | 
			
		||||
 | 
			
		||||
            for (const link of links) {
 | 
			
		||||
                delete link['lnk_id'];
 | 
			
		||||
 | 
			
		||||
                //await sql.insert('link', link);
 | 
			
		||||
                //await sql.insert(db, 'link', link);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await sync_table.addNoteSync(entity.note_id, sourceId);
 | 
			
		||||
            await eventLog.addNoteEvent(entity.note_id, "Synced note <note>");
 | 
			
		||||
            await sync_table.addNoteSync(db, entity.note_id, sourceId);
 | 
			
		||||
            await eventLog.addNoteEvent(db, entity.note_id, "Synced note <note>");
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        log.info("Update/sync note " + entity.note_id);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        await eventLog.addNoteEvent(entity.note_id, "Sync conflict in note <note>, " + utils.formatTwoTimestamps(origNote.date_modified, entity.date_modified));
 | 
			
		||||
        await eventLog.addNoteEvent(db, entity.note_id, "Sync conflict in note <note>, " + utils.formatTwoTimestamps(origNote.date_modified, entity.date_modified));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function updateNoteTree(entity, sourceId) {
 | 
			
		||||
    const orig = await sql.getSingleResultOrNull("SELECT * FROM notes_tree WHERE note_tree_id = ?", [entity.note_tree_id]);
 | 
			
		||||
 | 
			
		||||
    if (orig === null || orig.date_modified < entity.date_modified) {
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        if (orig === null || orig.date_modified < entity.date_modified) {
 | 
			
		||||
            delete entity.is_expanded;
 | 
			
		||||
 | 
			
		||||
            await sql.replace('notes_tree', entity);
 | 
			
		||||
            await sql.replace(db, 'notes_tree', entity);
 | 
			
		||||
 | 
			
		||||
            await sync_table.addNoteTreeSync(entity.note_tree_id, sourceId);
 | 
			
		||||
        });
 | 
			
		||||
            await sync_table.addNoteTreeSync(db, entity.note_tree_id, sourceId);
 | 
			
		||||
 | 
			
		||||
        log.info("Update/sync note tree " + entity.note_tree_id);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        await eventLog.addNoteEvent(entity.note_tree_id, "Sync conflict in note tree <note>, " + utils.formatTwoTimestamps(orig.date_modified, entity.date_modified));
 | 
			
		||||
    }
 | 
			
		||||
            log.info("Update/sync note tree " + entity.note_tree_id);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            await eventLog.addNoteEvent(db, entity.note_tree_id, "Sync conflict in note tree <note>, " + utils.formatTwoTimestamps(orig.date_modified, entity.date_modified));
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function updateNoteHistory(entity, sourceId) {
 | 
			
		||||
    const orig = await sql.getSingleResultOrNull("SELECT * FROM notes_history WHERE note_history_id = ?", [entity.note_history_id]);
 | 
			
		||||
 | 
			
		||||
    if (orig === null || orig.date_modified_to < entity.date_modified_to) {
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
            await sql.replace('notes_history', entity);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        if (orig === null || orig.date_modified_to < entity.date_modified_to) {
 | 
			
		||||
            await sql.replace(db, 'notes_history', entity);
 | 
			
		||||
 | 
			
		||||
            await sync_table.addNoteHistorySync(entity.note_history_id, sourceId);
 | 
			
		||||
        });
 | 
			
		||||
            await sync_table.addNoteHistorySync(db, entity.note_history_id, sourceId);
 | 
			
		||||
 | 
			
		||||
        log.info("Update/sync note history " + entity.note_history_id);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        await eventLog.addNoteEvent(entity.note_id, "Sync conflict in note history for <note>, " + utils.formatTwoTimestamps(orig.date_modified_to, entity.date_modified_to));
 | 
			
		||||
    }
 | 
			
		||||
            log.info("Update/sync note history " + entity.note_history_id);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            await eventLog.addNoteEvent(db, entity.note_id, "Sync conflict in note history for <note>, " + utils.formatTwoTimestamps(orig.date_modified_to, entity.date_modified_to));
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function updateNoteReordering(entity, sourceId) {
 | 
			
		||||
    await sql.doInTransaction(async () => {
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        Object.keys(entity.ordering).forEach(async key => {
 | 
			
		||||
            await sql.execute("UPDATE notes_tree SET note_pos = ? WHERE note_tree_id = ?", [entity.ordering[key], key]);
 | 
			
		||||
            await sql.execute(db, "UPDATE notes_tree SET note_pos = ? WHERE note_tree_id = ?", [entity.ordering[key], key]);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await sync_table.addNoteReorderingSync(entity.note_pid, sourceId);
 | 
			
		||||
        await sync_table.addNoteReorderingSync(db, entity.note_pid, sourceId);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -85,28 +85,28 @@ async function updateOptions(entity, sourceId) {
 | 
			
		||||
 | 
			
		||||
    const orig = await sql.getSingleResultOrNull("SELECT * FROM options WHERE opt_name = ?", [entity.opt_name]);
 | 
			
		||||
 | 
			
		||||
    if (orig === null || orig.date_modified < entity.date_modified) {
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
            await sql.replace('options', entity);
 | 
			
		||||
    await sql.doInTransaction(async db => {
 | 
			
		||||
        if (orig === null || orig.date_modified < entity.date_modified) {
 | 
			
		||||
            await sql.replace(db, 'options', entity);
 | 
			
		||||
 | 
			
		||||
            await sync_table.addOptionsSync(entity.opt_name, sourceId);
 | 
			
		||||
        });
 | 
			
		||||
            await sync_table.addOptionsSync(db, entity.opt_name, sourceId);
 | 
			
		||||
 | 
			
		||||
        await eventLog.addEvent("Synced option " + entity.opt_name);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        await eventLog.addEvent("Sync conflict in options for " + entity.opt_name + ", " + utils.formatTwoTimestamps(orig.date_modified, entity.date_modified));
 | 
			
		||||
    }
 | 
			
		||||
            await eventLog.addEvent(db, "Synced option " + entity.opt_name);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            await eventLog.addEvent(db, "Sync conflict in options for " + entity.opt_name + ", " + utils.formatTwoTimestamps(orig.date_modified, entity.date_modified));
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function updateRecentNotes(entity, sourceId) {
 | 
			
		||||
    const orig = await sql.getSingleResultOrNull("SELECT * FROM recent_notes WHERE note_path = ?", [entity.note_path]);
 | 
			
		||||
 | 
			
		||||
    if (orig === null || orig.date_accessed < entity.date_accessed) {
 | 
			
		||||
        await sql.doInTransaction(async () => {
 | 
			
		||||
            await sql.replace('recent_notes', entity);
 | 
			
		||||
        await sql.doInTransaction(async db => {
 | 
			
		||||
            await sql.replace(db, 'recent_notes', entity);
 | 
			
		||||
 | 
			
		||||
            await sync_table.addRecentNoteSync(entity.note_path, sourceId);
 | 
			
		||||
            await sync_table.addRecentNoteSync(db, entity.note_path, sourceId);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user