diff --git a/esbuild.config.mjs b/esbuild.config.mjs new file mode 100644 index 0000000..b1e0f44 --- /dev/null +++ b/esbuild.config.mjs @@ -0,0 +1,37 @@ +import esbuild from "esbuild"; +import process from "process"; +import builtins from "builtin-modules"; +import sveltePlugin from "esbuild-svelte"; +import sveltePreprocess from "svelte-preprocess"; + +const banner = `/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ +`; + +const prod = process.argv[2] === "production"; + +esbuild + .build({ + banner: { + js: banner, + }, + entryPoints: ["src/main.ts"], + bundle: true, + external: ["obsidian", "electron", ...builtins], + format: "cjs", + watch: !prod, + target: "es2015", + logLevel: "info", + sourcemap: prod ? false : "inline", + treeShaking: true, + plugins: [ + sveltePlugin({ + preprocess: sveltePreprocess(), + compilerOptions: { css: true }, + }), + ], + outfile: "main.js", + }) + .catch(() => process.exit(1)); diff --git a/manifest.json b/manifest.json index d92f744..6d36796 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-livesync", "name": "Self-hosted LiveSync", - "version": "0.6.1", + "version": "0.7.0", "minAppVersion": "0.9.12", "description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.", "author": "vorotamoroz", diff --git a/package-lock.json b/package-lock.json index e432d52..295b1e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "obsidian-livesync", - "version": "0.6.1", + "version": "0.7.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "obsidian-livesync", - "version": "0.6.1", + "version": "0.7.0", "license": "MIT", "dependencies": { "diff-match-patch": "^1.0.5", @@ -17,14 +17,19 @@ "@rollup/plugin-node-resolve": "^11.2.1", "@rollup/plugin-typescript": "^8.2.1", "@types/diff-match-patch": "^1.0.32", + "@types/pouchdb": "^6.4.0", "@types/pouchdb-browser": "^6.1.3", "@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/parser": "^5.0.0", + "builtin-modules": "^3.2.0", + "esbuild": "0.13.12", + "esbuild-svelte": "^0.6.0", "eslint": "^7.32.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-plugin-import": "^2.25.2", "obsidian": "^0.13.11", "rollup": "^2.32.1", + "svelte-preprocess": "^4.10.2", "tslib": "^2.2.0", "typescript": "^4.2.4" } @@ -389,6 +394,47 @@ "integrity": "sha512-zv8ukKci1mrILYiQOwGSV4FpkZhyxQtuFWGya2GujWg+zVAeRQ4qbaMmWp9vb9889CFA8JECH7lkwCL6Ygg8kA==", "dev": true }, + "node_modules/@types/pouchdb": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@types/pouchdb/-/pouchdb-6.4.0.tgz", + "integrity": "sha512-eGCpX+NXhd5VLJuJMzwe3L79fa9+IDTrAG3CPaf4s/31PD56hOrhDJTSmRELSXuiqXr6+OHzzP0PldSaWsFt7w==", + "dev": true, + "dependencies": { + "@types/pouchdb-adapter-cordova-sqlite": "*", + "@types/pouchdb-adapter-fruitdown": "*", + "@types/pouchdb-adapter-http": "*", + "@types/pouchdb-adapter-idb": "*", + "@types/pouchdb-adapter-leveldb": "*", + "@types/pouchdb-adapter-localstorage": "*", + "@types/pouchdb-adapter-memory": "*", + "@types/pouchdb-adapter-node-websql": "*", + "@types/pouchdb-adapter-websql": "*", + "@types/pouchdb-browser": "*", + "@types/pouchdb-core": "*", + "@types/pouchdb-http": "*", + "@types/pouchdb-mapreduce": "*", + "@types/pouchdb-node": "*", + "@types/pouchdb-replication": "*" + } + }, + "node_modules/@types/pouchdb-adapter-cordova-sqlite": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-cordova-sqlite/-/pouchdb-adapter-cordova-sqlite-1.0.1.tgz", + "integrity": "sha512-nqlXpW1ho3KBg1mUQvZgH2755y3z/rw4UA7ZJCPMRTHofxGMY8izRVw5rHBL4/7P615or0J2udpRYxgkT3D02g==", + "dev": true, + "dependencies": { + "@types/pouchdb-core": "*" + } + }, + "node_modules/@types/pouchdb-adapter-fruitdown": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-fruitdown/-/pouchdb-adapter-fruitdown-6.1.3.tgz", + "integrity": "sha512-Wz1Z1JLOW1hgmFQjqnSkmyyfH7by/iWb4abKn684WMvQfmxx6BxKJpJ4+eulkVPQzzgMMSgU1MpnQOm9FgRkbw==", + "dev": true, + "dependencies": { + "@types/pouchdb-core": "*" + } + }, "node_modules/@types/pouchdb-adapter-http": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-http/-/pouchdb-adapter-http-6.1.3.tgz", @@ -407,6 +453,43 @@ "@types/pouchdb-core": "*" } }, + "node_modules/@types/pouchdb-adapter-leveldb": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-leveldb/-/pouchdb-adapter-leveldb-6.1.3.tgz", + "integrity": "sha512-ex8NFqQGFwEpFi7AaZ5YofmuemfZNsL3nTFZBUCAKYMBkazQij1pe2ILLStSvJr0XS0qxgXjCEW19T5Wqiiskg==", + "dev": true, + "dependencies": { + "@types/pouchdb-core": "*" + } + }, + "node_modules/@types/pouchdb-adapter-localstorage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-localstorage/-/pouchdb-adapter-localstorage-6.1.3.tgz", + "integrity": "sha512-oor040tye1KKiGLWYtIy7rRT7C2yoyX3Tf6elEJRpjOA7Ja/H8lKc4LaSh9ATbptIcES6MRqZDxtp7ly9hsW3Q==", + "dev": true, + "dependencies": { + "@types/pouchdb-core": "*" + } + }, + "node_modules/@types/pouchdb-adapter-memory": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-memory/-/pouchdb-adapter-memory-6.1.3.tgz", + "integrity": "sha512-gVbsIMzDzgZYThFVT4eVNsmuZwVm/4jDxP1sjlgc3qtDIxbtBhGgyNfcskwwz9Zu5Lv1avkDsIWvcxQhnvRlHg==", + "dev": true, + "dependencies": { + "@types/pouchdb-core": "*" + } + }, + "node_modules/@types/pouchdb-adapter-node-websql": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-node-websql/-/pouchdb-adapter-node-websql-6.1.3.tgz", + "integrity": "sha512-F/P+os6Jsa7CgHtH64+Z0HfwIcj0hIRB5z8gNhF7L7dxPWoAfkopK5H2gydrP3sQrlGyN4WInF+UJW/Zu1+FKg==", + "dev": true, + "dependencies": { + "@types/pouchdb-adapter-websql": "*", + "@types/pouchdb-core": "*" + } + }, "node_modules/@types/pouchdb-adapter-websql": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-websql/-/pouchdb-adapter-websql-6.1.4.tgz", @@ -449,6 +532,16 @@ "@types/pouchdb-core": "*" } }, + "node_modules/@types/pouchdb-http": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-http/-/pouchdb-http-6.1.3.tgz", + "integrity": "sha512-0e9E5SqNOyPl/3FnEIbENssB4FlJsNYuOy131nxrZk36S+y1R/6qO7ZVRypWpGTqBWSuVd7gCsq2UDwO/285+w==", + "dev": true, + "dependencies": { + "@types/pouchdb-adapter-http": "*", + "@types/pouchdb-core": "*" + } + }, "node_modules/@types/pouchdb-mapreduce": { "version": "6.1.5", "resolved": "https://registry.npmjs.org/@types/pouchdb-mapreduce/-/pouchdb-mapreduce-6.1.5.tgz", @@ -458,6 +551,19 @@ "@types/pouchdb-core": "*" } }, + "node_modules/@types/pouchdb-node": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/pouchdb-node/-/pouchdb-node-6.1.4.tgz", + "integrity": "sha512-wnTCH8X1JOPpNOfVhz8HW0AvmdHh6pt40MuRj0jQnK7QEHsHS79WujsKTKSOF8QXtPwpvCNSsI7ut7H7tfxxJQ==", + "dev": true, + "dependencies": { + "@types/pouchdb-adapter-http": "*", + "@types/pouchdb-adapter-leveldb": "*", + "@types/pouchdb-core": "*", + "@types/pouchdb-mapreduce": "*", + "@types/pouchdb-replication": "*" + } + }, "node_modules/@types/pouchdb-replication": { "version": "6.4.3", "resolved": "https://registry.npmjs.org/@types/pouchdb-replication/-/pouchdb-replication-6.4.3.tgz", @@ -468,6 +574,12 @@ "@types/pouchdb-find": "*" } }, + "node_modules/@types/pug": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", + "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", + "dev": true + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -477,6 +589,15 @@ "@types/node": "*" } }, + "node_modules/@types/sass": { + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", + "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/tern": { "version": "0.23.4", "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", @@ -831,6 +952,15 @@ "node": ">=8" } }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/builtin-modules": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", @@ -975,6 +1105,15 @@ "node": ">= 0.4" } }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/diff-match-patch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", @@ -1073,6 +1212,277 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, + "node_modules/esbuild": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.12.tgz", + "integrity": "sha512-vTKKUt+yoz61U/BbrnmlG9XIjwpdIxmHB8DlPR0AAW6OdS+nBQBci6LUHU2q9WbBobMEIQxxDpKbkmOGYvxsow==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "optionalDependencies": { + "esbuild-android-arm64": "0.13.12", + "esbuild-darwin-64": "0.13.12", + "esbuild-darwin-arm64": "0.13.12", + "esbuild-freebsd-64": "0.13.12", + "esbuild-freebsd-arm64": "0.13.12", + "esbuild-linux-32": "0.13.12", + "esbuild-linux-64": "0.13.12", + "esbuild-linux-arm": "0.13.12", + "esbuild-linux-arm64": "0.13.12", + "esbuild-linux-mips64le": "0.13.12", + "esbuild-linux-ppc64le": "0.13.12", + "esbuild-netbsd-64": "0.13.12", + "esbuild-openbsd-64": "0.13.12", + "esbuild-sunos-64": "0.13.12", + "esbuild-windows-32": "0.13.12", + "esbuild-windows-64": "0.13.12", + "esbuild-windows-arm64": "0.13.12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.12.tgz", + "integrity": "sha512-TSVZVrb4EIXz6KaYjXfTzPyyRpXV5zgYIADXtQsIenjZ78myvDGaPi11o4ZSaHIwFHsuwkB6ne5SZRBwAQ7maw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/esbuild-darwin-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.12.tgz", + "integrity": "sha512-c51C+N+UHySoV2lgfWSwwmlnLnL0JWj/LzuZt9Ltk9ub1s2Y8cr6SQV5W3mqVH1egUceew6KZ8GyI4nwu+fhsw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.12.tgz", + "integrity": "sha512-JvAMtshP45Hd8A8wOzjkY1xAnTKTYuP/QUaKp5eUQGX+76GIie3fCdUUr2ZEKdvpSImNqxiZSIMziEiGB5oUmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.12.tgz", + "integrity": "sha512-r6On/Skv9f0ZjTu6PW5o7pdXr8aOgtFOEURJZYf1XAJs0IQ+gW+o1DzXjVkIoT+n1cm3N/t1KRJfX71MPg/ZUA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.12.tgz", + "integrity": "sha512-F6LmI2Q1gii073kmBE3NOTt/6zLL5zvZsxNLF8PMAwdHc+iBhD1vzfI8uQZMJA1IgXa3ocr3L3DJH9fLGXy6Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-linux-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.12.tgz", + "integrity": "sha512-U1UZwG3UIwF7/V4tCVAo/nkBV9ag5KJiJTt+gaCmLVWH3bPLX7y+fNlhIWZy8raTMnXhMKfaTvWZ9TtmXzvkuQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.12.tgz", + "integrity": "sha512-YpXSwtu2NxN3N4ifJxEdsgd6Q5d8LYqskrAwjmoCT6yQnEHJSF5uWcxv783HWN7lnGpJi9KUtDvYsnMdyGw71Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.12.tgz", + "integrity": "sha512-SyiT/JKxU6J+DY2qUiSLZJqCAftIt3uoGejZ0HDnUM2MGJqEGSGh7p1ecVL2gna3PxS4P+j6WAehCwgkBPXNIw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.12.tgz", + "integrity": "sha512-sgDNb8kb3BVodtAlcFGgwk+43KFCYjnFOaOfJibXnnIojNWuJHpL6aQJ4mumzNWw8Rt1xEtDQyuGK9f+Y24jGA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.12.tgz", + "integrity": "sha512-qQJHlZBG+QwVIA8AbTEtbvF084QgDi4DaUsUnA+EolY1bxrG+UyOuGflM2ZritGhfS/k7THFjJbjH2wIeoKA2g==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.12.tgz", + "integrity": "sha512-2dSnm1ldL7Lppwlo04CGQUpwNn5hGqXI38OzaoPOkRsBRWFBozyGxTFSee/zHFS+Pdh3b28JJbRK3owrrRgWNw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.12.tgz", + "integrity": "sha512-D4raxr02dcRiQNbxOLzpqBzcJNFAdsDNxjUbKkDMZBkL54Z0vZh4LRndycdZAMcIdizC/l/Yp/ZsBdAFxc5nbA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ] + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.12.tgz", + "integrity": "sha512-KuLCmYMb2kh05QuPJ+va60bKIH5wHL8ypDkmpy47lzwmdxNsuySeCMHuTv5o2Af1RUn5KLO5ZxaZeq4GEY7DaQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/esbuild-sunos-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.12.tgz", + "integrity": "sha512-jBsF+e0woK3miKI8ufGWKG3o3rY9DpHvCVRn5eburMIIE+2c+y3IZ1srsthKyKI6kkXLvV4Cf/E7w56kLipMXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ] + }, + "node_modules/esbuild-svelte": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.6.2.tgz", + "integrity": "sha512-FRHcyaQqIm4ncFsbk97b+80fHAI0VA15Ty56zOai9zpOPOQ1kgqWJt7JYn0jNGm+1VSvJNaGUj8QB85H/P43jA==", + "dev": true, + "dependencies": { + "svelte": "^3.46.2" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "esbuild": ">=0.9.6" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.12.tgz", + "integrity": "sha512-L9m4lLFQrFeR7F+eLZXG82SbXZfUhyfu6CexZEil6vm+lc7GDCE0Q8DiNutkpzjv1+RAbIGVva9muItQ7HVTkQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.12.tgz", + "integrity": "sha512-k4tX4uJlSbSkfs78W5d9+I9gpd+7N95W7H2bgOMFPsYREVJs31+Q2gLLHlsnlY95zBoPQMIzHooUIsixQIBjaQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.12.tgz", + "integrity": "sha512-2tTv/BpYRIvuwHpp2M960nG7uvL+d78LFW/ikPItO+2GfK51CswIKSetSpDii+cjz8e9iSPgs+BU4o8nWICBwQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1649,6 +2059,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -2115,6 +2531,15 @@ "node": ">=8.6" } }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2133,6 +2558,18 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -2523,6 +2960,30 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/sander": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", + "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=", + "dev": true, + "dependencies": { + "es6-promise": "^3.1.2", + "graceful-fs": "^4.1.3", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.2" + } + }, + "node_modules/sander/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -2599,6 +3060,21 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/sorcery": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", + "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=", + "dev": true, + "dependencies": { + "buffer-crc32": "^0.2.5", + "minimist": "^1.2.0", + "sander": "^0.5.0", + "sourcemap-codec": "^1.3.0" + }, + "bin": { + "sorcery": "bin/index.js" + } + }, "node_modules/sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -2672,6 +3148,18 @@ "node": ">=4" } }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -2702,6 +3190,81 @@ "node": ">=8" } }, + "node_modules/svelte": { + "version": "3.46.4", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.46.4.tgz", + "integrity": "sha512-qKJzw6DpA33CIa+C/rGp4AUdSfii0DOTCzj/2YpSKKayw5WGSS624Et9L1nU1k2OVRS9vaENQXp2CVZNU+xvIg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/svelte-preprocess": { + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.3.tgz", + "integrity": "sha512-ttw17lJfb/dx2ZJT9sesaXT5l7mPQ9Apx1H496Kli3Hkk7orIRGpOw6rCPkRNzr6ueVPqb4vzodS5x7sBFhKHw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@types/pug": "^2.0.4", + "@types/sass": "^1.16.0", + "detect-indent": "^6.0.0", + "magic-string": "^0.25.7", + "sorcery": "^0.10.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">= 9.11.2" + }, + "peerDependencies": { + "@babel/core": "^7.10.2", + "coffeescript": "^2.5.1", + "less": "^3.11.3 || ^4.0.0", + "postcss": "^7 || ^8", + "postcss-load-config": "^2.1.0 || ^3.0.0", + "pug": "^3.0.0", + "sass": "^1.26.8", + "stylus": "^0.55.0", + "sugarss": "^2.0.0", + "svelte": "^3.23.0", + "typescript": "^3.9.5 || ^4.0.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "coffeescript": { + "optional": true + }, + "less": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "postcss": { + "optional": true + }, + "postcss-load-config": { + "optional": true + }, + "pug": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, "node_modules/table": { "version": "6.7.5", "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", @@ -3230,6 +3793,47 @@ "integrity": "sha512-zv8ukKci1mrILYiQOwGSV4FpkZhyxQtuFWGya2GujWg+zVAeRQ4qbaMmWp9vb9889CFA8JECH7lkwCL6Ygg8kA==", "dev": true }, + "@types/pouchdb": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@types/pouchdb/-/pouchdb-6.4.0.tgz", + "integrity": "sha512-eGCpX+NXhd5VLJuJMzwe3L79fa9+IDTrAG3CPaf4s/31PD56hOrhDJTSmRELSXuiqXr6+OHzzP0PldSaWsFt7w==", + "dev": true, + "requires": { + "@types/pouchdb-adapter-cordova-sqlite": "*", + "@types/pouchdb-adapter-fruitdown": "*", + "@types/pouchdb-adapter-http": "*", + "@types/pouchdb-adapter-idb": "*", + "@types/pouchdb-adapter-leveldb": "*", + "@types/pouchdb-adapter-localstorage": "*", + "@types/pouchdb-adapter-memory": "*", + "@types/pouchdb-adapter-node-websql": "*", + "@types/pouchdb-adapter-websql": "*", + "@types/pouchdb-browser": "*", + "@types/pouchdb-core": "*", + "@types/pouchdb-http": "*", + "@types/pouchdb-mapreduce": "*", + "@types/pouchdb-node": "*", + "@types/pouchdb-replication": "*" + } + }, + "@types/pouchdb-adapter-cordova-sqlite": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-cordova-sqlite/-/pouchdb-adapter-cordova-sqlite-1.0.1.tgz", + "integrity": "sha512-nqlXpW1ho3KBg1mUQvZgH2755y3z/rw4UA7ZJCPMRTHofxGMY8izRVw5rHBL4/7P615or0J2udpRYxgkT3D02g==", + "dev": true, + "requires": { + "@types/pouchdb-core": "*" + } + }, + "@types/pouchdb-adapter-fruitdown": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-fruitdown/-/pouchdb-adapter-fruitdown-6.1.3.tgz", + "integrity": "sha512-Wz1Z1JLOW1hgmFQjqnSkmyyfH7by/iWb4abKn684WMvQfmxx6BxKJpJ4+eulkVPQzzgMMSgU1MpnQOm9FgRkbw==", + "dev": true, + "requires": { + "@types/pouchdb-core": "*" + } + }, "@types/pouchdb-adapter-http": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-http/-/pouchdb-adapter-http-6.1.3.tgz", @@ -3248,6 +3852,43 @@ "@types/pouchdb-core": "*" } }, + "@types/pouchdb-adapter-leveldb": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-leveldb/-/pouchdb-adapter-leveldb-6.1.3.tgz", + "integrity": "sha512-ex8NFqQGFwEpFi7AaZ5YofmuemfZNsL3nTFZBUCAKYMBkazQij1pe2ILLStSvJr0XS0qxgXjCEW19T5Wqiiskg==", + "dev": true, + "requires": { + "@types/pouchdb-core": "*" + } + }, + "@types/pouchdb-adapter-localstorage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-localstorage/-/pouchdb-adapter-localstorage-6.1.3.tgz", + "integrity": "sha512-oor040tye1KKiGLWYtIy7rRT7C2yoyX3Tf6elEJRpjOA7Ja/H8lKc4LaSh9ATbptIcES6MRqZDxtp7ly9hsW3Q==", + "dev": true, + "requires": { + "@types/pouchdb-core": "*" + } + }, + "@types/pouchdb-adapter-memory": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-memory/-/pouchdb-adapter-memory-6.1.3.tgz", + "integrity": "sha512-gVbsIMzDzgZYThFVT4eVNsmuZwVm/4jDxP1sjlgc3qtDIxbtBhGgyNfcskwwz9Zu5Lv1avkDsIWvcxQhnvRlHg==", + "dev": true, + "requires": { + "@types/pouchdb-core": "*" + } + }, + "@types/pouchdb-adapter-node-websql": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-node-websql/-/pouchdb-adapter-node-websql-6.1.3.tgz", + "integrity": "sha512-F/P+os6Jsa7CgHtH64+Z0HfwIcj0hIRB5z8gNhF7L7dxPWoAfkopK5H2gydrP3sQrlGyN4WInF+UJW/Zu1+FKg==", + "dev": true, + "requires": { + "@types/pouchdb-adapter-websql": "*", + "@types/pouchdb-core": "*" + } + }, "@types/pouchdb-adapter-websql": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/@types/pouchdb-adapter-websql/-/pouchdb-adapter-websql-6.1.4.tgz", @@ -3290,6 +3931,16 @@ "@types/pouchdb-core": "*" } }, + "@types/pouchdb-http": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@types/pouchdb-http/-/pouchdb-http-6.1.3.tgz", + "integrity": "sha512-0e9E5SqNOyPl/3FnEIbENssB4FlJsNYuOy131nxrZk36S+y1R/6qO7ZVRypWpGTqBWSuVd7gCsq2UDwO/285+w==", + "dev": true, + "requires": { + "@types/pouchdb-adapter-http": "*", + "@types/pouchdb-core": "*" + } + }, "@types/pouchdb-mapreduce": { "version": "6.1.5", "resolved": "https://registry.npmjs.org/@types/pouchdb-mapreduce/-/pouchdb-mapreduce-6.1.5.tgz", @@ -3299,6 +3950,19 @@ "@types/pouchdb-core": "*" } }, + "@types/pouchdb-node": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/pouchdb-node/-/pouchdb-node-6.1.4.tgz", + "integrity": "sha512-wnTCH8X1JOPpNOfVhz8HW0AvmdHh6pt40MuRj0jQnK7QEHsHS79WujsKTKSOF8QXtPwpvCNSsI7ut7H7tfxxJQ==", + "dev": true, + "requires": { + "@types/pouchdb-adapter-http": "*", + "@types/pouchdb-adapter-leveldb": "*", + "@types/pouchdb-core": "*", + "@types/pouchdb-mapreduce": "*", + "@types/pouchdb-replication": "*" + } + }, "@types/pouchdb-replication": { "version": "6.4.3", "resolved": "https://registry.npmjs.org/@types/pouchdb-replication/-/pouchdb-replication-6.4.3.tgz", @@ -3309,6 +3973,12 @@ "@types/pouchdb-find": "*" } }, + "@types/pug": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz", + "integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==", + "dev": true + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -3318,6 +3988,15 @@ "@types/node": "*" } }, + "@types/sass": { + "version": "1.43.1", + "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.43.1.tgz", + "integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/tern": { "version": "0.23.4", "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz", @@ -3545,6 +4224,12 @@ "fill-range": "^7.0.1" } }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, "builtin-modules": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", @@ -3651,6 +4336,12 @@ "object-keys": "^1.0.12" } }, + "detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true + }, "diff-match-patch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", @@ -3728,6 +4419,165 @@ "is-symbol": "^1.0.2" } }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", + "dev": true + }, + "esbuild": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.12.tgz", + "integrity": "sha512-vTKKUt+yoz61U/BbrnmlG9XIjwpdIxmHB8DlPR0AAW6OdS+nBQBci6LUHU2q9WbBobMEIQxxDpKbkmOGYvxsow==", + "dev": true, + "requires": { + "esbuild-android-arm64": "0.13.12", + "esbuild-darwin-64": "0.13.12", + "esbuild-darwin-arm64": "0.13.12", + "esbuild-freebsd-64": "0.13.12", + "esbuild-freebsd-arm64": "0.13.12", + "esbuild-linux-32": "0.13.12", + "esbuild-linux-64": "0.13.12", + "esbuild-linux-arm": "0.13.12", + "esbuild-linux-arm64": "0.13.12", + "esbuild-linux-mips64le": "0.13.12", + "esbuild-linux-ppc64le": "0.13.12", + "esbuild-netbsd-64": "0.13.12", + "esbuild-openbsd-64": "0.13.12", + "esbuild-sunos-64": "0.13.12", + "esbuild-windows-32": "0.13.12", + "esbuild-windows-64": "0.13.12", + "esbuild-windows-arm64": "0.13.12" + } + }, + "esbuild-android-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.12.tgz", + "integrity": "sha512-TSVZVrb4EIXz6KaYjXfTzPyyRpXV5zgYIADXtQsIenjZ78myvDGaPi11o4ZSaHIwFHsuwkB6ne5SZRBwAQ7maw==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.12.tgz", + "integrity": "sha512-c51C+N+UHySoV2lgfWSwwmlnLnL0JWj/LzuZt9Ltk9ub1s2Y8cr6SQV5W3mqVH1egUceew6KZ8GyI4nwu+fhsw==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.12.tgz", + "integrity": "sha512-JvAMtshP45Hd8A8wOzjkY1xAnTKTYuP/QUaKp5eUQGX+76GIie3fCdUUr2ZEKdvpSImNqxiZSIMziEiGB5oUmQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.12.tgz", + "integrity": "sha512-r6On/Skv9f0ZjTu6PW5o7pdXr8aOgtFOEURJZYf1XAJs0IQ+gW+o1DzXjVkIoT+n1cm3N/t1KRJfX71MPg/ZUA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.12.tgz", + "integrity": "sha512-F6LmI2Q1gii073kmBE3NOTt/6zLL5zvZsxNLF8PMAwdHc+iBhD1vzfI8uQZMJA1IgXa3ocr3L3DJH9fLGXy6Yw==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.12.tgz", + "integrity": "sha512-U1UZwG3UIwF7/V4tCVAo/nkBV9ag5KJiJTt+gaCmLVWH3bPLX7y+fNlhIWZy8raTMnXhMKfaTvWZ9TtmXzvkuQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.12.tgz", + "integrity": "sha512-YpXSwtu2NxN3N4ifJxEdsgd6Q5d8LYqskrAwjmoCT6yQnEHJSF5uWcxv783HWN7lnGpJi9KUtDvYsnMdyGw71Q==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.12.tgz", + "integrity": "sha512-SyiT/JKxU6J+DY2qUiSLZJqCAftIt3uoGejZ0HDnUM2MGJqEGSGh7p1ecVL2gna3PxS4P+j6WAehCwgkBPXNIw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.12.tgz", + "integrity": "sha512-sgDNb8kb3BVodtAlcFGgwk+43KFCYjnFOaOfJibXnnIojNWuJHpL6aQJ4mumzNWw8Rt1xEtDQyuGK9f+Y24jGA==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.12.tgz", + "integrity": "sha512-qQJHlZBG+QwVIA8AbTEtbvF084QgDi4DaUsUnA+EolY1bxrG+UyOuGflM2ZritGhfS/k7THFjJbjH2wIeoKA2g==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.12.tgz", + "integrity": "sha512-2dSnm1ldL7Lppwlo04CGQUpwNn5hGqXI38OzaoPOkRsBRWFBozyGxTFSee/zHFS+Pdh3b28JJbRK3owrrRgWNw==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.12.tgz", + "integrity": "sha512-D4raxr02dcRiQNbxOLzpqBzcJNFAdsDNxjUbKkDMZBkL54Z0vZh4LRndycdZAMcIdizC/l/Yp/ZsBdAFxc5nbA==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.12.tgz", + "integrity": "sha512-KuLCmYMb2kh05QuPJ+va60bKIH5wHL8ypDkmpy47lzwmdxNsuySeCMHuTv5o2Af1RUn5KLO5ZxaZeq4GEY7DaQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.12.tgz", + "integrity": "sha512-jBsF+e0woK3miKI8ufGWKG3o3rY9DpHvCVRn5eburMIIE+2c+y3IZ1srsthKyKI6kkXLvV4Cf/E7w56kLipMXw==", + "dev": true, + "optional": true + }, + "esbuild-svelte": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.6.2.tgz", + "integrity": "sha512-FRHcyaQqIm4ncFsbk97b+80fHAI0VA15Ty56zOai9zpOPOQ1kgqWJt7JYn0jNGm+1VSvJNaGUj8QB85H/P43jA==", + "dev": true, + "requires": { + "svelte": "^3.46.2" + } + }, + "esbuild-windows-32": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.12.tgz", + "integrity": "sha512-L9m4lLFQrFeR7F+eLZXG82SbXZfUhyfu6CexZEil6vm+lc7GDCE0Q8DiNutkpzjv1+RAbIGVva9muItQ7HVTkQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.12.tgz", + "integrity": "sha512-k4tX4uJlSbSkfs78W5d9+I9gpd+7N95W7H2bgOMFPsYREVJs31+Q2gLLHlsnlY95zBoPQMIzHooUIsixQIBjaQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.13.12", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.12.tgz", + "integrity": "sha512-2tTv/BpYRIvuwHpp2M960nG7uvL+d78LFW/ikPItO+2GfK51CswIKSetSpDii+cjz8e9iSPgs+BU4o8nWICBwQ==", + "dev": true, + "optional": true + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -4182,6 +5032,12 @@ "slash": "^3.0.0" } }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4519,6 +5375,12 @@ "picomatch": "^2.2.3" } }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -4534,6 +5396,15 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -4796,6 +5667,29 @@ "queue-microtask": "^1.2.2" } }, + "sander": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", + "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=", + "dev": true, + "requires": { + "es6-promise": "^3.1.2", + "graceful-fs": "^4.1.3", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -4848,6 +5742,18 @@ "is-fullwidth-code-point": "^3.0.0" } }, + "sorcery": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", + "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=", + "dev": true, + "requires": { + "buffer-crc32": "^0.2.5", + "minimist": "^1.2.0", + "sander": "^0.5.0", + "sourcemap-codec": "^1.3.0" + } + }, "sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", @@ -4906,6 +5812,15 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4927,6 +5842,26 @@ "has-flag": "^4.0.0" } }, + "svelte": { + "version": "3.46.4", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.46.4.tgz", + "integrity": "sha512-qKJzw6DpA33CIa+C/rGp4AUdSfii0DOTCzj/2YpSKKayw5WGSS624Et9L1nU1k2OVRS9vaENQXp2CVZNU+xvIg==", + "dev": true + }, + "svelte-preprocess": { + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.3.tgz", + "integrity": "sha512-ttw17lJfb/dx2ZJT9sesaXT5l7mPQ9Apx1H496Kli3Hkk7orIRGpOw6rCPkRNzr6ueVPqb4vzodS5x7sBFhKHw==", + "dev": true, + "requires": { + "@types/pug": "^2.0.4", + "@types/sass": "^1.16.0", + "detect-indent": "^6.0.0", + "magic-string": "^0.25.7", + "sorcery": "^0.10.0", + "strip-indent": "^3.0.0" + } + }, "table": { "version": "6.7.5", "resolved": "https://registry.npmjs.org/table/-/table-6.7.5.tgz", diff --git a/package.json b/package.json index 96ebf18..f1bb567 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "obsidian-livesync", - "version": "0.6.1", + "version": "0.7.0", "description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.", "main": "main.js", + "type": "module", "scripts": { - "dev": "rollup --config rollup.config.js -w", - "build": "rollup --config rollup.config.js --environment BUILD:production", + "dev": "node esbuild.config.mjs", + "build": "node esbuild.config.mjs production", "lint": "eslint src" }, "keywords": [], @@ -16,6 +17,7 @@ "@rollup/plugin-node-resolve": "^11.2.1", "@rollup/plugin-typescript": "^8.2.1", "@types/diff-match-patch": "^1.0.32", + "@types/pouchdb": "^6.4.0", "@types/pouchdb-browser": "^6.1.3", "@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/parser": "^5.0.0", @@ -25,7 +27,11 @@ "obsidian": "^0.13.11", "rollup": "^2.32.1", "tslib": "^2.2.0", - "typescript": "^4.2.4" + "typescript": "^4.2.4", + "builtin-modules": "^3.2.0", + "esbuild": "0.13.12", + "esbuild-svelte": "^0.6.0", + "svelte-preprocess": "^4.10.2" }, "dependencies": { "diff-match-patch": "^1.0.5", diff --git a/src/ObsidianLiveSyncSettingTab.ts b/src/ObsidianLiveSyncSettingTab.ts index 7b60add..b97df9d 100644 --- a/src/ObsidianLiveSyncSettingTab.ts +++ b/src/ObsidianLiveSyncSettingTab.ts @@ -1,6 +1,6 @@ import { App, Notice, PluginSettingTab, Setting, sanitizeHTMLToDom } from "obsidian"; import { EntryDoc, LOG_LEVEL } from "./types"; -import { escapeStringToHTML, versionNumberString2Number, path2id, id2path, runWithLock } from "./utils"; +import { path2id, id2path, runWithLock } from "./utils"; import { Logger } from "./logger"; import { connectRemoteCouchDB } from "./utils_couchdb"; import { testCrypt } from "./e2ee"; @@ -830,14 +830,12 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { toggle.setValue(this.plugin.settings.usePluginSync).onChange(async (value) => { this.plugin.settings.usePluginSync = value; await this.plugin.saveSettings(); - updatePluginPane(); }) ); new Setting(containerPluginSettings).setName("Show own plugins and settings").addToggle((toggle) => toggle.setValue(this.plugin.settings.showOwnPlugins).onChange(async (value) => { this.plugin.settings.showOwnPlugins = value; await this.plugin.saveSettings(); - updatePluginPane(); }) ); @@ -884,233 +882,19 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { }); // text.inputEl.setAttribute("type", "password"); }); + new Setting(containerPluginSettings) + .setName("Open") + .setDesc("Open the plugin dialog") + .addButton((button) => { + button + .setButtonText("Open") + .setDisabled(false) + .onClick(() => { + this.plugin.showPluginSyncModal(); + }); + }); updateDisabledOfDeviceAndVaultName(); - const sweepPlugin = async (showMessage: boolean) => { - if (!this.plugin.settings.usePluginSync) { - return; - } - await this.plugin.sweepPlugin(showMessage); - updatePluginPane(); - }; - const updatePluginPane = async () => { - pluginConfig.innerHTML = "
Retrieving...
"; - const { plugins, allPlugins, thisDevicePlugins } = await this.plugin.getPluginList(); - let html = ` -
- - `; - for (const vaults in plugins) { - if (!this.plugin.settings.showOwnPlugins && vaults == this.plugin.settings.deviceAndVaultName) continue; - html += ` - - - - `; - for (const v of plugins[vaults]) { - const mtime = v.mtime == 0 ? "-" : new Date(v.mtime).toLocaleString(); - let settingApplyable: boolean | string = "-"; - let settingFleshness = ""; - let isSameVersion = false; - let isSameContents = false; - if (thisDevicePlugins[v.manifest.id]) { - if (thisDevicePlugins[v.manifest.id].manifest.version == v.manifest.version) { - isSameVersion = true; - } - if (thisDevicePlugins[v.manifest.id].styleCss == v.styleCss && thisDevicePlugins[v.manifest.id].mainJs == v.mainJs && thisDevicePlugins[v.manifest.id].manifestJson == v.manifestJson) { - isSameContents = true; - } - } - if (thisDevicePlugins[v.manifest.id] && v.dataJson) { - // have this plugin. - const localSetting = thisDevicePlugins[v.manifest.id].dataJson || null; - - try { - const remoteSetting = v.dataJson; - if (!localSetting) { - settingFleshness = "newer"; - settingApplyable = true; - } else if (localSetting == remoteSetting) { - settingApplyable = "even"; - } else { - if (v.mtime > thisDevicePlugins[v.manifest.id].mtime) { - settingFleshness = "newer"; - } else { - settingFleshness = "older"; - } - settingApplyable = true; - } - } catch (ex) { - settingApplyable = "could not decrypt"; - } - } else if (!v.dataJson) { - settingApplyable = "N/A"; - } - // very ugly way. - const piece = ` - - - - - - - - - - - - `; - html += piece; - } - html += ` - - - -`; - } - html += "
${escapeStringToHTML(vaults)} - - - -
${escapeStringToHTML(v.manifest.name)}${isSameContents ? "even" : ``}
${escapeStringToHTML(mtime)}${settingApplyable === true ? "" : settingApplyable}
"; - pluginConfig.innerHTML = html; - pluginConfig.querySelectorAll(".apply-plugin-data").forEach((e) => - e.addEventListener("click", async (evt) => { - const plugin = allPlugins[e.attributes.getNamedItem("data-key").value]; - Logger(`Updating plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await this.plugin.applyPluginData(plugin); - Logger(`Setting done:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await sweepPlugin(true); - }) - ); - pluginConfig.querySelectorAll(".apply-plugin-version").forEach((e) => - e.addEventListener("click", async (evt) => { - const plugin = allPlugins[e.attributes.getNamedItem("data-key").value]; - Logger(`Setting plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await this.plugin.applyPlugin(plugin); - Logger(`Updated plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await sweepPlugin(true); - }) - ); - pluginConfig.querySelectorAll(".sls-plugin-apply-all-newer-plugin").forEach((e) => - e.addEventListener("click", async (evt) => { - Logger("Apply all newer plugins.", LOG_LEVEL.NOTICE); - const vaultname = e.attributes.getNamedItem("data-key").value; - const plugins = Object.values(allPlugins).filter((e) => e.deviceVaultName == vaultname && e.manifest.id != "obsidian-livesync"); - for (const plugin of plugins) { - const currentPlugin = thisDevicePlugins[plugin.manifest.id]; - if (currentPlugin) { - const thisVersion = versionNumberString2Number(plugin.manifest.version); - const currentVersion = versionNumberString2Number(currentPlugin.manifest.version); - if (thisVersion > currentVersion) { - Logger(`Updating plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await this.plugin.applyPlugin(plugin); - Logger(`Updated plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - } else { - Logger(`Plugin ${plugin.manifest.name} is not new`); - } - } else { - Logger(`Updating plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await this.plugin.applyPlugin(plugin); - Logger(`Updated plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - } - } - await sweepPlugin(true); - Logger("Done", LOG_LEVEL.NOTICE); - }) - ); - pluginConfig.querySelectorAll(".sls-plugin-apply-all-newer-setting").forEach((e) => - e.addEventListener("click", async (evt) => { - Logger("Apply all newer settings.", LOG_LEVEL.NOTICE); - const vaultname = e.attributes.getNamedItem("data-key").value; - const plugins = Object.values(allPlugins).filter((e) => e.deviceVaultName == vaultname && e.manifest.id != "obsidian-livesync"); - for (const plugin of plugins) { - const currentPlugin = thisDevicePlugins[plugin.manifest.id]; - if (currentPlugin) { - const thisVersion = plugin.mtime; - const currentVersion = currentPlugin.mtime; - if (thisVersion > currentVersion) { - Logger(`Setting plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await this.plugin.applyPluginData(plugin); - Logger(`Setting done:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - } else { - Logger(`Setting ${plugin.manifest.name} is not new`); - } - } else { - Logger(`Setting plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - await this.plugin.applyPluginData(plugin); - Logger(`Setting done:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); - } - } - await sweepPlugin(true); - Logger("Done", LOG_LEVEL.NOTICE); - }) - ); - pluginConfig.querySelectorAll(".sls-plugin-delete").forEach((e) => - e.addEventListener("click", async (evt) => { - const db = this.plugin.localDatabase.localDatabase; - const vaultname = e.attributes.getNamedItem("data-key").value; - const oldDocs = await db.allDocs({ startkey: `ps:${vaultname}-`, endkey: `ps:${vaultname}.`, include_docs: true }); - Logger(`Deleting ${vaultname}`, LOG_LEVEL.NOTICE); - const delDocs = oldDocs.rows.map((e) => { - e.doc._deleted = true; - return e.doc; - }); - await db.bulkDocs(delDocs); - Logger(`Deleted ${vaultname}`, LOG_LEVEL.NOTICE); - await this.plugin.replicate(true); - await updatePluginPane(); - }) - ); - }; - - const pluginConfig = containerPluginSettings.createEl("div"); - - new Setting(containerPluginSettings) - .setName("Reload") - .setDesc("Replicate once and reload the list") - .addButton((button) => - button - .setButtonText("Reload") - .setDisabled(false) - .onClick(async () => { - if (!this.plugin.settings.usePluginSync) { - return; - } - await this.plugin.replicate(true); - await updatePluginPane(); - }) - ); - new Setting(containerPluginSettings) - .setName("Save plugins into the database") - .setDesc("") - .addButton((button) => - button - .setButtonText("Save plugins") - .setDisabled(false) - .onClick(async () => { - if (!this.plugin.settings.usePluginSync) { - return; - } - Logger("Save plugins.", LOG_LEVEL.NOTICE); - await sweepPlugin(true); - Logger("All plugins have been saved.", LOG_LEVEL.NOTICE); - await this.plugin.replicate(true); - }) - ); - new Setting(containerPluginSettings) - .setName("Check updates") - .setDesc("") - .addButton((button) => - button - .setButtonText("Check") - .setDisabled(false) - .onClick(async () => { - Logger("Checking plugins.", LOG_LEVEL.NOTICE); - await this.plugin.checkPluginUpdate(); - }) - ); - updatePluginPane(); addScreenElement("60", containerPluginSettings); diff --git a/src/PluginPane.svelte b/src/PluginPane.svelte new file mode 100644 index 0000000..a6f4a19 --- /dev/null +++ b/src/PluginPane.svelte @@ -0,0 +1,290 @@ + + +
+

Plugins and their settings

+
+ Show own items +
+
+
+ + + + + + + {#if devicePluginList.length == 0} + + + + {/if} + {#each devicePluginList as [deviceName, devicePlugins]} + + + + + {#each devicePlugins as plugin} + + + + + + + + + + + + + {/each} + {/each} +
NameInfoTarget
Retrieving...
{deviceName} + +
{plugin.manifest.name}{plugin.versionInfo}{getDispString(plugin.versionFlag)} + {#if plugin.versionFlag === "EVEN" || plugin.versionFlag === ""} + - + {:else} +
+
toggleTarget(plugin.deviceVaultName + "---" + plugin.manifest.id + "---plugin")} + /> +
+ {/if} +
Settings{plugin.mtimeInfo}{getDispString(plugin.mtimeFlag)} + {#if plugin.mtimeFlag === "EVEN" || plugin.mtimeFlag === ""} + - + {:else} +
+
toggleTarget(plugin.deviceVaultName + "---" + plugin.manifest.id + "---setting")} + /> +
+ {/if} +
+
+
+
+ + +
+ +
+ + + +
+ + + +
+ + diff --git a/src/main.ts b/src/main.ts index 6595a1d..0baa9c6 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import { debounce, Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, PluginManifest } from "obsidian"; +import { debounce, Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, PluginManifest, Modal, App } from "obsidian"; import { diff_match_patch } from "diff-match-patch"; import { @@ -26,6 +26,36 @@ import { ConflictResolveModal } from "./ConflictResolveModal"; import { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab"; import { DocumentHistoryModal } from "./DocumentHistoryModal"; +import PluginPane from "./PluginPane.svelte"; + +class PluginDialogModal extends Modal { + plugin: ObsidianLiveSyncPlugin; + logEl: HTMLDivElement; + component: PluginPane = null; + + constructor(app: App, plugin: ObsidianLiveSyncPlugin) { + super(app); + this.plugin = plugin; + } + + onOpen() { + const { contentEl } = this; + if (this.component == null) { + this.component = new PluginPane({ + target: contentEl, + props: { plugin: this.plugin }, + }); + } + } + + onClose() { + if (this.component != null) { + this.component.$destroy(); + this.component = null; + } + } +} + export default class ObsidianLiveSyncPlugin extends Plugin { settings: ObsidianLiveSyncSettings; localDatabase: LocalPouchDB; @@ -39,6 +69,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { this.registerInterval(timer); return timer; } + isRedFlagRaised(): boolean { const redflag = this.app.vault.getAbstractFileByPath(normalizePath(FLAGMD_REDFLAG)); if (redflag != null) { @@ -46,6 +77,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } return false; } + showHistory(file: TFile) { if (!this.settings.useHistory) { Logger("You have to enable Use History in misc.", LOG_LEVEL.NOTICE); @@ -53,6 +85,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { new DocumentHistoryModal(this.app, this, file).open(); } } + async onload() { setLogger(this.addLog.bind(this)); // Logger moved to global. Logger("loading plugin"); @@ -116,6 +149,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { this.periodicSync = this.periodicSync.bind(this); this.setPeriodicSync = this.setPeriodicSync.bind(this); + this.getPluginList = this.getPluginList.bind(this); // this.registerWatchEvents(); this.addSettingTab(new ObsidianLiveSyncSettingTab(this.app, this)); @@ -223,8 +257,35 @@ export default class ObsidianLiveSyncPlugin extends Plugin { setLockNotifier(() => { this.refreshStatusText(); }); + this.addCommand({ + id: "livesync-plugin-dialog", + name: "Show Plugins and their settings", + callback: () => { + this.showPluginSyncModal(); + }, + }); } + + pluginDialog: PluginDialogModal = null; + + showPluginSyncModal() { + if (this.pluginDialog != null) { + this.pluginDialog.open(); + } else { + this.pluginDialog = new PluginDialogModal(this.app, this); + this.pluginDialog.open(); + } + } + + hidePluginSyncModal() { + if (this.pluginDialog != null) { + this.pluginDialog.close(); + this.pluginDialog = null; + } + } + onunload() { + this.hidePluginSyncModal(); this.localDatabase.onunload(); if (this.gcTimerHandler != null) { clearTimeout(this.gcTimerHandler); @@ -250,6 +311,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { }; await this.localDatabase.initializeDatabase(); } + async garbageCollect() { await this.localDatabase.garbageCollect(); } @@ -263,12 +325,15 @@ export default class ObsidianLiveSyncPlugin extends Plugin { triggerRealizeSettingSyncMode() { (async () => await this.realizeSettingSyncMode())(); } + async saveSettings() { await this.saveData(this.settings); this.localDatabase.settings = this.settings; this.triggerRealizeSettingSyncMode(); } + gcTimerHandler: any = null; + gcHook() { if (this.settings.gcDelay == 0) return; if (this.settings.useHistory) return; @@ -282,6 +347,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { this.garbageCollect(); }, GC_DELAY); } + registerWatchEvents() { this.registerEvent(this.app.vault.on("modify", this.watchVaultChange)); this.registerEvent(this.app.vault.on("delete", this.watchVaultDelete)); @@ -294,6 +360,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { watchWindowVisiblity() { this.watchWindowVisiblityAsync(); } + async watchWindowVisiblityAsync() { if (this.settings.suspendFileWatching) return; // if (this.suspended) return; @@ -325,6 +392,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { if (this.settings.suspendFileWatching) return; this.watchWorkspaceOpenAsync(file); } + async watchWorkspaceOpenAsync(file: TFile) { await this.applyBatchChange(); if (file == null) return; @@ -335,10 +403,12 @@ export default class ObsidianLiveSyncPlugin extends Plugin { await this.showIfConflicted(file); this.gcHook(); } + watchVaultCreate(file: TFile, ...args: any[]) { if (this.settings.suspendFileWatching) return; this.watchVaultChangeAsync(file, ...args); } + watchVaultChange(file: TAbstractFile, ...args: any[]) { if (!(file instanceof TFile)) { return; @@ -352,6 +422,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } this.watchVaultChangeAsync(file, ...args); } + async applyBatchChange() { if (!this.settings.batchSave || this.batchFileChange.length == 0) { return []; @@ -375,19 +446,23 @@ export default class ObsidianLiveSyncPlugin extends Plugin { return await Promise.all(promises); }); } + batchFileChange: string[] = []; + async watchVaultChangeAsync(file: TFile, ...args: any[]) { if (file instanceof TFile) { await this.updateIntoDB(file); this.gcHook(); } } + watchVaultDelete(file: TAbstractFile) { // When save is delayed, it should be cancelled. this.batchFileChange = this.batchFileChange.filter((e) => e == file.path); if (this.settings.suspendFileWatching) return; - this.watchVaultDeleteAsync(file); + this.watchVaultDeleteAsync(file).then(() => {}); } + async watchVaultDeleteAsync(file: TAbstractFile) { if (file instanceof TFile) { await this.deleteFromDB(file); @@ -396,6 +471,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } this.gcHook(); } + GetAllFilesRecursively(file: TAbstractFile): TFile[] { if (file instanceof TFile) { return [file]; @@ -410,10 +486,12 @@ export default class ObsidianLiveSyncPlugin extends Plugin { throw new Error(`Filetype error:${file.path}`); } } + watchVaultRename(file: TAbstractFile, oldFile: any) { if (this.settings.suspendFileWatching) return; - this.watchVaultRenameAsync(file, oldFile); + this.watchVaultRenameAsync(file, oldFile).then(() => {}); } + getFilePath(file: TAbstractFile): string { if (file instanceof TFolder) { if (file.isRoot()) return ""; @@ -425,6 +503,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { return this.getFilePath(file.parent) + "/" + file.name; } + async watchVaultRenameAsync(file: TAbstractFile, oldFile: any) { Logger(`${oldFile} renamed to ${file.path}`, LOG_LEVEL.VERBOSE); try { @@ -461,9 +540,11 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } this.gcHook(); } + addLogHook: () => void = null; //--> Basic document Functions notifies: { [key: string]: { notice: Notice; timer: NodeJS.Timeout; count: number } } = {}; + // eslint-disable-next-line require-await async addLog(message: any, level: LOG_LEVEL = LOG_LEVEL.INFO) { if (level < LOG_LEVEL.INFO && this.settings && this.settings.lessInformationInLog) { @@ -547,7 +628,10 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } await this.ensureDirectory(path); try { - const newfile = await this.app.vault.createBinary(normalizePath(path), bin, { ctime: doc.ctime, mtime: doc.mtime }); + const newfile = await this.app.vault.createBinary(normalizePath(path), bin, { + ctime: doc.ctime, + mtime: doc.mtime, + }); Logger("live : write to local (newfile:b) " + path); this.app.vault.trigger("create", newfile); } catch (ex) { @@ -562,7 +646,10 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } await this.ensureDirectory(path); try { - const newfile = await this.app.vault.create(normalizePath(path), doc.data, { ctime: doc.ctime, mtime: doc.mtime }); + const newfile = await this.app.vault.create(normalizePath(path), doc.data, { + ctime: doc.ctime, + mtime: doc.mtime, + }); Logger("live : write to local (newfile:p) " + path); this.app.vault.trigger("create", newfile); } catch (ex) { @@ -590,6 +677,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } } } + async doc2storate_modify(docEntry: EntryBody, file: TFile, force?: boolean) { const pathSrc = id2path(docEntry._id); if (shouldBeIgnored(pathSrc)) { @@ -597,7 +685,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } if (docEntry._deleted) { //basically pass. - //but if there're no docs left, delete file. + //but if there are no docs left, delete file. const lastDocs = await this.localDatabase.getDBEntry(pathSrc); if (lastDocs === false) { await this.deleteVaultItem(file); @@ -657,6 +745,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { //eq.case } } + async handleDBChanged(change: EntryBody) { const targetFile = this.app.vault.getAbstractFileByPath(id2path(change._id)); if (targetFile == null) { @@ -676,6 +765,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } periodicSyncHandler: number = null; + //---> Sync async parseReplicationResult(docs: Array>): Promise { this.refreshStatusText(); @@ -702,61 +792,81 @@ export default class ObsidianLiveSyncPlugin extends Plugin { this.gcHook(); } } + triggerCheckPluginUpdate() { (async () => await this.checkPluginUpdate())(); } + async checkPluginUpdate() { if (!this.settings.usePluginSync) return; await this.sweepPlugin(false); const { allPlugins, thisDevicePlugins } = await this.getPluginList(); const arrPlugins = Object.values(allPlugins); + let updateFound = false; for (const plugin of arrPlugins) { - const currentPlugin = thisDevicePlugins[plugin.manifest.id]; - if (currentPlugin) { - const thisVersion = versionNumberString2Number(plugin.manifest.version); - const currentVersion = versionNumberString2Number(currentPlugin.manifest.version); - if (thisVersion > currentVersion) { - Logger(`the device ${plugin.deviceVaultName} has the newer plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); + const ownPlugin = thisDevicePlugins[plugin.manifest.id]; + if (ownPlugin) { + const remoteVersion = versionNumberString2Number(plugin.manifest.version); + const ownVersion = versionNumberString2Number(ownPlugin.manifest.version); + if (remoteVersion > ownVersion) { + updateFound = true; } - if (plugin.mtime > currentPlugin.mtime) { - Logger(`the device ${plugin.deviceVaultName} has the newer settings of the plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); + if (((plugin.mtime / 1000) | 0) > ((ownPlugin.mtime / 1000) | 0) && (plugin.dataJson ?? "") != (ownPlugin.dataJson ?? "")) { + updateFound = true; } - } else { - Logger(`the device ${plugin.deviceVaultName} has the new plugin:${plugin.manifest.name}`, LOG_LEVEL.NOTICE); } } + if (updateFound) { + const fragment = createFragment((doc) => { + doc.createEl("a", null, (a) => { + a.text = "There're some new plugins or their settings"; + a.addEventListener("click", () => this.showPluginSyncModal()); + }); + }); + new Notice(fragment, 10000); + } else { + Logger("Everything is up to date.", LOG_LEVEL.NOTICE); + } } + clearPeriodicSync() { if (this.periodicSyncHandler != null) { clearInterval(this.periodicSyncHandler); this.periodicSyncHandler = null; } } + setPeriodicSync() { if (this.settings.periodicReplication && this.settings.periodicReplicationInterval > 0) { this.clearPeriodicSync(); this.periodicSyncHandler = this.setInterval(async () => await this.periodicSync(), Math.max(this.settings.periodicReplicationInterval, 30) * 1000); } } + async periodicSync() { await this.replicate(); } + periodicPluginSweepHandler: number = null; + clearPluginSweep() { if (this.periodicPluginSweepHandler != null) { clearInterval(this.periodicPluginSweepHandler); this.periodicPluginSweepHandler = null; } } + setPluginSweep() { if (this.settings.autoSweepPluginsPeriodic) { this.clearPluginSweep(); this.periodicPluginSweepHandler = this.setInterval(async () => await this.periodicPluginSweep(), PERIODIC_PLUGIN_SWEEP * 1000); } } + async periodicPluginSweep() { await this.sweepPlugin(false); } + async realizeSettingSyncMode() { this.localDatabase.closeReplication(); this.clearPeriodicSync(); @@ -774,7 +884,9 @@ export default class ObsidianLiveSyncPlugin extends Plugin { this.setPeriodicSync(); this.setPluginSweep(); } + lastMessage = ""; + refreshStatusText() { const sent = this.localDatabase.docSent; const arrived = this.localDatabase.docArrived; @@ -811,6 +923,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { const message = `Sync:${w} ↑${sent} ↓${arrived}${waiting}${procsDisp}`; this.setStatusBarText(message); } + setStatusBarText(message: string) { if (this.lastMessage != message) { this.statusBar.setText(message); @@ -824,6 +937,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { this.lastMessage = message; } } + async replicate(showMessage?: boolean) { if (this.settings.versionUpFlash != "") { new Notice("Open settings and check message, please."); @@ -840,21 +954,26 @@ export default class ObsidianLiveSyncPlugin extends Plugin { await this.openDatabase(); await this.syncAllFiles(showingNotice); } + async replicateAllToServer(showingNotice?: boolean) { if (this.settings.autoSweepPlugins) { await this.sweepPlugin(showingNotice); } return await this.localDatabase.replicateAllToServer(this.settings, showingNotice); } + async markRemoteLocked() { return await this.localDatabase.markRemoteLocked(this.settings, true); } + async markRemoteUnlocked() { return await this.localDatabase.markRemoteLocked(this.settings, false); } + async markRemoteResolved() { return await this.localDatabase.markRemoteResolved(this.settings); } + async syncAllFiles(showingNotice?: boolean) { // synchronize all files between database and storage. let notice: Notice = null; @@ -896,6 +1015,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { Logger(ex); } }); + // @ts-ignore if (!Promise.allSettled) { await Promise.all( procs.map((p) => @@ -911,6 +1031,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { ) ); } else { + // @ts-ignore await Promise.allSettled(procs); } }; @@ -932,6 +1053,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { Logger("Initialize done!", LOG_LEVEL.NOTICE); } } + async deleteFolderOnDB(folder: TFolder) { Logger(`delete folder:${folder.path}`); await this.localDatabase.deleteDBEntryPrefix(folder.path + "/"); @@ -1016,6 +1138,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } return false; } + /** * Getting file conflicted status. * @param path the file location @@ -1076,6 +1199,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { diff: diff, }; } + showMergeDialog(file: TFile, conflictCheckResult: diff_result): Promise { return new Promise((res, rej) => { Logger("open conflict dialog", LOG_LEVEL.VERBOSE); @@ -1121,10 +1245,12 @@ export default class ObsidianLiveSyncPlugin extends Plugin { }).open(); }); } + conflictedCheckFiles: string[] = []; // queueing the conflicted file check conflictedCheckTimer: number; + queueConflictedCheck(file: TFile) { this.conflictedCheckFiles = this.conflictedCheckFiles.filter((e) => e != file.path); this.conflictedCheckFiles.push(file.path); @@ -1146,6 +1272,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } }, 1000); } + async showIfConflicted(file: TFile) { await runWithLock("conflicted", false, async () => { const conflictCheckResult = await this.getConflictedStatus(file.path); @@ -1165,6 +1292,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { await this.showMergeDialog(file, conflictCheckResult); }); } + async pullFile(filename: string, fileList?: TFile[], force?: boolean, rev?: string, waitForReady = true) { const targetFile = this.app.vault.getAbstractFileByPath(id2path(filename)); if (targetFile == null) { @@ -1184,6 +1312,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } //when to opened file; } + async syncFileBetweenDBandStorage(file: TFile, fileList?: TFile[]) { const doc = await this.localDatabase.getDBEntryMeta(file.path); if (doc === false) return; @@ -1257,6 +1386,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { await this.replicate(); } } + async deleteFromDB(file: TFile) { const fullpath = file.path; Logger(`deleteDB By path:${fullpath}`); @@ -1265,6 +1395,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { await this.replicate(); } } + async deleteFromDBbyPath(fullpath: string) { await this.localDatabase.deleteDBEntry(fullpath); if (this.settings.syncOnSave && !this.suspended) { @@ -1275,12 +1406,15 @@ export default class ObsidianLiveSyncPlugin extends Plugin { async resetLocalDatabase() { await this.localDatabase.resetDatabase(); } + async tryResetRemoteDatabase() { await this.localDatabase.tryResetRemoteDatabase(this.settings); } + async tryCreateRemoteDatabase() { await this.localDatabase.tryCreateRemoteDatabase(this.settings); } + async getPluginList(): Promise<{ plugins: PluginList; allPlugins: DevicePluginList; thisDevicePlugins: DevicePluginList }> { const db = this.localDatabase.localDatabase; const docList = await db.allDocs({ startkey: `ps:`, endkey: `ps;`, include_docs: false }); @@ -1300,6 +1434,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } return { plugins, allPlugins, thisDevicePlugins }; } + async sweepPlugin(showMessage = false) { if (!this.settings.usePluginSync) return; await runWithLock("sweepplugin", false, async () => { @@ -1314,7 +1449,11 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } Logger("Sweeping plugins", logLevel); const db = this.localDatabase.localDatabase; - const oldDocs = await db.allDocs({ startkey: `ps:${this.settings.deviceAndVaultName}-`, endkey: `ps:${this.settings.deviceAndVaultName}.`, include_docs: true }); + const oldDocs = await db.allDocs({ + startkey: `ps:${this.settings.deviceAndVaultName}-`, + endkey: `ps:${this.settings.deviceAndVaultName}.`, + include_docs: true, + }); Logger("OLD DOCS.", LOG_LEVEL.VERBOSE); // sweep current plugin. // @ts-ignore @@ -1383,12 +1522,13 @@ export default class ObsidianLiveSyncPlugin extends Plugin { Logger(`Sweep plugin done.`, logLevel); }); } + async applyPluginData(plugin: PluginDataEntry) { await runWithLock("plugin-" + plugin.manifest.id, false, async () => { const pluginTargetFolderPath = normalizePath(plugin.manifest.dir) + "/"; const adapter = this.app.vault.adapter; // @ts-ignore - const stat = this.app.plugins.enabledPlugins[plugin.manifest.id]; + const stat = this.app.plugins.enabledPlugins.has(plugin.manifest.id) == true; if (stat) { // @ts-ignore await this.app.plugins.unloadPlugin(plugin.manifest.id); @@ -1396,7 +1536,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } if (plugin.dataJson) await adapter.write(pluginTargetFolderPath + "data.json", plugin.dataJson); Logger("wrote:" + pluginTargetFolderPath + "data.json", LOG_LEVEL.NOTICE); - // @ts-ignore if (stat) { // @ts-ignore await this.app.plugins.loadPlugin(plugin.manifest.id); @@ -1404,10 +1543,11 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } }); } + async applyPlugin(plugin: PluginDataEntry) { await runWithLock("plugin-" + plugin.manifest.id, false, async () => { // @ts-ignore - const stat = this.app.plugins.enabledPlugins[plugin.manifest.id]; + const stat = this.app.plugins.enabledPlugins.has(plugin.manifest.id) == true; if (stat) { // @ts-ignore await this.app.plugins.unloadPlugin(plugin.manifest.id); @@ -1422,7 +1562,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin { await adapter.write(pluginTargetFolderPath + "main.js", plugin.mainJs); await adapter.write(pluginTargetFolderPath + "manifest.json", plugin.manifestJson); if (plugin.styleCss) await adapter.write(pluginTargetFolderPath + "styles.css", plugin.styleCss); - // if (plugin.dataJson) await adapter.write(pluginTargetFolderPath + "data.json", plugin.dataJson); if (stat) { // @ts-ignore await this.app.plugins.loadPlugin(plugin.manifest.id); diff --git a/src/types.ts b/src/types.ts index f07beeb..5c42751 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,6 +2,7 @@ // and cloudant limitation is 1MB , we use 900kb; import { PluginManifest } from "obsidian"; +import * as PouchDB from "pouchdb"; export const MAX_DOC_SIZE = 1000; // for .md file, but if delimiters exists. use that before. export const MAX_DOC_SIZE_BIN = 102400; // 100kb @@ -58,7 +59,7 @@ export interface ObsidianLiveSyncSettings { checkIntegrityOnSave: boolean; batch_size: number; batches_limit: number; - useHistory:boolean; + useHistory: boolean; } export const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = { @@ -99,7 +100,7 @@ export const DEFAULT_SETTINGS: ObsidianLiveSyncSettings = { checkIntegrityOnSave: false, batch_size: 250, batches_limit: 40, - useHistory:false, + useHistory: false, }; export const PERIODIC_PLUGIN_SWEEP = 60; diff --git a/styles.css b/styles.css index 6a32cfe..6f53088 100644 --- a/styles.css +++ b/styles.css @@ -34,11 +34,13 @@ .sls-plugins-wrap { display: flex; flex-grow: 1; - /* overflow: scroll; */ + max-height: 50vh; + overflow-y: scroll; } .sls-plugins-tbl { border: 1px solid var(--background-modifier-border); width: 100%; + max-height: 80%; } .divider th { border-top: 1px solid var(--background-modifier-border); diff --git a/tsconfig.json b/tsconfig.json index 04128a6..5a6e010 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,21 +1,17 @@ { "compilerOptions": { "baseUrl": ".", - "inlineSourceMap": true, - "inlineSources": true, "module": "ESNext", - "target": "es6", + "target": "ES6", "allowJs": true, "noImplicitAny": true, "moduleResolution": "node", + "types": ["svelte", "node"], + // "importsNotUsedAsValues": "error", "importHelpers": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "strictFunctionTypes": true, "alwaysStrict": true, - "lib": ["dom", "es5", "ES6", "ES7", "es2020"] + "lib": ["es2018", "DOM", "ES5", "ES6", "ES7"] }, - "include": ["./src/*.ts"], - // "files": ["./src/main.ts"], + "include": ["**/*.ts"], "exclude": ["pouchdb-browser-webpack"] }