Add e2e-test (not passed yet)

Refine readme
This commit is contained in:
vorotamoroz
2026-03-12 12:20:39 +09:00
parent fa14531599
commit 5d80258a77
16 changed files with 520 additions and 177 deletions
+24 -62
View File
@@ -1939,7 +1939,6 @@
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.4.tgz", "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.4.tgz",
"integrity": "sha512-pUxEGmR+uu21OG/icAovjlu1fcYJzyVhhT0rsCrn+zi+nHtrS43Bp9KPn9KGa4NMspCUE++nkyiqziuIvJdwzw==", "integrity": "sha512-pUxEGmR+uu21OG/icAovjlu1fcYJzyVhhT0rsCrn+zi+nHtrS43Bp9KPn9KGa4NMspCUE++nkyiqziuIvJdwzw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"dependencies": { "dependencies": {
"@firebase/component": "0.7.0", "@firebase/component": "0.7.0",
"@firebase/logger": "0.5.0", "@firebase/logger": "0.5.0",
@@ -2006,7 +2005,6 @@
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.4.tgz", "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.4.tgz",
"integrity": "sha512-T7ifGmb+awJEcp542Ek4HtNfBxcBrnuk1ggUdqyFEdsXHdq7+wVlhvE6YukTL7NS8hIkEfL7TMAPx/uCNqt30g==", "integrity": "sha512-T7ifGmb+awJEcp542Ek4HtNfBxcBrnuk1ggUdqyFEdsXHdq7+wVlhvE6YukTL7NS8hIkEfL7TMAPx/uCNqt30g==",
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"dependencies": { "dependencies": {
"@firebase/app": "0.14.4", "@firebase/app": "0.14.4",
"@firebase/component": "0.7.0", "@firebase/component": "0.7.0",
@@ -2022,8 +2020,7 @@
"version": "0.9.3", "version": "0.9.3",
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
"integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==", "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==",
"license": "Apache-2.0", "license": "Apache-2.0"
"peer": true
}, },
"node_modules/@firebase/app/node_modules/idb": { "node_modules/@firebase/app/node_modules/idb": {
"version": "7.1.1", "version": "7.1.1",
@@ -2492,7 +2489,6 @@
"integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"dependencies": { "dependencies": {
"tslib": "^2.1.0" "tslib": "^2.1.0"
}, },
@@ -3085,7 +3081,8 @@
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT",
"peer": true
}, },
"node_modules/@multiformats/dns": { "node_modules/@multiformats/dns": {
"version": "1.0.10", "version": "1.0.10",
@@ -4947,7 +4944,6 @@
"integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
"deepmerge": "^4.3.1", "deepmerge": "^4.3.1",
@@ -5427,7 +5423,6 @@
"integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1", "@typescript-eslint/types": "8.56.1",
@@ -5632,7 +5627,6 @@
"integrity": "sha512-t4toy8X/YTnjYEPoY0pbDBg3EvDPg1elCDrfc+VupPHwoN/5/FNQ8Z+xBYIaEnOE2vVEyKwqYBzZ9h9rJtZVcg==", "integrity": "sha512-t4toy8X/YTnjYEPoY0pbDBg3EvDPg1elCDrfc+VupPHwoN/5/FNQ8Z+xBYIaEnOE2vVEyKwqYBzZ9h9rJtZVcg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@vitest/mocker": "4.0.16", "@vitest/mocker": "4.0.16",
"@vitest/utils": "4.0.16", "@vitest/utils": "4.0.16",
@@ -5656,7 +5650,6 @@
"integrity": "sha512-I2Fy/ANdphi1yI46d15o0M1M4M0UJrUiVKkH5oKeRZZCdPg0fw/cfTKZzv9Ge9eobtJYp4BGblMzXdXH0vcl5g==", "integrity": "sha512-I2Fy/ANdphi1yI46d15o0M1M4M0UJrUiVKkH5oKeRZZCdPg0fw/cfTKZzv9Ge9eobtJYp4BGblMzXdXH0vcl5g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@vitest/browser": "4.0.16", "@vitest/browser": "4.0.16",
"@vitest/mocker": "4.0.16", "@vitest/mocker": "4.0.16",
@@ -6401,7 +6394,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -7410,7 +7402,8 @@
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT",
"peer": true
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
@@ -8293,7 +8286,6 @@
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"esbuild": "bin/esbuild" "esbuild": "bin/esbuild"
}, },
@@ -8404,7 +8396,6 @@
"integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
@@ -10777,7 +10768,6 @@
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"jiti": "lib/jiti-cli.mjs" "jiti": "lib/jiti-cli.mjs"
} }
@@ -11329,7 +11319,6 @@
"resolved": "https://registry.npmjs.org/libp2p/-/libp2p-2.8.11.tgz", "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-2.8.11.tgz",
"integrity": "sha512-EjkyN0CI6uP+e4OOkEcZvhbZtlwFl4Y0rkkMvDbXmcfILX4E4n/jKE4Ppoc1qhNufxToxVWCMDS2ipniQgiYaw==", "integrity": "sha512-EjkyN0CI6uP+e4OOkEcZvhbZtlwFl4Y0rkkMvDbXmcfILX4E4n/jKE4Ppoc1qhNufxToxVWCMDS2ipniQgiYaw==",
"license": "Apache-2.0 OR MIT", "license": "Apache-2.0 OR MIT",
"peer": true,
"dependencies": { "dependencies": {
"@chainsafe/is-ip": "^2.1.0", "@chainsafe/is-ip": "^2.1.0",
"@chainsafe/netmask": "^2.0.0", "@chainsafe/netmask": "^2.0.0",
@@ -12630,7 +12619,6 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"nanoid": "^3.3.11", "nanoid": "^3.3.11",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
@@ -12655,7 +12643,6 @@
"url": "https://github.com/sponsors/ai" "url": "https://github.com/sponsors/ai"
} }
], ],
"peer": true,
"dependencies": { "dependencies": {
"lilconfig": "^3.1.1" "lilconfig": "^3.1.1"
}, },
@@ -14226,7 +14213,8 @@
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz",
"integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT",
"peer": true
}, },
"node_modules/sublevel-pouchdb": { "node_modules/sublevel-pouchdb": {
"version": "9.0.0", "version": "9.0.0",
@@ -14293,7 +14281,6 @@
"integrity": "sha512-0a/huwc8e2es+7KFi70esqsReRfRbrT8h1cJSY/+z1lF0yKM6TT+//HYu28Yxstr50H7ifaqZRDGd0KuKDxP7w==", "integrity": "sha512-0a/huwc8e2es+7KFi70esqsReRfRbrT8h1cJSY/+z1lF0yKM6TT+//HYu28Yxstr50H7ifaqZRDGd0KuKDxP7w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@jridgewell/remapping": "^2.3.4", "@jridgewell/remapping": "^2.3.4",
"@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/sourcemap-codec": "^1.5.0",
@@ -14611,7 +14598,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -14739,7 +14725,6 @@
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "~0.27.0", "esbuild": "~0.27.0",
"get-tsconfig": "^4.7.5" "get-tsconfig": "^4.7.5"
@@ -15345,7 +15330,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -15482,7 +15466,6 @@
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.27.0", "esbuild": "^0.27.0",
"fdir": "^6.5.0", "fdir": "^6.5.0",
@@ -16043,7 +16026,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -16077,7 +16059,6 @@
"integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==", "integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@vitest/expect": "4.0.16", "@vitest/expect": "4.0.16",
"@vitest/mocker": "4.0.16", "@vitest/mocker": "4.0.16",
@@ -16173,7 +16154,8 @@
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT",
"peer": true
}, },
"node_modules/wait-port": { "node_modules/wait-port": {
"version": "1.1.0", "version": "1.1.0",
@@ -16689,7 +16671,6 @@
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"peer": true,
"bin": { "bin": {
"yaml": "bin.mjs" "yaml": "bin.mjs"
}, },
@@ -18037,7 +18018,6 @@
"version": "0.14.4", "version": "0.14.4",
"resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.4.tgz", "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.4.tgz",
"integrity": "sha512-pUxEGmR+uu21OG/icAovjlu1fcYJzyVhhT0rsCrn+zi+nHtrS43Bp9KPn9KGa4NMspCUE++nkyiqziuIvJdwzw==", "integrity": "sha512-pUxEGmR+uu21OG/icAovjlu1fcYJzyVhhT0rsCrn+zi+nHtrS43Bp9KPn9KGa4NMspCUE++nkyiqziuIvJdwzw==",
"peer": true,
"requires": { "requires": {
"@firebase/component": "0.7.0", "@firebase/component": "0.7.0",
"@firebase/logger": "0.5.0", "@firebase/logger": "0.5.0",
@@ -18091,7 +18071,6 @@
"version": "0.5.4", "version": "0.5.4",
"resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.4.tgz", "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.4.tgz",
"integrity": "sha512-T7ifGmb+awJEcp542Ek4HtNfBxcBrnuk1ggUdqyFEdsXHdq7+wVlhvE6YukTL7NS8hIkEfL7TMAPx/uCNqt30g==", "integrity": "sha512-T7ifGmb+awJEcp542Ek4HtNfBxcBrnuk1ggUdqyFEdsXHdq7+wVlhvE6YukTL7NS8hIkEfL7TMAPx/uCNqt30g==",
"peer": true,
"requires": { "requires": {
"@firebase/app": "0.14.4", "@firebase/app": "0.14.4",
"@firebase/component": "0.7.0", "@firebase/component": "0.7.0",
@@ -18103,8 +18082,7 @@
"@firebase/app-types": { "@firebase/app-types": {
"version": "0.9.3", "version": "0.9.3",
"resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz",
"integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==", "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw=="
"peer": true
}, },
"@firebase/auth": { "@firebase/auth": {
"version": "1.11.0", "version": "1.11.0",
@@ -18432,7 +18410,6 @@
"version": "1.13.0", "version": "1.13.0",
"resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz",
"integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==",
"peer": true,
"requires": { "requires": {
"tslib": "^2.1.0" "tslib": "^2.1.0"
} }
@@ -18905,7 +18882,8 @@
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
"dev": true "dev": true,
"peer": true
}, },
"@multiformats/dns": { "@multiformats/dns": {
"version": "1.0.10", "version": "1.0.10",
@@ -20089,7 +20067,6 @@
"resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.4.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.4.tgz",
"integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
"deepmerge": "^4.3.1", "deepmerge": "^4.3.1",
@@ -20517,7 +20494,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz",
"integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/scope-manager": "8.56.1",
"@typescript-eslint/types": "8.56.1", "@typescript-eslint/types": "8.56.1",
@@ -20625,7 +20601,6 @@
"resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.0.16.tgz", "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.0.16.tgz",
"integrity": "sha512-t4toy8X/YTnjYEPoY0pbDBg3EvDPg1elCDrfc+VupPHwoN/5/FNQ8Z+xBYIaEnOE2vVEyKwqYBzZ9h9rJtZVcg==", "integrity": "sha512-t4toy8X/YTnjYEPoY0pbDBg3EvDPg1elCDrfc+VupPHwoN/5/FNQ8Z+xBYIaEnOE2vVEyKwqYBzZ9h9rJtZVcg==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@vitest/mocker": "4.0.16", "@vitest/mocker": "4.0.16",
"@vitest/utils": "4.0.16", "@vitest/utils": "4.0.16",
@@ -20642,7 +20617,6 @@
"resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.0.16.tgz", "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.0.16.tgz",
"integrity": "sha512-I2Fy/ANdphi1yI46d15o0M1M4M0UJrUiVKkH5oKeRZZCdPg0fw/cfTKZzv9Ge9eobtJYp4BGblMzXdXH0vcl5g==", "integrity": "sha512-I2Fy/ANdphi1yI46d15o0M1M4M0UJrUiVKkH5oKeRZZCdPg0fw/cfTKZzv9Ge9eobtJYp4BGblMzXdXH0vcl5g==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@vitest/browser": "4.0.16", "@vitest/browser": "4.0.16",
"@vitest/mocker": "4.0.16", "@vitest/mocker": "4.0.16",
@@ -21165,8 +21139,7 @@
"version": "8.15.0", "version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true
"peer": true
}, },
"acorn-jsx": { "acorn-jsx": {
"version": "5.3.2", "version": "5.3.2",
@@ -21840,7 +21813,8 @@
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
"dev": true "dev": true,
"peer": true
}, },
"cross-spawn": { "cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
@@ -22433,7 +22407,6 @@
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
"integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@esbuild/aix-ppc64": "0.25.0", "@esbuild/aix-ppc64": "0.25.0",
"@esbuild/android-arm": "0.25.0", "@esbuild/android-arm": "0.25.0",
@@ -22509,7 +22482,6 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz",
"integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
@@ -24105,8 +24077,7 @@
"version": "2.6.1", "version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"dev": true, "dev": true
"peer": true
}, },
"js-sdsl": { "js-sdsl": {
"version": "4.3.0", "version": "4.3.0",
@@ -24500,7 +24471,6 @@
"version": "2.8.11", "version": "2.8.11",
"resolved": "https://registry.npmjs.org/libp2p/-/libp2p-2.8.11.tgz", "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-2.8.11.tgz",
"integrity": "sha512-EjkyN0CI6uP+e4OOkEcZvhbZtlwFl4Y0rkkMvDbXmcfILX4E4n/jKE4Ppoc1qhNufxToxVWCMDS2ipniQgiYaw==", "integrity": "sha512-EjkyN0CI6uP+e4OOkEcZvhbZtlwFl4Y0rkkMvDbXmcfILX4E4n/jKE4Ppoc1qhNufxToxVWCMDS2ipniQgiYaw==",
"peer": true,
"requires": { "requires": {
"@chainsafe/is-ip": "^2.1.0", "@chainsafe/is-ip": "^2.1.0",
"@chainsafe/netmask": "^2.0.0", "@chainsafe/netmask": "^2.0.0",
@@ -25385,7 +25355,6 @@
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"nanoid": "^3.3.11", "nanoid": "^3.3.11",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
@@ -25397,7 +25366,6 @@
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
"integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"lilconfig": "^3.1.1" "lilconfig": "^3.1.1"
} }
@@ -26500,7 +26468,8 @@
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz",
"integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==",
"dev": true "dev": true,
"peer": true
}, },
"sublevel-pouchdb": { "sublevel-pouchdb": {
"version": "9.0.0", "version": "9.0.0",
@@ -26555,7 +26524,6 @@
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.41.1.tgz", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.41.1.tgz",
"integrity": "sha512-0a/huwc8e2es+7KFi70esqsReRfRbrT8h1cJSY/+z1lF0yKM6TT+//HYu28Yxstr50H7ifaqZRDGd0KuKDxP7w==", "integrity": "sha512-0a/huwc8e2es+7KFi70esqsReRfRbrT8h1cJSY/+z1lF0yKM6TT+//HYu28Yxstr50H7ifaqZRDGd0KuKDxP7w==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@jridgewell/remapping": "^2.3.4", "@jridgewell/remapping": "^2.3.4",
"@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/sourcemap-codec": "^1.5.0",
@@ -26740,8 +26708,7 @@
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true
"peer": true
} }
} }
}, },
@@ -26839,7 +26806,6 @@
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"esbuild": "~0.27.0", "esbuild": "~0.27.0",
"fsevents": "~2.3.3", "fsevents": "~2.3.3",
@@ -27139,8 +27105,7 @@
"version": "5.9.3", "version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true
"peer": true
}, },
"uint8-varint": { "uint8-varint": {
"version": "2.0.4", "version": "2.0.4",
@@ -27241,7 +27206,6 @@
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz",
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"esbuild": "^0.27.0", "esbuild": "^0.27.0",
"fdir": "^6.5.0", "fdir": "^6.5.0",
@@ -27472,8 +27436,7 @@
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true
"peer": true
} }
} }
}, },
@@ -27489,7 +27452,6 @@
"resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.16.tgz", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.16.tgz",
"integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==", "integrity": "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==",
"dev": true, "dev": true,
"peer": true,
"requires": { "requires": {
"@vitest/expect": "4.0.16", "@vitest/expect": "4.0.16",
"@vitest/mocker": "4.0.16", "@vitest/mocker": "4.0.16",
@@ -27530,7 +27492,8 @@
"version": "2.2.8", "version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"dev": true "dev": true,
"peer": true
}, },
"wait-port": { "wait-port": {
"version": "1.1.0", "version": "1.1.0",
@@ -27899,8 +27862,7 @@
"version": "2.8.2", "version": "2.8.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
"integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
"dev": true, "dev": true
"peer": true
}, },
"yargs": { "yargs": {
"version": "17.7.2", "version": "17.7.2",
+8
View File
@@ -0,0 +1,8 @@
hostname=http://127.0.0.1:5989/
dbname=livesync-test-db2
minioEndpoint=http://127.0.0.1:9000
username=admin
password=testpassword
accessKey=minioadmin
secretKey=minioadmin
bucketName=livesync-test-bucket
+74 -50
View File
@@ -16,12 +16,12 @@ This CLI version is built using the same core as the Obsidian plugin:
``` ```
CLI Main CLI Main
└─ LiveSyncBaseCore<ServiceContext, IMinimumLiveSyncCommands> └─ LiveSyncBaseCore<ServiceContext, IMinimumLiveSyncCommands>
├─ HeadlessServiceHub (All services without Obsidian dependencies) ├─ NodeServiceHub (All services without Obsidian dependencies)
└─ ServiceModules (Ported from main.ts) └─ ServiceModules (wired by initialiseServiceModulesCLI)
├─ FileAccessCLI (Node.js FileSystemAdapter) ├─ FileAccessCLI (Node.js FileSystemAdapter)
├─ StorageEventManagerCLI ├─ StorageEventManagerCLI
├─ ServiceFileAccessCLI ├─ ServiceFileAccessCLI
├─ ServiceDatabaseFileAccess ├─ ServiceDatabaseFileAccessCLI
├─ ServiceFileHandler ├─ ServiceFileHandler
└─ ServiceRebuilder └─ ServiceRebuilder
``` ```
@@ -33,10 +33,14 @@ CLI Main
- Implements same interface as Obsidian's file system - Implements same interface as Obsidian's file system
2. **Service Modules** (`serviceModules/`) 2. **Service Modules** (`serviceModules/`)
- Direct port from `main.ts` `initialiseServiceModules` - Initialised by `initialiseServiceModulesCLI`
- All core sync functionality preserved - All core sync functionality preserved
3. **Main Entry Point** (`main.ts`) 3. **Service Hub and Settings Services** (`services/`)
- `NodeServiceHub` provides the CLI service context
- Node-specific settings and key-value services are provided without Obsidian dependencies
4. **Main Entry Point** (`main.ts`)
- Command-line interface - Command-line interface
- Settings management (JSON file) - Settings management (JSON file)
- Graceful shutdown handling - Graceful shutdown handling
@@ -59,43 +63,43 @@ As you know, the CLI is designed to be used in a headless environment. Hence all
```bash ```bash
# Sync local database with CouchDB (no files will be changed). # Sync local database with CouchDB (no files will be changed).
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json sync npm run cli -- /path/to/your-local-database --settings /path/to/settings.json sync
# Push files to local database # Push files to local database
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json push /your/storage/file.md /vault/path/file.md npm run cli -- /path/to/your-local-database --settings /path/to/settings.json push /your/storage/file.md /vault/path/file.md
# Pull files from local database # Pull files from local database
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json pull /vault/path/file.md /your/storage/file.md npm run cli -- /path/to/your-local-database --settings /path/to/settings.json pull /vault/path/file.md /your/storage/file.md
# Verbose logging # Verbose logging
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json --verbose npm run cli -- /path/to/your-local-database --settings /path/to/settings.json --verbose
# Apply setup URI to settings file (settings only; does not run synchronisation) # Apply setup URI to settings file (settings only; does not run synchronisation)
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json setup "obsidian://setuplivesync?settings=..." npm run cli -- /path/to/your-local-database --settings /path/to/settings.json setup "obsidian://setuplivesync?settings=..."
# Put text from stdin into local database # Put text from stdin into local database
echo "Hello from stdin" | node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json put /vault/path/file.md echo "Hello from stdin" | npm run cli -- /path/to/your-local-database --settings /path/to/settings.json put /vault/path/file.md
# Output a file from local database to stdout # Output a file from local database to stdout
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json cat /vault/path/file.md npm run cli -- /path/to/your-local-database --settings /path/to/settings.json cat /vault/path/file.md
# Output a specific revision of a file from local database # Output a specific revision of a file from local database
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json cat-rev /vault/path/file.md 3-abcdef npm run cli -- /path/to/your-local-database --settings /path/to/settings.json cat-rev /vault/path/file.md 3-abcdef
# Pull a specific revision of a file from local database to local storage # Pull a specific revision of a file from local database to local storage
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json pull-rev /vault/path/file.md /your/storage/file.old.md 3-abcdef npm run cli -- /path/to/your-local-database --settings /path/to/settings.json pull-rev /vault/path/file.md /your/storage/file.old.md 3-abcdef
# List files in local database # List files in local database
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json ls /vault/path/ npm run cli -- /path/to/your-local-database --settings /path/to/settings.json ls /vault/path/
# Show metadata for a file in local database # Show metadata for a file in local database
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json info /vault/path/file.md npm run cli -- /path/to/your-local-database --settings /path/to/settings.json info /vault/path/file.md
# Mark a file as deleted in local database # Mark a file as deleted in local database
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json rm /vault/path/file.md npm run cli -- /path/to/your-local-database --settings /path/to/settings.json rm /vault/path/file.md
# Resolve conflict by keeping a specific revision # Resolve conflict by keeping a specific revision
node dist/index.cjs /path/to/your-local-database --settings /path/to/settings.json resolve /vault/path/file.md 3-abcdef npm run cli -- /path/to/your-local-database --settings /path/to/settings.json resolve /vault/path/file.md 3-abcdef
``` ```
### Configuration ### Configuration
@@ -157,15 +161,21 @@ Commands:
resolve <vaultPath> <revision> Resolve conflict by keeping the specified revision resolve <vaultPath> <revision> Resolve conflict by keeping the specified revision
``` ```
Run via npm script:
```bash
npm run cli -- [database-path] [options] [command] [command-args]
```
`info` output fields: `info` output fields:
- `ID`: Document ID - `id`: Document ID
- `Revision`: Current revision - `revision`: Current revision
- `Conflicts`: Conflicted revisions, or `N/A` - `conflicts`: Conflicted revisions, or `N/A`
- `Filename`: Basename of path - `filename`: Basename of path
- `Path`: Vault-relative path - `path`: Vault-relative path
- `Size`: Size in bytes - `size`: Size in bytes
- `PastRevisions`: Available non-current revisions - `revisions`: Available non-current revisions
- `Chunks`: Number of chunk IDs - `Chunks`: Number of chunk IDs
- `child: ...`: Chunk ID list - `child: ...`: Chunk ID list
@@ -187,9 +197,9 @@ TODO: Conflict and resolution checks for real local databases.
Create default settings, apply a setup URI, then run one sync cycle. Create default settings, apply a setup URI, then run one sync cycle.
```bash ```bash
node dist/index.cjs init-settings /data/livesync-settings.json npm run cli -- init-settings /data/livesync-settings.json
printf '%s\n' "$SETUP_PASSPHRASE" | node dist/index.cjs /data/vault --settings /data/livesync-settings.json setup "$SETUP_URI" printf '%s\n' "$SETUP_PASSPHRASE" | npm run cli -- /data/vault --settings /data/livesync-settings.json setup "$SETUP_URI"
node dist/index.cjs /data/vault --settings /data/livesync-settings.json sync npm run cli -- /data/vault --settings /data/livesync-settings.json sync
``` ```
### 2. Scripted import and export ### 2. Scripted import and export
@@ -197,8 +207,8 @@ node dist/index.cjs /data/vault --settings /data/livesync-settings.json sync
Push local files into the database from automation, and pull them back for export or backup. Push local files into the database from automation, and pull them back for export or backup.
```bash ```bash
node dist/index.cjs /data/vault --settings /data/livesync-settings.json push ./note.md notes/note.md npm run cli -- /data/vault --settings /data/livesync-settings.json push ./note.md notes/note.md
node dist/index.cjs /data/vault --settings /data/livesync-settings.json pull notes/note.md ./exports/note.md npm run cli -- /data/vault --settings /data/livesync-settings.json pull notes/note.md ./exports/note.md
``` ```
### 3. Revision inspection and restore ### 3. Revision inspection and restore
@@ -206,9 +216,9 @@ node dist/index.cjs /data/vault --settings /data/livesync-settings.json pull not
List metadata, find an older revision, then restore it by content (`cat-rev`) or file output (`pull-rev`). List metadata, find an older revision, then restore it by content (`cat-rev`) or file output (`pull-rev`).
```bash ```bash
node dist/index.cjs /data/vault --settings /data/livesync-settings.json info notes/note.md npm run cli -- /data/vault --settings /data/livesync-settings.json info notes/note.md
node dist/index.cjs /data/vault --settings /data/livesync-settings.json cat-rev notes/note.md 3-abcdef npm run cli -- /data/vault --settings /data/livesync-settings.json cat-rev notes/note.md 3-abcdef
node dist/index.cjs /data/vault --settings /data/livesync-settings.json pull-rev notes/note.md ./restore/note.old.md 3-abcdef npm run cli -- /data/vault --settings /data/livesync-settings.json pull-rev notes/note.md ./restore/note.old.md 3-abcdef
``` ```
### 4. Conflict and cleanup workflow ### 4. Conflict and cleanup workflow
@@ -216,9 +226,9 @@ node dist/index.cjs /data/vault --settings /data/livesync-settings.json pull-rev
Inspect conflicted revisions, resolve by keeping one revision, then delete obsolete files. Inspect conflicted revisions, resolve by keeping one revision, then delete obsolete files.
```bash ```bash
node dist/index.cjs /data/vault --settings /data/livesync-settings.json info notes/note.md npm run cli -- /data/vault --settings /data/livesync-settings.json info notes/note.md
node dist/index.cjs /data/vault --settings /data/livesync-settings.json resolve notes/note.md 3-abcdef npm run cli -- /data/vault --settings /data/livesync-settings.json resolve notes/note.md 3-abcdef
node dist/index.cjs /data/vault --settings /data/livesync-settings.json rm notes/obsolete.md npm run cli -- /data/vault --settings /data/livesync-settings.json rm notes/obsolete.md
``` ```
### 5. CI smoke test for content round-trip ### 5. CI smoke test for content round-trip
@@ -226,8 +236,8 @@ node dist/index.cjs /data/vault --settings /data/livesync-settings.json rm notes
Validate that `put`/`cat` is behaving as expected in a pipeline. Validate that `put`/`cat` is behaving as expected in a pipeline.
```bash ```bash
echo "hello-ci" | node dist/index.cjs /data/vault --settings /data/livesync-settings.json put ci/test.md echo "hello-ci" | npm run cli -- /data/vault --settings /data/livesync-settings.json put ci/test.md
node dist/index.cjs /data/vault --settings /data/livesync-settings.json cat ci/test.md npm run cli -- /data/vault --settings /data/livesync-settings.json cat ci/test.md
``` ```
## Development ## Development
@@ -236,26 +246,40 @@ node dist/index.cjs /data/vault --settings /data/livesync-settings.json cat ci/t
``` ```
src/apps/cli/ src/apps/cli/
├── commands/ # Command dispatcher and command utilities ├── commands/ # Command dispatcher and command utilities
│ ├── runCommand.ts │ ├── runCommand.ts
│ ├── types.ts │ ├── types.ts
│ └── utils.ts │ └── utils.ts
├── adapters/ # Node.js FileSystem Adapter ├── adapters/ # Node.js FileSystem Adapter
│ ├── NodeConversionAdapter.ts
│ ├── NodeFileSystemAdapter.ts │ ├── NodeFileSystemAdapter.ts
│ ├── NodePathAdapter.ts │ ├── NodePathAdapter.ts
│ ├── NodeTypeGuardAdapter.ts
│ ├── NodeConversionAdapter.ts
│ ├── NodeStorageAdapter.ts │ ├── NodeStorageAdapter.ts
│ ├── NodeVaultAdapter.ts │ ├── NodeTypeGuardAdapter.ts
│ └── NodeTypes.ts │ ├── NodeTypes.ts
├── managers/ # CLI-specific managers │ └── NodeVaultAdapter.ts
├── lib/
│ └── pouchdb-node.ts
├── managers/ # CLI-specific managers
│ ├── CLIStorageEventManagerAdapter.ts │ ├── CLIStorageEventManagerAdapter.ts
│ └── StorageEventManagerCLI.ts │ └── StorageEventManagerCLI.ts
├── serviceModules/ # Service modules (ported from main.ts) ├── serviceModules/ # Service modules (ported from main.ts)
│ ├── CLIServiceModules.ts │ ├── CLIServiceModules.ts
│ ├── DatabaseFileAccess.ts
│ ├── FileAccessCLI.ts │ ├── FileAccessCLI.ts
│ ├── ServiceFileAccessImpl.ts │ └── ServiceFileAccessImpl.ts
│ └── DatabaseFileAccess.ts ├── services/
├── main.ts # CLI entry point │ ├── NodeKeyValueDBService.ts
└── README.md # This file │ ├── NodeServiceHub.ts
│ └── NodeSettingService.ts
├── test/
│ ├── test-push-pull-linux.sh
│ ├── test-setup-put-cat-linux.sh
│ └── test-sync-two-local-databases-linux.sh
├── .gitignore
├── main.ts # CLI entry point
├── package.json
├── README.md # This file
├── tsconfig.json
└── vite.config.ts
``` ```
+13 -16
View File
@@ -237,22 +237,19 @@ export async function runCommand(options: CLIOptions, context: CLICommandContext
}) })
.map((entry: { rev: string }) => entry.rev); .map((entry: { rev: string }) => entry.rev);
const pastRevisionsText = const pastRevisionsText =
pastRevisions.length > 0 ? pastRevisions.map((rev: string) => ` rev: ${rev}`) : [" N/A"]; pastRevisions.length > 0 ? pastRevisions.map((rev: string) => `${rev}`) : ["N/A"];
const out = {
const out = id: doc._id,
[ revision: doc._rev ?? "",
`ID: ${doc._id}`, conflicts: conflictsText,
`Revision: ${doc._rev ?? ""}`, filename: filename,
`Conflicts: ${conflictsText}`, path: docPath,
`Filename: ${filename}`, size: doc.size,
`Path: ${docPath}`, revisions: pastRevisionsText,
`Size: ${doc.size}`, chunks: children.length,
`PastRevisions:`, children: children,
...pastRevisionsText, };
`Chunks: ${children.length}`, process.stdout.write(JSON.stringify(out, null, 2) + "\n");
...children.map((id) => ` child: ${id}`),
].join("\n") + "\n";
process.stdout.write(out);
return true; return true;
} }
+5 -3
View File
@@ -2,14 +2,16 @@
"name": "self-hosted-livesync-cli", "name": "self-hosted-livesync-cli",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"main": "dist/index.cjs",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"preview": "vite preview", "preview": "vite preview",
"run": "node dist/index.cjs", "cli": "node dist/index.cjs",
"buildRun": "npm run build && npm run", "buildRun": "npm run build && npm run cli --",
"check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json" "check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json",
"test:e2e:two-vaults": "bash test/test-e2e-two-vaults-with-docker-linux.sh"
}, },
"dependencies": {}, "dependencies": {},
"devDependencies": {} "devDependencies": {}
@@ -0,0 +1,247 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
CLI_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
cd "$CLI_DIR"
# verbose
CLI_CMD=(npm run cli -- -v )
RUN_BUILD="${RUN_BUILD:-1}"
KEEP_TEST_DATA="${KEEP_TEST_DATA:-0}"
TEST_ENV_FILE="${TEST_ENV_FILE:-$CLI_DIR/.test.env}"
if [[ ! -f "$TEST_ENV_FILE" ]]; then
echo "[ERROR] test env file not found: $TEST_ENV_FILE" >&2
exit 1
fi
set -a
source "$TEST_ENV_FILE"
set +a
for var in hostname dbname username password; do
if [[ -z "${!var:-}" ]]; then
echo "[ERROR] required variable '$var' is missing in $TEST_ENV_FILE" >&2
exit 1
fi
done
COUCHDB_URI="${hostname%/}"
DB_SUFFIX="$(date +%s)-$RANDOM"
COUCHDB_DBNAME="${dbname}-${DB_SUFFIX}"
VAULT_ROOT="$CLI_DIR/.livesync"
VAULT_A="$VAULT_ROOT/testvault_a"
VAULT_B="$VAULT_ROOT/testvault_b"
SETTINGS_A="$VAULT_ROOT/test-settings-a.json"
SETTINGS_B="$VAULT_ROOT/test-settings-b.json"
WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/livesync-cli-e2e.XXXXXX")"
cleanup() {
local exit_code=$?
bash "$CLI_DIR/util/couchdb-stop.sh" >/dev/null 2>&1 || true
if [[ "$KEEP_TEST_DATA" != "1" ]]; then
rm -rf "$VAULT_A" "$VAULT_B" "$SETTINGS_A" "$SETTINGS_B" "$WORK_DIR"
else
echo "[INFO] KEEP_TEST_DATA=1, preserving test artefacts"
echo " vault a: $VAULT_A"
echo " vault b: $VAULT_B"
echo " settings: $SETTINGS_A, $SETTINGS_B"
echo " work dir: $WORK_DIR"
fi
exit "$exit_code"
}
trap cleanup EXIT
run_cli() {
"${CLI_CMD[@]}" "$@"
}
run_cli_a() {
run_cli "$VAULT_A" --settings "$SETTINGS_A" "$@"
}
run_cli_b() {
run_cli "$VAULT_B" --settings "$SETTINGS_B" "$@"
}
assert_contains() {
local haystack="$1"
local needle="$2"
local message="$3"
if ! grep -Fq "$needle" <<< "$haystack"; then
echo "[FAIL] $message" >&2
echo "[FAIL] expected to find: $needle" >&2
echo "[FAIL] actual output:" >&2
echo "$haystack" >&2
exit 1
fi
}
assert_equal() {
local expected="$1"
local actual="$2"
local message="$3"
if [[ "$expected" != "$actual" ]]; then
echo "[FAIL] $message" >&2
echo "[FAIL] expected: $expected" >&2
echo "[FAIL] actual: $actual" >&2
exit 1
fi
}
assert_command_fails() {
local message="$1"
shift
set +e
"$@" >"$WORK_DIR/failed-command.log" 2>&1
local exit_code=$?
set -e
if [[ "$exit_code" -eq 0 ]]; then
echo "[FAIL] $message" >&2
cat "$WORK_DIR/failed-command.log" >&2
exit 1
fi
}
sanitise_cat_stdout() {
sed '/^\[CLIWatchAdapter\] File watching is not enabled in CLI version$/d'
}
sync_both() {
run_cli_a sync >/dev/null
run_cli_b sync >/dev/null
}
curl_json() {
curl -4 -sS --fail --connect-timeout 3 --max-time 15 "$@"
}
init_settings() {
local settings_file="$1"
run_cli init-settings --force "$settings_file" >/dev/null
SETTINGS_FILE="$settings_file" \
COUCHDB_URI="$COUCHDB_URI" \
COUCHDB_USER="$username" \
COUCHDB_PASSWORD="$password" \
COUCHDB_DBNAME="$COUCHDB_DBNAME" \
node <<'NODE'
const fs = require("node:fs");
const settingsPath = process.env.SETTINGS_FILE;
const data = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
data.couchDB_URI = process.env.COUCHDB_URI;
data.couchDB_USER = process.env.COUCHDB_USER;
data.couchDB_PASSWORD = process.env.COUCHDB_PASSWORD;
data.couchDB_DBNAME = process.env.COUCHDB_DBNAME;
data.liveSync = true;
data.syncOnStart = false;
data.syncOnSave = false;
data.usePluginSync = false;
data.isConfigured = true;
fs.writeFileSync(settingsPath, JSON.stringify(data, null, 2), "utf-8");
NODE
cat "$settings_file"
}
echo "[INFO] stopping leftover CouchDB container if present"
bash "$CLI_DIR/util/couchdb-stop.sh" >/dev/null 2>&1 || true
echo "[INFO] starting CouchDB test container"
bash "$CLI_DIR/util/couchdb-start.sh"
echo "status"
docker ps --filter "name=couchdb-test"
echo "[INFO] initialising CouchDB test container"
bash "$CLI_DIR/util/couchdb-init.sh"
echo "[INFO] CouchDB create test database: $COUCHDB_DBNAME"
until (curl_json -X PUT --user "${username}:${password}" "${hostname}/${COUCHDB_DBNAME}" ); do sleep 5; done
if [[ "$RUN_BUILD" == "1" ]]; then
echo "[INFO] building CLI"
npm run build
fi
echo "[INFO] preparing vaults and settings"
rm -rf "$VAULT_A" "$VAULT_B" "$SETTINGS_A" "$SETTINGS_B"
mkdir -p "$VAULT_A" "$VAULT_B"
init_settings "$SETTINGS_A"
init_settings "$SETTINGS_B"
echo "[INFO] test DB: $COUCHDB_DBNAME"
TARGET_A_ONLY="e2e/a-only-info.md"
TARGET_SYNC="e2e/sync-info.md"
TARGET_PUSH="e2e/pushed-from-a.md"
TARGET_PUT="e2e/put-from-a.md"
TARGET_CONFLICT="e2e/conflict.md"
echo "[CASE] A puts and A can get info"
printf 'alpha-from-a\n' | run_cli_a put "$TARGET_A_ONLY" >/dev/null
INFO_A_ONLY="$(run_cli_a info "$TARGET_A_ONLY")"
assert_contains "$INFO_A_ONLY" "\"path\": \"$TARGET_A_ONLY\"" "A info should include path after put"
echo "[PASS] A put/info"
echo "[CASE] A puts, both sync, and B can get info"
printf 'visible-after-sync\n' | run_cli_a put "$TARGET_SYNC" >/dev/null
sync_both
INFO_B_SYNC="$(run_cli_b info "$TARGET_SYNC")"
assert_contains "$INFO_B_SYNC" "\"path\": \"$TARGET_SYNC\"" "B info should include path after sync"
echo "[PASS] sync A->B and B info"
echo "[CASE] A pushes and puts, both sync, and B can pull and cat"
PUSH_SRC="$WORK_DIR/push-source.txt"
PULL_DST="$WORK_DIR/pull-destination.txt"
printf 'pushed-content-%s\n' "$DB_SUFFIX" > "$PUSH_SRC"
run_cli_a push "$PUSH_SRC" "$TARGET_PUSH" >/dev/null
printf 'put-content-%s\n' "$DB_SUFFIX" | run_cli_a put "$TARGET_PUT" >/dev/null
sync_both
run_cli_b pull "$TARGET_PUSH" "$PULL_DST" >/dev/null
if ! cmp -s "$PUSH_SRC" "$PULL_DST"; then
echo "[FAIL] B pull result does not match pushed source" >&2
echo "--- source ---" >&2
cat "$PUSH_SRC" >&2
echo "--- pulled ---" >&2
cat "$PULL_DST" >&2
exit 1
fi
CAT_B_PUT="$(run_cli_b cat "$TARGET_PUT" | sanitise_cat_stdout)"
assert_equal "put-content-$DB_SUFFIX" "$CAT_B_PUT" "B cat should return A put content"
echo "[PASS] push/pull and put/cat across vaults"
echo "[CASE] A removes, both sync, and B can no longer cat"
run_cli_a rm "$TARGET_PUT" >/dev/null
sync_both
assert_command_fails "B cat should fail after A removed the file and synced" run_cli_b cat "$TARGET_PUT"
echo "[PASS] rm is replicated"
echo "[CASE] verify conflict detection"
printf 'conflict-base\n' | run_cli_a put "$TARGET_CONFLICT" >/dev/null
sync_both
INFO_B_BASE="$(run_cli_b info "$TARGET_CONFLICT")"
assert_contains "$INFO_B_BASE" "\"path\": \"$TARGET_CONFLICT\"" "B should be able to info before creating conflict"
printf 'conflict-from-a-%s\n' "$DB_SUFFIX" | run_cli_a put "$TARGET_CONFLICT" >/dev/null
printf 'conflict-from-b-%s\n' "$DB_SUFFIX" | run_cli_b put "$TARGET_CONFLICT" >/dev/null
run_cli_a sync >/dev/null
run_cli_b sync >/dev/null
run_cli_a sync >/dev/null
INFO_A_CONFLICT="$(run_cli_a info "$TARGET_CONFLICT")"
INFO_B_CONFLICT="$(run_cli_b info "$TARGET_CONFLICT")"
if grep -qF '"conflicts": "N/A"' <<< "$INFO_A_CONFLICT" && grep -qF '"conflicts": "N/A"' <<< "$INFO_B_CONFLICT"; then
echo "[FAIL] conflict was expected but both A and B show Conflicts: N/A" >&2
echo "--- A info ---" >&2
echo "$INFO_A_CONFLICT" >&2
echo "--- B info ---" >&2
echo "$INFO_B_CONFLICT" >&2
exit 1
fi
echo "[PASS] conflict detected by info"
echo "[PASS] all requested E2E scenarios completed"
+7 -8
View File
@@ -5,7 +5,7 @@ SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
CLI_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)" CLI_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
cd "$CLI_DIR" cd "$CLI_DIR"
CLI_ENTRY="${CLI_ENTRY:-$CLI_DIR/dist/index.cjs}" CLI_CMD=(npm run cli --)
RUN_BUILD="${RUN_BUILD:-1}" RUN_BUILD="${RUN_BUILD:-1}"
REMOTE_PATH="${REMOTE_PATH:-test/push-pull.txt}" REMOTE_PATH="${REMOTE_PATH:-test/push-pull.txt}"
@@ -19,13 +19,12 @@ if [[ "$RUN_BUILD" == "1" ]]; then
npm run build npm run build
fi fi
if [[ ! -f "$CLI_ENTRY" ]]; then run_cli() {
echo "[ERROR] CLI entry not found: $CLI_ENTRY" >&2 "${CLI_CMD[@]}" "$@"
exit 1 }
fi
echo "[INFO] generating settings from DEFAULT_SETTINGS -> $SETTINGS_FILE" echo "[INFO] generating settings from DEFAULT_SETTINGS -> $SETTINGS_FILE"
node "$CLI_ENTRY" init-settings --force "$SETTINGS_FILE" run_cli init-settings --force "$SETTINGS_FILE"
if [[ -n "${COUCHDB_URI:-}" && -n "${COUCHDB_USER:-}" && -n "${COUCHDB_PASSWORD:-}" && -n "${COUCHDB_DBNAME:-}" ]]; then if [[ -n "${COUCHDB_URI:-}" && -n "${COUCHDB_USER:-}" && -n "${COUCHDB_PASSWORD:-}" && -n "${COUCHDB_DBNAME:-}" ]]; then
echo "[INFO] applying CouchDB env vars to generated settings" echo "[INFO] applying CouchDB env vars to generated settings"
@@ -52,10 +51,10 @@ PULLED_FILE="$WORK_DIR/pull-result.txt"
printf 'push-pull-test %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$SRC_FILE" printf 'push-pull-test %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$SRC_FILE"
echo "[INFO] push -> $REMOTE_PATH" echo "[INFO] push -> $REMOTE_PATH"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" push "$SRC_FILE" "$REMOTE_PATH" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" push "$SRC_FILE" "$REMOTE_PATH"
echo "[INFO] pull <- $REMOTE_PATH" echo "[INFO] pull <- $REMOTE_PATH"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" pull "$REMOTE_PATH" "$PULLED_FILE" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" pull "$REMOTE_PATH" "$PULLED_FILE"
if cmp -s "$SRC_FILE" "$PULLED_FILE"; then if cmp -s "$SRC_FILE" "$PULLED_FILE"; then
echo "[PASS] push/pull roundtrip matched" echo "[PASS] push/pull roundtrip matched"
+27 -28
View File
@@ -6,7 +6,7 @@ CLI_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
REPO_ROOT="$(cd -- "$CLI_DIR/../../.." && pwd)" REPO_ROOT="$(cd -- "$CLI_DIR/../../.." && pwd)"
cd "$CLI_DIR" cd "$CLI_DIR"
CLI_ENTRY="${CLI_ENTRY:-$CLI_DIR/dist/index.cjs}" CLI_CMD=(npm run cli --)
RUN_BUILD="${RUN_BUILD:-1}" RUN_BUILD="${RUN_BUILD:-1}"
REMOTE_PATH="${REMOTE_PATH:-test/setup-put-cat.txt}" REMOTE_PATH="${REMOTE_PATH:-test/setup-put-cat.txt}"
SETUP_PASSPHRASE="${SETUP_PASSPHRASE:-setup-passphrase}" SETUP_PASSPHRASE="${SETUP_PASSPHRASE:-setup-passphrase}"
@@ -21,13 +21,12 @@ if [[ "$RUN_BUILD" == "1" ]]; then
npm run build npm run build
fi fi
if [[ ! -f "$CLI_ENTRY" ]]; then run_cli() {
echo "[ERROR] CLI entry not found: $CLI_ENTRY" >&2 "${CLI_CMD[@]}" "$@"
exit 1 }
fi
echo "[INFO] generating settings from DEFAULT_SETTINGS -> $SETTINGS_FILE" echo "[INFO] generating settings from DEFAULT_SETTINGS -> $SETTINGS_FILE"
node "$CLI_ENTRY" init-settings --force "$SETTINGS_FILE" run_cli init-settings --force "$SETTINGS_FILE"
echo "[INFO] creating setup URI from settings" echo "[INFO] creating setup URI from settings"
SETUP_URI="$( SETUP_URI="$(
@@ -57,7 +56,7 @@ mkdir -p "$VAULT_DIR/test"
echo "[INFO] applying setup URI" echo "[INFO] applying setup URI"
SETUP_LOG="$WORK_DIR/setup-output.log" SETUP_LOG="$WORK_DIR/setup-output.log"
set +e set +e
printf '%s\n' "$SETUP_PASSPHRASE" | node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" setup "$SETUP_URI" \ printf '%s\n' "$SETUP_PASSPHRASE" | run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" setup "$SETUP_URI" \
>"$SETUP_LOG" 2>&1 >"$SETUP_LOG" 2>&1
SETUP_EXIT=$? SETUP_EXIT=$?
set -e set -e
@@ -78,11 +77,11 @@ SRC_FILE="$WORK_DIR/put-source.txt"
printf 'setup-put-cat-test %s\nline-2\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$SRC_FILE" printf 'setup-put-cat-test %s\nline-2\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$SRC_FILE"
echo "[INFO] put -> $REMOTE_PATH" echo "[INFO] put -> $REMOTE_PATH"
cat "$SRC_FILE" | node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REMOTE_PATH" cat "$SRC_FILE" | run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REMOTE_PATH"
echo "[INFO] cat <- $REMOTE_PATH" echo "[INFO] cat <- $REMOTE_PATH"
CAT_OUTPUT="$WORK_DIR/cat-output.txt" CAT_OUTPUT="$WORK_DIR/cat-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" cat "$REMOTE_PATH" > "$CAT_OUTPUT" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" cat "$REMOTE_PATH" > "$CAT_OUTPUT"
CAT_OUTPUT_CLEAN="$WORK_DIR/cat-output-clean.txt" CAT_OUTPUT_CLEAN="$WORK_DIR/cat-output-clean.txt"
grep -v '^\[CLIWatchAdapter\] File watching is not enabled in CLI version$' "$CAT_OUTPUT" > "$CAT_OUTPUT_CLEAN" || true grep -v '^\[CLIWatchAdapter\] File watching is not enabled in CLI version$' "$CAT_OUTPUT" > "$CAT_OUTPUT_CLEAN" || true
@@ -100,7 +99,7 @@ fi
echo "[INFO] ls $REMOTE_PATH" echo "[INFO] ls $REMOTE_PATH"
LS_OUTPUT="$WORK_DIR/ls-output.txt" LS_OUTPUT="$WORK_DIR/ls-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" ls "$REMOTE_PATH" > "$LS_OUTPUT" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" ls "$REMOTE_PATH" > "$LS_OUTPUT"
LS_LINE="$(grep -F "$REMOTE_PATH" "$LS_OUTPUT" | head -n 1 || true)" LS_LINE="$(grep -F "$REMOTE_PATH" "$LS_OUTPUT" | head -n 1 || true)"
if [[ -z "$LS_LINE" ]]; then if [[ -z "$LS_LINE" ]]; then
@@ -129,12 +128,12 @@ fi
echo "[PASS] ls output format matched" echo "[PASS] ls output format matched"
echo "[INFO] adding more files for ls test cases" echo "[INFO] adding more files for ls test cases"
printf 'file-a\n' | node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" put test/a-first.txt >/dev/null printf 'file-a\n' | run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" put test/a-first.txt >/dev/null
printf 'file-z\n' | node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" put test/z-last.txt >/dev/null printf 'file-z\n' | run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" put test/z-last.txt >/dev/null
echo "[INFO] ls test/ (prefix filter and sorting)" echo "[INFO] ls test/ (prefix filter and sorting)"
LS_PREFIX_OUTPUT="$WORK_DIR/ls-prefix-output.txt" LS_PREFIX_OUTPUT="$WORK_DIR/ls-prefix-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" ls test/ > "$LS_PREFIX_OUTPUT" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" ls test/ > "$LS_PREFIX_OUTPUT"
if [[ "$(wc -l < "$LS_PREFIX_OUTPUT")" -lt 3 ]]; then if [[ "$(wc -l < "$LS_PREFIX_OUTPUT")" -lt 3 ]]; then
echo "[FAIL] ls prefix output expected at least 3 rows" >&2 echo "[FAIL] ls prefix output expected at least 3 rows" >&2
@@ -164,7 +163,7 @@ echo "[PASS] ls prefix and sorting matched"
echo "[INFO] ls no-match prefix" echo "[INFO] ls no-match prefix"
LS_EMPTY_OUTPUT="$WORK_DIR/ls-empty-output.txt" LS_EMPTY_OUTPUT="$WORK_DIR/ls-empty-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" ls no-such-prefix/ > "$LS_EMPTY_OUTPUT" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" ls no-such-prefix/ > "$LS_EMPTY_OUTPUT"
if [[ -s "$LS_EMPTY_OUTPUT" ]]; then if [[ -s "$LS_EMPTY_OUTPUT" ]]; then
echo "[FAIL] ls no-match prefix should produce empty output" >&2 echo "[FAIL] ls no-match prefix should produce empty output" >&2
cat "$LS_EMPTY_OUTPUT" >&2 cat "$LS_EMPTY_OUTPUT" >&2
@@ -174,7 +173,7 @@ echo "[PASS] ls no-match prefix matched"
echo "[INFO] info $REMOTE_PATH" echo "[INFO] info $REMOTE_PATH"
INFO_OUTPUT="$WORK_DIR/info-output.txt" INFO_OUTPUT="$WORK_DIR/info-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" info "$REMOTE_PATH" > "$INFO_OUTPUT" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" info "$REMOTE_PATH" > "$INFO_OUTPUT"
# Check required label lines # Check required label lines
for label in "ID:" "Revision:" "Conflicts:" "Filename:" "Path:" "Size:" "Chunks:"; do for label in "ID:" "Revision:" "Conflicts:" "Filename:" "Path:" "Size:" "Chunks:"; do
@@ -225,7 +224,7 @@ echo "[PASS] info output format matched"
echo "[INFO] info non-existent path" echo "[INFO] info non-existent path"
INFO_MISSING_EXIT=0 INFO_MISSING_EXIT=0
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" info no-such-file.md > /dev/null || INFO_MISSING_EXIT=$? run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" info no-such-file.md > /dev/null || INFO_MISSING_EXIT=$?
if [[ "$INFO_MISSING_EXIT" -eq 0 ]]; then if [[ "$INFO_MISSING_EXIT" -eq 0 ]]; then
echo "[FAIL] info on non-existent file should exit non-zero" >&2 echo "[FAIL] info on non-existent file should exit non-zero" >&2
exit 1 exit 1
@@ -233,17 +232,17 @@ fi
echo "[PASS] info non-existent path returns non-zero" echo "[PASS] info non-existent path returns non-zero"
echo "[INFO] rm test/z-last.txt" echo "[INFO] rm test/z-last.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" rm test/z-last.txt > /dev/null run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" rm test/z-last.txt > /dev/null
RM_CAT_EXIT=0 RM_CAT_EXIT=0
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" cat test/z-last.txt > /dev/null || RM_CAT_EXIT=$? run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" cat test/z-last.txt > /dev/null || RM_CAT_EXIT=$?
if [[ "$RM_CAT_EXIT" -eq 0 ]]; then if [[ "$RM_CAT_EXIT" -eq 0 ]]; then
echo "[FAIL] rm target should not be readable by cat" >&2 echo "[FAIL] rm target should not be readable by cat" >&2
exit 1 exit 1
fi fi
LS_AFTER_RM="$WORK_DIR/ls-after-rm.txt" LS_AFTER_RM="$WORK_DIR/ls-after-rm.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" ls test/ > "$LS_AFTER_RM" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" ls test/ > "$LS_AFTER_RM"
if grep -Fq $'test/z-last.txt\t' "$LS_AFTER_RM"; then if grep -Fq $'test/z-last.txt\t' "$LS_AFTER_RM"; then
echo "[FAIL] rm target should not appear in ls output" >&2 echo "[FAIL] rm target should not appear in ls output" >&2
cat "$LS_AFTER_RM" >&2 cat "$LS_AFTER_RM" >&2
@@ -252,7 +251,7 @@ fi
echo "[PASS] rm removed target from visible entries" echo "[PASS] rm removed target from visible entries"
echo "[INFO] resolve test/a-first.txt using current revision" echo "[INFO] resolve test/a-first.txt using current revision"
RESOLVE_LS_LINE="$(node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" ls test/a-first.txt | head -n 1)" RESOLVE_LS_LINE="$(run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" ls test/a-first.txt | head -n 1)"
if [[ -z "$RESOLVE_LS_LINE" ]]; then if [[ -z "$RESOLVE_LS_LINE" ]]; then
echo "[FAIL] could not fetch revision for resolve test" >&2 echo "[FAIL] could not fetch revision for resolve test" >&2
exit 1 exit 1
@@ -263,12 +262,12 @@ if [[ -z "$RESOLVE_REV" ]]; then
exit 1 exit 1
fi fi
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" resolve test/a-first.txt "$RESOLVE_REV" > /dev/null run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" resolve test/a-first.txt "$RESOLVE_REV" > /dev/null
echo "[PASS] resolve accepted current revision" echo "[PASS] resolve accepted current revision"
echo "[INFO] resolve with non-existent revision" echo "[INFO] resolve with non-existent revision"
RESOLVE_BAD_EXIT=0 RESOLVE_BAD_EXIT=0
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" resolve test/a-first.txt 9-no-such-rev > /dev/null || RESOLVE_BAD_EXIT=$? run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" resolve test/a-first.txt 9-no-such-rev > /dev/null || RESOLVE_BAD_EXIT=$?
if [[ "$RESOLVE_BAD_EXIT" -eq 0 ]]; then if [[ "$RESOLVE_BAD_EXIT" -eq 0 ]]; then
echo "[FAIL] resolve with non-existent revision should exit non-zero" >&2 echo "[FAIL] resolve with non-existent revision should exit non-zero" >&2
exit 1 exit 1
@@ -285,13 +284,13 @@ printf 'revision-v1\n' > "$REV_V1_FILE"
printf 'revision-v2\n' > "$REV_V2_FILE" printf 'revision-v2\n' > "$REV_V2_FILE"
printf 'revision-v3\n' > "$REV_V3_FILE" printf 'revision-v3\n' > "$REV_V3_FILE"
cat "$REV_V1_FILE" | node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REV_PATH" > /dev/null cat "$REV_V1_FILE" | run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REV_PATH" > /dev/null
cat "$REV_V2_FILE" | node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REV_PATH" > /dev/null cat "$REV_V2_FILE" | run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REV_PATH" > /dev/null
cat "$REV_V3_FILE" | node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REV_PATH" > /dev/null cat "$REV_V3_FILE" | run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" put "$REV_PATH" > /dev/null
echo "[INFO] info $REV_PATH (past revisions)" echo "[INFO] info $REV_PATH (past revisions)"
REV_INFO_OUTPUT="$WORK_DIR/rev-info-output.txt" REV_INFO_OUTPUT="$WORK_DIR/rev-info-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" info "$REV_PATH" > "$REV_INFO_OUTPUT" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" info "$REV_PATH" > "$REV_INFO_OUTPUT"
PAST_REV="$(grep '^ rev: ' "$REV_INFO_OUTPUT" | head -n 1 | sed 's/^ rev: //')" PAST_REV="$(grep '^ rev: ' "$REV_INFO_OUTPUT" | head -n 1 | sed 's/^ rev: //')"
if [[ -z "$PAST_REV" ]]; then if [[ -z "$PAST_REV" ]]; then
@@ -302,7 +301,7 @@ fi
echo "[INFO] cat-rev $REV_PATH @ $PAST_REV" echo "[INFO] cat-rev $REV_PATH @ $PAST_REV"
REV_CAT_OUTPUT="$WORK_DIR/rev-cat-output.txt" REV_CAT_OUTPUT="$WORK_DIR/rev-cat-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" cat-rev "$REV_PATH" "$PAST_REV" > "$REV_CAT_OUTPUT" run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" cat-rev "$REV_PATH" "$PAST_REV" > "$REV_CAT_OUTPUT"
if cmp -s "$REV_CAT_OUTPUT" "$REV_V1_FILE" || cmp -s "$REV_CAT_OUTPUT" "$REV_V2_FILE"; then if cmp -s "$REV_CAT_OUTPUT" "$REV_V1_FILE" || cmp -s "$REV_CAT_OUTPUT" "$REV_V2_FILE"; then
echo "[PASS] cat-rev matched one of the past revisions from info" echo "[PASS] cat-rev matched one of the past revisions from info"
@@ -321,7 +320,7 @@ fi
echo "[INFO] pull-rev $REV_PATH @ $PAST_REV" echo "[INFO] pull-rev $REV_PATH @ $PAST_REV"
REV_PULL_OUTPUT="$WORK_DIR/rev-pull-output.txt" REV_PULL_OUTPUT="$WORK_DIR/rev-pull-output.txt"
node "$CLI_ENTRY" "$VAULT_DIR" --settings "$SETTINGS_FILE" pull-rev "$REV_PATH" "$REV_PULL_OUTPUT" "$PAST_REV" > /dev/null run_cli "$VAULT_DIR" --settings "$SETTINGS_FILE" pull-rev "$REV_PATH" "$REV_PULL_OUTPUT" "$PAST_REV" > /dev/null
if cmp -s "$REV_PULL_OUTPUT" "$REV_V1_FILE" || cmp -s "$REV_PULL_OUTPUT" "$REV_V2_FILE"; then if cmp -s "$REV_PULL_OUTPUT" "$REV_V1_FILE" || cmp -s "$REV_PULL_OUTPUT" "$REV_V2_FILE"; then
echo "[PASS] pull-rev matched one of the past revisions from info" echo "[PASS] pull-rev matched one of the past revisions from info"
@@ -6,7 +6,7 @@ SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
CLI_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)" CLI_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
cd "$CLI_DIR" cd "$CLI_DIR"
CLI_ENTRY="${CLI_ENTRY:-$CLI_DIR/dist/index.cjs}" CLI_CMD=(npm run cli --)
RUN_BUILD="${RUN_BUILD:-1}" RUN_BUILD="${RUN_BUILD:-1}"
COUCHDB_URI="${COUCHDB_URI:-}" COUCHDB_URI="${COUCHDB_URI:-}"
COUCHDB_USER="${COUCHDB_USER:-}" COUCHDB_USER="${COUCHDB_USER:-}"
@@ -26,10 +26,9 @@ if [[ "$RUN_BUILD" == "1" ]]; then
npm run build npm run build
fi fi
if [[ ! -f "$CLI_ENTRY" ]]; then run_cli() {
echo "[ERROR] CLI entry not found: $CLI_ENTRY" >&2 "${CLI_CMD[@]}" "$@"
exit 1 }
fi
DB_SUFFIX="$(date +%s)-$RANDOM" DB_SUFFIX="$(date +%s)-$RANDOM"
COUCHDB_DBNAME="${COUCHDB_DBNAME_BASE}-${DB_SUFFIX}" COUCHDB_DBNAME="${COUCHDB_DBNAME_BASE}-${DB_SUFFIX}"
@@ -42,8 +41,8 @@ SETTINGS_A="$WORK_DIR/a-settings.json"
SETTINGS_B="$WORK_DIR/b-settings.json" SETTINGS_B="$WORK_DIR/b-settings.json"
mkdir -p "$VAULT_A" "$VAULT_B" mkdir -p "$VAULT_A" "$VAULT_B"
node "$CLI_ENTRY" init-settings --force "$SETTINGS_A" >/dev/null run_cli init-settings --force "$SETTINGS_A" >/dev/null
node "$CLI_ENTRY" init-settings --force "$SETTINGS_B" >/dev/null run_cli init-settings --force "$SETTINGS_B" >/dev/null
apply_settings() { apply_settings() {
local settings_file="$1" local settings_file="$1"
@@ -73,11 +72,11 @@ apply_settings "$SETTINGS_A"
apply_settings "$SETTINGS_B" apply_settings "$SETTINGS_B"
run_cli_a() { run_cli_a() {
node "$CLI_ENTRY" "$VAULT_A" --settings "$SETTINGS_A" "$@" run_cli "$VAULT_A" --settings "$SETTINGS_A" "$@"
} }
run_cli_b() { run_cli_b() {
node "$CLI_ENTRY" "$VAULT_B" --settings "$SETTINGS_B" "$@" run_cli "$VAULT_B" --settings "$SETTINGS_B" "$@"
} }
sync_a() { sync_a() {
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
set -euo pipefail
if [[ -z "${hostname:-}" ]]; then
echo "ERROR: Hostname missing"
exit 1
fi
if [[ -z "${username:-}" ]]; then
echo "ERROR: Username missing"
exit 1
fi
if [[ -z "${password:-}" ]]; then
echo "ERROR: Password missing"
exit 1
fi
if [[ -z "${node:-}" ]]; then
echo "INFO: defaulting to _local"
node=_local
fi
hostname="${hostname%/}"
# Podman environments often resolve localhost to ::1 while published ports are IPv4-only.
hostname="${hostname/localhost/127.0.0.1}"
curl_json() {
curl -4 -sS --fail --connect-timeout 3 --max-time 15 "$@"
}
echo "-- Configuring CouchDB by REST APIs... -->"
echo " Hostname: $hostname"
echo " Username: $username"
until (curl_json -X POST "${hostname}/_cluster_setup" -H "Content-Type: application/json" -d "{\"action\":\"enable_single_node\",\"username\":\"${username}\",\"password\":\"${password}\",\"bind_address\":\"0.0.0.0\",\"port\":5984,\"singlenode\":true}" --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/chttpd/require_valid_user" -H "Content-Type: application/json" -d '"true"' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/chttpd_auth/require_valid_user" -H "Content-Type: application/json" -d '"true"' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/httpd/WWW-Authenticate" -H "Content-Type: application/json" -d '"Basic realm=\"couchdb\""' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/httpd/enable_cors" -H "Content-Type: application/json" -d '"true"' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/chttpd/enable_cors" -H "Content-Type: application/json" -d '"true"' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/chttpd/max_http_request_size" -H "Content-Type: application/json" -d '"4294967296"' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/couchdb/max_document_size" -H "Content-Type: application/json" -d '"50000000"' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/cors/credentials" -H "Content-Type: application/json" -d '"true"' --user "${username}:${password}"); do sleep 5; done
until (curl_json -X PUT "${hostname}/_node/${node}/_config/cors/origins" -H "Content-Type: application/json" -d '"*"' --user "${username}:${password}"); do sleep 5; done
# Create test database
until (curl_json -X PUT --user "${username}:${password}" "${hostname}/${dbname}" >/dev/null); do sleep 5; done
echo "<-- Configuring CouchDB by REST APIs Done!"
+4
View File
@@ -0,0 +1,4 @@
#!/bin/bash
set -e
echo "username: $username"
docker run -d --name couchdb-test -p 5989:5984 -e COUCHDB_USER=$username -e COUCHDB_PASSWORD=$password -e COUCHDB_SINGLE_NODE=y couchdb:3.5.0
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
docker stop couchdb-test
docker rm couchdb-test
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
set -e
cat >/tmp/mybucket-rw.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetBucketLocation","s3:ListBucket"],
"Resource": ["arn:aws:s3:::$bucketName"]
},
{
"Effect": "Allow",
"Action": ["s3:GetObject","s3:PutObject","s3:DeleteObject"],
"Resource": ["arn:aws:s3:::$bucketName/*"]
}
]
}
EOF
# echo "<CORSConfiguration>
# <CORSRule>
# <AllowedOrigin>http://localhost:63315</AllowedOrigin>
# <AllowedOrigin>http://localhost:63316</AllowedOrigin>
# <AllowedOrigin>http://localhost</AllowedOrigin>
# <AllowedMethod>GET</AllowedMethod>
# <AllowedMethod>PUT</AllowedMethod>
# <AllowedMethod>POST</AllowedMethod>
# <AllowedMethod>DELETE</AllowedMethod>
# <AllowedMethod>HEAD</AllowedMethod>
# <AllowedHeader>*</AllowedHeader>
# </CORSRule>
# </CORSConfiguration>" > /tmp/cors.xml
# docker run --rm --network host -v /tmp/mybucket-rw.json:/tmp/mybucket-rw.json --entrypoint=/bin/sh minio/mc -c "
# mc alias set myminio $minioEndpoint $username $password
# mc mb --ignore-existing myminio/$bucketName
# mc admin policy create myminio my-custom-policy /tmp/mybucket-rw.json
# echo 'Creating service account for user $username with access key $accessKey'
# mc admin user svcacct add --access-key '$accessKey' --secret-key '$secretKey' myminio '$username'
# mc admin policy attach myminio my-custom-policy --user '$accessKey'
# echo 'Verifying policy and user creation:'
# mc admin user svcacct info myminio '$accessKey'
# "
docker run --rm --network host -v /tmp/mybucket-rw.json:/tmp/mybucket-rw.json --entrypoint=/bin/sh minio/mc -c "
mc alias set myminio $minioEndpoint $accessKey $secretKey
mc mb --ignore-existing myminio/$bucketName
"
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
docker run -d --name minio-test -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=$accessKey -e MINIO_ROOT_PASSWORD=$secretKey -e MINIO_SERVER_URL=$minioEndpoint minio/minio server /data --console-address ':9001'
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
docker stop minio-test
docker rm minio-test
+1 -1
Submodule src/lib updated: 3ce1f81a21...41e2340235