mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-06-11 00:40:14 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b9bd473cf | |||
| 4be4fa6cc7 | |||
| a9745e850e | |||
| 7b9515a47e | |||
| 220dce51f2 | |||
| a23fc866c0 | |||
| 5c86966d89 | |||
| 29ed4d2b95 | |||
| 16c6c52128 | |||
| 8b94a0b72e | |||
| c5ac76d916 | |||
| b67a6db8a1 | |||
| d4202161e8 | |||
| 2a2b39009c | |||
| bf3a6e7570 |
@@ -68,6 +68,7 @@ Synchronization status is shown in the status bar with the following icons.
|
|||||||
- 💾 Working write storage processes
|
- 💾 Working write storage processes
|
||||||
- ⏳ Working read storage processes
|
- ⏳ Working read storage processes
|
||||||
- 🛫 Pending read storage processes
|
- 🛫 Pending read storage processes
|
||||||
|
- 📬 Batched read storage processes
|
||||||
- ⚙️ Working or pending storage processes of hidden files
|
- ⚙️ Working or pending storage processes of hidden files
|
||||||
- 🧩 Waiting chunks
|
- 🧩 Waiting chunks
|
||||||
- 🔌 Working Customisation items (Configuration, snippets, and plug-ins)
|
- 🔌 Working Customisation items (Configuration, snippets, and plug-ins)
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# How to add translations
|
||||||
|
|
||||||
|
## Getting ready
|
||||||
|
|
||||||
|
1. Clone this repository recursively.
|
||||||
|
```sh
|
||||||
|
git clone --recursive https://github.com/vrtmrz/obsidian-livesync
|
||||||
|
```
|
||||||
|
2. Make `ls-debug` folder under your vault's `.obsidian` folder (as like `.../dev/.obsidian/ls-debug`).
|
||||||
|
|
||||||
|
## Add translations for already defined terms
|
||||||
|
|
||||||
|
1. Install dependencies, and build the plug-in as dev. build.
|
||||||
|
```sh
|
||||||
|
cd obsidian-livesync
|
||||||
|
npm i -D
|
||||||
|
npm run buildDev
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Copy the `main.js` to `.obsidian/plugins/obsidian-livesync` folder of your vault, and run Obsidian-Self-hosted LiveSync.
|
||||||
|
3. You will get the `missing-translation-yyyy-mm-dd.jsonl`, please fill in new translations.
|
||||||
|
4. Build the plug-in again, and confirm that displayed things were expected.
|
||||||
|
5. Merge them into `rosetta.ts`, and make the PR to `https://github.com/vrtmrz/livesync-commonlib`.
|
||||||
|
|
||||||
|
## Make messages to be translated
|
||||||
|
|
||||||
|
1. Find the message that you want to be translated.
|
||||||
|
2. Change the literal to a tagged template literal using `$f`, like below.
|
||||||
|
```diff
|
||||||
|
- Logger("Could not determine passphrase to save data.json! You probably make the configuration sure again!", LOG_LEVEL_URGENT);
|
||||||
|
+ Logger($f`Could not determine passphrase to save data.json! You probably make the configuration sure again!`, LOG_LEVEL_URGENT);
|
||||||
|
```
|
||||||
|
3. Make the PR to `https://github.com/vrtmrz/obsidian-livesync`.
|
||||||
|
4. Follow the steps of "Add translations for already defined terms" to add the translations.
|
||||||
@@ -108,13 +108,18 @@ $ export database=obsidiannotes #Please change as you like
|
|||||||
$ export passphrase=dfsapkdjaskdjasdas #Please change as you like
|
$ export passphrase=dfsapkdjaskdjasdas #Please change as you like
|
||||||
$ deno run -A https://raw.githubusercontent.com/vrtmrz/obsidian-livesync/main/utils/flyio/generate_setupuri.ts
|
$ deno run -A https://raw.githubusercontent.com/vrtmrz/obsidian-livesync/main/utils/flyio/generate_setupuri.ts
|
||||||
obsidian://setuplivesync?settings=%5B%22tm2DpsOE74nJAryprZO2M93wF%2Fvg.......4b26ed33230729%22%5D
|
obsidian://setuplivesync?settings=%5B%22tm2DpsOE74nJAryprZO2M93wF%2Fvg.......4b26ed33230729%22%5D
|
||||||
|
|
||||||
|
Your passphrase of Setup-URI is: patient-haze
|
||||||
|
This passphrase is never shown again, so please note it in a safe place.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Please keep your passphrase of Setup-URI.
|
||||||
|
|
||||||
### 2. Setup Self-hosted LiveSync to Obsidian
|
### 2. Setup Self-hosted LiveSync to Obsidian
|
||||||
[This video](https://youtu.be/7sa_I1832Xc?t=146) may help us.
|
[This video](https://youtu.be/7sa_I1832Xc?t=146) may help us.
|
||||||
1. Install Self-hosted LiveSync
|
1. Install Self-hosted LiveSync
|
||||||
2. Choose `Use the copied setup URI` from the command palette and paste the setup URI. (obsidian://setuplivesync?settings=.....).
|
2. Choose `Use the copied setup URI` from the command palette and paste the setup URI. (obsidian://setuplivesync?settings=.....).
|
||||||
3. Type `welcome` for setup-uri passphrase.
|
3. Type the previously displayed passphrase (`patient-haze`) for setup-uri passphrase.
|
||||||
4. Answer `yes` and `Set it up...`, and finish the first dialogue with `Keep them disabled`.
|
4. Answer `yes` and `Set it up...`, and finish the first dialogue with `Keep them disabled`.
|
||||||
5. `Reload app without save` once.
|
5. `Reload app without save` once.
|
||||||
|
|
||||||
|
|||||||
+50
-65
@@ -8,27 +8,31 @@ import sveltePreprocess from "svelte-preprocess";
|
|||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
// import terser from "terser";
|
// import terser from "terser";
|
||||||
import { minify } from "terser";
|
import { minify } from "terser";
|
||||||
|
import inlineWorkerPlugin from "esbuild-plugin-inline-worker";
|
||||||
const banner = `/*
|
const banner = `/*
|
||||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD AND TERSER
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD AND TERSER
|
||||||
if you want to view the source, please visit the github repository of this plugin
|
if you want to view the source, please visit the github repository of this plugin
|
||||||
*/
|
*/
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
||||||
const prod = process.argv[2] === "production";
|
const prod = process.argv[2] === "production";
|
||||||
const keepTest = !prod;
|
const dev = process.argv[2] === "dev";
|
||||||
|
|
||||||
|
const keepTest = !prod || dev;
|
||||||
|
|
||||||
const terserOpt = {
|
const terserOpt = {
|
||||||
sourceMap: (!prod ? {
|
sourceMap: !prod
|
||||||
url: "inline"
|
? {
|
||||||
} : {}),
|
url: "inline",
|
||||||
|
}
|
||||||
|
: {},
|
||||||
format: {
|
format: {
|
||||||
indent_level: 2,
|
indent_level: 2,
|
||||||
beautify: true,
|
beautify: true,
|
||||||
comments: "some",
|
comments: "some",
|
||||||
ecma: 2018,
|
ecma: 2018,
|
||||||
preamble: banner,
|
preamble: banner,
|
||||||
webkit: true
|
webkit: true,
|
||||||
},
|
},
|
||||||
parse: {
|
parse: {
|
||||||
// parse options
|
// parse options
|
||||||
@@ -53,16 +57,6 @@ const terserOpt = {
|
|||||||
ecma: 2018,
|
ecma: 2018,
|
||||||
unused: true,
|
unused: true,
|
||||||
},
|
},
|
||||||
// mangle: {
|
|
||||||
// // mangle options
|
|
||||||
// keep_classnames: true,
|
|
||||||
// keep_fnames: true,
|
|
||||||
|
|
||||||
// properties: {
|
|
||||||
// // mangle property options
|
|
||||||
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
|
|
||||||
ecma: 2018, // specify one of: 5, 2015, 2016, etc.
|
ecma: 2018, // specify one of: 5, 2015, 2016, etc.
|
||||||
enclose: false, // or specify true, or "args:values"
|
enclose: false, // or specify true, or "args:values"
|
||||||
@@ -72,42 +66,43 @@ const terserOpt = {
|
|||||||
module: false,
|
module: false,
|
||||||
// nameCache: null, // or specify a name cache object
|
// nameCache: null, // or specify a name cache object
|
||||||
safari10: false,
|
safari10: false,
|
||||||
toplevel: false
|
toplevel: false,
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
const manifestJson = JSON.parse(fs.readFileSync("./manifest.json") + "");
|
const manifestJson = JSON.parse(fs.readFileSync("./manifest.json") + "");
|
||||||
const packageJson = JSON.parse(fs.readFileSync("./package.json") + "");
|
const packageJson = JSON.parse(fs.readFileSync("./package.json") + "");
|
||||||
const updateInfo = JSON.stringify(fs.readFileSync("./updates.md") + "");
|
const updateInfo = JSON.stringify(fs.readFileSync("./updates.md") + "");
|
||||||
|
|
||||||
/** @type esbuild.Plugin[] */
|
/** @type esbuild.Plugin[] */
|
||||||
const plugins = [{
|
const plugins = [
|
||||||
name: 'my-plugin',
|
{
|
||||||
setup(build) {
|
name: "my-plugin",
|
||||||
let count = 0;
|
setup(build) {
|
||||||
build.onEnd(async result => {
|
let count = 0;
|
||||||
if (count++ === 0) {
|
build.onEnd(async (result) => {
|
||||||
console.log('first build:', result);
|
if (count++ === 0) {
|
||||||
|
console.log("first build:", result);
|
||||||
} else {
|
} else {
|
||||||
console.log('subsequent build:');
|
console.log("subsequent build:");
|
||||||
}
|
|
||||||
if (prod) {
|
|
||||||
console.log("Performing terser");
|
|
||||||
const src = fs.readFileSync("./main_org.js").toString();
|
|
||||||
// @ts-ignore
|
|
||||||
const ret = await minify(src, terserOpt);
|
|
||||||
if (ret && ret.code) {
|
|
||||||
fs.writeFileSync("./main.js", ret.code);
|
|
||||||
}
|
}
|
||||||
console.log("Finished terser");
|
if (prod) {
|
||||||
} else {
|
console.log("Performing terser");
|
||||||
fs.copyFileSync("./main_org.js", "./main.js");
|
const src = fs.readFileSync("./main_org.js").toString();
|
||||||
}
|
// @ts-ignore
|
||||||
});
|
const ret = await minify(src, terserOpt);
|
||||||
|
if (ret && ret.code) {
|
||||||
|
fs.writeFileSync("./main.js", ret.code);
|
||||||
|
}
|
||||||
|
console.log("Finished terser");
|
||||||
|
} else {
|
||||||
|
fs.copyFileSync("./main_org.js", "./main.js");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}];
|
];
|
||||||
|
|
||||||
|
const externals = ["obsidian", "electron", "crypto", "@codemirror/autocomplete", "@codemirror/collab", "@codemirror/commands", "@codemirror/language", "@codemirror/lint", "@codemirror/search", "@codemirror/state", "@codemirror/view", "@lezer/common", "@lezer/highlight", "@lezer/lr"];
|
||||||
const context = await esbuild.context({
|
const context = await esbuild.context({
|
||||||
banner: {
|
banner: {
|
||||||
js: banner,
|
js: banner,
|
||||||
@@ -115,26 +110,12 @@ const context = await esbuild.context({
|
|||||||
entryPoints: ["src/main.ts"],
|
entryPoints: ["src/main.ts"],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
define: {
|
define: {
|
||||||
"MANIFEST_VERSION": `"${manifestJson.version}"`,
|
MANIFEST_VERSION: `"${manifestJson.version}"`,
|
||||||
"PACKAGE_VERSION": `"${packageJson.version}"`,
|
PACKAGE_VERSION: `"${packageJson.version}"`,
|
||||||
"UPDATE_INFO": `${updateInfo}`,
|
UPDATE_INFO: `${updateInfo}`,
|
||||||
"global": "window",
|
global: "window",
|
||||||
},
|
},
|
||||||
external: [
|
external: externals,
|
||||||
"obsidian",
|
|
||||||
"electron",
|
|
||||||
"crypto",
|
|
||||||
"@codemirror/autocomplete",
|
|
||||||
"@codemirror/collab",
|
|
||||||
"@codemirror/commands",
|
|
||||||
"@codemirror/language",
|
|
||||||
"@codemirror/lint",
|
|
||||||
"@codemirror/search",
|
|
||||||
"@codemirror/state",
|
|
||||||
"@codemirror/view",
|
|
||||||
"@lezer/common",
|
|
||||||
"@lezer/highlight",
|
|
||||||
"@lezer/lr"],
|
|
||||||
// minifyWhitespace: true,
|
// minifyWhitespace: true,
|
||||||
format: "cjs",
|
format: "cjs",
|
||||||
target: "es2018",
|
target: "es2018",
|
||||||
@@ -151,15 +132,19 @@ const context = await esbuild.context({
|
|||||||
dropLabels: prod && !keepTest ? ["TEST", "DEV"] : [],
|
dropLabels: prod && !keepTest ? ["TEST", "DEV"] : [],
|
||||||
// keepNames: true,
|
// keepNames: true,
|
||||||
plugins: [
|
plugins: [
|
||||||
|
inlineWorkerPlugin({
|
||||||
|
external: externals,
|
||||||
|
treeShaking: true,
|
||||||
|
}),
|
||||||
sveltePlugin({
|
sveltePlugin({
|
||||||
preprocess: sveltePreprocess(),
|
preprocess: sveltePreprocess(),
|
||||||
compilerOptions: { css: "injected", preserveComments: false },
|
compilerOptions: { css: "injected", preserveComments: false },
|
||||||
}),
|
}),
|
||||||
...plugins
|
...plugins,
|
||||||
],
|
],
|
||||||
})
|
});
|
||||||
|
|
||||||
if (prod) {
|
if (prod || dev) {
|
||||||
await context.rebuild();
|
await context.rebuild();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-livesync",
|
"id": "obsidian-livesync",
|
||||||
"name": "Self-hosted LiveSync",
|
"name": "Self-hosted LiveSync",
|
||||||
"version": "0.23.10",
|
"version": "0.23.16",
|
||||||
"minAppVersion": "0.9.12",
|
"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.",
|
"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",
|
"author": "vorotamoroz",
|
||||||
|
|||||||
Generated
+271
-132
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.23.10",
|
"version": "0.23.16",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.23.10",
|
"version": "0.23.16",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.556.0",
|
"@aws-sdk/client-s3": "^3.556.0",
|
||||||
@@ -14,9 +14,11 @@
|
|||||||
"@smithy/protocol-http": "^3.3.0",
|
"@smithy/protocol-http": "^3.3.0",
|
||||||
"@smithy/querystring-builder": "^2.2.0",
|
"@smithy/querystring-builder": "^2.2.0",
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
|
"esbuild-plugin-inline-worker": "^0.1.1",
|
||||||
"fflate": "^0.8.2",
|
"fflate": "^0.8.2",
|
||||||
"idb": "^8.0.0",
|
"idb": "^8.0.0",
|
||||||
"minimatch": "^9.0.3",
|
"minimatch": "^9.0.3",
|
||||||
|
"octagonal-wheels": "^0.1.12",
|
||||||
"xxhash-wasm": "0.4.2",
|
"xxhash-wasm": "0.4.2",
|
||||||
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
||||||
},
|
},
|
||||||
@@ -54,7 +56,7 @@
|
|||||||
"pouchdb-merge": "^8.0.1",
|
"pouchdb-merge": "^8.0.1",
|
||||||
"pouchdb-replication": "^8.0.1",
|
"pouchdb-replication": "^8.0.1",
|
||||||
"pouchdb-utils": "^8.0.1",
|
"pouchdb-utils": "^8.0.1",
|
||||||
"svelte": "^4.2.12",
|
"svelte": "^4.2.16",
|
||||||
"svelte-preprocess": "^5.1.3",
|
"svelte-preprocess": "^5.1.3",
|
||||||
"terser": "^5.29.2",
|
"terser": "^5.29.2",
|
||||||
"transform-pouch": "^2.0.0",
|
"transform-pouch": "^2.0.0",
|
||||||
@@ -909,7 +911,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"aix"
|
"aix"
|
||||||
@@ -925,7 +926,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@@ -941,7 +941,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@@ -957,7 +956,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@@ -973,7 +971,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@@ -989,7 +986,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@@ -1005,7 +1001,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
@@ -1021,7 +1016,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
@@ -1037,7 +1031,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1053,7 +1046,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1069,7 +1061,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1085,7 +1076,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1101,7 +1091,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1117,7 +1106,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1133,7 +1121,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1149,7 +1136,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1165,7 +1151,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@@ -1181,7 +1166,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"netbsd"
|
"netbsd"
|
||||||
@@ -1197,7 +1181,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"openbsd"
|
"openbsd"
|
||||||
@@ -1213,7 +1196,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"sunos"
|
"sunos"
|
||||||
@@ -1229,7 +1211,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@@ -1245,7 +1226,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@@ -1261,7 +1241,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@@ -2885,12 +2864,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/braces": {
|
"node_modules/braces": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fill-range": "^7.0.1"
|
"fill-range": "^7.1.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
@@ -3013,6 +2992,11 @@
|
|||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/commondir": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
|
||||||
|
},
|
||||||
"node_modules/concat-map": {
|
"node_modules/concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
@@ -3053,9 +3037,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -3288,7 +3272,6 @@
|
|||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
||||||
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
|
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
|
||||||
"dev": true,
|
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"esbuild": "bin/esbuild"
|
"esbuild": "bin/esbuild"
|
||||||
@@ -3322,6 +3305,15 @@
|
|||||||
"@esbuild/win32-x64": "0.20.2"
|
"@esbuild/win32-x64": "0.20.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/esbuild-plugin-inline-worker": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild-plugin-inline-worker/-/esbuild-plugin-inline-worker-0.1.1.tgz",
|
||||||
|
"integrity": "sha512-VmFqsQKxUlbM51C1y5bRiMeyc1x2yTdMXhKB6S//++g9aCBg8TfGsbKxl5ZDkCGquqLY+RmEk93TBNd0i35dPA==",
|
||||||
|
"dependencies": {
|
||||||
|
"esbuild": "latest",
|
||||||
|
"find-cache-dir": "^3.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/esbuild-svelte": {
|
"node_modules/esbuild-svelte": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.8.0.tgz",
|
||||||
@@ -3804,9 +3796,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fill-range": {
|
"node_modules/fill-range": {
|
||||||
"version": "7.0.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
@@ -3815,6 +3807,22 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/find-cache-dir": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
|
||||||
|
"dependencies": {
|
||||||
|
"commondir": "^1.0.1",
|
||||||
|
"make-dir": "^3.0.2",
|
||||||
|
"pkg-dir": "^4.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/find-up": {
|
"node_modules/find-up": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||||
@@ -4567,18 +4575,6 @@
|
|||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/lru-cache": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"yallist": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.8",
|
"version": "0.30.8",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
|
||||||
@@ -4591,6 +4587,28 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/make-dir": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/make-dir/node_modules/semver": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdn-data": {
|
"node_modules/mdn-data": {
|
||||||
"version": "2.0.30",
|
"version": "2.0.30",
|
||||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
@@ -4830,6 +4848,16 @@
|
|||||||
"@codemirror/view": "^6.0.0"
|
"@codemirror/view": "^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/octagonal-wheels": {
|
||||||
|
"version": "0.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/octagonal-wheels/-/octagonal-wheels-0.1.12.tgz",
|
||||||
|
"integrity": "sha512-pReKb681tUrrrvQCWmzsUFCeq4x5ClvkWMhUMz+WBjUCE5r0+5+Wzpd2sYWa0tpl7vwLa764MO7/p1THMEcXoA==",
|
||||||
|
"dependencies": {
|
||||||
|
"idb": "^8.0.0",
|
||||||
|
"xxhash-wasm": "0.4.2",
|
||||||
|
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/once": {
|
"node_modules/once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
@@ -4886,6 +4914,14 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/p-try": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -4902,7 +4938,6 @@
|
|||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@@ -4969,6 +5004,65 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pkg-dir": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"find-up": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pkg-dir/node_modules/find-up": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||||
|
"dependencies": {
|
||||||
|
"locate-path": "^5.0.0",
|
||||||
|
"path-exists": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pkg-dir/node_modules/locate-path": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||||
|
"dependencies": {
|
||||||
|
"p-locate": "^4.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pkg-dir/node_modules/p-limit": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||||
|
"dependencies": {
|
||||||
|
"p-try": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pkg-dir/node_modules/p-locate": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||||
|
"dependencies": {
|
||||||
|
"p-limit": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/possible-typed-array-names": {
|
"node_modules/possible-typed-array-names": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
|
||||||
@@ -5510,13 +5604,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.6.0",
|
"version": "7.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
|
||||||
"lru-cache": "^6.0.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
},
|
},
|
||||||
@@ -5780,9 +5871,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/svelte": {
|
"node_modules/svelte": {
|
||||||
"version": "4.2.12",
|
"version": "4.2.17",
|
||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.17.tgz",
|
||||||
"integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==",
|
"integrity": "sha512-N7m1YnoXtRf5wya5Gyx3TWuTddI4nAyayyIWFojiWV5IayDYNV5i2mRp/7qNGol4DtxEYxljmrbgp1HM6hUbmQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.1",
|
"@ampproject/remapping": "^2.2.1",
|
||||||
@@ -5958,9 +6049,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
|
||||||
},
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
@@ -6226,12 +6317,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz",
|
||||||
"integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A=="
|
"integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A=="
|
||||||
},
|
},
|
||||||
"node_modules/yallist": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/yaml": {
|
"node_modules/yaml": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
|
||||||
@@ -7015,161 +7100,138 @@
|
|||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
|
||||||
"integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
|
"integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/android-arm": {
|
"@esbuild/android-arm": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
|
||||||
"integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
|
"integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/android-arm64": {
|
"@esbuild/android-arm64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
|
"integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/android-x64": {
|
"@esbuild/android-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
|
"integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/darwin-arm64": {
|
"@esbuild/darwin-arm64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
|
"integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/darwin-x64": {
|
"@esbuild/darwin-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
|
"integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/freebsd-arm64": {
|
"@esbuild/freebsd-arm64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
|
"integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/freebsd-x64": {
|
"@esbuild/freebsd-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
|
"integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-arm": {
|
"@esbuild/linux-arm": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
|
||||||
"integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
|
"integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-arm64": {
|
"@esbuild/linux-arm64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
|
"integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-ia32": {
|
"@esbuild/linux-ia32": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
|
||||||
"integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
|
"integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-loong64": {
|
"@esbuild/linux-loong64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
|
||||||
"integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
|
"integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-mips64el": {
|
"@esbuild/linux-mips64el": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
|
||||||
"integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
|
"integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-ppc64": {
|
"@esbuild/linux-ppc64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
|
||||||
"integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
|
"integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-riscv64": {
|
"@esbuild/linux-riscv64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
|
||||||
"integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
|
"integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-s390x": {
|
"@esbuild/linux-s390x": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
|
||||||
"integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
|
"integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/linux-x64": {
|
"@esbuild/linux-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
|
"integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/netbsd-x64": {
|
"@esbuild/netbsd-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
|
"integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/openbsd-x64": {
|
"@esbuild/openbsd-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
|
"integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/sunos-x64": {
|
"@esbuild/sunos-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
|
"integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/win32-arm64": {
|
"@esbuild/win32-arm64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
|
||||||
"integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
|
"integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/win32-ia32": {
|
"@esbuild/win32-ia32": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
|
||||||
"integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
|
"integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@esbuild/win32-x64": {
|
"@esbuild/win32-x64": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
|
||||||
"integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
|
"integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
|
||||||
"dev": true,
|
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@eslint-community/eslint-utils": {
|
"@eslint-community/eslint-utils": {
|
||||||
@@ -8447,12 +8509,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"braces": {
|
"braces": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fill-range": "^7.0.1"
|
"fill-range": "^7.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buffer-crc32": {
|
"buffer-crc32": {
|
||||||
@@ -8542,6 +8604,11 @@
|
|||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"commondir": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="
|
||||||
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
@@ -8576,9 +8643,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
"integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
@@ -8758,7 +8825,6 @@
|
|||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
|
||||||
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
|
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@esbuild/aix-ppc64": "0.20.2",
|
"@esbuild/aix-ppc64": "0.20.2",
|
||||||
"@esbuild/android-arm": "0.20.2",
|
"@esbuild/android-arm": "0.20.2",
|
||||||
@@ -8785,6 +8851,15 @@
|
|||||||
"@esbuild/win32-x64": "0.20.2"
|
"@esbuild/win32-x64": "0.20.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"esbuild-plugin-inline-worker": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esbuild-plugin-inline-worker/-/esbuild-plugin-inline-worker-0.1.1.tgz",
|
||||||
|
"integrity": "sha512-VmFqsQKxUlbM51C1y5bRiMeyc1x2yTdMXhKB6S//++g9aCBg8TfGsbKxl5ZDkCGquqLY+RmEk93TBNd0i35dPA==",
|
||||||
|
"requires": {
|
||||||
|
"esbuild": "latest",
|
||||||
|
"find-cache-dir": "^3.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"esbuild-svelte": {
|
"esbuild-svelte": {
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild-svelte/-/esbuild-svelte-0.8.0.tgz",
|
||||||
@@ -9160,14 +9235,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fill-range": {
|
"fill-range": {
|
||||||
"version": "7.0.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"to-regex-range": "^5.0.1"
|
"to-regex-range": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"find-cache-dir": {
|
||||||
|
"version": "3.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
|
||||||
|
"integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
|
||||||
|
"requires": {
|
||||||
|
"commondir": "^1.0.1",
|
||||||
|
"make-dir": "^3.0.2",
|
||||||
|
"pkg-dir": "^4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"find-up": {
|
"find-up": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||||
@@ -9703,15 +9788,6 @@
|
|||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lru-cache": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"yallist": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"magic-string": {
|
"magic-string": {
|
||||||
"version": "0.30.8",
|
"version": "0.30.8",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
|
||||||
@@ -9721,6 +9797,21 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"make-dir": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||||
|
"requires": {
|
||||||
|
"semver": "^6.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"mdn-data": {
|
"mdn-data": {
|
||||||
"version": "2.0.30",
|
"version": "2.0.30",
|
||||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
@@ -9885,6 +9976,16 @@
|
|||||||
"moment": "2.29.4"
|
"moment": "2.29.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"octagonal-wheels": {
|
||||||
|
"version": "0.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/octagonal-wheels/-/octagonal-wheels-0.1.12.tgz",
|
||||||
|
"integrity": "sha512-pReKb681tUrrrvQCWmzsUFCeq4x5ClvkWMhUMz+WBjUCE5r0+5+Wzpd2sYWa0tpl7vwLa764MO7/p1THMEcXoA==",
|
||||||
|
"requires": {
|
||||||
|
"idb": "^8.0.0",
|
||||||
|
"xxhash-wasm": "0.4.2",
|
||||||
|
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"once": {
|
"once": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
@@ -9926,6 +10027,11 @@
|
|||||||
"p-limit": "^3.0.2"
|
"p-limit": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"p-try": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
||||||
|
},
|
||||||
"parent-module": {
|
"parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -9938,8 +10044,7 @@
|
|||||||
"path-exists": {
|
"path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"path-is-absolute": {
|
"path-is-absolute": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -9988,6 +10093,49 @@
|
|||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"pkg-dir": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
|
||||||
|
"requires": {
|
||||||
|
"find-up": "^4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"find-up": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||||
|
"requires": {
|
||||||
|
"locate-path": "^5.0.0",
|
||||||
|
"path-exists": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"locate-path": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||||
|
"requires": {
|
||||||
|
"p-locate": "^4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p-limit": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||||
|
"requires": {
|
||||||
|
"p-try": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"p-locate": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||||
|
"requires": {
|
||||||
|
"p-limit": "^2.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"possible-typed-array-names": {
|
"possible-typed-array-names": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
|
||||||
@@ -10412,13 +10560,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.6.0",
|
"version": "7.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {
|
|
||||||
"lru-cache": "^6.0.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"set-function-length": {
|
"set-function-length": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
@@ -10610,9 +10755,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"svelte": {
|
"svelte": {
|
||||||
"version": "4.2.12",
|
"version": "4.2.17",
|
||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.12.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.17.tgz",
|
||||||
"integrity": "sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==",
|
"integrity": "sha512-N7m1YnoXtRf5wya5Gyx3TWuTddI4nAyayyIWFojiWV5IayDYNV5i2mRp/7qNGol4DtxEYxljmrbgp1HM6hUbmQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ampproject/remapping": "^2.2.1",
|
"@ampproject/remapping": "^2.2.1",
|
||||||
@@ -10718,9 +10863,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
|
||||||
},
|
},
|
||||||
"type-check": {
|
"type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
@@ -10924,12 +11069,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz",
|
||||||
"integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A=="
|
"integrity": "sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A=="
|
||||||
},
|
},
|
||||||
"yallist": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"yaml": {
|
"yaml": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
|
||||||
|
|||||||
+5
-2
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.23.10",
|
"version": "0.23.16",
|
||||||
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
"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",
|
"main": "main.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node esbuild.config.mjs",
|
"dev": "node esbuild.config.mjs",
|
||||||
"build": "node esbuild.config.mjs production",
|
"build": "node esbuild.config.mjs production",
|
||||||
|
"buildDev": "node esbuild.config.mjs dev",
|
||||||
"lint": "eslint src"
|
"lint": "eslint src"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
@@ -46,7 +47,7 @@
|
|||||||
"pouchdb-merge": "^8.0.1",
|
"pouchdb-merge": "^8.0.1",
|
||||||
"pouchdb-replication": "^8.0.1",
|
"pouchdb-replication": "^8.0.1",
|
||||||
"pouchdb-utils": "^8.0.1",
|
"pouchdb-utils": "^8.0.1",
|
||||||
"svelte": "^4.2.12",
|
"svelte": "^4.2.16",
|
||||||
"svelte-preprocess": "^5.1.3",
|
"svelte-preprocess": "^5.1.3",
|
||||||
"terser": "^5.29.2",
|
"terser": "^5.29.2",
|
||||||
"transform-pouch": "^2.0.0",
|
"transform-pouch": "^2.0.0",
|
||||||
@@ -59,9 +60,11 @@
|
|||||||
"@smithy/protocol-http": "^3.3.0",
|
"@smithy/protocol-http": "^3.3.0",
|
||||||
"@smithy/querystring-builder": "^2.2.0",
|
"@smithy/querystring-builder": "^2.2.0",
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
|
"esbuild-plugin-inline-worker": "^0.1.1",
|
||||||
"fflate": "^0.8.2",
|
"fflate": "^0.8.2",
|
||||||
"idb": "^8.0.0",
|
"idb": "^8.0.0",
|
||||||
"minimatch": "^9.0.3",
|
"minimatch": "^9.0.3",
|
||||||
|
"octagonal-wheels": "^0.1.12",
|
||||||
"xxhash-wasm": "0.4.2",
|
"xxhash-wasm": "0.4.2",
|
||||||
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,10 @@
|
|||||||
{
|
{
|
||||||
"nbformat": 4,
|
|
||||||
"nbformat_minor": 0,
|
|
||||||
"metadata": {
|
|
||||||
"colab": {
|
|
||||||
"provenance": [],
|
|
||||||
"private_outputs": true,
|
|
||||||
"authorship_tag": "ABX9TyMexQ5pErH5LBG2tENtEVWf",
|
|
||||||
"include_colab_link": true
|
|
||||||
},
|
|
||||||
"kernelspec": {
|
|
||||||
"name": "python3",
|
|
||||||
"display_name": "Python 3"
|
|
||||||
},
|
|
||||||
"language_info": {
|
|
||||||
"name": "python"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"id": "view-in-github",
|
"colab_type": "text",
|
||||||
"colab_type": "text"
|
"id": "view-in-github"
|
||||||
},
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"<a href=\"https://colab.research.google.com/gist/vrtmrz/9402b101746e08e969b1a4f5f0deb465/setup-flyio-on-the-fly-v2.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
"<a href=\"https://colab.research.google.com/gist/vrtmrz/9402b101746e08e969b1a4f5f0deb465/setup-flyio-on-the-fly-v2.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
|
||||||
@@ -29,12 +12,12 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"source": [
|
|
||||||
"- Initial version 7th Feb. 2024"
|
|
||||||
],
|
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"id": "AzLlAcLFRO5A"
|
"id": "AzLlAcLFRO5A"
|
||||||
}
|
},
|
||||||
|
"source": [
|
||||||
|
"- Initial version 7th Feb. 2024"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
@@ -55,27 +38,32 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"source": [
|
"execution_count": null,
|
||||||
"# Login up sign up\n",
|
|
||||||
"!flyctl auth signup"
|
|
||||||
],
|
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"id": "mGN08BaFDviy"
|
"id": "mGN08BaFDviy"
|
||||||
},
|
},
|
||||||
"execution_count": null,
|
"outputs": [],
|
||||||
"outputs": []
|
"source": [
|
||||||
|
"# Login up sign up\n",
|
||||||
|
"!flyctl auth signup"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
"source": [
|
|
||||||
"Select a region and execute the block."
|
|
||||||
],
|
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"id": "BBFTFOP6vA8m"
|
"id": "BBFTFOP6vA8m"
|
||||||
}
|
},
|
||||||
|
"source": [
|
||||||
|
"Select a region and execute the block."
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {
|
||||||
|
"id": "TNl0A603EF9E"
|
||||||
|
},
|
||||||
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"# see https://fly.io/docs/reference/regions/\n",
|
"# see https://fly.io/docs/reference/regions/\n",
|
||||||
"region = \"nrt/Tokyo, Japan\" #@param [\"ams/Amsterdam, Netherlands\",\"arn/Stockholm, Sweden\",\"atl/Atlanta, Georgia (US)\",\"bog/Bogotá, Colombia\",\"bos/Boston, Massachusetts (US)\",\"cdg/Paris, France\",\"den/Denver, Colorado (US)\",\"dfw/Dallas, Texas (US)\",\"ewr/Secaucus, NJ (US)\",\"eze/Ezeiza, Argentina\",\"gdl/Guadalajara, Mexico\",\"gig/Rio de Janeiro, Brazil\",\"gru/Sao Paulo, Brazil\",\"hkg/Hong Kong, Hong Kong\",\"iad/Ashburn, Virginia (US)\",\"jnb/Johannesburg, South Africa\",\"lax/Los Angeles, California (US)\",\"lhr/London, United Kingdom\",\"mad/Madrid, Spain\",\"mia/Miami, Florida (US)\",\"nrt/Tokyo, Japan\",\"ord/Chicago, Illinois (US)\",\"otp/Bucharest, Romania\",\"phx/Phoenix, Arizona (US)\",\"qro/Querétaro, Mexico\",\"scl/Santiago, Chile\",\"sea/Seattle, Washington (US)\",\"sin/Singapore, Singapore\",\"sjc/San Jose, California (US)\",\"syd/Sydney, Australia\",\"waw/Warsaw, Poland\",\"yul/Montreal, Canada\",\"yyz/Toronto, Canada\" ] {allow-input: true}\n",
|
"region = \"nrt/Tokyo, Japan\" #@param [\"ams/Amsterdam, Netherlands\",\"arn/Stockholm, Sweden\",\"atl/Atlanta, Georgia (US)\",\"bog/Bogotá, Colombia\",\"bos/Boston, Massachusetts (US)\",\"cdg/Paris, France\",\"den/Denver, Colorado (US)\",\"dfw/Dallas, Texas (US)\",\"ewr/Secaucus, NJ (US)\",\"eze/Ezeiza, Argentina\",\"gdl/Guadalajara, Mexico\",\"gig/Rio de Janeiro, Brazil\",\"gru/Sao Paulo, Brazil\",\"hkg/Hong Kong, Hong Kong\",\"iad/Ashburn, Virginia (US)\",\"jnb/Johannesburg, South Africa\",\"lax/Los Angeles, California (US)\",\"lhr/London, United Kingdom\",\"mad/Madrid, Spain\",\"mia/Miami, Florida (US)\",\"nrt/Tokyo, Japan\",\"ord/Chicago, Illinois (US)\",\"otp/Bucharest, Romania\",\"phx/Phoenix, Arizona (US)\",\"qro/Querétaro, Mexico\",\"scl/Santiago, Chile\",\"sea/Seattle, Washington (US)\",\"sin/Singapore, Singapore\",\"sjc/San Jose, California (US)\",\"syd/Sydney, Australia\",\"waw/Warsaw, Poland\",\"yul/Montreal, Canada\",\"yyz/Toronto, Canada\" ] {allow-input: true}\n",
|
||||||
@@ -98,31 +86,29 @@
|
|||||||
" last_line = str.strip(last_line)\n",
|
" last_line = str.strip(last_line)\n",
|
||||||
"\n",
|
"\n",
|
||||||
"if last_line.startswith(\"obsidian://\"):\n",
|
"if last_line.startswith(\"obsidian://\"):\n",
|
||||||
" result = HTML(f\"Copy your setup-URI with this button! -> <button onclick=\\\"navigator.clipboard.writeText('{last_line}')\\\">Copy setup uri</button><br>Importing passphrase is `welcome`. <br>If you want to synchronise in live mode, please apply a preset after ensuring the imported configuration works.\")\n",
|
" result = HTML(f\"Copy your setup-URI with this button! -> <button onclick=\\\"navigator.clipboard.writeText('{last_line}')\\\">Copy setup uri</button><br>Importing passphrase is displayed one. <br>If you want to synchronise in live mode, please apply a preset after ensuring the imported configuration works.\")\n",
|
||||||
"else:\n",
|
"else:\n",
|
||||||
" result = \"Failed to encrypt the setup URI\"\n",
|
" result = \"Failed to encrypt the setup URI\"\n",
|
||||||
"result"
|
"result"
|
||||||
],
|
]
|
||||||
"metadata": {
|
|
||||||
"id": "TNl0A603EF9E"
|
|
||||||
},
|
|
||||||
"execution_count": null,
|
|
||||||
"outputs": []
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"id": "oeIzExnEKhFp"
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"If you see the `Copy setup URI` button, Congratulations! Your CouchDB is ready to use! Please click the button. And open this on Obsidian.\n",
|
"If you see the `Copy setup URI` button, Congratulations! Your CouchDB is ready to use! Please click the button. And open this on Obsidian.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"And, you should keep the output to your secret memo.\n",
|
"And, you should keep the output to your secret memo.\n",
|
||||||
"\n"
|
"\n"
|
||||||
],
|
]
|
||||||
"metadata": {
|
|
||||||
"id": "oeIzExnEKhFp"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "markdown",
|
"cell_type": "markdown",
|
||||||
|
"metadata": {
|
||||||
|
"id": "sdQrqOjERN3K"
|
||||||
|
},
|
||||||
"source": [
|
"source": [
|
||||||
"\n",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
@@ -131,21 +117,35 @@
|
|||||||
"\n",
|
"\n",
|
||||||
"If you want to delete this CouchDB instance, you can do it by executing next cell. \n",
|
"If you want to delete this CouchDB instance, you can do it by executing next cell. \n",
|
||||||
"If your fly.toml has been gone, access https://fly.io/dashboard and check the existing app."
|
"If your fly.toml has been gone, access https://fly.io/dashboard and check the existing app."
|
||||||
],
|
]
|
||||||
"metadata": {
|
|
||||||
"id": "sdQrqOjERN3K"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"source": [
|
"execution_count": null,
|
||||||
"!./delete-server.sh"
|
|
||||||
],
|
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"id": "7JMSkNvVIIfg"
|
"id": "7JMSkNvVIIfg"
|
||||||
},
|
},
|
||||||
"execution_count": null,
|
"outputs": [],
|
||||||
"outputs": []
|
"source": [
|
||||||
|
"!./delete-server.sh"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
}
|
"metadata": {
|
||||||
|
"colab": {
|
||||||
|
"authorship_tag": "ABX9TyMexQ5pErH5LBG2tENtEVWf",
|
||||||
|
"include_colab_link": true,
|
||||||
|
"private_outputs": true,
|
||||||
|
"provenance": []
|
||||||
|
},
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"name": "python"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 0
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ export type FileEventItem = {
|
|||||||
type: FileEventType,
|
type: FileEventType,
|
||||||
args: FileEventArgs,
|
args: FileEventArgs,
|
||||||
key: string,
|
key: string,
|
||||||
|
skipBatchWait?: boolean,
|
||||||
|
cancelled?: boolean,
|
||||||
|
batched?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hidden items (Now means `chunk`)
|
// Hidden items (Now means `chunk`)
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@ import { LOG_LEVEL_VERBOSE, type AnyEntry, type DocumentID, type EntryHasPath, t
|
|||||||
import { CHeader, ICHeader, ICHeaderLength, ICXHeader, PSCHeader } from "./types.ts";
|
import { CHeader, ICHeader, ICHeaderLength, ICXHeader, PSCHeader } from "./types.ts";
|
||||||
import { InputStringDialog, PopoverSelectString } from "./dialogs.ts";
|
import { InputStringDialog, PopoverSelectString } from "./dialogs.ts";
|
||||||
import type ObsidianLiveSyncPlugin from "../main.ts";
|
import type ObsidianLiveSyncPlugin from "../main.ts";
|
||||||
import { writeString } from "../lib/src/string_and_binary/strbin.ts";
|
import { writeString } from "../lib/src/string_and_binary/convert.ts";
|
||||||
import { fireAndForget } from "../lib/src/common/utils.ts";
|
import { fireAndForget } from "../lib/src/common/utils.ts";
|
||||||
import { sameChangePairs } from "./stores.ts";
|
import { sameChangePairs } from "./stores.ts";
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import { Notice, type PluginManifest, parseYaml, normalizePath, type ListedFiles
|
|||||||
import type { EntryDoc, LoadedEntry, InternalFileEntry, FilePathWithPrefix, FilePath, DocumentID, AnyEntry, SavingEntry } from "../lib/src/common/types.ts";
|
import type { EntryDoc, LoadedEntry, InternalFileEntry, FilePathWithPrefix, FilePath, DocumentID, AnyEntry, SavingEntry } from "../lib/src/common/types.ts";
|
||||||
import { LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE, MODE_SELECTIVE } from "../lib/src/common/types.ts";
|
import { LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE, MODE_SELECTIVE } from "../lib/src/common/types.ts";
|
||||||
import { ICXHeader, PERIODIC_PLUGIN_SWEEP, } from "../common/types.ts";
|
import { ICXHeader, PERIODIC_PLUGIN_SWEEP, } from "../common/types.ts";
|
||||||
import { createSavingEntryFromLoadedEntry, createTextBlob, delay, fireAndForget, getDocDataAsArray, isDocContentSame, throttle } from "../lib/src/common/utils.ts";
|
import { createSavingEntryFromLoadedEntry, createTextBlob, delay, fireAndForget, getDocDataAsArray, isDocContentSame } from "../lib/src/common/utils.ts";
|
||||||
import { Logger } from "../lib/src/common/logger.ts";
|
import { Logger } from "../lib/src/common/logger.ts";
|
||||||
import { readString, decodeBinary, arrayBufferToBase64, digestHash } from "../lib/src/string_and_binary/strbin.ts";
|
import { digestHash } from "../lib/src/string_and_binary/hash.ts";
|
||||||
|
import { arrayBufferToBase64, decodeBinary, readString } from 'src/lib/src/string_and_binary/convert.ts';
|
||||||
import { serialized, shareRunningResult } from "../lib/src/concurrency/lock.ts";
|
import { serialized, shareRunningResult } from "../lib/src/concurrency/lock.ts";
|
||||||
import { LiveSyncCommands } from "./LiveSyncCommands.ts";
|
import { LiveSyncCommands } from "./LiveSyncCommands.ts";
|
||||||
import { stripAllPrefixes } from "../lib/src/string_and_binary/path.ts";
|
import { stripAllPrefixes } from "../lib/src/string_and_binary/path.ts";
|
||||||
@@ -19,7 +20,6 @@ import type ObsidianLiveSyncPlugin from '../main.ts';
|
|||||||
|
|
||||||
const d = "\u200b";
|
const d = "\u200b";
|
||||||
const d2 = "\n";
|
const d2 = "\n";
|
||||||
const delimiters = /(?<=[\n|\u200b])/g;
|
|
||||||
|
|
||||||
|
|
||||||
function serialize(data: PluginDataEx): string {
|
function serialize(data: PluginDataEx): string {
|
||||||
@@ -42,8 +42,45 @@ function serialize(data: PluginDataEx): string {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function splitWithDelimiters(sources: string[]): string[] {
|
||||||
|
const result: string[] = [];
|
||||||
|
for (const str of sources) {
|
||||||
|
let startIndex = 0;
|
||||||
|
const maxLen = str.length;
|
||||||
|
let i = -1;
|
||||||
|
let i1;
|
||||||
|
let i2;
|
||||||
|
do {
|
||||||
|
i1 = str.indexOf(d, startIndex);
|
||||||
|
i2 = str.indexOf(d2, startIndex);
|
||||||
|
if (i1 == -1 && i2 == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i1 == -1) {
|
||||||
|
i = i2;
|
||||||
|
} else if (i2 == -1) {
|
||||||
|
i = i1;
|
||||||
|
} else {
|
||||||
|
i = i1 < i2 ? i1 : i2;
|
||||||
|
}
|
||||||
|
result.push(str.slice(startIndex, i + 1));
|
||||||
|
startIndex = i + 1;
|
||||||
|
} while (i < maxLen);
|
||||||
|
if (startIndex < maxLen) {
|
||||||
|
result.push(str.slice(startIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To keep compatibilities
|
||||||
|
if (sources[sources.length - 1] == "") {
|
||||||
|
result.push("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function getTokenizer(source: string[]) {
|
function getTokenizer(source: string[]) {
|
||||||
const sources = source.flatMap(e => e.split(delimiters))
|
const sources = splitWithDelimiters(source);
|
||||||
sources[0] = sources[0].substring(1);
|
sources[0] = sources[0].substring(1);
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
let lineRunOut = false;
|
let lineRunOut = false;
|
||||||
@@ -318,8 +355,7 @@ export class ConfigSync extends LiveSyncCommands {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
createMissingConfigurationEntry = throttle(() => this._createMissingConfigurationEntry(), 1000);
|
async createMissingConfigurationEntry() {
|
||||||
_createMissingConfigurationEntry() {
|
|
||||||
let saveRequired = false;
|
let saveRequired = false;
|
||||||
for (const v of this.pluginList) {
|
for (const v of this.pluginList) {
|
||||||
const key = `${v.category}/${v.name}`;
|
const key = `${v.category}/${v.name}`;
|
||||||
@@ -337,7 +373,7 @@ export class ConfigSync extends LiveSyncCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (saveRequired) {
|
if (saveRequired) {
|
||||||
this.plugin.saveSettingData();
|
await this.plugin.saveSettingData();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -365,7 +401,11 @@ export class ConfigSync extends LiveSyncCommands {
|
|||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}, { suspended: false, batchSize: 1, concurrentLimit: 10, delay: 100, yieldThreshold: 10, maintainDelay: false, totalRemainingReactiveSource: pluginScanningCount }).startPipeline().root.onUpdateProgress(() => {
|
}, { suspended: false, batchSize: 1, concurrentLimit: 10, delay: 100, yieldThreshold: 10, maintainDelay: false, totalRemainingReactiveSource: pluginScanningCount }).startPipeline().root.onUpdateProgress(() => {
|
||||||
this.createMissingConfigurationEntry();
|
scheduleTask("checkMissingConfigurations", 250, async () => {
|
||||||
|
if (this.pluginScanProcessor.isIdle()) {
|
||||||
|
await this.createMissingConfigurationEntry();
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -654,7 +694,7 @@ export class ConfigSync extends LiveSyncCommands {
|
|||||||
for (const target of fileTargets) {
|
for (const target of fileTargets) {
|
||||||
const data = await this.makeEntryFromFile(target);
|
const data = await this.makeEntryFromFile(target);
|
||||||
if (data == false) {
|
if (data == false) {
|
||||||
// Logger(`Config: skipped: ${target} `, LOG_LEVEL_VERBOSE);
|
Logger(`Config: skipped (Possibly is not exist): ${target} `, LOG_LEVEL_VERBOSE);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (data.version) {
|
if (data.version) {
|
||||||
@@ -703,13 +743,15 @@ export class ConfigSync extends LiveSyncCommands {
|
|||||||
const oldC = await this.localDatabase.getDBEntryFromMeta(old, {}, false, false);
|
const oldC = await this.localDatabase.getDBEntryFromMeta(old, {}, false, false);
|
||||||
if (oldC) {
|
if (oldC) {
|
||||||
const d = await deserialize(getDocDataAsArray(oldC.data), {}) as PluginDataEx;
|
const d = await deserialize(getDocDataAsArray(oldC.data), {}) as PluginDataEx;
|
||||||
const diffs = (d.files.map(previous => ({ prev: previous, curr: dt.files.find(e => e.filename == previous.filename) })).map(async e => {
|
if (d.files.length == dt.files.length) {
|
||||||
try { return await isDocContentSame(e.curr?.data ?? [], e.prev.data) } catch (_) { return false }
|
const diffs = (d.files.map(previous => ({ prev: previous, curr: dt.files.find(e => e.filename == previous.filename) })).map(async e => {
|
||||||
}))
|
try { return await isDocContentSame(e.curr?.data ?? [], e.prev.data) } catch (_) { return false }
|
||||||
const isSame = (await Promise.all(diffs)).every(e => e == true);
|
}))
|
||||||
if (isSame) {
|
const isSame = (await Promise.all(diffs)).every(e => e == true);
|
||||||
Logger(`STORAGE --> DB:${prefixedFileName}: (config) Skipped (Same content)`, LOG_LEVEL_VERBOSE);
|
if (isSame) {
|
||||||
return true;
|
Logger(`STORAGE --> DB:${prefixedFileName}: (config) Skipped (Same content)`, LOG_LEVEL_VERBOSE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveData =
|
saveData =
|
||||||
@@ -757,9 +799,11 @@ export class ConfigSync extends LiveSyncCommands {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
this.recentProcessedInternalFiles = [key, ...this.recentProcessedInternalFiles].slice(0, 100);
|
this.recentProcessedInternalFiles = [key, ...this.recentProcessedInternalFiles].slice(0, 100);
|
||||||
|
// To prevent saving half-collected file sets.
|
||||||
this.storeCustomizationFiles(path).then(() => {/* Fire and forget */ });
|
const keySchedule = this.filenameToUnifiedKey(path);
|
||||||
|
scheduleTask(keySchedule, 100, async () => {
|
||||||
|
await this.storeCustomizationFiles(path);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
Submodule src/lib updated: 302a2e7c0b...dc60c7b52a
+113
-126
@@ -2,9 +2,9 @@ const isDebug = false;
|
|||||||
|
|
||||||
import { type Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch, stringifyYaml, parseYaml } from "./deps";
|
import { type Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch, stringifyYaml, parseYaml } from "./deps";
|
||||||
import { Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, type RequestUrlParam, type RequestUrlResponse, requestUrl, type MarkdownFileInfo } from "./deps";
|
import { Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, type RequestUrlParam, type RequestUrlResponse, requestUrl, type MarkdownFileInfo } from "./deps";
|
||||||
import { type EntryDoc, type LoadedEntry, type ObsidianLiveSyncSettings, type diff_check_result, type diff_result_leaf, type EntryBody, LOG_LEVEL, VER, DEFAULT_SETTINGS, type diff_result, FLAGMD_REDFLAG, SYNCINFO_ID, SALT_OF_PASSPHRASE, type ConfigPassphraseStore, type CouchDBConnection, FLAGMD_REDFLAG2, FLAGMD_REDFLAG3, PREFIXMD_LOGFILE, type DatabaseConnectingStatus, type EntryHasPath, type DocumentID, type FilePathWithPrefix, type FilePath, type AnyEntry, LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_URGENT, LOG_LEVEL_VERBOSE, type SavingEntry, MISSING_OR_ERROR, NOT_CONFLICTED, AUTO_MERGED, CANCELLED, LEAVE_TO_SUBSEQUENT, FLAGMD_REDFLAG2_HR, FLAGMD_REDFLAG3_HR, REMOTE_MINIO, REMOTE_COUCHDB, type BucketSyncSetting, TweakValuesShouldMatchedTemplate, confName, type TweakValues, } from "./lib/src/common/types.ts";
|
import { type EntryDoc, type LoadedEntry, type ObsidianLiveSyncSettings, type diff_check_result, type diff_result_leaf, type EntryBody, type LOG_LEVEL, VER, DEFAULT_SETTINGS, type diff_result, FLAGMD_REDFLAG, SYNCINFO_ID, SALT_OF_PASSPHRASE, type ConfigPassphraseStore, type CouchDBConnection, FLAGMD_REDFLAG2, FLAGMD_REDFLAG3, PREFIXMD_LOGFILE, type DatabaseConnectingStatus, type EntryHasPath, type DocumentID, type FilePathWithPrefix, type FilePath, type AnyEntry, LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_URGENT, LOG_LEVEL_VERBOSE, type SavingEntry, MISSING_OR_ERROR, NOT_CONFLICTED, AUTO_MERGED, CANCELLED, LEAVE_TO_SUBSEQUENT, FLAGMD_REDFLAG2_HR, FLAGMD_REDFLAG3_HR, REMOTE_MINIO, REMOTE_COUCHDB, type BucketSyncSetting, TweakValuesShouldMatchedTemplate, confName, type TweakValues, } from "./lib/src/common/types.ts";
|
||||||
import { type InternalFileInfo, type CacheData, type FileEventItem, FileWatchEventQueueMax } from "./common/types.ts";
|
import { type InternalFileInfo, type CacheData, type FileEventItem } from "./common/types.ts";
|
||||||
import { arrayToChunkedArray, createBlob, delay, determineTypeFromBlob, escapeMarkdownValue, extractObject, fireAndForget, getDocData, isAnyNote, isDocContentSame, isObjectDifferent, readContent, sendValue, throttle, type SimpleStore } from "./lib/src/common/utils.ts";
|
import { arrayToChunkedArray, createBlob, determineTypeFromBlob, escapeMarkdownValue, extractObject, fireAndForget, getDocData, isAnyNote, isDocContentSame, isObjectDifferent, readContent, sendValue, throttle, type SimpleStore } from "./lib/src/common/utils.ts";
|
||||||
import { Logger, setGlobalLogFunction } from "./lib/src/common/logger.ts";
|
import { Logger, setGlobalLogFunction } from "./lib/src/common/logger.ts";
|
||||||
import { PouchDB } from "./lib/src/pouchdb/pouchdb-browser.js";
|
import { PouchDB } from "./lib/src/pouchdb/pouchdb-browser.js";
|
||||||
import { ConflictResolveModal } from "./ui/ConflictResolveModal.ts";
|
import { ConflictResolveModal } from "./ui/ConflictResolveModal.ts";
|
||||||
@@ -15,10 +15,10 @@ import { encrypt, tryDecrypt } from "./lib/src/encryption/e2ee_v2.ts";
|
|||||||
import { balanceChunkPurgedDBs, enableCompression, enableEncryption, isCloudantURI, isErrorOfMissingDoc, isValidRemoteCouchDBURI, purgeUnreferencedChunks } from "./lib/src/pouchdb/utils_couchdb.ts";
|
import { balanceChunkPurgedDBs, enableCompression, enableEncryption, isCloudantURI, isErrorOfMissingDoc, isValidRemoteCouchDBURI, purgeUnreferencedChunks } from "./lib/src/pouchdb/utils_couchdb.ts";
|
||||||
import { logStore, type LogEntry, collectingChunks, pluginScanningCount, hiddenFilesProcessingCount, hiddenFilesEventCount, logMessages } from "./lib/src/mock_and_interop/stores.ts";
|
import { logStore, type LogEntry, collectingChunks, pluginScanningCount, hiddenFilesProcessingCount, hiddenFilesEventCount, logMessages } from "./lib/src/mock_and_interop/stores.ts";
|
||||||
import { setNoticeClass } from "./lib/src/mock_and_interop/wrapper.ts";
|
import { setNoticeClass } from "./lib/src/mock_and_interop/wrapper.ts";
|
||||||
import { versionNumberString2Number, writeString, decodeBinary, readString } from "./lib/src/string_and_binary/strbin.ts";
|
import { versionNumberString2Number, writeString, decodeBinary, readString } from "./lib/src/string_and_binary/convert.ts";
|
||||||
import { addPrefix, isAcceptedAll, isPlainText, shouldBeIgnored, stripAllPrefixes } from "./lib/src/string_and_binary/path.ts";
|
import { addPrefix, isAcceptedAll, isPlainText, shouldBeIgnored, stripAllPrefixes } from "./lib/src/string_and_binary/path.ts";
|
||||||
import { isLockAcquired, serialized, shareRunningResult, skipIfDuplicated } from "./lib/src/concurrency/lock.ts";
|
import { isLockAcquired, serialized, shareRunningResult, skipIfDuplicated } from "./lib/src/concurrency/lock.ts";
|
||||||
import { StorageEventManager, StorageEventManagerObsidian } from "./storages/StorageEventManager.ts";
|
import { StorageEventManager, StorageEventManagerObsidian, type FileEvent } from "./storages/StorageEventManager.ts";
|
||||||
import { LiveSyncLocalDB, type LiveSyncLocalDBEnv } from "./lib/src/pouchdb/LiveSyncLocalDB.ts";
|
import { LiveSyncLocalDB, type LiveSyncLocalDBEnv } from "./lib/src/pouchdb/LiveSyncLocalDB.ts";
|
||||||
import { LiveSyncAbstractReplicator, type LiveSyncReplicatorEnv } from "./lib/src/replication/LiveSyncAbstractReplicator.js";
|
import { LiveSyncAbstractReplicator, type LiveSyncReplicatorEnv } from "./lib/src/replication/LiveSyncAbstractReplicator.js";
|
||||||
import { type KeyValueDatabase, OpenKeyValueDatabase } from "./common/KeyValueDB.ts";
|
import { type KeyValueDatabase, OpenKeyValueDatabase } from "./common/KeyValueDB.ts";
|
||||||
@@ -32,7 +32,7 @@ import { LogPaneView, VIEW_TYPE_LOG } from "./ui/LogPaneView.ts";
|
|||||||
import { LRUCache } from "./lib/src/memory/LRUCache.ts";
|
import { LRUCache } from "./lib/src/memory/LRUCache.ts";
|
||||||
import { SerializedFileAccess } from "./storages/SerializedFileAccess.js";
|
import { SerializedFileAccess } from "./storages/SerializedFileAccess.js";
|
||||||
import { QueueProcessor, stopAllRunningProcessors } from "./lib/src/concurrency/processor.js";
|
import { QueueProcessor, stopAllRunningProcessors } from "./lib/src/concurrency/processor.js";
|
||||||
import { reactive, reactiveSource, type ReactiveValue } from "./lib/src/dataobject/reactive.js";
|
import { computed, reactive, reactiveSource, type ReactiveValue } from "./lib/src/dataobject/reactive.js";
|
||||||
import { initializeStores } from "./common/stores.js";
|
import { initializeStores } from "./common/stores.js";
|
||||||
import { JournalSyncMinio } from "./lib/src/replication/journal/objectstore/JournalSyncMinio.js";
|
import { JournalSyncMinio } from "./lib/src/replication/journal/objectstore/JournalSyncMinio.js";
|
||||||
import { LiveSyncJournalReplicator, type LiveSyncJournalReplicatorEnv } from "./lib/src/replication/journal/LiveSyncJournalReplicator.js";
|
import { LiveSyncJournalReplicator, type LiveSyncJournalReplicatorEnv } from "./lib/src/replication/journal/LiveSyncJournalReplicator.js";
|
||||||
@@ -41,6 +41,8 @@ import type { CheckPointInfo } from "./lib/src/replication/journal/JournalSyncTy
|
|||||||
import { ObsHttpHandler } from "./common/ObsHttpHandler.js";
|
import { ObsHttpHandler } from "./common/ObsHttpHandler.js";
|
||||||
import { TestPaneView, VIEW_TYPE_TEST } from "./tests/TestPaneView.js"
|
import { TestPaneView, VIEW_TYPE_TEST } from "./tests/TestPaneView.js"
|
||||||
import { $f, __onMissingTranslation, setLang } from "./lib/src/common/i18n.ts";
|
import { $f, __onMissingTranslation, setLang } from "./lib/src/common/i18n.ts";
|
||||||
|
import { enableTestFunction } from "./tests/testUtils.ts";
|
||||||
|
import { terminateWorker } from "./lib/src/worker/splitWorker.ts";
|
||||||
|
|
||||||
|
|
||||||
setNoticeClass(Notice);
|
setNoticeClass(Notice);
|
||||||
@@ -97,6 +99,15 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
|||||||
set suspended(value: boolean) {
|
set suspended(value: boolean) {
|
||||||
this._suspended = value;
|
this._suspended = value;
|
||||||
}
|
}
|
||||||
|
get shouldBatchSave() {
|
||||||
|
return this.settings?.batchSave && this.settings?.liveSync != true;
|
||||||
|
}
|
||||||
|
get batchSaveMinimumDelay(): number {
|
||||||
|
return this.settings?.batchSaveMinimumDelay ?? DEFAULT_SETTINGS.batchSaveMinimumDelay
|
||||||
|
}
|
||||||
|
get batchSaveMaximumDelay(): number {
|
||||||
|
return this.settings?.batchSaveMaximumDelay ?? DEFAULT_SETTINGS.batchSaveMaximumDelay
|
||||||
|
}
|
||||||
deviceAndVaultName = "";
|
deviceAndVaultName = "";
|
||||||
isReady = false;
|
isReady = false;
|
||||||
packageVersion = "";
|
packageVersion = "";
|
||||||
@@ -855,6 +866,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
|||||||
);
|
);
|
||||||
// eslint-disable-next-line no-unused-labels
|
// eslint-disable-next-line no-unused-labels
|
||||||
TEST: {
|
TEST: {
|
||||||
|
enableTestFunction(this);
|
||||||
this.registerView(
|
this.registerView(
|
||||||
VIEW_TYPE_TEST,
|
VIEW_TYPE_TEST,
|
||||||
(leaf) => new TestPaneView(leaf, this)
|
(leaf) => new TestPaneView(leaf, this)
|
||||||
@@ -870,14 +882,13 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
|||||||
this.showView(VIEW_TYPE_TEST);
|
this.showView(VIEW_TYPE_TEST);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onload() {
|
async onload() {
|
||||||
logStore.pipeTo(new QueueProcessor(logs => logs.forEach(e => this.addLog(e.message, e.level, e.key)), { suspended: false, batchSize: 20, concurrentLimit: 1, delay: 0 })).startPipeline();
|
logStore.pipeTo(new QueueProcessor(logs => logs.forEach(e => this.addLog(e.message, e.level, e.key)), { suspended: false, batchSize: 20, concurrentLimit: 1, delay: 0 })).startPipeline();
|
||||||
Logger("loading plugin");
|
Logger("loading plugin");
|
||||||
|
__onMissingTranslation(() => { });
|
||||||
// eslint-disable-next-line no-unused-labels
|
// eslint-disable-next-line no-unused-labels
|
||||||
DEV: {
|
DEV: {
|
||||||
__onMissingTranslation((key) => {
|
__onMissingTranslation((key) => {
|
||||||
@@ -893,6 +904,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
|||||||
const writePiece = piece.substring(1, piece.length - 1) + ",";
|
const writePiece = piece.substring(1, piece.length - 1) + ",";
|
||||||
fireAndForget(async () => {
|
fireAndForget(async () => {
|
||||||
try {
|
try {
|
||||||
|
await this.vaultAccess.ensureDirectory(this.app.vault.configDir + "/ls-debug/");
|
||||||
await this.vaultAccess.adapterAppend(this.app.vault.configDir + "/ls-debug/" + outFile, writePiece + "\n")
|
await this.vaultAccess.adapterAppend(this.app.vault.configDir + "/ls-debug/" + outFile, writePiece + "\n")
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Logger(`Could not write ${outFile}`, LOG_LEVEL_VERBOSE);
|
Logger(`Could not write ${outFile}`, LOG_LEVEL_VERBOSE);
|
||||||
@@ -944,6 +956,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
|||||||
localStorage.setItem(lsKey, `${VER}`);
|
localStorage.setItem(lsKey, `${VER}`);
|
||||||
await this.openDatabase();
|
await this.openDatabase();
|
||||||
this.watchWorkspaceOpen = this.watchWorkspaceOpen.bind(this);
|
this.watchWorkspaceOpen = this.watchWorkspaceOpen.bind(this);
|
||||||
|
this.watchEditorChange = this.watchEditorChange.bind(this);
|
||||||
this.watchWindowVisibility = this.watchWindowVisibility.bind(this)
|
this.watchWindowVisibility = this.watchWindowVisibility.bind(this)
|
||||||
this.watchOnline = this.watchOnline.bind(this);
|
this.watchOnline = this.watchOnline.bind(this);
|
||||||
this.realizeSettingSyncMode = this.realizeSettingSyncMode.bind(this);
|
this.realizeSettingSyncMode = this.realizeSettingSyncMode.bind(this);
|
||||||
@@ -981,6 +994,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
|||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
|
terminateWorker();
|
||||||
cancelAllPeriodicTask();
|
cancelAllPeriodicTask();
|
||||||
cancelAllTasks();
|
cancelAllTasks();
|
||||||
stopAllRunningProcessors();
|
stopAllRunningProcessors();
|
||||||
@@ -1133,16 +1147,17 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
|||||||
}
|
}
|
||||||
this.deviceAndVaultName = localStorage.getItem(lsKey) || "";
|
this.deviceAndVaultName = localStorage.getItem(lsKey) || "";
|
||||||
this.ignoreFiles = this.settings.ignoreFiles.split(",").map(e => e.trim());
|
this.ignoreFiles = this.settings.ignoreFiles.split(",").map(e => e.trim());
|
||||||
this.fileEventQueue.delay = (!this.settings.liveSync && this.settings.batchSave) ? 5000 : 100;
|
|
||||||
this.settingTab.requestReload()
|
this.settingTab.requestReload()
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveSettingData() {
|
saveDeviceAndVaultName() {
|
||||||
const lsKey = "obsidian-live-sync-vaultanddevicename-" + this.getVaultName();
|
const lsKey = "obsidian-live-sync-vaultanddevicename-" + this.getVaultName();
|
||||||
|
|
||||||
localStorage.setItem(lsKey, this.deviceAndVaultName || "");
|
localStorage.setItem(lsKey, this.deviceAndVaultName || "");
|
||||||
|
}
|
||||||
|
async saveSettingData() {
|
||||||
|
this.saveDeviceAndVaultName();
|
||||||
const settings = { ...this.settings };
|
const settings = { ...this.settings };
|
||||||
|
settings.deviceAndVaultName = "";
|
||||||
if (this.usedPassphrase == "" && !await this.getPassphrase(settings)) {
|
if (this.usedPassphrase == "" && !await this.getPassphrase(settings)) {
|
||||||
Logger("Could not determine passphrase for saving data.json! Our data.json have insecure items!", LOG_LEVEL_NOTICE);
|
Logger("Could not determine passphrase for saving data.json! Our data.json have insecure items!", LOG_LEVEL_NOTICE);
|
||||||
} else {
|
} else {
|
||||||
@@ -1180,7 +1195,6 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
|||||||
this.localDatabase.settings = this.settings;
|
this.localDatabase.settings = this.settings;
|
||||||
setLang(this.settings.displayLanguage);
|
setLang(this.settings.displayLanguage);
|
||||||
this.settingTab.requestReload();
|
this.settingTab.requestReload();
|
||||||
this.fileEventQueue.delay = (!this.settings.liveSync && this.settings.batchSave) ? 5000 : 100;
|
|
||||||
this.ignoreFiles = this.settings.ignoreFiles.split(",").map(e => e.trim());
|
this.ignoreFiles = this.settings.ignoreFiles.split(",").map(e => e.trim());
|
||||||
if (this.settings.settingSyncFile != "") {
|
if (this.settings.settingSyncFile != "") {
|
||||||
fireAndForget(() => this.saveSettingToMarkdown(this.settings.settingSyncFile));
|
fireAndForget(() => this.saveSettingToMarkdown(this.settings.settingSyncFile));
|
||||||
@@ -1346,6 +1360,7 @@ We can perform a command in this file.
|
|||||||
vaultManager: StorageEventManager = new StorageEventManagerObsidian(this);
|
vaultManager: StorageEventManager = new StorageEventManagerObsidian(this);
|
||||||
registerFileWatchEvents() {
|
registerFileWatchEvents() {
|
||||||
this.vaultManager.beginWatch();
|
this.vaultManager.beginWatch();
|
||||||
|
this.registerEvent(this.app.workspace.on("editor-change", this.watchEditorChange));
|
||||||
}
|
}
|
||||||
_initialCallback: any;
|
_initialCallback: any;
|
||||||
swapSaveCommand() {
|
swapSaveCommand() {
|
||||||
@@ -1363,8 +1378,8 @@ We can perform a command in this file.
|
|||||||
saveCommandDefinition.callback = this._initialCallback;
|
saveCommandDefinition.callback = this._initialCallback;
|
||||||
this._initialCallback = undefined;
|
this._initialCallback = undefined;
|
||||||
} else {
|
} else {
|
||||||
Logger("Sync on Editor Save.", LOG_LEVEL_VERBOSE);
|
|
||||||
if (this.settings.syncOnEditorSave) {
|
if (this.settings.syncOnEditorSave) {
|
||||||
|
Logger("Sync on Editor Save.", LOG_LEVEL_VERBOSE);
|
||||||
this.replicate();
|
this.replicate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1447,37 +1462,10 @@ We can perform a command in this file.
|
|||||||
}
|
}
|
||||||
|
|
||||||
cancelRelativeEvent(item: FileEventItem) {
|
cancelRelativeEvent(item: FileEventItem) {
|
||||||
this.fileEventQueue.modifyQueue((items) => [...items.filter(e => e.key != item.key)])
|
this.vaultManager.cancelQueue(item.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
queueNextFileEvent(items: FileEventItem[], newItem: FileEventItem): FileEventItem[] {
|
|
||||||
if (this.settings.batchSave && !this.settings.liveSync) {
|
|
||||||
const file = newItem.args.file;
|
|
||||||
// if the latest event is the same type, omit that
|
|
||||||
// a.md MODIFY <- this should be cancelled when a.md MODIFIED
|
|
||||||
// b.md MODIFY <- this should be cancelled when b.md MODIFIED
|
|
||||||
// a.md MODIFY
|
|
||||||
// a.md CREATE
|
|
||||||
// :
|
|
||||||
let i = items.length;
|
|
||||||
L1:
|
|
||||||
while (i >= 0) {
|
|
||||||
i--;
|
|
||||||
if (i < 0) break L1;
|
|
||||||
if (items[i].args.file.path != file.path) {
|
|
||||||
continue L1;
|
|
||||||
}
|
|
||||||
if (items[i].type != newItem.type) break L1;
|
|
||||||
items.remove(items[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
items.push(newItem);
|
|
||||||
// When deleting or renaming, the queue must be flushed once before processing subsequent processes to prevent unexpected race condition.
|
|
||||||
if (newItem.type == "DELETE" || newItem.type == "RENAME") {
|
|
||||||
this.fileEventQueue.requestNextFlush();
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
async handleFileEvent(queue: FileEventItem): Promise<any> {
|
async handleFileEvent(queue: FileEventItem): Promise<any> {
|
||||||
const file = queue.args.file;
|
const file = queue.args.file;
|
||||||
const lockKey = `handleFile:${file.path}`;
|
const lockKey = `handleFile:${file.path}`;
|
||||||
@@ -1531,21 +1519,8 @@ We can perform a command in this file.
|
|||||||
|
|
||||||
pendingFileEventCount = reactiveSource(0);
|
pendingFileEventCount = reactiveSource(0);
|
||||||
processingFileEventCount = reactiveSource(0);
|
processingFileEventCount = reactiveSource(0);
|
||||||
fileEventQueue =
|
|
||||||
new QueueProcessor(
|
|
||||||
async (items: FileEventItem[]) => {
|
|
||||||
await this.handleFileEvent(items[0]);
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
,
|
|
||||||
{ suspended: true, batchSize: 1, concurrentLimit: 5, delay: 100, yieldThreshold: FileWatchEventQueueMax, totalRemainingReactiveSource: this.pendingFileEventCount, processingEntitiesReactiveSource: this.processingFileEventCount }
|
|
||||||
).replaceEnqueueProcessor((items, newItem) => this.queueNextFileEvent(items, newItem));
|
|
||||||
|
|
||||||
|
|
||||||
flushFileEventQueue() {
|
|
||||||
return this.fileEventQueue.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
watchWorkspaceOpen(file: TFile | null) {
|
watchWorkspaceOpen(file: TFile | null) {
|
||||||
if (this.settings.suspendFileWatching) return;
|
if (this.settings.suspendFileWatching) return;
|
||||||
if (!this.settings.isConfigured) return;
|
if (!this.settings.isConfigured) return;
|
||||||
@@ -1554,6 +1529,34 @@ We can perform a command in this file.
|
|||||||
scheduleTask("watch-workspace-open", 500, () => fireAndForget(() => this.watchWorkspaceOpenAsync(file)));
|
scheduleTask("watch-workspace-open", 500, () => fireAndForget(() => this.watchWorkspaceOpenAsync(file)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
flushFileEventQueue() {
|
||||||
|
return this.vaultManager.flushQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
watchEditorChange(editor: Editor, info: any) {
|
||||||
|
if (!("path" in info)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.shouldBatchSave) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const file = info?.file as TFile;
|
||||||
|
if (!file) return;
|
||||||
|
if (!this.vaultManager.isWaiting(file.path as FilePath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = info?.data as string;
|
||||||
|
const fi: FileEvent = {
|
||||||
|
type: "CHANGED",
|
||||||
|
file: file,
|
||||||
|
cachedData: data,
|
||||||
|
}
|
||||||
|
this.vaultManager.appendQueue([
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
async watchWorkspaceOpenAsync(file: TFile) {
|
async watchWorkspaceOpenAsync(file: TFile) {
|
||||||
if (this.settings.suspendFileWatching) return;
|
if (this.settings.suspendFileWatching) return;
|
||||||
if (!this.settings.isConfigured) return;
|
if (!this.settings.isConfigured) return;
|
||||||
@@ -1961,53 +1964,44 @@ We can perform a command in this file.
|
|||||||
observeForLogs() {
|
observeForLogs() {
|
||||||
const padSpaces = `\u{2007}`.repeat(10);
|
const padSpaces = `\u{2007}`.repeat(10);
|
||||||
// const emptyMark = `\u{2003}`;
|
// const emptyMark = `\u{2003}`;
|
||||||
const rerenderTimer = new Map<string, [ReturnType<typeof setTimeout>, number]>();
|
function padLeftSpComputed(numI: ReactiveValue<number>, mark: string) {
|
||||||
const tick = reactiveSource(0);
|
const formatted = reactiveSource("");
|
||||||
function padLeftSp(num: number, mark: string) {
|
let timer: ReturnType<typeof setTimeout> | undefined = undefined;
|
||||||
const numLen = `${num}`.length + 1;
|
let maxLen = 1;
|
||||||
const [timer, len] = rerenderTimer.get(mark) ?? [undefined, numLen];
|
numI.onChanged(numX => {
|
||||||
if (num || timer) {
|
const num = numX.value;
|
||||||
if (num) {
|
const numLen = `${Math.abs(num)}`.length + 1;
|
||||||
if (timer) clearTimeout(timer);
|
maxLen = maxLen < numLen ? numLen : maxLen;
|
||||||
rerenderTimer.set(mark, [setTimeout(async () => {
|
if (timer) clearTimeout(timer);
|
||||||
rerenderTimer.delete(mark);
|
if (num == 0) {
|
||||||
await delay(100);
|
timer = setTimeout(() => {
|
||||||
tick.value = tick.value + 1;
|
formatted.value = "";
|
||||||
}, 3000), Math.max(len, numLen)]);
|
maxLen = 1;
|
||||||
|
}, 3000);
|
||||||
}
|
}
|
||||||
return ` ${mark}${`${padSpaces}${num}`.slice(-(len))}`;
|
formatted.value = ` ${mark}${`${padSpaces}${num}`.slice(-(maxLen))}`;
|
||||||
} else {
|
})
|
||||||
return "";
|
return computed(() => formatted.value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// const logStore
|
const labelReplication = padLeftSpComputed(this.replicationResultCount, `📥`);
|
||||||
const queueCountLabel = reactive(() => {
|
const labelDBCount = padLeftSpComputed(this.databaseQueueCount, `📄`);
|
||||||
// For invalidating
|
const labelStorageCount = padLeftSpComputed(this.storageApplyingCount, `💾`);
|
||||||
// @ts-ignore
|
const labelChunkCount = padLeftSpComputed(collectingChunks, `🧩`);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
const labelPluginScanCount = padLeftSpComputed(pluginScanningCount, `🔌`);
|
||||||
const _ = tick.value;
|
const labelConflictProcessCount = padLeftSpComputed(this.conflictProcessQueueCount, `🔩`);
|
||||||
const dbCount = this.databaseQueueCount.value;
|
const hiddenFilesCount = reactive(() => hiddenFilesEventCount.value + hiddenFilesProcessingCount.value);
|
||||||
const replicationCount = this.replicationResultCount.value;
|
const labelHiddenFilesCount = padLeftSpComputed(hiddenFilesCount, `⚙️`)
|
||||||
const storageApplyingCount = this.storageApplyingCount.value;
|
const queueCountLabelX = reactive(() => {
|
||||||
const chunkCount = collectingChunks.value;
|
return `${labelReplication()}${labelDBCount()}${labelStorageCount()}${labelChunkCount()}${labelPluginScanCount()}${labelHiddenFilesCount()}${labelConflictProcessCount()}`;
|
||||||
const pluginScanCount = pluginScanningCount.value;
|
|
||||||
const hiddenFilesCount = hiddenFilesEventCount.value + hiddenFilesProcessingCount.value;
|
|
||||||
const conflictProcessCount = this.conflictProcessQueueCount.value;
|
|
||||||
const labelReplication = padLeftSp(replicationCount, `📥`);
|
|
||||||
const labelDBCount = padLeftSp(dbCount, `📄`);
|
|
||||||
const labelStorageCount = padLeftSp(storageApplyingCount, `💾`);
|
|
||||||
const labelChunkCount = padLeftSp(chunkCount, `🧩`);
|
|
||||||
const labelPluginScanCount = padLeftSp(pluginScanCount, `🔌`);
|
|
||||||
const labelHiddenFilesCount = padLeftSp(hiddenFilesCount, `⚙️`)
|
|
||||||
const labelConflictProcessCount = padLeftSp(conflictProcessCount, `🔩`);
|
|
||||||
return `${labelReplication}${labelDBCount}${labelStorageCount}${labelChunkCount}${labelPluginScanCount}${labelHiddenFilesCount}${labelConflictProcessCount}`;
|
|
||||||
})
|
})
|
||||||
const requestingStatLabel = reactive(() => {
|
const queueCountLabel = () => queueCountLabelX.value;
|
||||||
|
|
||||||
|
const requestingStatLabel = computed(() => {
|
||||||
const diff = this.requestCount.value - this.responseCount.value;
|
const diff = this.requestCount.value - this.responseCount.value;
|
||||||
return diff != 0 ? "📲 " : "";
|
return diff != 0 ? "📲 " : "";
|
||||||
})
|
})
|
||||||
|
|
||||||
const replicationStatLabel = reactive(() => {
|
const replicationStatLabel = computed(() => {
|
||||||
const e = this.replicationStat.value;
|
const e = this.replicationStat.value;
|
||||||
const sent = e.sent;
|
const sent = e.sent;
|
||||||
const arrived = e.arrived;
|
const arrived = e.arrived;
|
||||||
@@ -2050,42 +2044,36 @@ We can perform a command in this file.
|
|||||||
}
|
}
|
||||||
return { w, sent, pushLast, arrived, pullLast };
|
return { w, sent, pushLast, arrived, pullLast };
|
||||||
})
|
})
|
||||||
const waitingLabel = reactive(() => {
|
const labelProc = padLeftSpComputed(this.vaultManager.processing, `⏳`);
|
||||||
// For invalidating
|
const labelPend = padLeftSpComputed(this.vaultManager.totalQueued, `🛫`);
|
||||||
// @ts-ignore
|
const labelInBatchDelay = padLeftSpComputed(this.vaultManager.batched, `📬`);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
const waitingLabel = computed(() => {
|
||||||
const _ = tick.value;
|
return `${labelProc()}${labelPend()}${labelInBatchDelay()}`;
|
||||||
const e = this.pendingFileEventCount.value;
|
|
||||||
const proc = this.processingFileEventCount.value;
|
|
||||||
const pend = e - proc;
|
|
||||||
const labelProc = padLeftSp(proc, `⏳`);
|
|
||||||
const labelPend = padLeftSp(pend, `🛫`);
|
|
||||||
return `${labelProc}${labelPend}`;
|
|
||||||
})
|
})
|
||||||
const statusLineLabel = reactive(() => {
|
const statusLineLabel = computed(() => {
|
||||||
const { w, sent, pushLast, arrived, pullLast } = replicationStatLabel.value;
|
const { w, sent, pushLast, arrived, pullLast } = replicationStatLabel();
|
||||||
const queued = queueCountLabel.value;
|
const queued = queueCountLabel();
|
||||||
const waiting = waitingLabel.value;
|
const waiting = waitingLabel();
|
||||||
const networkActivity = requestingStatLabel.value;
|
const networkActivity = requestingStatLabel();
|
||||||
return {
|
return {
|
||||||
message: `${networkActivity}Sync: ${w} ↑ ${sent}${pushLast} ↓ ${arrived}${pullLast}${waiting}${queued}`,
|
message: `${networkActivity}Sync: ${w} ↑ ${sent}${pushLast} ↓ ${arrived}${pullLast}${waiting}${queued}`,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
const statusBarLabels = reactive(() => {
|
const statusBarLabels = reactive(() => {
|
||||||
const scheduleMessage = this.isReloadingScheduled ? `WARNING! RESTARTING OBSIDIAN IS SCHEDULED!\n` : "";
|
const scheduleMessage = this.isReloadingScheduled ? `WARNING! RESTARTING OBSIDIAN IS SCHEDULED!\n` : "";
|
||||||
const { message } = statusLineLabel.value;
|
const { message } = statusLineLabel();
|
||||||
const status = scheduleMessage + this.statusLog.value;
|
const status = scheduleMessage + this.statusLog.value;
|
||||||
return {
|
return {
|
||||||
message, status
|
message, status
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const applyToDisplay = throttle(() => {
|
const applyToDisplay = throttle((label: typeof statusBarLabels.value) => {
|
||||||
const v = statusBarLabels.value;
|
const v = label;
|
||||||
this.applyStatusBarText(v.message, v.status);
|
this.applyStatusBarText(v.message, v.status);
|
||||||
|
|
||||||
}, 20);
|
}, 20);
|
||||||
statusBarLabels.onChanged(applyToDisplay);
|
statusBarLabels.onChanged(label => applyToDisplay(label.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
applyStatusBarText(message: string, log: string) {
|
applyStatusBarText(message: string, log: string) {
|
||||||
@@ -2101,7 +2089,6 @@ We can perform a command in this file.
|
|||||||
// root.style.setProperty("--log-text", "'" + (newMsg + "\\A " + newLog) + "'");
|
// root.style.setProperty("--log-text", "'" + (newMsg + "\\A " + newLog) + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scheduleTask("log-hide", 3000, () => { this.statusLog.value = "" });
|
scheduleTask("log-hide", 3000, () => { this.statusLog.value = "" });
|
||||||
}
|
}
|
||||||
async askResolvingMismatchedTweaks(): Promise<"OK" | "CHECKAGAIN" | "IGNORE"> {
|
async askResolvingMismatchedTweaks(): Promise<"OK" | "CHECKAGAIN" | "IGNORE"> {
|
||||||
@@ -3060,28 +3047,28 @@ Or if you are sure know what had been happened, we can unlock the database from
|
|||||||
const ret = await this.localDatabase.putDBEntry(d);
|
const ret = await this.localDatabase.putDBEntry(d);
|
||||||
if (ret !== false) {
|
if (ret !== false) {
|
||||||
Logger(msg + fullPath);
|
Logger(msg + fullPath);
|
||||||
if (this.settings.syncOnSave && !this.suspended) {
|
this.scheduleReplicateIfSyncOnSave();
|
||||||
scheduleTask("perform-replicate-after-save", 250, () => this.replicate());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ret != false;
|
return ret != false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scheduleReplicateIfSyncOnSave() {
|
||||||
|
if (this.settings.syncOnSave && !this.suspended) {
|
||||||
|
scheduleTask("perform-replicate-after-save", 250, () => this.replicate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async deleteFromDB(file: TFile) {
|
async deleteFromDB(file: TFile) {
|
||||||
if (!await this.isTargetFile(file)) return;
|
if (!await this.isTargetFile(file)) return;
|
||||||
const fullPath = getPathFromTFile(file);
|
const fullPath = getPathFromTFile(file);
|
||||||
Logger(`deleteDB By path:${fullPath}`);
|
Logger(`deleteDB By path:${fullPath}`);
|
||||||
await this.deleteFromDBbyPath(fullPath);
|
await this.deleteFromDBbyPath(fullPath);
|
||||||
if (this.settings.syncOnSave && !this.suspended) {
|
this.scheduleReplicateIfSyncOnSave();
|
||||||
await this.replicate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteFromDBbyPath(fullPath: FilePath) {
|
async deleteFromDBbyPath(fullPath: FilePath) {
|
||||||
await this.localDatabase.deleteDBEntry(fullPath);
|
await this.localDatabase.deleteDBEntry(fullPath);
|
||||||
if (this.settings.syncOnSave && !this.suspended) {
|
this.scheduleReplicateIfSyncOnSave();
|
||||||
await this.replicate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async resetLocalDatabase() {
|
async resetLocalDatabase() {
|
||||||
|
|||||||
@@ -2,14 +2,34 @@ import type { SerializedFileAccess } from "./SerializedFileAccess.ts";
|
|||||||
import { Plugin, TAbstractFile, TFile, TFolder } from "../deps.ts";
|
import { Plugin, TAbstractFile, TFile, TFolder } from "../deps.ts";
|
||||||
import { Logger } from "../lib/src/common/logger.ts";
|
import { Logger } from "../lib/src/common/logger.ts";
|
||||||
import { shouldBeIgnored } from "../lib/src/string_and_binary/path.ts";
|
import { shouldBeIgnored } from "../lib/src/string_and_binary/path.ts";
|
||||||
import type { QueueProcessor } from "../lib/src/concurrency/processor.ts";
|
import { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, type FilePath, type ObsidianLiveSyncSettings } from "../lib/src/common/types.ts";
|
||||||
import { LOG_LEVEL_NOTICE, type FilePath, type ObsidianLiveSyncSettings } from "../lib/src/common/types.ts";
|
import { delay, fireAndForget } from "../lib/src/common/utils.ts";
|
||||||
import { delay } from "../lib/src/common/utils.ts";
|
|
||||||
import { type FileEventItem, type FileEventType, type FileInfo, type InternalFileInfo } from "../common/types.ts";
|
import { type FileEventItem, type FileEventType, type FileInfo, type InternalFileInfo } from "../common/types.ts";
|
||||||
|
import { skipIfDuplicated } from "../lib/src/concurrency/lock.ts";
|
||||||
|
import { finishAllWaitingForTimeout, finishWaitingForTimeout, isWaitingForTimeout, waitForTimeout } from "../lib/src/concurrency/task.ts";
|
||||||
|
import { reactiveSource, type ReactiveSource } from "../lib/src/dataobject/reactive.ts";
|
||||||
|
import { Semaphore } from "../lib/src/concurrency/semaphore.ts";
|
||||||
|
|
||||||
|
|
||||||
|
export type FileEvent = {
|
||||||
|
type: FileEventType;
|
||||||
|
file: TAbstractFile | InternalFileInfo;
|
||||||
|
oldPath?: string;
|
||||||
|
cachedData?: string;
|
||||||
|
skipBatchWait?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export abstract class StorageEventManager {
|
export abstract class StorageEventManager {
|
||||||
abstract beginWatch(): void;
|
abstract beginWatch(): void;
|
||||||
|
abstract flushQueue(): void;
|
||||||
|
abstract appendQueue(items: FileEvent[], ctx?: any): void;
|
||||||
|
abstract cancelQueue(key: string): void;
|
||||||
|
abstract isWaiting(filename: FilePath): boolean;
|
||||||
|
abstract totalQueued: ReactiveSource<number>;
|
||||||
|
abstract batched: ReactiveSource<number>;
|
||||||
|
abstract processing: ReactiveSource<number>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LiveSyncForStorageEventManager = Plugin &
|
type LiveSyncForStorageEventManager = Plugin &
|
||||||
@@ -17,15 +37,33 @@ type LiveSyncForStorageEventManager = Plugin &
|
|||||||
settings: ObsidianLiveSyncSettings
|
settings: ObsidianLiveSyncSettings
|
||||||
ignoreFiles: string[],
|
ignoreFiles: string[],
|
||||||
vaultAccess: SerializedFileAccess
|
vaultAccess: SerializedFileAccess
|
||||||
|
shouldBatchSave: boolean
|
||||||
|
batchSaveMinimumDelay: number;
|
||||||
|
batchSaveMaximumDelay: number;
|
||||||
|
|
||||||
} & {
|
} & {
|
||||||
isTargetFile: (file: string | TAbstractFile) => Promise<boolean>,
|
isTargetFile: (file: string | TAbstractFile) => Promise<boolean>,
|
||||||
fileEventQueue: QueueProcessor<FileEventItem, any>,
|
// fileEventQueue: QueueProcessor<FileEventItem, any>,
|
||||||
|
handleFileEvent: (queue: FileEventItem) => Promise<any>,
|
||||||
isFileSizeExceeded: (size: number) => boolean;
|
isFileSizeExceeded: (size: number) => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export class StorageEventManagerObsidian extends StorageEventManager {
|
export class StorageEventManagerObsidian extends StorageEventManager {
|
||||||
|
totalQueued = reactiveSource(0);
|
||||||
|
batched = reactiveSource(0);
|
||||||
|
processing = reactiveSource(0);
|
||||||
plugin: LiveSyncForStorageEventManager;
|
plugin: LiveSyncForStorageEventManager;
|
||||||
|
|
||||||
|
get shouldBatchSave() {
|
||||||
|
return this.plugin.shouldBatchSave;
|
||||||
|
}
|
||||||
|
get batchSaveMinimumDelay(): number {
|
||||||
|
return this.plugin.batchSaveMinimumDelay;
|
||||||
|
}
|
||||||
|
get batchSaveMaximumDelay(): number {
|
||||||
|
return this.plugin.batchSaveMaximumDelay
|
||||||
|
}
|
||||||
constructor(plugin: LiveSyncForStorageEventManager) {
|
constructor(plugin: LiveSyncForStorageEventManager) {
|
||||||
super();
|
super();
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
@@ -43,25 +81,25 @@ export class StorageEventManagerObsidian extends StorageEventManager {
|
|||||||
plugin.registerEvent(plugin.app.vault.on("create", this.watchVaultCreate));
|
plugin.registerEvent(plugin.app.vault.on("create", this.watchVaultCreate));
|
||||||
//@ts-ignore : Internal API
|
//@ts-ignore : Internal API
|
||||||
plugin.registerEvent(plugin.app.vault.on("raw", this.watchVaultRawEvents));
|
plugin.registerEvent(plugin.app.vault.on("raw", this.watchVaultRawEvents));
|
||||||
plugin.fileEventQueue.startPipeline();
|
// plugin.fileEventQueue.startPipeline();
|
||||||
}
|
}
|
||||||
|
|
||||||
watchVaultCreate(file: TAbstractFile, ctx?: any) {
|
watchVaultCreate(file: TAbstractFile, ctx?: any) {
|
||||||
this.appendWatchEvent([{ type: "CREATE", file }], ctx);
|
this.appendQueue([{ type: "CREATE", file }], ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
watchVaultChange(file: TAbstractFile, ctx?: any) {
|
watchVaultChange(file: TAbstractFile, ctx?: any) {
|
||||||
this.appendWatchEvent([{ type: "CHANGED", file }], ctx);
|
this.appendQueue([{ type: "CHANGED", file }], ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
watchVaultDelete(file: TAbstractFile, ctx?: any) {
|
watchVaultDelete(file: TAbstractFile, ctx?: any) {
|
||||||
this.appendWatchEvent([{ type: "DELETE", file }], ctx);
|
this.appendQueue([{ type: "DELETE", file }], ctx);
|
||||||
}
|
}
|
||||||
watchVaultRename(file: TAbstractFile, oldFile: string, ctx?: any) {
|
watchVaultRename(file: TAbstractFile, oldFile: string, ctx?: any) {
|
||||||
if (file instanceof TFile) {
|
if (file instanceof TFile) {
|
||||||
this.appendWatchEvent([
|
this.appendQueue([
|
||||||
{ type: "DELETE", file: { path: oldFile as FilePath, mtime: file.stat.mtime, ctime: file.stat.ctime, size: file.stat.size, deleted: true } },
|
{ type: "DELETE", file: { path: oldFile as FilePath, mtime: file.stat.mtime, ctime: file.stat.ctime, size: file.stat.size, deleted: true }, skipBatchWait: true },
|
||||||
{ type: "CREATE", file },
|
{ type: "CREATE", file, skipBatchWait: true },
|
||||||
], ctx);
|
], ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,16 +121,17 @@ export class StorageEventManagerObsidian extends StorageEventManager {
|
|||||||
.replace(/\n| /g, "")
|
.replace(/\n| /g, "")
|
||||||
.split(",").filter(e => e).map(e => new RegExp(e, "i"));
|
.split(",").filter(e => e).map(e => new RegExp(e, "i"));
|
||||||
if (ignorePatterns.some(e => path.match(e))) return;
|
if (ignorePatterns.some(e => path.match(e))) return;
|
||||||
this.appendWatchEvent(
|
this.appendQueue(
|
||||||
[{
|
[{
|
||||||
type: "INTERNAL",
|
type: "INTERNAL",
|
||||||
file: { path, mtime: 0, ctime: 0, size: 0 }
|
file: { path, mtime: 0, ctime: 0, size: 0 }
|
||||||
}], null);
|
}], null);
|
||||||
}
|
}
|
||||||
// Cache file and waiting to can be proceed.
|
// Cache file and waiting to can be proceed.
|
||||||
async appendWatchEvent(params: { type: FileEventType, file: TAbstractFile | InternalFileInfo, oldPath?: string }[], ctx?: any) {
|
async appendQueue(params: FileEvent[], ctx?: any) {
|
||||||
if (!this.plugin.settings.isConfigured) return;
|
if (!this.plugin.settings.isConfigured) return;
|
||||||
if (this.plugin.settings.suspendFileWatching) return;
|
if (this.plugin.settings.suspendFileWatching) return;
|
||||||
|
const processFiles = new Set<FilePath>();
|
||||||
for (const param of params) {
|
for (const param of params) {
|
||||||
if (shouldBeIgnored(param.file.path)) {
|
if (shouldBeIgnored(param.file.path)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -118,13 +157,6 @@ export class StorageEventManagerObsidian extends StorageEventManager {
|
|||||||
if (this.plugin.vaultAccess.recentlyTouched(file)) {
|
if (this.plugin.vaultAccess.recentlyTouched(file)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// cache = await this.plugin.vaultAccess.vaultReadAuto(file);
|
|
||||||
// if (!isPlainText(file.name)) {
|
|
||||||
// cache = await this.plugin.vaultAccess.vaultReadBinary(file);
|
|
||||||
// } else {
|
|
||||||
// cache = await this.plugin.vaultAccess.vaultCacheRead(file);
|
|
||||||
// if (!cache) cache = await this.plugin.vaultAccess.vaultRead(file);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
const fileInfo = file instanceof TFile ? {
|
const fileInfo = file instanceof TFile ? {
|
||||||
ctime: file.stat.ctime,
|
ctime: file.stat.ctime,
|
||||||
@@ -133,16 +165,143 @@ export class StorageEventManagerObsidian extends StorageEventManager {
|
|||||||
path: file.path,
|
path: file.path,
|
||||||
size: file.stat.size
|
size: file.stat.size
|
||||||
} as FileInfo : file as InternalFileInfo;
|
} as FileInfo : file as InternalFileInfo;
|
||||||
this.plugin.fileEventQueue.enqueue({
|
let cache: string | undefined = undefined;
|
||||||
|
if (param.cachedData) {
|
||||||
|
cache = param.cachedData
|
||||||
|
}
|
||||||
|
this.enqueue({
|
||||||
type,
|
type,
|
||||||
args: {
|
args: {
|
||||||
file: fileInfo,
|
file: fileInfo,
|
||||||
oldPath,
|
oldPath,
|
||||||
// cache,
|
cache,
|
||||||
ctx
|
ctx,
|
||||||
},
|
},
|
||||||
|
skipBatchWait: param.skipBatchWait,
|
||||||
key: atomicKey
|
key: atomicKey
|
||||||
})
|
})
|
||||||
|
processFiles.add(file.path as FilePath);
|
||||||
|
if (oldPath) {
|
||||||
|
processFiles.add(oldPath as FilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const path of processFiles) {
|
||||||
|
fireAndForget(() => this.startStandingBy(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bufferedQueuedItems = [] as FileEventItem[];
|
||||||
|
|
||||||
|
enqueue(newItem: FileEventItem) {
|
||||||
|
const filename = newItem.args.file.path;
|
||||||
|
if (this.shouldBatchSave) {
|
||||||
|
Logger(`Request cancel for waiting of previous ${filename}`, LOG_LEVEL_DEBUG);
|
||||||
|
finishWaitingForTimeout(`storage-event-manager-batchsave-${filename}`);
|
||||||
|
}
|
||||||
|
this.bufferedQueuedItems.push(newItem);
|
||||||
|
// When deleting or renaming, the queue must be flushed once before processing subsequent processes to prevent unexpected race condition.
|
||||||
|
if (newItem.type == "DELETE" || newItem.type == "RENAME") {
|
||||||
|
return this.flushQueue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
concurrentProcessing = Semaphore(5);
|
||||||
|
waitedSince = new Map<FilePath, number>();
|
||||||
|
async startStandingBy(filename: FilePath) {
|
||||||
|
// If waited, cancel previous waiting.
|
||||||
|
await skipIfDuplicated(`storage-event-manager-${filename}`, async () => {
|
||||||
|
Logger(`Processing ${filename}: Starting`, LOG_LEVEL_DEBUG);
|
||||||
|
const release = await this.concurrentProcessing.acquire();
|
||||||
|
try {
|
||||||
|
Logger(`Processing ${filename}: Started`, LOG_LEVEL_DEBUG);
|
||||||
|
let noMoreFiles = false;
|
||||||
|
do {
|
||||||
|
const target = this.bufferedQueuedItems.find(e => e.args.file.path == filename);
|
||||||
|
if (target === undefined) {
|
||||||
|
noMoreFiles = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const operationType = target.type;
|
||||||
|
|
||||||
|
// if (target.waitedFrom + this.batchSaveMaximumDelay > now) {
|
||||||
|
// this.requestProcessQueue(target);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
const type = target.type;
|
||||||
|
if (target.cancelled) {
|
||||||
|
Logger(`Processing ${filename}: Cancelled (scheduled): ${operationType}`, LOG_LEVEL_DEBUG)
|
||||||
|
this.cancelStandingBy(target);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!target.skipBatchWait) {
|
||||||
|
if (this.shouldBatchSave && (type == "CREATE" || type == "CHANGED")) {
|
||||||
|
const waitedSince = this.waitedSince.get(filename);
|
||||||
|
let canWait = true;
|
||||||
|
const now = Date.now();
|
||||||
|
if (waitedSince !== undefined) {
|
||||||
|
if (waitedSince + (this.batchSaveMaximumDelay * 1000) < now) {
|
||||||
|
Logger(`Processing ${filename}: Could not wait no more: ${operationType}`, LOG_LEVEL_INFO)
|
||||||
|
canWait = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canWait) {
|
||||||
|
if (waitedSince === undefined) this.waitedSince.set(filename, now)
|
||||||
|
target.batched = true
|
||||||
|
Logger(`Processing ${filename}: Waiting for batch save delay: ${operationType}`, LOG_LEVEL_DEBUG)
|
||||||
|
this.updateStatus();
|
||||||
|
const result = await waitForTimeout(`storage-event-manager-batchsave-${filename}`, this.batchSaveMinimumDelay * 1000);
|
||||||
|
if (!result) {
|
||||||
|
Logger(`Processing ${filename}: Cancelled by new queue: ${operationType}`, LOG_LEVEL_DEBUG)
|
||||||
|
// If could not wait for the timeout, possibly we got a new queue. therefore, currently processing one should be cancelled
|
||||||
|
this.cancelStandingBy(target);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger(`Processing ${filename}:Requested to perform immediately ${filename}: ${operationType}`, LOG_LEVEL_DEBUG)
|
||||||
|
}
|
||||||
|
Logger(`Processing ${filename}: Request main to process: ${operationType}`, LOG_LEVEL_DEBUG)
|
||||||
|
this.requestProcessQueue(target);
|
||||||
|
} while (!noMoreFiles)
|
||||||
|
} finally {
|
||||||
|
release()
|
||||||
|
}
|
||||||
|
Logger(`Processing ${filename}: Finished`, LOG_LEVEL_DEBUG);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelStandingBy(fei: FileEventItem) {
|
||||||
|
this.bufferedQueuedItems.remove(fei);
|
||||||
|
this.updateStatus();
|
||||||
|
}
|
||||||
|
processingCount = 0;
|
||||||
|
async requestProcessQueue(fei: FileEventItem) {
|
||||||
|
try {
|
||||||
|
this.processingCount++;
|
||||||
|
this.bufferedQueuedItems.remove(fei);
|
||||||
|
this.updateStatus()
|
||||||
|
this.waitedSince.delete(fei.args.file.path);
|
||||||
|
await this.plugin.handleFileEvent(fei);
|
||||||
|
} finally {
|
||||||
|
this.processingCount--;
|
||||||
|
this.updateStatus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isWaiting(filename: FilePath) {
|
||||||
|
return isWaitingForTimeout(`storage-event-manager-batchsave-${filename}`);
|
||||||
|
}
|
||||||
|
flushQueue() {
|
||||||
|
this.bufferedQueuedItems.forEach(e => e.skipBatchWait = true)
|
||||||
|
finishAllWaitingForTimeout("storage-event-manager-batchsave-", true);
|
||||||
|
}
|
||||||
|
cancelQueue(key: string) {
|
||||||
|
this.bufferedQueuedItems.forEach(e => {
|
||||||
|
if (e.key === key) e.skipBatchWait = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
updateStatus() {
|
||||||
|
const allItems = this.bufferedQueuedItems.filter(e => !e.cancelled)
|
||||||
|
this.batched.value = allItems.filter(e => e.batched && !e.skipBatchWait).length;
|
||||||
|
this.processing.value = this.processingCount;
|
||||||
|
this.totalQueued.value = allItems.length - this.batched.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import { fireAndForget } from "src/lib/src/common/utils";
|
||||||
|
import { serialized } from "src/lib/src/concurrency/lock";
|
||||||
|
import type ObsidianLiveSyncPlugin from "src/main";
|
||||||
|
|
||||||
|
let plugin: ObsidianLiveSyncPlugin;
|
||||||
|
export function enableTestFunction(plugin_: ObsidianLiveSyncPlugin) {
|
||||||
|
plugin = plugin_;
|
||||||
|
}
|
||||||
|
export function addDebugFileLog(message: any, stackLog = false) {
|
||||||
|
fireAndForget(serialized("debug-log", async () => {
|
||||||
|
const now = new Date();
|
||||||
|
const filename = `debug-log`
|
||||||
|
const time = now.toISOString().split("T")[0];
|
||||||
|
const outFile = `${filename}${time}.jsonl`;
|
||||||
|
// const messageContent = typeof message == "string" ? message : message instanceof Error ? `${message.name}:${message.message}` : JSON.stringify(message, null, 2);
|
||||||
|
const timestamp = now.toLocaleString();
|
||||||
|
const timestampEpoch = now;
|
||||||
|
let out = { "timestamp": timestamp, epoch: timestampEpoch, } as Record<string, any>;
|
||||||
|
if (message instanceof Error) {
|
||||||
|
// debugger;
|
||||||
|
// console.dir(message.stack);
|
||||||
|
out = { ...out, message };
|
||||||
|
} else if (stackLog) {
|
||||||
|
if (stackLog) {
|
||||||
|
const stackE = new Error();
|
||||||
|
const stack = stackE.stack;
|
||||||
|
out = { ...out, stack }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof message == "object") {
|
||||||
|
out = { ...out, ...message, }
|
||||||
|
} else {
|
||||||
|
out = {
|
||||||
|
result: message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const out = "--" + timestamp + "--\n" + messageContent + " " + (stack || "");
|
||||||
|
// const out
|
||||||
|
try {
|
||||||
|
await plugin.vaultAccess.adapterAppend(plugin.app.vault.configDir + "/ls-debug/" + outFile, JSON.stringify(out) + "\n")
|
||||||
|
} catch (ex) {
|
||||||
|
//NO OP
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { App, Modal } from "../deps.ts";
|
import { App, Modal } from "../deps.ts";
|
||||||
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from "diff-match-patch";
|
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from "diff-match-patch";
|
||||||
import { CANCELLED, LEAVE_TO_SUBSEQUENT, RESULT_TIMED_OUT, type diff_result } from "../lib/src/common/types.ts";
|
import { CANCELLED, LEAVE_TO_SUBSEQUENT, RESULT_TIMED_OUT, type diff_result } from "../lib/src/common/types.ts";
|
||||||
import { escapeStringToHTML } from "../lib/src/string_and_binary/strbin.ts";
|
import { escapeStringToHTML } from "../lib/src/string_and_binary/convert.ts";
|
||||||
import { delay, sendValue, waitForValue } from "../lib/src/common/utils.ts";
|
import { delay, sendValue, waitForValue } from "../lib/src/common/utils.ts";
|
||||||
|
|
||||||
export type MergeDialogResult = typeof LEAVE_TO_SUBSEQUENT | typeof CANCELLED | string;
|
export type MergeDialogResult = typeof LEAVE_TO_SUBSEQUENT | typeof CANCELLED | string;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TFile, Modal, App, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "../deps.ts";
|
import { TFile, Modal, App, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "../deps.ts";
|
||||||
import { getPathFromTFile, isValidPath } from "../common/utils.ts";
|
import { getPathFromTFile, isValidPath } from "../common/utils.ts";
|
||||||
import { decodeBinary, escapeStringToHTML, readString } from "../lib/src/string_and_binary/strbin.ts";
|
import { decodeBinary, escapeStringToHTML, readString } from "../lib/src/string_and_binary/convert.ts";
|
||||||
import ObsidianLiveSyncPlugin from "../main.ts";
|
import ObsidianLiveSyncPlugin from "../main.ts";
|
||||||
import { type DocumentID, type FilePathWithPrefix, type LoadedEntry, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "../lib/src/common/types.ts";
|
import { type DocumentID, type FilePathWithPrefix, type LoadedEntry, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "../lib/src/common/types.ts";
|
||||||
import { Logger } from "../lib/src/common/logger.ts";
|
import { Logger } from "../lib/src/common/logger.ts";
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export class JsonResolveModal extends Modal {
|
|||||||
nameA: this.nameA,
|
nameA: this.nameA,
|
||||||
nameB: this.nameB,
|
nameB: this.nameB,
|
||||||
defaultSelect: this.defaultSelect,
|
defaultSelect: this.defaultSelect,
|
||||||
callback: (keepRev, mergedStr) => this.UICallback(keepRev, mergedStr),
|
callback: (keepRev: string | undefined, mergedStr: string | undefined) => this.UICallback(keepRev, mergedStr),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type Diff, DIFF_DELETE, DIFF_INSERT, diff_match_patch } from "../deps";
|
import { type Diff, DIFF_DELETE, DIFF_INSERT, diff_match_patch } from "../deps";
|
||||||
import type { FilePath, LoadedEntry } from "../lib/src/common/types";
|
import type { FilePath, LoadedEntry } from "../lib/src/common/types";
|
||||||
import { decodeBinary, readString } from "../lib/src/string_and_binary/strbin";
|
import { decodeBinary, readString } from "../lib/src/string_and_binary/convert";
|
||||||
import { getDocData } from "../lib/src/common/utils";
|
import { getDocData } from "../lib/src/common/utils";
|
||||||
import { mergeObject } from "../common/utils";
|
import { mergeObject } from "../common/utils";
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
type ConfigurationItem
|
type ConfigurationItem
|
||||||
} from "../lib/src/common/types.ts";
|
} from "../lib/src/common/types.ts";
|
||||||
import { createBlob, delay, isDocContentSame, isObjectDifferent, readAsBlob, unique } from "../lib/src/common/utils.ts";
|
import { createBlob, delay, isDocContentSame, isObjectDifferent, readAsBlob, unique } from "../lib/src/common/utils.ts";
|
||||||
import { versionNumberString2Number } from "../lib/src/string_and_binary/strbin.ts";
|
import { versionNumberString2Number } from "../lib/src/string_and_binary/convert.ts";
|
||||||
import { Logger } from "../lib/src/common/logger.ts";
|
import { Logger } from "../lib/src/common/logger.ts";
|
||||||
import { checkSyncInfo, isCloudantURI } from "../lib/src/pouchdb/utils_couchdb.ts";
|
import { checkSyncInfo, isCloudantURI } from "../lib/src/pouchdb/utils_couchdb.ts";
|
||||||
import { testCrypt } from "../lib/src/encryption/e2ee_v2.ts";
|
import { testCrypt } from "../lib/src/encryption/e2ee_v2.ts";
|
||||||
@@ -439,6 +439,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
}
|
}
|
||||||
if (key == "deviceAndVaultName") {
|
if (key == "deviceAndVaultName") {
|
||||||
this.plugin.deviceAndVaultName = this.editingSettings?.[key];
|
this.plugin.deviceAndVaultName = this.editingSettings?.[key];
|
||||||
|
this.plugin.saveDeviceAndVaultName();
|
||||||
return await Promise.resolve();
|
return await Promise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -519,12 +520,12 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
/**
|
/**
|
||||||
* Reread all settings and request invalidate
|
* Reread all settings and request invalidate
|
||||||
*/
|
*/
|
||||||
reloadAllSettings() {
|
reloadAllSettings(skipUpdate: boolean = false) {
|
||||||
const localSetting = this.reloadAllLocalSettings();
|
const localSetting = this.reloadAllLocalSettings();
|
||||||
this._editingSettings = { ...this.plugin.settings, ...localSetting };
|
this._editingSettings = { ...this.plugin.settings, ...localSetting };
|
||||||
this._editingSettings = { ...this.editingSettings, ...this.computeAllLocalSettings() };
|
this._editingSettings = { ...this.editingSettings, ...this.computeAllLocalSettings() };
|
||||||
this.initialSettings = { ...this.editingSettings, };
|
this.initialSettings = { ...this.editingSettings, };
|
||||||
this.requestUpdate();
|
if (!skipUpdate) this.requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -643,6 +644,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
const keys = Object.keys(newConf) as (keyof ObsidianLiveSyncSettings)[];
|
const keys = Object.keys(newConf) as (keyof ObsidianLiveSyncSettings)[];
|
||||||
let hasLoaded = false;
|
let hasLoaded = false;
|
||||||
for (const k of keys) {
|
for (const k of keys) {
|
||||||
|
if (k === "deviceAndVaultName") continue;
|
||||||
if (isObjectDifferent(newConf[k], this.initialSettings?.[k])) {
|
if (isObjectDifferent(newConf[k], this.initialSettings?.[k])) {
|
||||||
// Something has changed
|
// Something has changed
|
||||||
if (this.isDirty(k as AllSettingItemKey)) {
|
if (this.isDirty(k as AllSettingItemKey)) {
|
||||||
@@ -667,9 +669,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
|||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Logger(`reread: all! hidden`, LOG_LEVEL_VERBOSE)
|
this.reloadAllSettings(true);
|
||||||
this.reloadAllSettings();
|
|
||||||
this.display();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1702,7 +1702,7 @@ However, your report is needed to stabilise this. I appreciate you for your grea
|
|||||||
{
|
{
|
||||||
target: patSetting.controlEl,
|
target: patSetting.controlEl,
|
||||||
props: {
|
props: {
|
||||||
patterns: pat, originals: [...pat], apply: async (newPatterns) => {
|
patterns: pat, originals: [...pat], apply: async (newPatterns: string[]) => {
|
||||||
this.editingSettings.syncInternalFilesIgnorePatterns = newPatterns.map(e => e.trim()).filter(e => e != "").join(", ");
|
this.editingSettings.syncInternalFilesIgnorePatterns = newPatterns.map(e => e.trim()).filter(e => e != "").join(", ");
|
||||||
await this.saveAllDirtySettings();
|
await this.saveAllDirtySettings();
|
||||||
this.display();
|
this.display();
|
||||||
@@ -1740,6 +1740,24 @@ However, your report is needed to stabilise this. I appreciate you for your grea
|
|||||||
new Setting(containerSyncSettingEl)
|
new Setting(containerSyncSettingEl)
|
||||||
.setClass("wizardHidden")
|
.setClass("wizardHidden")
|
||||||
.autoWireToggle("batchSave")
|
.autoWireToggle("batchSave")
|
||||||
|
new Setting(containerSyncSettingEl)
|
||||||
|
.setClass("wizardHidden")
|
||||||
|
.autoWireNumeric("batchSaveMinimumDelay",
|
||||||
|
{
|
||||||
|
acceptZero: true,
|
||||||
|
onUpdate: visibleOnly(() => this.isConfiguredAs("batchSave", true))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
new Setting(containerSyncSettingEl)
|
||||||
|
.setClass("wizardHidden")
|
||||||
|
.autoWireNumeric("batchSaveMaximumDelay",
|
||||||
|
{
|
||||||
|
acceptZero: true,
|
||||||
|
onUpdate: visibleOnly(() => this.isConfiguredAs("batchSave", true))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
new Setting(containerSyncSettingEl)
|
new Setting(containerSyncSettingEl)
|
||||||
.setClass("wizardHidden")
|
.setClass("wizardHidden")
|
||||||
@@ -1749,6 +1767,10 @@ However, your report is needed to stabilise this. I appreciate you for your grea
|
|||||||
.setClass("wizardHidden")
|
.setClass("wizardHidden")
|
||||||
.autoWireToggle("readChunksOnline", { onUpdate: onlyOnCouchDB })
|
.autoWireToggle("readChunksOnline", { onUpdate: onlyOnCouchDB })
|
||||||
|
|
||||||
|
new Setting(containerSyncSettingEl)
|
||||||
|
.setClass("wizardHidden")
|
||||||
|
.autoWireToggle("enableChunkSplitterV2")
|
||||||
|
|
||||||
this.createEl(containerSyncSettingEl, "h4", {
|
this.createEl(containerSyncSettingEl, "h4", {
|
||||||
text: sanitizeHTMLToDom(`Targets`),
|
text: sanitizeHTMLToDom(`Targets`),
|
||||||
}).addClass("wizardHidden");
|
}).addClass("wizardHidden");
|
||||||
@@ -1763,8 +1785,8 @@ However, your report is needed to stabilise this. I appreciate you for your grea
|
|||||||
props: {
|
props: {
|
||||||
patterns: this.editingSettings.syncOnlyRegEx.split("|[]|"),
|
patterns: this.editingSettings.syncOnlyRegEx.split("|[]|"),
|
||||||
originals: [...this.editingSettings.syncOnlyRegEx.split("|[]|")],
|
originals: [...this.editingSettings.syncOnlyRegEx.split("|[]|")],
|
||||||
apply: async (newPatterns) => {
|
apply: async (newPatterns: string[]) => {
|
||||||
this.editingSettings.syncOnlyRegEx = newPatterns.map(e => e.trim()).filter(e => e != "").join("|[]|");
|
this.editingSettings.syncOnlyRegEx = newPatterns.map((e: string) => e.trim()).filter(e => e != "").join("|[]|");
|
||||||
await this.saveAllDirtySettings();
|
await this.saveAllDirtySettings();
|
||||||
this.display();
|
this.display();
|
||||||
}
|
}
|
||||||
@@ -1783,7 +1805,7 @@ However, your report is needed to stabilise this. I appreciate you for your grea
|
|||||||
props: {
|
props: {
|
||||||
patterns: this.editingSettings.syncIgnoreRegEx.split("|[]|"),
|
patterns: this.editingSettings.syncIgnoreRegEx.split("|[]|"),
|
||||||
originals: [...this.editingSettings.syncIgnoreRegEx.split("|[]|")],
|
originals: [...this.editingSettings.syncIgnoreRegEx.split("|[]|")],
|
||||||
apply: async (newPatterns) => {
|
apply: async (newPatterns: string[]) => {
|
||||||
this.editingSettings.syncIgnoreRegEx = newPatterns.map(e => e.trim()).filter(e => e != "").join("|[]|");
|
this.editingSettings.syncIgnoreRegEx = newPatterns.map(e => e.trim()).filter(e => e != "").join("|[]|");
|
||||||
await this.saveAllDirtySettings();
|
await this.saveAllDirtySettings();
|
||||||
this.display();
|
this.display();
|
||||||
@@ -2185,6 +2207,14 @@ ${stringifyYaml(pluginConfig)}`;
|
|||||||
new Setting(containerHatchEl)
|
new Setting(containerHatchEl)
|
||||||
.autoWireToggle("disableCheckingConfigMismatch")
|
.autoWireToggle("disableCheckingConfigMismatch")
|
||||||
|
|
||||||
|
new Setting(containerHatchEl)
|
||||||
|
.autoWireToggle("disableWorkerForGeneratingChunks")
|
||||||
|
|
||||||
|
new Setting(containerHatchEl)
|
||||||
|
.autoWireToggle("processSmallFilesInUIThread", {
|
||||||
|
onUpdate: visibleOnly(() => this.isConfiguredAs("disableWorkerForGeneratingChunks", false))
|
||||||
|
})
|
||||||
|
|
||||||
addScreenElement("50", containerHatchEl);
|
addScreenElement("50", containerHatchEl);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { PluginDataExDisplay } from "../../features/CmdConfigSync";
|
import type { PluginDataExDisplay } from "../../features/CmdConfigSync";
|
||||||
import { Logger } from "../../lib/src/common/logger";
|
import { Logger } from "../../lib/src/common/logger";
|
||||||
import { versionNumberString2Number } from "../../lib/src/string_and_binary/strbin";
|
import { versionNumberString2Number } from "../../lib/src/string_and_binary/convert";
|
||||||
import { type FilePath, LOG_LEVEL_NOTICE } from "../../lib/src/common/types";
|
import { type FilePath, LOG_LEVEL_NOTICE } from "../../lib/src/common/types";
|
||||||
import { getDocData } from "../../lib/src/common/utils";
|
import { getDocData } from "../../lib/src/common/utils";
|
||||||
import type ObsidianLiveSyncPlugin from "../../main";
|
import type ObsidianLiveSyncPlugin from "../../main";
|
||||||
|
|||||||
@@ -67,11 +67,11 @@ export const SettingInformation: Partial<Record<keyof AllSettings, Configuration
|
|||||||
},
|
},
|
||||||
"lessInformationInLog": {
|
"lessInformationInLog": {
|
||||||
"name": "Show only notifications",
|
"name": "Show only notifications",
|
||||||
"desc": "Prevent logging and show only notification"
|
"desc": "Prevent logging and show only notification. Please disable when you report the logs"
|
||||||
},
|
},
|
||||||
"showVerboseLog": {
|
"showVerboseLog": {
|
||||||
"name": "Verbose Log",
|
"name": "Verbose Log",
|
||||||
"desc": "Show verbose log"
|
"desc": "Show verbose log. Please enable when you report the logs"
|
||||||
},
|
},
|
||||||
"hashCacheMaxCount": {
|
"hashCacheMaxCount": {
|
||||||
"name": "Memory cache size (by total items)"
|
"name": "Memory cache size (by total items)"
|
||||||
@@ -300,6 +300,26 @@ export const SettingInformation: Partial<Record<keyof AllSettings, Configuration
|
|||||||
"displayLanguage": {
|
"displayLanguage": {
|
||||||
"name": "Display Language",
|
"name": "Display Language",
|
||||||
"desc": "Not all messages have been translated. And, please revert to \"Default\" when reporting errors."
|
"desc": "Not all messages have been translated. And, please revert to \"Default\" when reporting errors."
|
||||||
|
},
|
||||||
|
enableChunkSplitterV2: {
|
||||||
|
name: "Use splitting-limit-capped chunk splitter",
|
||||||
|
desc: "If enabled, chunks will be split into no more than 100 items. However, dedupe is slightly weaker."
|
||||||
|
},
|
||||||
|
disableWorkerForGeneratingChunks: {
|
||||||
|
name: "Do not split chunks in the background",
|
||||||
|
desc: "If disabled(toggled), chunks will be split on the UI thread (Previous behaviour)."
|
||||||
|
},
|
||||||
|
processSmallFilesInUIThread: {
|
||||||
|
name: "Process small files in the foreground",
|
||||||
|
desc: "If enabled, the file under 1kb will be processed in the UI thread."
|
||||||
|
},
|
||||||
|
batchSaveMinimumDelay: {
|
||||||
|
name: "Minimum delay for batch database updating",
|
||||||
|
desc: "Seconds. Saving to the local database will be delayed until this value after we stop typing or saving."
|
||||||
|
},
|
||||||
|
batchSaveMaximumDelay: {
|
||||||
|
name: "Maximum delay for batch database updating",
|
||||||
|
desc: "Saving will be performed forcefully after this number of seconds."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function translateInfo(infoSrc: ConfigurationItem | undefined | false) {
|
function translateInfo(infoSrc: ConfigurationItem | undefined | false) {
|
||||||
|
|||||||
+31
-31
@@ -18,39 +18,39 @@ I have a lot of respect for that plugin, even though it is sometimes treated as
|
|||||||
Hooray for open source, and generous licences, and the sharing of knowledge by experts.
|
Hooray for open source, and generous licences, and the sharing of knowledge by experts.
|
||||||
|
|
||||||
#### Version history
|
#### Version history
|
||||||
- 0.23.10
|
- 0.23.16:
|
||||||
|
- Maintenance Update:
|
||||||
|
- Library refining (Phase 1 - step 2). There are no significant changes on the user side.
|
||||||
|
- Including the following fixes of potentially problems:
|
||||||
|
- the problem which the path had been obfuscating twice has been resolved.
|
||||||
|
- Note: Potential problems of the library; which has not happened in Self-hosted LiveSync for some reasons.
|
||||||
|
- 0.23.15:
|
||||||
|
- Maintenance Update:
|
||||||
|
- Library refining (Phase 1). There are no significant changes on the user side.
|
||||||
|
- 0.23.14:
|
||||||
- Fixed:
|
- Fixed:
|
||||||
- No longer configurations have been locked in the minimal setup.
|
- No longer batch-saving ignores editor inputs.
|
||||||
- 0.23.9
|
- The file-watching and serialisation processes have been changed to the one which is similar to previous implementations.
|
||||||
- Fixed:
|
- We can configure the settings (Especially about text-boxes) even if we have configured the device name.
|
||||||
- No longer unexpected parallel replication is performed.
|
|
||||||
- Now we can set the device name and enable customised synchronisation again.
|
|
||||||
- 0.23.8
|
|
||||||
- New feature:
|
|
||||||
- Now we are ready for i18n.
|
|
||||||
- Patch or PR of `rosetta.ts` are welcome!
|
|
||||||
- The setting dialogue has been refined. Very controllable, clearly displayed disabled items, and ready to i18n.
|
|
||||||
- Fixed:
|
|
||||||
- Many memory leaks have been rescued.
|
|
||||||
- Chunk caches now work well.
|
|
||||||
- Many trivial but potential bugs are fixed.
|
|
||||||
- No longer error messages will be shown on retrieving checkpoint or server information.
|
|
||||||
- Now we can check and correct tweak mismatch during the setup
|
|
||||||
- Improved:
|
- Improved:
|
||||||
- Customisation synchronisation has got more smoother.
|
- We can configure the delay of batch-saving.
|
||||||
- Tidied
|
- Default: 5 seconds, the same as the previous hard-coded value. (Note: also, the previous behaviour was not correct).
|
||||||
- Practically unused functions have been removed or are being prepared for removal.
|
- Also, we can configure the limit of delaying batch-saving.
|
||||||
- Many of the type-errors and lint errors have been corrected.
|
- The performance of showing status indicators has been improved.
|
||||||
- Unused files have been removed.
|
- 0.23.13:
|
||||||
- Note:
|
|
||||||
- From this version, some test files have been included. However, they are not enabled and released in the release build.
|
|
||||||
- To try them, please run Self-hosted LiveSync in the dev build.
|
|
||||||
- 0.23.7
|
|
||||||
- Fixed:
|
- Fixed:
|
||||||
- No longer missing tasks which have queued as the same key (e.g., for the same operation to the same file).
|
- No longer files have been trimmed even delimiters have been continuous.
|
||||||
- This occurs, for example, with hidden files that have been changed multiple times in a very short period of time, such as `appearance.json`. Thanks for the report!
|
- Fixed the toggle title to `Do not split chunks in the background` from `Do not split chunks in the foreground`.
|
||||||
- Some trivial issues have been fixed.
|
- Non-configured item mismatches are no longer detected.
|
||||||
- New feature:
|
- 0.23.12:
|
||||||
- Reloading Obsidian can be scheduled until that file and database operations are stable.
|
- Improved:
|
||||||
|
- Now notes will be split into chunks in the background thread to improve smoothness.
|
||||||
|
- Default enabled, to disable, toggle `Do not split chunks in the foreground` on `Hatch` -> `Compatibility`.
|
||||||
|
- If you want to process very small notes in the foreground, please enable `Process small files in the foreground` on `Hatch` -> `Compatibility`.
|
||||||
|
- We can use a `splitting-limit-capped chunk splitter`; which performs more simple and make less amount of chunks.
|
||||||
|
- Default disabled, to enable, toggle `Use splitting-limit-capped chunk splitter` on `Sync settings` -> `Performance tweaks`
|
||||||
|
- Tidied
|
||||||
|
- Some files have been separated into multiple files to make them more explicit in what they are responsible for.
|
||||||
|
|
||||||
|
|
||||||
Older notes is in [updates_old.md](https://github.com/vrtmrz/obsidian-livesync/blob/main/updates_old.md).
|
Older notes is in [updates_old.md](https://github.com/vrtmrz/obsidian-livesync/blob/main/updates_old.md).
|
||||||
@@ -18,6 +18,49 @@ I have a lot of respect for that plugin, even though it is sometimes treated as
|
|||||||
Hooray for open source, and generous licences, and the sharing of knowledge by experts.
|
Hooray for open source, and generous licences, and the sharing of knowledge by experts.
|
||||||
|
|
||||||
#### Version history
|
#### Version history
|
||||||
|
- 0.23.11:
|
||||||
|
- Fixed:
|
||||||
|
- Now we *surely* can set the device name and enable customised synchronisation.
|
||||||
|
- Unnecessary dialogue update processes have been eliminated.
|
||||||
|
- Customisation sync no longer stores half-collected files.
|
||||||
|
- No longer hangs up when removing or renaming files with the `Sync on Save` toggle enabled.
|
||||||
|
- Improved:
|
||||||
|
- Customisation sync now performs data deserialization more smoothly.
|
||||||
|
- New translations have been merged.
|
||||||
|
- 0.23.10
|
||||||
|
- Fixed:
|
||||||
|
- No longer configurations have been locked in the minimal setup.
|
||||||
|
- 0.23.9
|
||||||
|
- Fixed:
|
||||||
|
- No longer unexpected parallel replication is performed.
|
||||||
|
- Now we can set the device name and enable customised synchronisation again.
|
||||||
|
- 0.23.8
|
||||||
|
- New feature:
|
||||||
|
- Now we are ready for i18n.
|
||||||
|
- Patch or PR of `rosetta.ts` are welcome!
|
||||||
|
- The setting dialogue has been refined. Very controllable, clearly displayed disabled items, and ready to i18n.
|
||||||
|
- Fixed:
|
||||||
|
- Many memory leaks have been rescued.
|
||||||
|
- Chunk caches now work well.
|
||||||
|
- Many trivial but potential bugs are fixed.
|
||||||
|
- No longer error messages will be shown on retrieving checkpoint or server information.
|
||||||
|
- Now we can check and correct tweak mismatch during the setup
|
||||||
|
- Improved:
|
||||||
|
- Customisation synchronisation has got more smoother.
|
||||||
|
- Tidied
|
||||||
|
- Practically unused functions have been removed or are being prepared for removal.
|
||||||
|
- Many of the type-errors and lint errors have been corrected.
|
||||||
|
- Unused files have been removed.
|
||||||
|
- Note:
|
||||||
|
- From this version, some test files have been included. However, they are not enabled and released in the release build.
|
||||||
|
- To try them, please run Self-hosted LiveSync in the dev build.
|
||||||
|
- 0.23.7
|
||||||
|
- Fixed:
|
||||||
|
- No longer missing tasks which have queued as the same key (e.g., for the same operation to the same file).
|
||||||
|
- This occurs, for example, with hidden files that have been changed multiple times in a very short period of time, such as `appearance.json`. Thanks for the report!
|
||||||
|
- Some trivial issues have been fixed.
|
||||||
|
- New feature:
|
||||||
|
- Reloading Obsidian can be scheduled until that file and database operations are stable.
|
||||||
- 0.23.6:
|
- 0.23.6:
|
||||||
- Fixed:
|
- Fixed:
|
||||||
- Now the remote chunks could be decrypted even if we are using `Incubate chunks in Document`. (The note of 0.23.6 has been fixed).
|
- Now the remote chunks could be decrypted even if we are using `Incubate chunks in Document`. (The note of 0.23.6 has been fixed).
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ echo "OK!"
|
|||||||
|
|
||||||
if command -v deno >/dev/null 2>&1; then
|
if command -v deno >/dev/null 2>&1; then
|
||||||
echo "Setup finished! Also, we can set up Self-hosted LiveSync instantly, by the following setup uri."
|
echo "Setup finished! Also, we can set up Self-hosted LiveSync instantly, by the following setup uri."
|
||||||
echo "Passphrase of setup-uri is \`welcome\`".
|
echo "Passphrase of setup-uri will be printed only one time. Keep it safe!"
|
||||||
echo "--- configured ---"
|
echo "--- configured ---"
|
||||||
echo "database : ${database}"
|
echo "database : ${database}"
|
||||||
echo "E2EE passphrase: ${passphrase}"
|
echo "E2EE passphrase: ${passphrase}"
|
||||||
|
|||||||
@@ -1,153 +1,13 @@
|
|||||||
import { webcrypto } from "node:crypto";
|
import { encrypt } from "npm:octagonal-wheels@0.1.11/encryption/encryption.js";
|
||||||
|
|
||||||
const KEY_RECYCLE_COUNT = 100;
|
const noun = ["waterfall", "river", "breeze", "moon", "rain", "wind", "sea", "morning", "snow", "lake", "sunset", "pine", "shadow", "leaf", "dawn", "glitter", "forest", "hill", "cloud", "meadow", "sun", "glade", "bird", "brook", "butterfly", "bush", "dew", "dust", "field", "fire", "flower", "firefly", "feather", "grass", "haze", "mountain", "night", "pond", "darkness", "snowflake", "silence", "sound", "sky", "shape", "surf", "thunder", "violet", "water", "wildflower", "wave", "water", "resonance", "sun", "log", "dream", "cherry", "tree", "fog", "frost", "voice", "paper", "frog", "smoke", "star"];
|
||||||
type KeyBuffer = {
|
const adjectives = ["autumn", "hidden", "bitter", "misty", "silent", "empty", "dry", "dark", "summer", "icy", "delicate", "quiet", "white", "cool", "spring", "winter", "patient", "twilight", "dawn", "crimson", "wispy", "weathered", "blue", "billowing", "broken", "cold", "damp", "falling", "frosty", "green", "long", "late", "lingering", "bold", "little", "morning", "muddy", "old", "red", "rough", "still", "small", "sparkling", "thrumming", "shy", "wandering", "withered", "wild", "black", "young", "holy", "solitary", "fragrant", "aged", "snowy", "proud", "floral", "restless", "divine", "polished", "ancient", "purple", "lively", "nameless"];
|
||||||
key: CryptoKey;
|
function friendlyString() {
|
||||||
salt: Uint8Array;
|
return `${adjectives[Math.floor(Math.random() * adjectives.length)]}-${noun[Math.floor(Math.random() * noun.length)]}`;
|
||||||
count: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
let semiStaticFieldBuffer: Uint8Array;
|
|
||||||
const nonceBuffer: Uint32Array = new Uint32Array(1);
|
|
||||||
const writeString = (string: string) => {
|
|
||||||
// Prepare enough buffer.
|
|
||||||
const buffer = new Uint8Array(string.length * 4);
|
|
||||||
const length = string.length;
|
|
||||||
let index = 0;
|
|
||||||
let chr = 0;
|
|
||||||
let idx = 0;
|
|
||||||
while (idx < length) {
|
|
||||||
chr = string.charCodeAt(idx++);
|
|
||||||
if (chr < 128) {
|
|
||||||
buffer[index++] = chr;
|
|
||||||
} else if (chr < 0x800) {
|
|
||||||
// 2 bytes
|
|
||||||
buffer[index++] = 0xC0 | (chr >>> 6);
|
|
||||||
buffer[index++] = 0x80 | (chr & 0x3F);
|
|
||||||
} else if (chr < 0xD800 || chr > 0xDFFF) {
|
|
||||||
// 3 bytes
|
|
||||||
buffer[index++] = 0xE0 | (chr >>> 12);
|
|
||||||
buffer[index++] = 0x80 | ((chr >>> 6) & 0x3F);
|
|
||||||
buffer[index++] = 0x80 | (chr & 0x3F);
|
|
||||||
} else {
|
|
||||||
// 4 bytes - surrogate pair
|
|
||||||
chr = (((chr - 0xD800) << 10) | (string.charCodeAt(idx++) - 0xDC00)) + 0x10000;
|
|
||||||
buffer[index++] = 0xF0 | (chr >>> 18);
|
|
||||||
buffer[index++] = 0x80 | ((chr >>> 12) & 0x3F);
|
|
||||||
buffer[index++] = 0x80 | ((chr >>> 6) & 0x3F);
|
|
||||||
buffer[index++] = 0x80 | (chr & 0x3F);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buffer.slice(0, index);
|
|
||||||
};
|
|
||||||
const KeyBuffs = new Map<string, KeyBuffer>();
|
|
||||||
async function getKeyForEncrypt(passphrase: string, autoCalculateIterations: boolean): Promise<[CryptoKey, Uint8Array]> {
|
|
||||||
// For performance, the plugin reuses the key KEY_RECYCLE_COUNT times.
|
|
||||||
const buffKey = `${passphrase}-${autoCalculateIterations}`;
|
|
||||||
const f = KeyBuffs.get(buffKey);
|
|
||||||
if (f) {
|
|
||||||
f.count--;
|
|
||||||
if (f.count > 0) {
|
|
||||||
return [f.key, f.salt];
|
|
||||||
}
|
|
||||||
f.count--;
|
|
||||||
}
|
|
||||||
const passphraseLen = 15 - passphrase.length;
|
|
||||||
const iteration = autoCalculateIterations ? ((passphraseLen > 0 ? passphraseLen : 0) * 1000) + 121 - passphraseLen : 100000;
|
|
||||||
const passphraseBin = new TextEncoder().encode(passphrase);
|
|
||||||
const digest = await webcrypto.subtle.digest({ name: "SHA-256" }, passphraseBin);
|
|
||||||
const keyMaterial = await webcrypto.subtle.importKey("raw", digest, { name: "PBKDF2" }, false, ["deriveKey"]);
|
|
||||||
const salt = webcrypto.getRandomValues(new Uint8Array(16));
|
|
||||||
const key = await webcrypto.subtle.deriveKey(
|
|
||||||
{
|
|
||||||
name: "PBKDF2",
|
|
||||||
salt,
|
|
||||||
iterations: iteration,
|
|
||||||
hash: "SHA-256",
|
|
||||||
},
|
|
||||||
keyMaterial,
|
|
||||||
{ name: "AES-GCM", length: 256 },
|
|
||||||
false,
|
|
||||||
["encrypt"]
|
|
||||||
);
|
|
||||||
KeyBuffs.set(buffKey, {
|
|
||||||
key,
|
|
||||||
salt,
|
|
||||||
count: KEY_RECYCLE_COUNT,
|
|
||||||
});
|
|
||||||
return [key, salt];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSemiStaticField(reset?: boolean) {
|
const uri_passphrase = `${Deno.env.get("uri_passphrase") ?? friendlyString()}`;
|
||||||
// return fixed field of iv.
|
|
||||||
if (semiStaticFieldBuffer != null && !reset) {
|
|
||||||
return semiStaticFieldBuffer;
|
|
||||||
}
|
|
||||||
semiStaticFieldBuffer = webcrypto.getRandomValues(new Uint8Array(12));
|
|
||||||
return semiStaticFieldBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNonce() {
|
|
||||||
// This is nonce, so do not send same thing.
|
|
||||||
nonceBuffer[0]++;
|
|
||||||
if (nonceBuffer[0] > 10000) {
|
|
||||||
// reset semi-static field.
|
|
||||||
getSemiStaticField(true);
|
|
||||||
}
|
|
||||||
return nonceBuffer;
|
|
||||||
}
|
|
||||||
function arrayBufferToBase64internalBrowser(buffer: DataView | Uint8Array): Promise<string> {
|
|
||||||
return new Promise((res, rej) => {
|
|
||||||
const blob = new Blob([buffer], { type: "application/octet-binary" });
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = function (evt) {
|
|
||||||
const dataURI = evt.target?.result?.toString() || "";
|
|
||||||
if (buffer.byteLength != 0 && (dataURI == "" || dataURI == "data:")) return rej(new TypeError("Could not parse the encoded string"));
|
|
||||||
const result = dataURI.substring(dataURI.indexOf(",") + 1);
|
|
||||||
res(result);
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(blob);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map for converting hexString
|
|
||||||
const revMap: { [key: string]: number } = {};
|
|
||||||
const numMap: { [key: number]: string } = {};
|
|
||||||
for (let i = 0; i < 256; i++) {
|
|
||||||
revMap[(`00${i.toString(16)}`.slice(-2))] = i;
|
|
||||||
numMap[i] = (`00${i.toString(16)}`.slice(-2));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function uint8ArrayToHexString(src: Uint8Array): string {
|
|
||||||
return [...src].map(e => numMap[e]).join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
const QUANTUM = 32768;
|
|
||||||
async function arrayBufferToBase64Single(buffer: ArrayBuffer): Promise<string> {
|
|
||||||
const buf = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
||||||
if (buf.byteLength < QUANTUM) return btoa(String.fromCharCode.apply(null, [...buf]));
|
|
||||||
return await arrayBufferToBase64internalBrowser(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export async function encrypt(input: string, passphrase: string, autoCalculateIterations: boolean) {
|
|
||||||
const [key, salt] = await getKeyForEncrypt(passphrase, autoCalculateIterations);
|
|
||||||
// Create initial vector with semi-fixed part and incremental part
|
|
||||||
// I think it's not good against related-key attacks.
|
|
||||||
const fixedPart = getSemiStaticField();
|
|
||||||
const invocationPart = getNonce();
|
|
||||||
const iv = new Uint8Array([...fixedPart, ...new Uint8Array(invocationPart.buffer)]);
|
|
||||||
const plainStringified = JSON.stringify(input);
|
|
||||||
|
|
||||||
// const plainStringBuffer: Uint8Array = tex.encode(plainStringified)
|
|
||||||
const plainStringBuffer: Uint8Array = writeString(plainStringified);
|
|
||||||
const encryptedDataArrayBuffer = await webcrypto.subtle.encrypt({ name: "AES-GCM", iv }, key, plainStringBuffer);
|
|
||||||
const encryptedData2 = (await arrayBufferToBase64Single(encryptedDataArrayBuffer));
|
|
||||||
//return data with iv and salt.
|
|
||||||
const ret = `["${encryptedData2}","${uint8ArrayToHexString(iv)}","${uint8ArrayToHexString(salt)}"]`;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const URIBASE = "obsidian://setuplivesync?settings=";
|
const URIBASE = "obsidian://setuplivesync?settings=";
|
||||||
async function main() {
|
async function main() {
|
||||||
@@ -173,8 +33,10 @@ async function main() {
|
|||||||
"concurrencyOfReadChunksOnline": 100,
|
"concurrencyOfReadChunksOnline": 100,
|
||||||
"minimumIntervalOfReadChunksOnline": 100,
|
"minimumIntervalOfReadChunksOnline": 100,
|
||||||
}
|
}
|
||||||
const encryptedConf = encodeURIComponent(await encrypt(JSON.stringify(conf), "welcome", false));
|
const encryptedConf = encodeURIComponent(await encrypt(JSON.stringify(conf), uri_passphrase, false));
|
||||||
const theURI = `${URIBASE}${encryptedConf}`;
|
const theURI = `${URIBASE}${encryptedConf}`;
|
||||||
console.log(theURI);
|
console.log(theURI);
|
||||||
|
console.log("\nYour passphrase of Setup-URI is: ", uri_passphrase);
|
||||||
|
console.log("This passphrase is never shown again, so please note it in a safe place.")
|
||||||
}
|
}
|
||||||
await main();
|
await main();
|
||||||
+4
-1
@@ -129,12 +129,15 @@ curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection to young-
|
|||||||
<-- Configuring CouchDB by REST APIs Done!
|
<-- Configuring CouchDB by REST APIs Done!
|
||||||
OK!
|
OK!
|
||||||
Setup finished! Also, we can set up Self-hosted LiveSync instantly, by the following setup uri.
|
Setup finished! Also, we can set up Self-hosted LiveSync instantly, by the following setup uri.
|
||||||
Passphrase of setup-uri is `welcome`.
|
Passphrase of setup-uri will be printed only one time. Keep it safe!
|
||||||
--- configured ---
|
--- configured ---
|
||||||
database : obsidiannotes
|
database : obsidiannotes
|
||||||
E2EE passphrase: dark-wildflower-26467
|
E2EE passphrase: dark-wildflower-26467
|
||||||
--- setup uri ---
|
--- setup uri ---
|
||||||
obsidian://setuplivesync?settings=%5B%22gZkBwjFbLqxbdSIbJymU%2FmTPBPAKUiHVGDRKYiNnKhW0auQeBgJOfvnxexZtMCn8sNiIUTAlxNaMGF2t%2BCEhpJoeCP%2FO%2BrwfN5LaNDQyky1Uf7E%2B64A5UWyjOYvZDOgq4iCKSdBAXp9oO%2BwKh4MQjUZ78vIVvJp8Mo6NWHfm5fkiWoAoddki1xBMvi%2BmmN%2FhZatQGcslVb9oyYWpZocduTl0a5Dv%2FQviGwlYQ%2F4NY0dVDIoOdvaYS%2FX4GhNAnLzyJKMXhPEJHo9FvR%2FEOBuwyfMdftV1SQUZ8YDCuiR3T7fh7Kn1c6OFgaFMpFm%2BWgIJ%2FZpmAyhZFpEcjpd7ty%2BN9kfd9gQsZM4%2BYyU9OwDd2DahVMBWkqoV12QIJ8OlJScHHdcUfMW5ex%2F4UZTWKNEHJsigITXBrtq11qGk3rBfHys8O0vY6sz%2FaYNM3iAOsR1aoZGyvwZm4O6VwtzK8edg0T15TL4O%2B7UajQgtCGxgKNYxb8EMOGeskv7NifYhjCWcveeTYOJzBhnIDyRbYaWbkAXQgHPBxzJRkkG%2FpBPfBBoJarj7wgjMvhLJ9xtL4FbP6sBNlr8jtAUCoq4L7LJcRNF4hlgvjJpL2BpFZMzkRNtUBcsRYR5J%2BM1X2buWi2BHncbSiRRDKEwNOQkc%2FmhMJjbAn%2F8eNKRuIICOLD5OvxD7FZNCJ0R%2BWzgrzcNV%22%2C%22ec7edc900516b4fcedb4c7cc01000000%22%2C%22fceb5fe54f6619ee266ed9a887634e07%22%5D
|
obsidian://setuplivesync?settings=%5B%22gZkBwjFbLqxbdSIbJymU%2FmTPBPAKUiHVGDRKYiNnKhW0auQeBgJOfvnxexZtMCn8sNiIUTAlxNaMGF2t%2BCEhpJoeCP%2FO%2BrwfN5LaNDQyky1Uf7E%2B64A5UWyjOYvZDOgq4iCKSdBAXp9oO%2BwKh4MQjUZ78vIVvJp8Mo6NWHfm5fkiWoAoddki1xBMvi%2BmmN%2FhZatQGcslVb9oyYWpZocduTl0a5Dv%2FQviGwlYQ%2F4NY0dVDIoOdvaYS%2FX4GhNAnLzyJKMXhPEJHo9FvR%2FEOBuwyfMdftV1SQUZ8YDCuiR3T7fh7Kn1c6OFgaFMpFm%2BWgIJ%2FZpmAyhZFpEcjpd7ty%2BN9kfd9gQsZM4%2BYyU9OwDd2DahVMBWkqoV12QIJ8OlJScHHdcUfMW5ex%2F4UZTWKNEHJsigITXBrtq11qGk3rBfHys8O0vY6sz%2FaYNM3iAOsR1aoZGyvwZm4O6VwtzK8edg0T15TL4O%2B7UajQgtCGxgKNYxb8EMOGeskv7NifYhjCWcveeTYOJzBhnIDyRbYaWbkAXQgHPBxzJRkkG%2FpBPfBBoJarj7wgjMvhLJ9xtL4FbP6sBNlr8jtAUCoq4L7LJcRNF4hlgvjJpL2BpFZMzkRNtUBcsRYR5J%2BM1X2buWi2BHncbSiRRDKEwNOQkc%2FmhMJjbAn%2F8eNKRuIICOLD5OvxD7FZNCJ0R%2BWzgrzcNV%22%2C%22ec7edc900516b4fcedb4c7cc01000000%22%2C%22fceb5fe54f6619ee266ed9a887634e07%22%5D
|
||||||
|
|
||||||
|
Your passphrase of Setup-URI is: patient-haze
|
||||||
|
This passphrase is never shown again, so please note it in a safe place.
|
||||||
```
|
```
|
||||||
|
|
||||||
All we have to do is copy the setup-URI (`obsidian`://...`) and open it from Self-hosted LiveSync on Obsidian.
|
All we have to do is copy the setup-URI (`obsidian`://...`) and open it from Self-hosted LiveSync on Obsidian.
|
||||||
|
|||||||
Reference in New Issue
Block a user