From 5907033daac882b7cad89b9eef9ef3336e8c6b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?He=CC=84sperus?= Date: Mon, 24 Aug 2026 12:29:32 +0800 Subject: [PATCH 1/2] refactor(various): improve codebase hygiene --- AGENTS.md | 2 +- bun.lock | 52 +- docs/.vitepress/i18n.ts | 2 +- docs/package.json | 1 - docs/src/pages/en/deep-dive/architecture.md | 2 +- .../src/pages/en/development/miscellaneous.md | 6 +- docs/src/pages/en/development/registration.md | 4 +- .../pages/en/development/settings-and-ui.md | 2 +- package.json | 2 +- packages/gdrive/package.json | 1 - packages/gdrive/test/auth.test.ts | 2 +- packages/gdrive/test/mocks.ts | 3 +- packages/plugin/dist/dev.spec.d.ts | 97 --- packages/plugin/dist/index-LOl_cerr.spec.d.ts | 558 ------------ packages/plugin/dist/index.spec.d.ts | 797 ------------------ packages/plugin/src/fs/vault/request.ts | 3 +- packages/plugin/src/global.css | 7 +- packages/plugin/src/modules/Extensibility.ts | 21 +- packages/plugin/src/settings/development.ts | 4 +- packages/plugin/src/settings/filter.ts | 4 +- packages/plugin/src/settings/miscellaneous.ts | 3 +- packages/plugin/src/settings/utils.ts | 1 + packages/plugin/src/types.ts | 5 +- packages/plugin/test/e2e-utils.ts | 22 - packages/plugin/test/mocks.ts | 3 +- packages/plugin/tsdown.config.ts | 2 +- packages/s3/test/mocks.ts | 3 +- packages/shared/package.json | 2 +- packages/shared/src/binary.ts | 2 +- packages/shared/src/e2e-utils.spec.ts | 11 + .../src/{mocks.ts => obsidian-mock.spec.ts} | 7 +- packages/shared/src/obsidian-mock.ts | 4 + packages/smart-merge/test/mocks.ts | 3 +- packages/webdav/test/mocks.ts | 2 +- 34 files changed, 70 insertions(+), 1570 deletions(-) delete mode 100644 packages/plugin/dist/dev.spec.d.ts delete mode 100644 packages/plugin/dist/index-LOl_cerr.spec.d.ts delete mode 100644 packages/plugin/dist/index.spec.d.ts delete mode 100644 packages/plugin/test/e2e-utils.ts create mode 100644 packages/shared/src/e2e-utils.spec.ts rename packages/shared/src/{mocks.ts => obsidian-mock.spec.ts} (82%) create mode 100644 packages/shared/src/obsidian-mock.ts diff --git a/AGENTS.md b/AGENTS.md index 2efc8d73..ad04a134 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,7 +48,7 @@ This is the monorepo for an extensible Obsidian syncing plugin to sync vault fil - For mobile compatibility, Node.js API prohibited. - Sentence case for UI text. - Module-specific behavior should not pollute plugin core. -- All Obsidian API mocks go `packages/shared/src/obsidian-mock.ts`. +- All Obsidian API mocks go `packages/shared/test/obsidian-mock.ts`. - Use inline Tailwind CSS for common styling, only use semantic CSS for animations and complex compositions. (Documentation website doesn't use TailwindCSS, you need to edit `docs/.vitepress/theme/styles.css`) - When any function or class needs to use `Context` as argument, prefer structural typing instead of direct `Context`. - Excluding main plugin, shared utils and documentation site, all packages are Sync Engine modules, they use the SDK and follow unified module structure. diff --git a/bun.lock b/bun.lock index 257cc31e..749562f5 100644 --- a/bun.lock +++ b/bun.lock @@ -14,7 +14,7 @@ "oxlint-tsgolint": "^7.0.2001", "tsdown": "^0.22.14", "turbo": "^2.10.11", - "typescript": "^7.0.2", + "typescript": "^6.0.3", }, }, "docs": { @@ -27,7 +27,6 @@ "vue": "^3.5.41", }, "devDependencies": { - "typescript": "^6.0.0", "vite-plugin-json-canvas": "^1.0.1", "vue-tsc": "^3.3.9", }, @@ -49,7 +48,6 @@ "devDependencies": { "@hesprs/sync-engine-sdk": "workspace:*", "@repo/shared": "workspace:*", - "hash-wasm": "^4.12.0", "uni-kv": "../../uni-kv.tgz", }, }, @@ -62,7 +60,7 @@ }, "packages/plugin": { "name": "@hesprs/sync-engine-sdk", - "version": "3.1.0", + "version": "3.1.1", "dependencies": { "obsidian": "^1.13.1", }, @@ -429,46 +427,6 @@ "@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="], - "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], - - "@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="], - - "@typescript/typescript-darwin-x64": ["@typescript/typescript-darwin-x64@7.0.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA=="], - - "@typescript/typescript-freebsd-arm64": ["@typescript/typescript-freebsd-arm64@7.0.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ=="], - - "@typescript/typescript-freebsd-x64": ["@typescript/typescript-freebsd-x64@7.0.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw=="], - - "@typescript/typescript-linux-arm": ["@typescript/typescript-linux-arm@7.0.2", "", { "os": "linux", "cpu": "arm" }, "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ=="], - - "@typescript/typescript-linux-arm64": ["@typescript/typescript-linux-arm64@7.0.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ=="], - - "@typescript/typescript-linux-loong64": ["@typescript/typescript-linux-loong64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ=="], - - "@typescript/typescript-linux-mips64el": ["@typescript/typescript-linux-mips64el@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA=="], - - "@typescript/typescript-linux-ppc64": ["@typescript/typescript-linux-ppc64@7.0.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA=="], - - "@typescript/typescript-linux-riscv64": ["@typescript/typescript-linux-riscv64@7.0.2", "", { "os": "linux", "cpu": "none" }, "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ=="], - - "@typescript/typescript-linux-s390x": ["@typescript/typescript-linux-s390x@7.0.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw=="], - - "@typescript/typescript-linux-x64": ["@typescript/typescript-linux-x64@7.0.2", "", { "os": "linux", "cpu": "x64" }, "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A=="], - - "@typescript/typescript-netbsd-arm64": ["@typescript/typescript-netbsd-arm64@7.0.2", "", { "os": "none", "cpu": "arm64" }, "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA=="], - - "@typescript/typescript-netbsd-x64": ["@typescript/typescript-netbsd-x64@7.0.2", "", { "os": "none", "cpu": "x64" }, "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA=="], - - "@typescript/typescript-openbsd-arm64": ["@typescript/typescript-openbsd-arm64@7.0.2", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ=="], - - "@typescript/typescript-openbsd-x64": ["@typescript/typescript-openbsd-x64@7.0.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg=="], - - "@typescript/typescript-sunos-x64": ["@typescript/typescript-sunos-x64@7.0.2", "", { "os": "sunos", "cpu": "x64" }, "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g=="], - - "@typescript/typescript-win32-arm64": ["@typescript/typescript-win32-arm64@7.0.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ=="], - - "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], - "@ungap/structured-clone": ["@ungap/structured-clone@1.3.3", "", {}, "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg=="], "@unocss/cli": ["@unocss/cli@66.7.5", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "@unocss/config": "66.7.5", "@unocss/core": "66.7.5", "@unocss/preset-wind3": "66.7.5", "@unocss/preset-wind4": "66.7.5", "@unocss/transformer-directives": "66.7.5", "cac": "^7.0.0", "chokidar": "^5.0.0", "colorette": "^2.0.20", "consola": "^3.4.2", "magic-string": "^0.30.21", "pathe": "^2.0.3", "perfect-debounce": "^2.1.0", "tinyglobby": "^0.2.17", "unplugin-utils": "^0.3.1" }, "bin": { "unocss": "./bin/unocss.mjs" } }, "sha512-fgWkECRn2LGVo9sEpmjk/KJ3NSKUDitaZCNrJcEYM93DG+ELriTHcL+VWBlF4rcZf9fdGlq1nKbbRHUZirFCHQ=="], @@ -923,7 +881,7 @@ "type-level-regexp": ["type-level-regexp@0.1.17", "", {}, "sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg=="], - "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], "ufo": ["ufo@1.6.4", "", {}, "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA=="], @@ -1003,8 +961,6 @@ "caniuse-api/browserslist": ["browserslist@4.28.7", "", { "dependencies": { "baseline-browser-mapping": "^2.10.44", "caniuse-lite": "^1.0.30001806", "electron-to-chromium": "^1.5.393", "node-releases": "^2.0.51", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw=="], - "docs/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], - "json-canvas-viewer/marked": ["marked@18.0.9", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-/Sa4qiiHZxf0/FQdBBowr9q4r10krCwMvpK48FUBdXdUXScDxiQGR9zCPrFgRVR5LU3iySOiIjy09ZQvADir1w=="], "magic-regexp/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], @@ -1015,8 +971,6 @@ "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - "synthkernel/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], - "vitepress-theme-trito/vitepress": ["vitepress@2.0.0-alpha.18", "", { "dependencies": { "@docsearch/css": "^4.6.3", "@docsearch/js": "^4.6.3", "@docsearch/sidepanel-js": "^4.6.3", "@iconify-json/simple-icons": "^1.2.87", "@shikijs/core": "^4.3.0", "@shikijs/transformers": "^4.3.0", "@shikijs/types": "^4.3.0", "@types/markdown-it": "^14.1.2", "@vitejs/plugin-vue": "^6.0.7", "@vue/devtools-api": "^8.1.4", "@vue/shared": "^3.5.39", "@vueuse/core": "^14.3.0", "@vueuse/integrations": "^14.3.0", "focus-trap": "^8.2.2", "mark.js": "8.11.1", "minisearch": "^7.2.0", "shiki": "^4.3.0", "vite": "^8.1.3", "vue": "^3.5.39" }, "peerDependencies": { "markdown-it-mathjax3": "^4", "postcss": "^8" }, "optionalPeers": ["markdown-it-mathjax3", "postcss"], "bin": { "vitepress": "bin/vitepress.js" } }, "sha512-Lk1G2/QqSf+MwNLICl9fmzWOtoCEwjZoWgaQy41QvWTfcGpLE9XwJDbcCyES/9rj6R2g1zFqFvLVkYKLLDALFw=="], } } diff --git a/docs/.vitepress/i18n.ts b/docs/.vitepress/i18n.ts index c174214d..59129d84 100644 --- a/docs/.vitepress/i18n.ts +++ b/docs/.vitepress/i18n.ts @@ -39,7 +39,7 @@ const en = { s3: 'S3', security: 'Security', settings: 'Settings', - settingsAndUI: 'Settings And UI', + settingsAndUI: 'Settings and UI', sideDescription: 'Next-generation syncing plugin for Obsidian.', smartMerge: 'Smart Merge', storage: 'Storage', diff --git a/docs/package.json b/docs/package.json index ecbe168e..64b17eec 100644 --- a/docs/package.json +++ b/docs/package.json @@ -17,7 +17,6 @@ "vue": "^3.5.41" }, "devDependencies": { - "typescript": "^6.0.0", "vite-plugin-json-canvas": "^1.0.1", "vue-tsc": "^3.3.9" } diff --git a/docs/src/pages/en/deep-dive/architecture.md b/docs/src/pages/en/deep-dive/architecture.md index f465f1e3..60dad926 100644 --- a/docs/src/pages/en/deep-dive/architecture.md +++ b/docs/src/pages/en/deep-dive/architecture.md @@ -89,7 +89,7 @@ Registration entries are consumed according to their role: - **Factories and ID maps:** the selected remote backend, decider, and conflict resolver are looked up by the ID in settings. Missing IDs fail with an explicit error. - **Wrappers:** request and file-system wrappers are grouped by numeric priority and applied in ascending priority order. Within one priority, the first wrapper that returns a replacement wins; returning `undefined` declines the current value. - **First-match pipelines:** listers and optimizers are also priority ordered. The first entry that returns a result supplies the implementation for that operation. -- **Settings:** setting-definition trees are ordered by priority and merged into the native plugin settings tab. See [Settings And UI](../development/settings-and-ui). +- **Settings:** setting-definition trees are ordered by priority and merged into the native plugin settings tab. See [Settings and UI](../development/settings-and-ui). Bootstrap uses these same APIs to build the production pipeline. For example, cancellation, rate limiting, retry, custom headers, memory control, optimization, context caching, and asymmetric storage are independent registrations layered around the base request and file-system implementations. Their behavior is specified in [Request Middleware](./request-middleware) and [File System Wrappers](./file-system-wrappers). diff --git a/docs/src/pages/en/development/miscellaneous.md b/docs/src/pages/en/development/miscellaneous.md index c6dbce16..31ab3f9a 100644 --- a/docs/src/pages/en/development/miscellaneous.md +++ b/docs/src/pages/en/development/miscellaneous.md @@ -8,11 +8,11 @@ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | | `digOriginal` | Unwraps nested wrappers to root filesystem. See [file system](./file-system#digoriginal). | | `prefixWrapper` | Exposes a prefixed directory as an `Fs` root. See [file system](./file-system#prefixwrapper). | -| `setNeedMigration` | Adds migration confirmation behavior to a setting toggle; see [Settings And UI](./settings-and-ui#migration-aware-toggles). | +| `setNeedMigration` | Adds migration confirmation behavior to a setting toggle; see [Settings and UI](./settings-and-ui#migration-aware-toggles). | | `pipe` | Transfer a file between two filesystems with auto-streaming. See [file system](./file-system#pipe). | | `readWithSize` | Read a file with auto-streaming by size threshold. See [file system](./file-system#readwithsize). | | `writeWithValue` | Write a value with auto-streaming by input type. See [file system](./file-system#writewithvalue). | -| `s` | Combines a parent setting definition with nested setting definitions. See [Settings And UI](./settings-and-ui#nested-setting-registration). | +| `s` | Combines a parent setting definition with nested setting definitions. See [Settings and UI](./settings-and-ui#nested-setting-registration). | ### `/dev` runtime exports @@ -145,7 +145,7 @@ These Context members are not commonly used by modules. Explore source code to o | `on(key, cb)` | Subscribes to typed SDK event. See [events](./events). | | `dispatch(key, payload?)` | Dispatches typed SDK event. See [events](./events). | | `isIdle` | SynthKernel `Ref` for sync-idle state. | -| `translate` | Translates a key from merged resources. See [Settings And UI](./settings-and-ui#internationalization). | +| `translate` | Translates a key from merged resources. See [Settings and UI](./settings-and-ui#internationalization). | | `rerenderSettingTab()` | Renders contributed settings again. | | `refreshSettingTab()` | Cheap setting page rerender that makes Obsidian reevaluate the visibility of each setting entry. | diff --git a/docs/src/pages/en/development/registration.md b/docs/src/pages/en/development/registration.md index 9658995c..c3b48c44 100644 --- a/docs/src/pages/en/development/registration.md +++ b/docs/src/pages/en/development/registration.md @@ -126,9 +126,9 @@ type ConflictResolverEntry = { prettyName: () => string; resolver: ConflictResol ctx.registerConflictResolver(id: string, entry: ConflictResolverEntry): () => boolean; ``` -## Settings And UI +## Settings and UI -Register nested setting definitions, translations, and migration-aware controls as described in [Settings And UI](./settings-and-ui). +Register nested setting definitions, translations, and migration-aware controls as described in [Settings and UI](./settings-and-ui). ## CSS diff --git a/docs/src/pages/en/development/settings-and-ui.md b/docs/src/pages/en/development/settings-and-ui.md index 2d159e5e..20a9d51b 100644 --- a/docs/src/pages/en/development/settings-and-ui.md +++ b/docs/src/pages/en/development/settings-and-ui.md @@ -1,4 +1,4 @@ -# Settings And UI +# Settings and UI Sync Engine settings use Obsidian's setting definitions. Modules can contribute nested groups, pages, lists, controls, and custom rendered settings without owning the plugin settings tab. This page also covers the translation and migration helpers used by module UI. diff --git a/package.json b/package.json index e34a364e..98e8edbd 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "oxlint-tsgolint": "^7.0.2001", "tsdown": "^0.22.14", "turbo": "^2.10.11", - "typescript": "^7.0.2" + "typescript": "^6.0.3" }, "packageManager": "bun@1.3.13" } diff --git a/packages/gdrive/package.json b/packages/gdrive/package.json index c3e4a1bf..2dbd9de0 100644 --- a/packages/gdrive/package.json +++ b/packages/gdrive/package.json @@ -25,7 +25,6 @@ "devDependencies": { "@hesprs/sync-engine-sdk": "workspace:*", "@repo/shared": "workspace:*", - "hash-wasm": "^4.12.0", "uni-kv": "../../uni-kv.tgz" } } diff --git a/packages/gdrive/test/auth.test.ts b/packages/gdrive/test/auth.test.ts index dc9fb052..1ea050cc 100644 --- a/packages/gdrive/test/auth.test.ts +++ b/packages/gdrive/test/auth.test.ts @@ -1,6 +1,6 @@ import type { Request, RequestParam, RequestResponse } from '@hesprs/sync-engine-sdk'; import type { SecretStorage } from 'obsidian'; -import * as ObsidianMock from '@repo/shared/mocks'; +import ObsidianMock from '@repo/shared/obsidian-mock'; import { expect, mock, test } from 'bun:test'; type HttpResponse = { json: unknown; status?: number }; diff --git a/packages/gdrive/test/mocks.ts b/packages/gdrive/test/mocks.ts index 45f6b609..7e8474f7 100644 --- a/packages/gdrive/test/mocks.ts +++ b/packages/gdrive/test/mocks.ts @@ -1,5 +1,4 @@ -// oxlint-disable-next-line import/no-namespace -import * as ObsidianMock from '@repo/shared/mocks'; +import ObsidianMock from '@repo/shared/obsidian-mock'; import { mock } from 'bun:test'; process.env.CLIENT_ID = btoa(process.env.GDRIVE_CLIENT_ID ?? ''); diff --git a/packages/plugin/dist/dev.spec.d.ts b/packages/plugin/dist/dev.spec.d.ts deleted file mode 100644 index 59aad76c..00000000 --- a/packages/plugin/dist/dev.spec.d.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { $ as RootFs, G as Fs, P as TaskNames, ct as RecordStat, dt as StatsMap, et as WrappedFs, h as RequestParam, it as FolderStat, lt as RecordStatsMap, m as Request, nt as Binary, rt as FileStat, ut as Stat, v as Decider } from "./index-LOl_cerr.spec.js"; -//#region src/sdk/debug-wrapper.d.ts -declare function debugWrapper(original: Fs, log: (content: string) => void): WrappedFs; -//#endregion -//#region test/test-kit.d.ts -type FsCalls = { - delete: Array; - exists: Array; - list: Array; - mkdir: Array; - move: Array<[string, string]>; - read: Array<[string, FileStat]>; - readStream: Array<[string, FileStat]>; - stat: Array; - write: Array<[string, Binary, FileStat]>; - writeStream: Array<[string, FileStat]>; -}; -type FsOptions = { - control?: Partial; - uid?: string; -}; -type FsHarness = { - calls: FsCalls; - control: Fs; - fs: RootFs; -}; -type RequestHarness = { - calls: Array; - request: Request; -}; -type ExtractedTask = { - key: string; - local?: Stat; - name: TaskNames; - remote?: Stat; -}; -declare function bytes(value: string): Binary; -declare function file(key: string, options?: { - mtime?: number; - size?: number; - uid?: string; -}): FileStat; -declare function folder(key: string): FolderStat; -declare function fileRecord(local: string, remote: string): RecordStat; -declare function folderRecord(): RecordStat; -declare function runDecider(decider: Decider, input: { - localStats?: StatsMap; - remoteStats?: StatsMap; - records?: RecordStatsMap; -}): Array; -declare function taskNames(tasks: Array): Array; -declare function taskKeys(tasks: Array): Array; -declare function findTask(tasks: Array, key: string): ExtractedTask; -declare function stream(chunks?: Array): ReadableStream; -declare function deferred(): { - promise: Promise; - reject: (reason?: unknown) => void; - resolve: (value: T | PromiseLike) => void; -}; -declare function flush(turns?: number): Promise; -declare function request(control: Request): RequestHarness; -declare function fs(options?: FsOptions): FsHarness; -declare const testKit: { - bytes: typeof bytes; - deferred: typeof deferred; - file: typeof file; - fileRecord: typeof fileRecord; - findTask: typeof findTask; - flush: typeof flush; - folder: typeof folder; - folderRecord: typeof folderRecord; - fs: typeof fs; - request: typeof request; - runDecider: typeof runDecider; - stream: typeof stream; - taskKeys: typeof taskKeys; - taskNames: typeof taskNames; -}; -//#endregion -//#region src/utils/sha-256.d.ts -declare function sha256(input: string): Promise; -//#endregion -//#region src/sdk/transform.d.ts -type SyncEngineConfig = { - deps?: { - neverBundle?: true | string | RegExp | Array | ((id: string, parentId: string | undefined, isResolved: boolean) => boolean | null | undefined); - }; -}; -declare function syncEngineTransform(): { - name: string; - renderChunk(code: string): { - code: string; - } | undefined; - tsdownConfig(config: SyncEngineConfig): void; -}; -//#endregion -export { debugWrapper, sha256, syncEngineTransform, testKit }; \ No newline at end of file diff --git a/packages/plugin/dist/index-LOl_cerr.spec.d.ts b/packages/plugin/dist/index-LOl_cerr.spec.d.ts deleted file mode 100644 index a8064016..00000000 --- a/packages/plugin/dist/index-LOl_cerr.spec.d.ts +++ /dev/null @@ -1,558 +0,0 @@ -import { App, ListedFiles, RequestUrlParam, Stat } from "obsidian"; -//#region test/e2e-utils.d.ts -type General = any; -//#endregion -//#region src/types.d.ts -type MaybePromise = Promise | T; -type TogglableValue = { - enabled: boolean; - value: T; -}; -type FileStat = { - isDir: false; - key: string; - mtime: number; - size: number; - uid: string; -}; -type FolderStat = { - isDir: true; - key: string; -}; -type Stat$1 = FileStat | FolderStat; -type RecordStat = { - isDir: false; - local: string; - remote: string; -} | { - isDir: true; -}; -type StatsMap = Map; -type RecordStatsMap = Map; -type GlobMatchRule = { - expr: string; - caseSensitive: boolean; -}; -type Progress = { - total: number; - completed: number; - current?: T; -}; -type Binary = Uint8Array; -//#endregion -//#region src/fs/interface.d.ts -/** - * All keys use unified format: - * - root: `/` - * - file: `note.md`, `folder/note.md` - * - folder: `folder/`, `folder/nested/` - */ -type RootFs = { - getUid(): string; - read(key: string, stat: FileStat): MaybePromise; - readStream(key: string, stat: FileStat): MaybePromise>; - write(key: string, value: Binary, stat: FileStat): MaybePromise; - writeStream(key: string, value: ReadableStream, stat: FileStat): MaybePromise; - delete(key: string): MaybePromise; - move(oldKey: string, newKey: string): MaybePromise; - mkdir(key: string, recursive?: boolean): MaybePromise; - stat(key: string): MaybePromise; - exists(key: string): MaybePromise; - list(key: string, reporter: ListReporter): MaybePromise>; -}; -type ListReporter = (progress: Required) => MaybePromise<'include' | 'exclude' | 'advance'>; -type WrappedFs = RootFs & { - original: Fs; -}; -type Fs = WrappedFs | RootFs; -type WriteAtom = { - type: 'write'; - key: string; - execute: () => MaybePromise; - resolve: (uid: string) => void; - reject: (err: Error) => void; -}; -type DeleteAtom = { - type: 'delete'; - key: string; - execute: () => MaybePromise; - resolve: () => void; - reject: (err: Error) => void; -}; -type MoveAtom = { - type: 'move'; - oldKey: string; - newKey: string; - execute: () => MaybePromise; - resolve: () => void; - reject: (err: Error) => void; -}; -type MkdirAtom = { - type: 'mkdir'; - key: string; - execute: () => MaybePromise; - resolve: () => void; - reject: (err: Error) => void; -}; -type InputAtom = WriteAtom | DeleteAtom | MoveAtom | MkdirAtom; -type CustomAtom = { - type: 'custom'; - execute: () => MaybePromise; -}; -type OutputAtom = InputAtom | CustomAtom; -type OptimizerInput = { - atoms: Array; - fs: Fs; - executeAtom: (atom: OutputAtom) => Promise; -}; -type OptimizerOutput = Array; -type BatchOptimizer = (input: OptimizerInput) => OptimizerOutput; -//#endregion -//#region ../../node_modules/.bun/uni-kv@..+..+uni-kv.tgz/node_modules/uni-kv/dist/interface.d.ts -//#region src/interface.d.ts -type Database, M extends Record, F extends boolean> = { - getStore(name: K): Store; - getStoreNames(): IsPromise, F>; - deleteStore(name: string): IsPromise; - clearStores(): IsPromise; - getMeta(key: T): IsPromise; - setMeta(key: T, value: M[T]): IsPromise; - dispose(): IsPromise; -}; -type Store = { - get(key: string): IsPromise; - set(key: string, value: T): IsPromise; - delete(key: string): IsPromise; - clear(): IsPromise; - keys(): IsPromise, F>; - values(): IsPromise, F>; - entries(): IsPromise, F>; - batch(operations: Array>): IsPromise>, F>; -}; -type StoreSync = Store; -type StoreAsync = Store; -type DatabaseSync = Record, M extends Record = {}> = Database; -type DatabaseAsync = Record, M extends Record = {}> = Database; -type GetOperation = { - type: 'get'; - key: string; -}; -type GetResult = { - key: string; - value: T | undefined; -}; -type SetOperation = { - type: 'set'; - key: string; - value: T; -}; -type DeleteOperation = { - type: 'delete'; - key: string; -}; -type StoreOperations = GetOperation | SetOperation | DeleteOperation; -type IsPromise = F extends true ? Promise : T; -//#endregion -//#region src/modules/Storage.d.ts -type RecordStore = StoreAsync; -declare class Storage { - private readonly ctx; - private readonly memoryDB; - private readonly indexedDB; - constructor(ctx: { - getNamespace: () => string; - }); - private readonly getRecordStore; - private readonly deleteRecordStore; - private readonly clearRecordStores; - private readonly recordStoreExists; - readonly root: { - clearRecordStores: () => Promise; - deleteRecordStore: (namespace?: string) => MaybePromise; - getRecordStore: (namespace?: string) => { - get(key: string): Promise; - set(key: string, value: RecordStat): Promise; - delete(key: string): Promise; - clear(): Promise; - keys(): Promise; - values(): Promise; - entries(): Promise<[string, RecordStat][]>; - batch(operations: StoreOperations[]): Promise[]>; - }; - indexedDB: DatabaseAsync; - memoryDB: { - getStore(name: K): { - get(key: string): any; - set(key: string, value: any): void; - delete(key: string): void; - clear(): void; - keys(): string[]; - values(): any[]; - entries(): [string, any][]; - batch(operations: StoreOperations[]): GetResult[]; - }; - getStoreNames(): string[]; - deleteStore(name: string): void; - clearStores(): void; - getMeta(key: T): any; - setMeta(key: T, value: any): void; - dispose(): void; - }; - recordStoreExists: (namespace?: string) => MaybePromise; - }; - readonly dispose: () => void; -} -//#endregion -//#region src/sync/tasks/interface.d.ts -type BaseTaskOptions = { - localFs: Fs; - remoteFs: Fs; - record: RecordStore; -}; -type TaskNames = 'addRecord' | 'removeRecord' | 'createLocalDir' | 'createRemoteDir' | 'download' | 'resolveConflict' | 'removeLocal' | 'removeRemote' | 'upload' | 'moveLocal' | 'moveRemote'; -type ConflictResolverPayload = { - local: FileStat; - remote: FileStat; - key: string; - localFs: Fs; - remoteFs: Fs; - record: RecordStore; -}; -type ConflictResolver = (payload: ConflictResolverPayload) => MaybePromise; -declare abstract class BaseTask { - readonly options: BaseTaskOptions & T; - constructor(options: BaseTaskOptions & T); - protected readonly remoteFs: Fs; - protected readonly localFs: Fs; - protected readonly record: RecordStore; - name: TaskNames; - prettyName: string; - readonly key: string; - readonly local: (BaseTaskOptions & T)['local']; - readonly remote: (BaseTaskOptions & T)['remote']; - abstract exec(): MaybePromise; -} -//#endregion -//#region src/sync/tasks/AddRecord.d.ts -declare class AddRecord extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/CreateRemoteDir.d.ts -declare class CreateRemoteDir extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/Download.d.ts -declare class Download extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/MoveLocal.d.ts -declare class MoveLocal extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/MoveRemote.d.ts -declare class MoveRemote extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/RemoveLocal.d.ts -declare class RemoveLocal extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/RemoveRecord.d.ts -declare class RemoveRecord extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/RemoveRemote.d.ts -declare class RemoveRemote extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/tasks/ResolveConflict.d.ts -declare class ResolveConflict extends BaseTask { - exec: () => MaybePromise; -} -//#endregion -//#region src/sync/tasks/Upload.d.ts -declare class Upload extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/sync/decision/interface.d.ts -type TaskOptions = { - key: string; - remote?: Stat$1; - local?: Stat$1; -}; -type OptionsWithRemoteFileStat = { - remote: FileStat; -} & TaskOptions; -type OptionsWithLocalFileStat = { - local: FileStat; -} & TaskOptions; -type OptionsWithRemoteFolderStat = { - remote: FolderStat; -} & TaskOptions; -type OptionsWithLocalFolderStat = { - local: FolderStat; -} & TaskOptions; -type OptionsWithLocalStat = { - local: Stat$1; -} & TaskOptions; -type OptionsWithRemoteStat = { - remote: Stat$1; -} & TaskOptions; -type OptionsWithBothStats = { - local: Stat$1; - remote: Stat$1; -} & TaskOptions; -type OptionsWithBothFileStats = { - local: FileStat; - remote: FileStat; -} & TaskOptions; -type OptionsWithLocalStatAndOldKey = { - local: Stat$1; - oldKey: string; -} & TaskOptions; -type OptionsWithRemoteStatAndOldKey = { - remote: Stat$1; - oldKey: string; -} & TaskOptions; -type TaskOptionsMap = { - download: OptionsWithRemoteFileStat; - upload: OptionsWithLocalFileStat; - resolveConflict: OptionsWithBothFileStats; - removeLocal: OptionsWithLocalStat; - removeRemote: OptionsWithRemoteStat; - createLocalDir: OptionsWithRemoteFolderStat; - createRemoteDir: OptionsWithLocalFolderStat; - removeRecord: TaskOptions; - addRecord: OptionsWithBothStats; - moveLocal: OptionsWithRemoteStatAndOldKey; - moveRemote: OptionsWithLocalStatAndOldKey; -}; -declare const taskMap: { - readonly addRecord: typeof AddRecord; - readonly createLocalDir: typeof CreateLocalDir; - readonly createRemoteDir: typeof CreateRemoteDir; - readonly download: typeof Download; - readonly moveLocal: typeof MoveLocal; - readonly moveRemote: typeof MoveRemote; - readonly removeLocal: typeof RemoveLocal; - readonly removeRecord: typeof RemoveRecord; - readonly removeRemote: typeof RemoveRemote; - readonly resolveConflict: typeof ResolveConflict; - readonly upload: typeof Upload; -}; -type TaskFactory = (name: N, options: TaskOptionsMap[N]) => InstanceType<(typeof taskMap)[N]>; -type Decider = (input: DeciderInput) => Array; -type DeciderInput = { - localStats: StatsMap; - remoteStats: StatsMap; - records: RecordStatsMap; - taskFactory: TaskFactory; - logger: (log: string) => void; -}; -//#endregion -//#region src/sync/tasks/CreateLocalDir.d.ts -declare class CreateLocalDir extends BaseTask { - exec(): Promise; -} -//#endregion -//#region src/modules/Registrar.d.ts -type RejectableWrapper = (value: T) => T | undefined; -type OrderedWrapperEntry = { - priority: number; - apply: RejectableWrapper; -}; -type RemoteRequestMiddlewareEntry = OrderedWrapperEntry; -type LocalRequestMiddlewareEntry = OrderedWrapperEntry; -type FsWrapperEntry = OrderedWrapperEntry; -type CheckConnectionResult = { - success: true; -} | { - success: false; - reason: string; -}; -type RemoteFsEntry = { - instantiate: (request: Request) => RootFs; - prettyName: () => string; - checkConnection: (request: Request) => MaybePromise; -}; -type DeciderEntry = { - decider: Decider; - prettyName: () => string; -}; -type ConflictResolverEntry = { - prettyName: () => string; - resolver: ConflictResolver; -}; -type GeneralFn = (...args: ReadonlyArray) => unknown; -type RejectableApply = (...input: Parameters) => ReturnType | undefined; -type OrderedApplyEntry = { - apply: RejectableApply; - priority: number; -}; -type RemoteLister = (info: Infras & { - trigger: string; - reporter: ListReporter; -}) => MaybePromise>; -type RemoteListerEntry = OrderedApplyEntry; -type OptimizerEntry = OrderedApplyEntry; -type RequestParam = Omit & { - body?: string | Binary; -}; -type RequestResponse = { - text: () => string; - bytes: () => Binary; - json: () => General; - headers: Record; - status: number; -}; -type Request = (params: RequestParam | string) => Promise; -type Infras = { - localFs: Fs; - remoteFs: Fs; - record: RecordStore; -}; -declare class Registrar { - private readonly ctx; - private readonly cleanupCallbacks; - private readonly localFsWrapperRegistry; - private readonly remoteFsWrapperRegistry; - private readonly localOptimizerRegistry; - private readonly remoteOptimizerRegistry; - private readonly remoteListerRegistry; - private readonly remoteRequestMiddlewareRegistry; - private readonly localRequestMiddlewareRegistry; - private readonly remoteFsRegistry; - private readonly deciderRegistry; - private readonly conflictResolverRegistry; - readonly settings: { - remoteFs: string; - decider: string; - conflictResolver: string; - }; - constructor(ctx: { - app: App; - getRecordStore: (namespace?: string) => StoreAsync; - }); - private readonly getVaultRequest; - private readonly createLocalFs; - private readonly createRemoteFs; - private readonly getRequest; - private readonly getCheckConnection; - private readonly getDecider; - private readonly optimizeLocal; - private readonly optimizeRemote; - private readonly listRemote; - private readonly getConflictResolver; - private readonly getNamespace; - private readonly initializeSync; - root: { - conflictResolverRegistry: Map; - createLocalFs: () => Fs; - createRemoteFs: (remoteFs?: string) => RootFs; - deciderRegistry: Map; - getCheckConnection: (remoteFs?: string) => () => MaybePromise; - getConflictResolver: () => ConflictResolver; - getDecider: () => Decider; - getNamespace: (localFs?: Fs, remoteFs?: Fs) => string; - getRequest: () => Request; - getVaultRequest: () => VaultRequest; - initializeSync: () => Infras; - listRemote: RemoteLister; - optimizeLocal: BatchOptimizer; - optimizeRemote: BatchOptimizer; - registerConflictResolver: (key: string, entry: ConflictResolverEntry) => () => boolean; - registerCss: (css: string) => () => void; - registerDecider: (key: string, entry: DeciderEntry) => () => boolean; - registerLocalFsWrapper: (entry: FsWrapperEntry) => () => boolean; - registerLocalOptimizer: (entry: OptimizerEntry) => () => boolean; - registerLocalRequestMiddleware: (entry: LocalRequestMiddlewareEntry) => () => boolean; - registerRemoteFs: (key: string, entry: RemoteFsEntry) => () => boolean; - registerRemoteFsWrapper: (entry: FsWrapperEntry) => () => boolean; - registerRemoteLister: (entry: RemoteListerEntry) => () => boolean; - registerRemoteOptimizer: (entry: OptimizerEntry) => () => boolean; - registerRemoteRequestMiddleware: (entry: RemoteRequestMiddlewareEntry) => () => boolean; - remoteFsRegistry: Map; - }; - readonly dispose: () => void; -} -//#endregion -//#region src/fs/vault/request.d.ts -type VaultRequestParam = { - method: 'GET'; - key: string; -} | { - method: 'GET_STREAM'; - key: string; -} | { - method: 'PUT'; - key: string; - value: Binary; - headers?: { - mtime?: number; - ctime?: number; - }; -} | { - method: 'APPEND'; - key: string; - value: Binary; - headers?: { - mtime?: number; - ctime?: number; - }; -} | { - method: 'DELETE'; - key: string; - headers?: { - permanent?: boolean; - }; -} | { - method: 'MOVE'; - key: string; - headers: { - destination: string; - }; -} | { - method: 'MKDIR'; - key: string; -} | { - method: 'EXISTS'; - key: string; -} | { - method: 'STAT'; - key: string; - headers?: { - cached?: boolean; - }; -} | { - method: 'LIST'; - key: string; - headers?: { - cached?: boolean; - }; -}; -type VaultRequestResponseMap = { - GET: Binary; - GET_STREAM: ReadableStream; - PUT: void; - APPEND: void; - DELETE: void; - MOVE: void; - MKDIR: void; - EXISTS: boolean; - STAT: Stat; - LIST: ListedFiles; -}; -type VaultRequest = (params: T) => Promise; -//#endregion -export { RootFs as $, AddRecord as A, StoreOperations as B, RemoveRemote as C, MoveLocal as D, MoveRemote as E, RecordStore as F, Fs as G, BatchOptimizer as H, Storage as I, MkdirAtom as J, InputAtom as K, DatabaseAsync as L, ConflictResolver as M, ConflictResolverPayload as N, Download as O, TaskNames as P, OutputAtom as Q, DatabaseSync as R, ResolveConflict as S, RemoveLocal as T, CustomAtom as U, StoreSync as V, DeleteAtom as W, OptimizerInput as X, MoveAtom as Y, OptimizerOutput as Z, CreateLocalDir as _, FsWrapperEntry as a, GlobMatchRule as at, TaskFactory as b, OptimizerEntry as c, RecordStat as ct, RemoteLister as d, StatsMap as dt, WrappedFs as et, RemoteListerEntry as f, TogglableValue as ft, RequestResponse as g, RequestParam as h, DeciderEntry as i, FolderStat as it, BaseTask as j, CreateRemoteDir as k, Registrar as l, RecordStatsMap as lt, Request as m, CheckConnectionResult as n, Binary as nt, Infras as o, MaybePromise as ot, RemoteRequestMiddlewareEntry as p, General as pt, ListReporter as q, ConflictResolverEntry as r, FileStat as rt, LocalRequestMiddlewareEntry as s, Progress as st, VaultRequest as t, WriteAtom as tt, RemoteFsEntry as u, Stat$1 as ut, Decider as v, RemoveRecord as w, Upload as x, DeciderInput as y, StoreAsync as z }; \ No newline at end of file diff --git a/packages/plugin/dist/index.spec.d.ts b/packages/plugin/dist/index.spec.d.ts deleted file mode 100644 index 5a60195c..00000000 --- a/packages/plugin/dist/index.spec.d.ts +++ /dev/null @@ -1,797 +0,0 @@ -import { $ as RootFs, A as AddRecord, B as StoreOperations, C as RemoveRemote, D as MoveLocal, E as MoveRemote, F as RecordStore, G as Fs, H as BatchOptimizer, I as Storage, J as MkdirAtom, K as InputAtom, L as DatabaseAsync, M as ConflictResolver, N as ConflictResolverPayload, O as Download, P as TaskNames, Q as OutputAtom, R as DatabaseSync, S as ResolveConflict, T as RemoveLocal, U as CustomAtom, V as StoreSync, W as DeleteAtom, X as OptimizerInput, Y as MoveAtom, Z as OptimizerOutput, _ as CreateLocalDir, a as FsWrapperEntry, at as GlobMatchRule, b as TaskFactory, c as OptimizerEntry, ct as RecordStat, d as RemoteLister, dt as StatsMap, et as WrappedFs, f as RemoteListerEntry, ft as TogglableValue, g as RequestResponse, h as RequestParam, i as DeciderEntry, it as FolderStat, j as BaseTask, k as CreateRemoteDir, l as Registrar, lt as RecordStatsMap, m as Request, n as CheckConnectionResult, nt as Binary, o as Infras, ot as MaybePromise, p as RemoteRequestMiddlewareEntry, pt as General$1, q as ListReporter, r as ConflictResolverEntry, rt as FileStat, s as LocalRequestMiddlewareEntry, st as Progress, t as VaultRequest, tt as WriteAtom, u as RemoteFsEntry, ut as Stat, v as Decider, w as RemoveRecord, x as Upload, y as DeciderInput, z as StoreAsync } from "./index-LOl_cerr.spec.js"; -import { App, Command, EventRef, IconName, Modal, Plugin, Setting, SettingDefinition, SettingDefinitionGroup, SettingDefinitionItem, SettingDefinitionList, SettingDefinitionPage, ToggleComponent } from "obsidian"; -//#region ../../node_modules/.bun/synthkernel@.+synthkernel.tgz/node_modules/synthkernel/dist/context.d.ts -//#region src/context.d.ts -type General = any; -type GeneralConstructor = new (...args: Array) => General; -type ModuleConstructor = new (context: C) => General; -type GeneralModuleInput = ReadonlyArray | ReadonlyArray; -type IsPlainObject = T extends object ? T extends Function | Date | RegExp | Array | Map | Set ? false : true : false; -type ShallowMerge = IsPlainObject extends true ? (IsPlainObject extends true ? Omit & B : B) : B; -type Keys = T extends General ? keyof T : never; -type InstanceEach = T extends ReadonlyArray ? { [K in keyof T]: InstanceType; } : T; -type PickEach, K extends PropertyKey> = { [I in keyof T]: Pick>; }; -type RootValue = RootKey extends keyof T ? Extract : {}; -type MergeRootEach> = { [I in keyof T]: ShallowMerge, RootValue>; }; -type ExtractKeyEach, K extends Keys> = { [I in keyof T]: K extends keyof T[I] ? T[I][K] : never; }; -type MergeObjects, O extends ReadonlyArray = MergeRootEach> = { [P in Keys]: MergeValues>; }; -type MergeSingleKey[number]>> = MergeValues, K>>; -type MergePair = [A] extends [never] ? B : [B] extends [never] ? A : ShallowMerge; -type MergeValues> = T extends readonly [infer First, ...infer Rest] ? [First] extends [never] ? MergeValues : Rest extends ReadonlyArray ? Rest['length'] extends 0 ? First : MergePair> : never : never; -type MergeResult[number]>, Pr extends object, Po extends object> = MergeObjects<[Pr, ...PickEach, K>, Po]>; -type Context$1[number]>, Pr extends object = {}, Po extends object = {}> = MergeResult & { - __modules__: WeakMap[number]>; - __getModule__: InstanceEach[number]>(ctor: C) => InstanceType; - __addModule__: >>(newModule: N) => Context$1<[...M, N], K, Pr, Po>; - __assign__: (obj: Partial>) => Context$1; -}; -declare const ROOT_KEY = "root"; -type RootKey = typeof ROOT_KEY; -//#endregion -//#region ../../node_modules/.bun/synthkernel@.+synthkernel.tgz/node_modules/synthkernel/dist/reactive.d.ts -//#region src/reactive.d.ts -type RefMatchingFunc = (newValue: T, oldValue: T) => unknown; -type Ref = { - (): T; - (newValue: T): void; - subscribe(func: RefMatchingFunc, options?: { - immediate?: boolean; - }): () => void; - unsubscribe(func: RefMatchingFunc): void; - clear(): void; -}; -//#endregion -//#region src/modules/EventBus.d.ts -type Dispatch = (...[key, payload]: undefined extends O[K] ? [K] : [K, O[K]]) => void; -type On = (key: K, callback: (payload: O[K]) => void) => () => void; -declare class EventBus { - readonly events: { - logSync: string; - logGeneral: string; - errorSync: string; - errorGeneral: string; - }; - private readonly cleanupCallbacks; - private readonly isIdle; - private readonly syncLogs; - private readonly generalLogs; - constructor(); - private readonly getThisSync; - private readonly putSyncLog; - private readonly putGeneralLog; - private readonly subscribers; - private readonly on; - private readonly dispatch; - private readonly getLogs; - readonly dispose: () => void; - readonly root: { - dispatch: Dispatch; - getLogs: () => string; - isIdle: Ref; - on: On; - }; -} -//#endregion -//#region src/modules/I18n.d.ts -type ObsidianLanguageCode = 'en' | 'af' | 'am' | 'ar' | 'az' | 'be' | 'bg' | 'bn' | 'ca' | 'cs' | 'da' | 'de' | 'dv' | 'el' | 'en-GB' | 'eo' | 'es' | 'eu' | 'fa' | 'fi' | 'fr' | 'ga' | 'gl' | 'he' | 'hi' | 'hr' | 'hu' | 'id' | 'it' | 'ja' | 'ka' | 'kh' | 'kn' | 'ko' | 'ky' | 'la' | 'lt' | 'lv' | 'ml' | 'ms' | 'nan-TW' | 'ne' | 'nl' | 'nn' | 'no' | 'oc' | 'or' | 'pl' | 'pt' | 'pt-BR' | 'ro' | 'ru' | 'sa' | 'si' | 'sk' | 'sl' | 'sq' | 'sr' | 'sv' | 'sw' | 'ta' | 'te' | 'th' | 'tl' | 'tr' | 'tt' | 'uk' | 'ur' | 'uz' | 'vi' | 'zh' | 'zh-TW'; -type Primitive = string | number | boolean | null | undefined; -type Fragment = (frag: DocumentFragment, args: A) => void; -type TranslationResource = Record>; -type InterpolationValues = Record; -type TranslateParams | string> = R extends Fragment ? ([undefined] extends [A] ? [] : [A]) : [] | [InterpolationValues]; -type Translate = (key: K, ...args: TranslateParams) => O[K] extends string ? string : DocumentFragment; -declare class I18n { - private readonly targetLangs; - readonly i18n: {}; - private readonly registerI18n; - private readonly translate; - root: { - registerI18n: (code: ObsidianLanguageCode, resource: TranslationResource) => void; - translate: Translate; - }; -} -//#endregion -//#region src/modules/Sync.d.ts -type SyncTerminateReason = { - result: 'cancelled'; -} | { - result: 'completed'; -} | { - result: 'failed'; - error: string; -} | { - result: 'noop'; -}; -type TaskInfo = { - name: TaskNames; - key: string; - prettyName: string; - isDir: boolean; -}; -type FailedTaskInfo = TaskInfo & { - error: string; -}; -declare class Sync { - private readonly ctx; - dispatch: Dispatch; - on: On; - constructor(ctx: { - dispatch: Dispatch; - initializeSync: () => Infras; - getDecider: () => Decider; - on: On; - translate: Translate; - listRemote: RemoteLister; - getConflictResolver: () => ConflictResolver; - }); - readonly events: { - syncStarted: { - isCancelled: Ref; - trigger: string; - }; - remoteWalkProgress: Progress; - syncTerminated: SyncTerminateReason; - requestConfirmDelete: Array; - requestConfirmTasks: Array; - syncCanceled: undefined; - taskCompleted: TaskInfo; - taskFailed: FailedTaskInfo; - executionStarted: Array; - }; - readonly settings: { - maxFileSize: TogglableValue; - exclusionRules: Array; - inclusionRules: Array; - confirmDeleteInAutoSync: boolean; - confirmTasksInSync: boolean; - }; - private readonly postProcess; - private readonly confirmTasks; - private readonly confirmDeletion; - private readonly executeSync; - private readonly convertDeleteToUpload; - root: { - executeSync: (trigger: string) => Promise<{ - result: 'cancelled'; - } | { - result: 'completed'; - } | { - result: 'failed'; - error: string; - } | { - result: 'noop'; - }>; - }; -} -//#endregion -//#region src/modules/Observability.d.ts -type SyncStage = 'none' | 'walkingRemote' | 'awaitingConfirmation' | 'executing' | 'completed' | 'completedNoop' | 'cancelled' | 'failed'; -type AddRibbonIcon = (icon: IconName, title: string, callback: (evt: MouseEvent) => void) => HTMLElement; -declare class Observability { - private readonly ctx; - private lastSyncTime; - private readonly sinceLastSyncText; - private readonly syncStage; - private readonly walkProgress; - private readonly executionProgress; - private readonly cleanupCallbacks; - private readonly t; - private readonly progressText; - readonly settings: { - noticeStatusOnMobile: boolean; - exportLogsDirectory: string; - }; - readonly i18n: { - startSync: string; - startNonInteractiveSync: string; - stopSync: string; - showProgress: string; - exportLogsToFile: string; - exportLogsFailed: string; - idle: string; - }; - constructor(ctx: { - addStatusBarItem: () => HTMLElement; - on: On; - translate: Translate; - isIdle: Ref; - dispatch: Dispatch; - requestSync: (trigger: string) => Promise; - showProgress: () => void; - addCommand: (command: Command) => Command; - addRibbonIcon: AddRibbonIcon; - getLogs: () => string; - app: App; - }); - readonly start: () => void; - private readonly setupStatus; - private readonly setupCommands; - private readonly exportLogs; - readonly dispose: () => void; - root: { - executionProgress: Ref>; - exportLogs: () => Promise; - syncStage: Ref; - walkProgress: Ref; - }; -} -//#endregion -//#region src/components/file-tree/index.d.ts -type FileTreeTranslations = { - selectAll: string; - xSelected: string; -}; -//#endregion -//#region src/modules/Extensibility.d.ts -type ModuleInstance = { - moduleSettings: object; - dispose?: () => void; - start?: () => void; -}; -type ModuleCtor = new (ctx: object) => ModuleInstance; -type ModuleMeta = { - id: string; - name: string; - version: string; - description: string; - main: string; - icon?: string; - minPluginVersion?: string; - integrity: string; -}; -type AugmentedModuleMeta = ModuleMeta & { - enabled: boolean; - source: string; - icon: string; -}; -declare class Extensibility { - private readonly ctx; - private readonly moduleDir; - private readonly sourceCache; - private readonly discoveredModules; - private readonly loadedModules; - private readonly moduleStore; - private autoUpdateTimeout?; - readonly settings: { - moduleSources: Array; - moduleAutoUpdate: boolean; - modules: Record; - }; - readonly i18n: { - failedToLoadModule: string; - failedToDownloadModule: string; - failedToFetchSource: string; - }; - readonly events: { - moduleLoaded: string; - moduleUnloaded: string; - }; - constructor(ctx: { - app: App; - __addModule__: Context['__addModule__']; - __getModule__: Context['__getModule__']; - dispatch: Dispatch; - translate: Translate; - allModules: Set; - isIdle: Ref; - saveSettings: () => Promise; - indexedDB: DatabaseAsync>; - }); - readonly start: () => void; - private readonly createOperationFactory; - private readonly loadAllModules; - private readonly loadModule; - private readonly unloadModule; - private readonly downloadModule; - private readonly deleteModule; - private readonly fetchSources; - private readonly updateModules; - private readonly updateModuleMeta; - private readonly enableModule; - private readonly disableModule; - private readonly getModulePath; - private readonly parseModulePath; - readonly dispose: () => void; - readonly root: { - deleteModule: (id: string) => Promise; - disableModule: (id: string) => void; - discoveredModules: Map; - downloadModule: (meta: AugmentedModuleMeta, waitIdle?: boolean) => Promise; - enableModule: (id: string) => Promise; - fetchSources: (manual?: boolean) => Promise; - loadAllModules: () => Promise; - loadModule: (meta: AugmentedModuleMeta, start?: boolean, module?: string) => Promise; - loadedModules: Map; - pluginOutdated: boolean; - unloadModule: (id: string) => void; - updateModuleMeta: (meta: AugmentedModuleMeta) => Promise; - updateModules: () => Promise; - }; -} -//#endregion -//#region src/components/ModuleEditorModal.d.ts -type ModuleEditorTranslations = { - editModuleInformation: string; - enable: string; - name: string; - namePlaceholder: string; - description: string; - descriptionPlaceholder: string; - icon: string; - iconDescription: Fragment; - iconPlaceholder: string; - updateSource: string; - updateSourceDescription: string; - updateSourcePlaceholder: string; - invalidValue: string; - integrityVerification: string; - integrityVerificationDescription: Fragment; - save: string; - cancel: string; -}; -//#endregion -//#region src/components/UnknownModuleModal.d.ts -type FileInfo = { - path: string; - size: string; - mtime: string; - ctime: string; - fileName: string; -}; -type UnknownModuleTranslations = { - unknownModule: string; - unknownModuleDescription: Fragment; - delete: string; - configure: string; -}; -//#endregion -//#region src/modules/Setting.d.ts -type SettingTree = { - (self: SettingTree): SettingDefinitionItem; - [key: number]: SettingTree; -}; -type NestedCallableTree = { - (self: SettingTree): SettingDefinitionItem; - [key: number]: CallableOrObjectTree; -}; -type CallableOrObjectTree = NestedCallableTree | { - [key: number]: CallableOrObjectTree; -}; -type SettingEntry = { - priority: number; - apply: CallableOrObjectTree; -}; -declare class Setting$1 { - private readonly ctx; - private readonly cleanupCallbacks; - private settingTab?; - private readonly settingRegistry; - readonly i18n: { - match: string; - matchLabelDescription: string; - speed: string; - speedLabelDescription: string; - }; - constructor(ctx: { - on: On; - translate: Translate; - registerSetting: (entry: SettingEntry) => () => boolean; - }); - readonly start: () => void; - private readonly matchLabel; - private readonly speedLabel; - private readonly addSettingTab; - private readonly rerenderSettingTab; - private readonly refreshSettingTab; - root: { - addSettingTab: (plugin: Plugin) => void; - matchLabel: () => { - text: string; - tooltip: string; - }; - refreshSettingTab: () => void | undefined; - registerSetting: (entry: SettingEntry) => () => boolean; - rerenderSettingTab: () => void | undefined; - speedLabel: () => { - color: string; - text: string; - textColor: string; - tooltip: string; - }; - }; - readonly dispose: () => void; -} -//#endregion -//#region src/settings/utils.d.ts -type AugmentedSettingDefinitionItem = SettingDefinitionGroup | SettingDefinitionList | (SettingDefinitionPage & { - labels?: Array; -}) | (SettingDefinition & { - labels?: Array; -}); -type LabelDefinition = { - text: string; - tooltip: string; - color?: string; - textColor?: string; -}; -declare function s(parent: (self: SettingTree) => AugmentedSettingDefinitionItem, children?: CallableOrObjectTree): CallableOrObjectTree; -//#endregion -//#region src/settings/controls.d.ts -type ControlsSettingTranslations = { - controls: string; - maxFileSize: string; - maxFileSizeDescription: string; - maxFileSizePlaceholder: string; - maxRequestConcurrency: string; - minRequestInterval: string; - minRequestIntervalDescription: string; - minRequestIntervalPlaceholder: string; - maxRequestConcurrencyPlaceholder: string; - maxRequestConcurrencyDescription: string; - maxMemoryConsumption: string; - maxMemoryConsumptionDescription: string; - maxMemoryConsumptionPlaceholder: string; -}; -//#endregion -//#region src/settings/development.d.ts -type DevelopmentSettingTranslations = { - development: string; - clearRecords: string; - recordsCleared: string; - clear: string; - clearRecordsDescription: string; - export: string; - exportLogsDescription: string; - exportLogsDirectoryPlaceholder: string; - exportLogsToFile: string; - moduleSources: string; - moduleSourcesDescription: string; - edit: string; - xConfigured: string; - addSource: string; - noSourceConfigured: string; - moduleSourcePlaceholder: string; -}; -//#endregion -//#region src/components/MigrationModal.d.ts -type MigrationModalTranslations = { - cancel: string; - remoteMigration: string; - migrationProcess: string; - startMigration: string; - migrationDescription: string; - migrationPhase1Description: string; - migrationPhase2Description: string; - migrationPhase3Description: string; - toggleWithoutMigration: string; - migrationFailed: string; - completed: string; - hide: string; - done: string; -}; -type MigrationEvents = { - migrationProgress: Progress; - migrationFailed: string; -}; -type MigrationContext = { - app: App; - on: On; - dispatch: Dispatch; - translate: Translate; - requestSync: (trigger: string) => Promise; - initializeSync: () => Infras; - memoryDB: ExistingMemoryDB; -}; -declare function setNeedMigration(ctx: MigrationContext, { toggle, needMigration, content, apply }: { - toggle: ToggleComponent; - needMigration?: (value: boolean) => MaybePromise; - content: (value: boolean) => string | DocumentFragment; - apply: (value: boolean) => MaybePromise; -}): void; -//#endregion -//#region src/settings/features.d.ts -type FeaturesSettingTranslations = { - features: string; - realtimeSyncFastMode: string; - realtimeSyncFastModeDescription: string; - realtimeSync: string; - realtimeSyncDescription: string; - realtimeSyncPlaceholder: string; - startupSync: string; - startupSyncDescription: string; - startupSyncPlaceholder: string; - scheduledSync: string; - scheduledSyncDescription: string; - scheduledSyncPlaceholder: string; - asymmetricStorage: string; - asymmetricStorageDescription: Fragment; - asymmetricStorageMigration: Fragment<'enable' | 'disable'>; -} & MigrationModalTranslations; -//#endregion -//#region src/settings/filter.d.ts -type FilterSettingTranslations = { - filterRules: string; - inclusionRules: string; - inclusionRulesDescription: Fragment; - exclusionRules: string; - exclusionRulesDescription: Fragment; - xConfigured: string; - addInclusionRule: string; - addExclusionRule: string; - noRuleConfigured: string; - filterPlaceholder: string; - caseSensitive: string; -}; -//#endregion -//#region src/settings/head.d.ts -type HeadSettingTranslations = { - moduleAutoUpdate: string; - moduleAutoUpdateDescription: string; - moduleManagement: string; - moduleManagementDescription: string; - backend: string; - backendDescription: string; - syncStrategy: string; - syncStrategyDescription: string; - checkConnectionFailed: string; - checkConnectionSuccess: string; - checkConnection: string; - conflictResolveStrategy: string; - conflictResolveStrategyDescription: string; - xEnabled: string; - settingTips: Fragment<{ - labels: Array; - addLabel: typeof addLabel; - }>; -}; -declare function addLabel(element: Element, { text, tooltip, color, textColor }: LabelDefinition): HTMLSpanElement; -//#endregion -//#region src/settings/miscellaneous.d.ts -type MiscellaneousSettingTranslations = { - miscellaneous: string; - diffMatchPatch: string; - keepLocal: string; - keepRemote: string; - skip: string; - noticeStatusOnMobile: string; - noticeStatusOnMobileDescription: string; - confirmTasksInSync: string; - confirmTasksInSyncDescription: string; - confirmDeleteInAutoSync: string; - confirmDeleteInAutoSyncDescription: string; - customHeaders: string; - customHeadersDescription: string; - edit: string; - xConfigured: string; - addHeader: string; - noHeaderConfigured: string; - headerKeyPlaceholder: string; - headerValuePlaceholder: string; - addSecretHeader: string; -}; -//#endregion -//#region src/components/module-management/index.d.ts -type ModuleManagementTranslations = { - disableModule: string; - downloadModule: string; - enableModule: string; - installed: string; - loadingModules: string; - noInstalledModulesFound: string; - noMatchingModulesFound: string; - noModulesAvailable: string; - updateAvailable: string; - updateModule: string; - deleteModule: string; - editModuleInformation: string; - official: string; - someModulesHidden: string; -}; -//#endregion -//#region src/settings/module-management.d.ts -type ModulesTranslations = ModuleManagementTranslations & { - searchModules: string; - moduleManagement: string; - showInstalledOnly: string; -}; -//#endregion -//#region src/modules/Bootstrap.d.ts -type CustomHeaders = Array<{ - type: 'plaintext' | 'secret'; - value: string; - key: string; -}>; -type ExistingMemoryDB = DatabaseSync<{ - localContext20000: Stat; - remoteContext10000: Stat; - remoteContext20000: Stat; -}, { - localContext20000Marker: string; - remoteContext10000Marker: string; - remoteContext20000Marker: string; -}>; -declare class Bootstrap { - private readonly ctx; - private readonly cleanupCallbacks; - private readonly memoryStates; - private isCancelled?; - private readonly localPool; - private readonly remotePool; - private localFs?; - private remoteFs?; - readonly i18n: { - bidirectional: string; - mirrorLocal: string; - mirrorRemote: string; - latestSurvive: string; - keepLocal: string; - keepRemote: string; - renameAndKeepBoth: string; - skip: string; - } & ControlsSettingTranslations & DevelopmentSettingTranslations & FeaturesSettingTranslations & FilterSettingTranslations & HeadSettingTranslations & MiscellaneousSettingTranslations & UnknownModuleTranslations & ModuleEditorTranslations & FileTreeTranslations & ModulesTranslations; - readonly settings: { - maxMemoryConsumption: TogglableValue; - maxRequestConcurrency: TogglableValue; - minRequestInterval: TogglableValue; - realtimeSyncFastMode: boolean; - asymmetricStorage: boolean; - customHeaders: CustomHeaders; - }; - constructor(ctx: { - app: App; - registerI18n: (code: ObsidianLanguageCode, resource: TranslationResource) => void; - on: On; - dispatch: Dispatch; - memoryDB: ExistingMemoryDB; - registerDecider: (id: string, entry: DeciderEntry) => void; - registerLocalFsWrapper: (entry: FsWrapperEntry) => void; - registerRemoteFs: (id: string, entry: RemoteFsEntry) => void; - registerRemoteFsWrapper: (entry: FsWrapperEntry) => void; - translate: Translate; - optimizeLocal: BatchOptimizer; - optimizeRemote: BatchOptimizer; - registerLocalOptimizer: (optimizer: OptimizerEntry) => void; - registerRemoteOptimizer: (optimizer: OptimizerEntry) => void; - registerRemoteLister: (entry: RemoteListerEntry) => () => boolean; - registerConflictResolver: (id: string, entry: ConflictResolverEntry) => void; - registerRemoteRequestMiddleware: (entry: RemoteRequestMiddlewareEntry) => void; - registerLocalRequestMiddleware: (entry: LocalRequestMiddlewareEntry) => void; - }); - readonly start: () => void; - readonly dispose: () => void; -} -//#endregion -//#region src/modules/ProgressModal.d.ts -type DeleteConfirmReturn = { - delete: Array; - reupload: Array; -}; -type TaskCounts = { - total: number; - deleteLocal: number; - deleteRemote: number; - conflict: number; -}; -declare class ProgressModal extends Modal { - private readonly ctx; - private readonly moduleCleanupCallbacks; - private readonly t; - private opening; - private readonly modalCleanupCallbacks; - private readonly dispatch; - private description?; - private detailContainer?; - private controls?; - constructor(ctx: { - app: App; - translate: Translate; - on: On; - dispatch: Dispatch; - syncStage: Ref; - walkProgress: Ref; - executionProgress: Ref>; - }); - readonly events: { - tasksConfirmed: Array; - deleteConfirmed: DeleteConfirmReturn; - }; - readonly i18n: { - syncProgress: string; - completed: string; - failedTasksDescription: string; - confirmDeleteDescription: string; - confirmTasksDescription: Fragment; - hide: string; - confirm: string; - cancel: string; - done: string; - stopSync: string; - } & Record; - private readonly renderHideStop; - private readonly renderConfirmCancel; - private readonly renderDone; - private readonly showDetails; - private readonly hideDetails; - onOpen(): void; - root: { - hideProgress: { - (): void; - (): void; - }; - showProgress: () => void; - }; - onClose(): void; - dispose(): void; -} -//#endregion -//#region src/modules/Scheduler.d.ts -declare class Scheduler { - private readonly ctx; - private readonly pendingRequests; - private isScheduling; - private realtimeSyncTimer?; - private scheduledSyncTimer?; - private startupSyncTimer?; - constructor(ctx: { - syncStage: Ref; - executeSync: (trigger: string) => Promise; - registerEvent: (ref: EventRef) => void; - app: App; - isIdle: Ref; - }); - settings: { - startupSync: TogglableValue; - scheduledSync: TogglableValue; - realtimeSync: TogglableValue; - exclusionRules: Array; - inclusionRules: Array; - }; - private readonly requestSync; - start: () => void; - dispose: () => void; - private readonly startScheduledSync; - private readonly stopScheduledSync; - private readonly onChange; - private readonly scheduleFlush; - private readonly flush; - root: { - requestSync: (trigger: string) => Promise; - startScheduledSync: () => void; - stopScheduledSync: () => void; - }; -} -//#endregion -//#region src/index.d.ts -declare const internalModules: readonly [typeof EventBus, typeof I18n, typeof Storage, typeof Extensibility, typeof Setting$1, typeof Registrar, typeof Sync, typeof Observability, typeof Scheduler, typeof ProgressModal, typeof Bootstrap]; -type InternalModules = typeof internalModules; -type MergeKeys = 'settings' | 'root' | 'events' | 'i18n'; -type Context = Context$1 Command; - registerEvent: (ref: EventRef) => void; - addRibbonIcon: AddRibbonIcon; - addStatusBarItem: () => HTMLElement; - saveSettings: () => Promise; -}>; -type Events = MergeSingleKey; -type Settings = MergeSingleKey; -type Translations = MergeSingleKey; -//#endregion -//#region src/sdk/prefix.d.ts -declare function prefixWrapper(original: Fs, prefix: string): WrappedFs; -//#endregion -//#region src/utils/pipe.d.ts -declare function pipe({ from, to, stat, key }: { - from: Fs; - to: Fs; - key: string; - stat: FileStat; -}): Promise; -declare function readWithSize(fs: Fs, key: string, stat: FileStat): Promise | undefined>; -declare function writeWithValue(fs: Fs, key: string, value: Binary | ReadableStream, stat: FileStat): MaybePromise; -//#endregion -//#region src/sdk/index.d.ts -declare function digOriginal(wrapped: Fs): RootFs; -type SelectFromContext = Context extends O ? O : never; -//#endregion -export { type AddRecord, type AugmentedModuleMeta, type BaseTask, type BatchOptimizer, type Binary, type CallableOrObjectTree, type CheckConnectionResult, type ConflictResolver, type ConflictResolverEntry, type ConflictResolverPayload, type Context, type CreateLocalDir, type CreateRemoteDir, type CustomAtom, type DatabaseAsync, type DatabaseSync, type Decider, type DeciderEntry, type DeciderInput, type DeleteAtom, type Dispatch, type Download, type Events, type ExistingMemoryDB, type FileStat, type FolderStat, type Fragment, type Fs, type FsWrapperEntry, type InputAtom, type LabelDefinition, type ListReporter, type LocalRequestMiddlewareEntry, type MaybePromise, type MkdirAtom, type ModuleMeta, type MoveAtom, type MoveLocal, type MoveRemote, type ObsidianLanguageCode, type On, type OptimizerEntry, type OptimizerInput, type OptimizerOutput, type OutputAtom, type Progress, type RecordStat, type RecordStatsMap, type RecordStore, type RemoteFsEntry, type RemoteLister, type RemoteListerEntry, type RemoteRequestMiddlewareEntry, type RemoveLocal, type RemoveRecord, type RemoveRemote, type Request, type RequestParam, type RequestResponse, type ResolveConflict, type RootFs, SelectFromContext, type SettingEntry, type Settings, type Stat, type StatsMap, type StoreAsync, type StoreOperations, type StoreSync, type SyncTerminateReason, type TaskFactory, type TaskNames, type Translate, type TranslationResource, type Translations, type Upload, type VaultRequest, type WrappedFs, type WriteAtom, digOriginal, pipe, prefixWrapper, readWithSize, s, setNeedMigration, writeWithValue }; \ No newline at end of file diff --git a/packages/plugin/src/fs/vault/request.ts b/packages/plugin/src/fs/vault/request.ts index 0eb2879f..bfa26bf5 100644 --- a/packages/plugin/src/fs/vault/request.ts +++ b/packages/plugin/src/fs/vault/request.ts @@ -1,5 +1,6 @@ import type { Vault, Stat, ListedFiles, App } from 'obsidian'; import { toArrayBuffer, toUint8Array } from '@repo/shared/binary'; +import { requestNative } from '@repo/shared/e2e-utils.spec'; import { basename, isFolder, stripEndSlash } from '@repo/shared/path'; import { Platform, TFile, TFolder } from 'obsidian'; import type { Binary, MaybePromise } from '@/types'; @@ -68,7 +69,7 @@ export default function createVaultRequest(app: App): VaultRequest { if (method === 'GET') return adapter.readBinary(path).then((buffer) => toUint8Array(buffer)) as never; if (method === 'GET_STREAM') { - const response = await fetch(adapter.getResourcePath(path)); + const response = await requestNative(adapter.getResourcePath(path)); if (!response.body) throw new Error('Streaming vault file is not supported!'); return response.body as never; } diff --git a/packages/plugin/src/global.css b/packages/plugin/src/global.css index b4b94d5c..445755b3 100644 --- a/packages/plugin/src/global.css +++ b/packages/plugin/src/global.css @@ -91,11 +91,8 @@ input[type='text'].sync-engine-invalid-input { .setting-item-info { display: none; } - .setting-item-control { - width: 100% !important; - input[type='text'] { - flex: 1; - } + .setting-item-control input[type='text'] { + flex: 1; } } diff --git a/packages/plugin/src/modules/Extensibility.ts b/packages/plugin/src/modules/Extensibility.ts index fb0d64da..2e38201a 100644 --- a/packages/plugin/src/modules/Extensibility.ts +++ b/packages/plugin/src/modules/Extensibility.ts @@ -1,13 +1,14 @@ import type { Context, Events, Translations } from '@'; -import type { App } from 'obsidian'; +import type { App, DataAdapter } from 'obsidian'; import type { Ref } from 'synthkernel'; import type { DatabaseAsync, StoreAsync, StoreOperations } from 'uni-kv'; -import loadModule from '$/e2e-utils'; import hash from '@repo/shared/crypto'; +import { importCode } from '@repo/shared/e2e-utils.spec'; import obsidian, { Notice, requestUrl } from 'obsidian'; import { compare } from 'verkit'; import type { General } from '@/types'; import UnknownModuleModal from '@/components/UnknownModuleModal'; +import sha256 from '@/utils/sha-256'; import toErrorMessage from '@/utils/to-error-message'; import untilTrue from '@/utils/until-true'; import type { Dispatch } from './EventBus'; @@ -22,6 +23,7 @@ export type ModuleInstance = { start?: () => void; }; export type ModuleCtor = new (ctx: object) => ModuleInstance; +type GeneralCtor = new (...args: ReadonlyArray) => General; export type ModuleMeta = { id: string; @@ -382,3 +384,18 @@ function isValidMeta(meta: unknown): meta is ModuleMeta { /^[0-9a-f]*$/u.test(meta.integrity) ); } + +export async function loadModule( + options: + | { path: string; integrity: string; adapter: DataAdapter } + | { module: string; integrity: string; adapter: DataAdapter }, +) { + const { adapter, integrity } = options; + const file = 'module' in options ? options.module : await adapter.read(options.path); + if (integrity && (await sha256(file)) !== integrity) + throw new Error('Module has been maliciously modified!'); + const module = await importCode<{ default?: GeneralCtor }>(file); + const ctor = module.default; + if (typeof ctor !== 'function') throw new Error(`Invalid module!`); + return ctor; +} diff --git a/packages/plugin/src/settings/development.ts b/packages/plugin/src/settings/development.ts index 6034fe7c..4960778e 100644 --- a/packages/plugin/src/settings/development.ts +++ b/packages/plugin/src/settings/development.ts @@ -5,7 +5,7 @@ import { normalizeBaseDir, normalizeUrl } from '@repo/shared/path'; import { Notice } from 'obsidian'; import type { Translate } from '@/modules/I18n'; import type { CallableOrObjectTree } from '@/modules/Setting'; -import type { MaybePromise } from '@/types'; +import type { General, MaybePromise } from '@/types'; import { generateEditableList, reactivelyValidate, s } from './utils'; export type DevelopmentSettingTranslations = { @@ -41,7 +41,7 @@ export default function developmentSettings({ exportLogs: () => Promise; settings: Settings; saveSettings: () => Promise; - memoryDB: DatabaseSync; + memoryDB: DatabaseSync; rerenderSettingTab: () => void; }): CallableOrObjectTree { return { diff --git a/packages/plugin/src/settings/filter.ts b/packages/plugin/src/settings/filter.ts index 28ad2397..fcdfd428 100644 --- a/packages/plugin/src/settings/filter.ts +++ b/packages/plugin/src/settings/filter.ts @@ -3,7 +3,7 @@ import type { SettingGroupItem } from 'obsidian'; import type { DatabaseSync } from 'uni-kv'; import type { Fragment, Translate } from '@/modules/I18n'; import type { CallableOrObjectTree } from '@/modules/Setting'; -import type { GlobMatchRule } from '@/types'; +import type { General, GlobMatchRule } from '@/types'; import { normalizeGlob } from '@/utils/glob-match'; import type { LabelDefinition } from './utils'; import { generateEditableList, reactivelyValidate, s } from './utils'; @@ -33,7 +33,7 @@ export default function filterSettings({ translate: Translate; saveSettings: () => Promise; settings: Settings; - memoryDB: DatabaseSync; + memoryDB: DatabaseSync; rerenderSettingTab: () => void; speedLabel: () => LabelDefinition; }): CallableOrObjectTree { diff --git a/packages/plugin/src/settings/miscellaneous.ts b/packages/plugin/src/settings/miscellaneous.ts index 6b0c2f90..924c00d5 100644 --- a/packages/plugin/src/settings/miscellaneous.ts +++ b/packages/plugin/src/settings/miscellaneous.ts @@ -4,6 +4,7 @@ import type { DatabaseSync } from 'uni-kv'; import { SecretComponent } from 'obsidian'; import type { Translate } from '@/modules/I18n'; import type { CallableOrObjectTree } from '@/modules/Setting'; +import type { General } from '@/types'; import { generateEditableList, reactivelyValidate, s } from './utils'; export type MiscellaneousSettingTranslations = { @@ -40,7 +41,7 @@ export default function miscellaneousSettings({ translate: Translate; saveSettings: () => Promise; settings: Settings; - memoryDB: DatabaseSync; + memoryDB: DatabaseSync; rerenderSettingTab: () => void; app: App; }): CallableOrObjectTree { diff --git a/packages/plugin/src/settings/utils.ts b/packages/plugin/src/settings/utils.ts index d3190b98..2cec8005 100644 --- a/packages/plugin/src/settings/utils.ts +++ b/packages/plugin/src/settings/utils.ts @@ -205,6 +205,7 @@ export function generateEditableList({ name: '', render: (setting) => { setting.settingEl.addClass('sync-engine-editable-list'); + setting.settingEl.querySelector('.setting-item-control')?.addClass('w-100%!'); return render(setting, item, saveEdit); }, searchable: false, diff --git a/packages/plugin/src/types.ts b/packages/plugin/src/types.ts index c7c5c53c..cd204be4 100644 --- a/packages/plugin/src/types.ts +++ b/packages/plugin/src/types.ts @@ -1,4 +1,5 @@ -export type { General } from '$/e2e-utils'; +export type { General } from '@repo/shared/e2e-utils.spec'; +export type { Binary } from '@repo/shared/binary'; export type MaybePromise = Promise | T; export type TogglableValue = { enabled: boolean; value: T }; @@ -30,5 +31,3 @@ export type Progress = { completed: number; current?: T; }; - -export type Binary = Uint8Array; diff --git a/packages/plugin/test/e2e-utils.ts b/packages/plugin/test/e2e-utils.ts deleted file mode 100644 index 558f7fa4..00000000 --- a/packages/plugin/test/e2e-utils.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { DataAdapter } from 'obsidian'; -import sha256 from '@/utils/sha-256'; - -// oxlint-disable-next-line typescript/no-explicit-any -export type General = any; -type GeneralCtor = new (...args: ReadonlyArray) => General; - -export default async function loadModule( - options: - | { path: string; integrity: string; adapter: DataAdapter } - | { module: string; integrity: string; adapter: DataAdapter }, -) { - const { adapter, integrity } = options; - const file = 'module' in options ? options.module : await adapter.read(options.path); - if (integrity && (await sha256(file)) !== integrity) - throw new Error('Module has been maliciously modified!'); - const blob = new Blob([file], { type: 'application/javascript' }); - const module = (await import(URL.createObjectURL(blob))) as { default?: GeneralCtor }; - const ctor = module.default; - if (typeof ctor !== 'function') throw new Error(`Invalid module!`); - return ctor; -} diff --git a/packages/plugin/test/mocks.ts b/packages/plugin/test/mocks.ts index bf6976b0..9fbd27fb 100644 --- a/packages/plugin/test/mocks.ts +++ b/packages/plugin/test/mocks.ts @@ -1,5 +1,4 @@ -// oxlint-disable-next-line import/no-namespace -import * as ObsidianMock from '@repo/shared/mocks'; +import ObsidianMock from '@repo/shared/obsidian-mock'; import { mock } from 'bun:test'; Object.assign(globalThis, { window: globalThis }); diff --git a/packages/plugin/tsdown.config.ts b/packages/plugin/tsdown.config.ts index 067f7a03..eda0814d 100644 --- a/packages/plugin/tsdown.config.ts +++ b/packages/plugin/tsdown.config.ts @@ -46,7 +46,7 @@ const pluginConfig = defineConfig({ const sdkConfig = defineConfig({ ...sharedConfig, clean: dtsPass, - dts: dtsPass, + dts: dtsPass ? { eager: true } : false, entry: { dev: 'src/sdk/dev.ts', index: 'src/sdk/index.ts' }, unbundle: !dtsPass, }); diff --git a/packages/s3/test/mocks.ts b/packages/s3/test/mocks.ts index d612befb..9a27a793 100644 --- a/packages/s3/test/mocks.ts +++ b/packages/s3/test/mocks.ts @@ -1,5 +1,4 @@ -// oxlint-disable-next-line import/no-namespace -import * as ObsidianMock from '@repo/shared/mocks'; +import ObsidianMock from '@repo/shared/obsidian-mock'; import { mock } from 'bun:test'; void mock.module('obsidian', () => ObsidianMock); diff --git a/packages/shared/package.json b/packages/shared/package.json index df73d2ef..ea332275 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -13,6 +13,6 @@ "scripts": { "fix": "oxlint --silent --fix && oxfmt", "check": "tsc && oxlint && oxfmt --check", - "tests": "bun test" + "tests": "bun test ./test" } } diff --git a/packages/shared/src/binary.ts b/packages/shared/src/binary.ts index 7188a096..b78d984a 100644 --- a/packages/shared/src/binary.ts +++ b/packages/shared/src/binary.ts @@ -1,7 +1,7 @@ const encoder = new TextEncoder(); const decoder = new TextDecoder(); -type Binary = Uint8Array; +export type Binary = Uint8Array; export function toUint8Array(buffer: ArrayBuffer) { return new Uint8Array(buffer); diff --git a/packages/shared/src/e2e-utils.spec.ts b/packages/shared/src/e2e-utils.spec.ts new file mode 100644 index 00000000..7fadc9bb --- /dev/null +++ b/packages/shared/src/e2e-utils.spec.ts @@ -0,0 +1,11 @@ +// oxlint-disable-next-line typescript/no-explicit-any +export type General = any; + +// oxlint-disable-next-line typescript/no-unnecessary-type-parameters +export function importCode(code: string): Promise { + return import( + URL.createObjectURL(new Blob([code], { type: 'application/javascript' })) + ) as Promise; +} + +export const requestNative: typeof fetch = fetch; diff --git a/packages/shared/src/mocks.ts b/packages/shared/src/obsidian-mock.spec.ts similarity index 82% rename from packages/shared/src/mocks.ts rename to packages/shared/src/obsidian-mock.spec.ts index bf7b34cd..01584b83 100644 --- a/packages/shared/src/mocks.ts +++ b/packages/shared/src/obsidian-mock.spec.ts @@ -1,9 +1,4 @@ -// oxlint-disable no-useless-constructor -// oxlint-disable typescript/no-extraneous-class -// oxlint-disable eslint/no-empty-function -// oxlint-disable eslint/require-await -// oxlint-disable typescript/require-await - +// oxlint-disable typescript/require-await typescript/no-extraneous-class no-useless-constructor no-empty-function export async function requestUrl() { return { headers: {}, diff --git a/packages/shared/src/obsidian-mock.ts b/packages/shared/src/obsidian-mock.ts new file mode 100644 index 00000000..a08dbebb --- /dev/null +++ b/packages/shared/src/obsidian-mock.ts @@ -0,0 +1,4 @@ +// oxlint-disable-next-line import/no-namespace +import * as ObsidianMock from './obsidian-mock.spec'; + +export default ObsidianMock; diff --git a/packages/smart-merge/test/mocks.ts b/packages/smart-merge/test/mocks.ts index d612befb..9a27a793 100644 --- a/packages/smart-merge/test/mocks.ts +++ b/packages/smart-merge/test/mocks.ts @@ -1,5 +1,4 @@ -// oxlint-disable-next-line import/no-namespace -import * as ObsidianMock from '@repo/shared/mocks'; +import ObsidianMock from '@repo/shared/obsidian-mock'; import { mock } from 'bun:test'; void mock.module('obsidian', () => ObsidianMock); diff --git a/packages/webdav/test/mocks.ts b/packages/webdav/test/mocks.ts index d612befb..89ff2a4d 100644 --- a/packages/webdav/test/mocks.ts +++ b/packages/webdav/test/mocks.ts @@ -1,5 +1,5 @@ // oxlint-disable-next-line import/no-namespace -import * as ObsidianMock from '@repo/shared/mocks'; +import ObsidianMock from '@repo/shared/obsidian-mock'; import { mock } from 'bun:test'; void mock.module('obsidian', () => ObsidianMock); From c526e005d0dd72c1243f96c7ed33d8cd8b4ada62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?He=CC=84sperus?= Date: Mon, 24 Aug 2026 12:40:05 +0800 Subject: [PATCH 2/2] fix(review): still need to commit artifact types --- packages/plugin/dist/dev.spec.d.ts | 97 +++ packages/plugin/dist/index-g3mTMY1u.spec.d.ts | 560 ++++++++++++ packages/plugin/dist/index.spec.d.ts | 797 ++++++++++++++++++ 3 files changed, 1454 insertions(+) create mode 100644 packages/plugin/dist/dev.spec.d.ts create mode 100644 packages/plugin/dist/index-g3mTMY1u.spec.d.ts create mode 100644 packages/plugin/dist/index.spec.d.ts diff --git a/packages/plugin/dist/dev.spec.d.ts b/packages/plugin/dist/dev.spec.d.ts new file mode 100644 index 00000000..068ff8e0 --- /dev/null +++ b/packages/plugin/dist/dev.spec.d.ts @@ -0,0 +1,97 @@ +import { $ as RootFs, G as Fs, P as TaskNames, ct as RecordStatsMap, et as WrappedFs, ft as Binary, h as RequestParam, lt as Stat, m as Request, nt as FileStat, rt as FolderStat, st as RecordStat, ut as StatsMap, v as Decider } from "./index-g3mTMY1u.spec.js"; +//#region src/sdk/debug-wrapper.d.ts +declare function debugWrapper(original: Fs, log: (content: string) => void): WrappedFs; +//#endregion +//#region test/test-kit.d.ts +type FsCalls = { + delete: Array; + exists: Array; + list: Array; + mkdir: Array; + move: Array<[string, string]>; + read: Array<[string, FileStat]>; + readStream: Array<[string, FileStat]>; + stat: Array; + write: Array<[string, Binary, FileStat]>; + writeStream: Array<[string, FileStat]>; +}; +type FsOptions = { + control?: Partial; + uid?: string; +}; +type FsHarness = { + calls: FsCalls; + control: Fs; + fs: RootFs; +}; +type RequestHarness = { + calls: Array; + request: Request; +}; +type ExtractedTask = { + key: string; + local?: Stat; + name: TaskNames; + remote?: Stat; +}; +declare function bytes(value: string): Binary; +declare function file(key: string, options?: { + mtime?: number; + size?: number; + uid?: string; +}): FileStat; +declare function folder(key: string): FolderStat; +declare function fileRecord(local: string, remote: string): RecordStat; +declare function folderRecord(): RecordStat; +declare function runDecider(decider: Decider, input: { + localStats?: StatsMap; + remoteStats?: StatsMap; + records?: RecordStatsMap; +}): Array; +declare function taskNames(tasks: Array): Array; +declare function taskKeys(tasks: Array): Array; +declare function findTask(tasks: Array, key: string): ExtractedTask; +declare function stream(chunks?: Array): ReadableStream; +declare function deferred(): { + promise: Promise; + reject: (reason?: unknown) => void; + resolve: (value: T | PromiseLike) => void; +}; +declare function flush(turns?: number): Promise; +declare function request(control: Request): RequestHarness; +declare function fs(options?: FsOptions): FsHarness; +declare const testKit: { + bytes: typeof bytes; + deferred: typeof deferred; + file: typeof file; + fileRecord: typeof fileRecord; + findTask: typeof findTask; + flush: typeof flush; + folder: typeof folder; + folderRecord: typeof folderRecord; + fs: typeof fs; + request: typeof request; + runDecider: typeof runDecider; + stream: typeof stream; + taskKeys: typeof taskKeys; + taskNames: typeof taskNames; +}; +//#endregion +//#region src/utils/sha-256.d.ts +declare function sha256(input: string): Promise; +//#endregion +//#region src/sdk/transform.d.ts +type SyncEngineConfig = { + deps?: { + neverBundle?: true | string | RegExp | Array | ((id: string, parentId: string | undefined, isResolved: boolean) => boolean | null | undefined); + }; +}; +declare function syncEngineTransform(): { + name: string; + renderChunk(code: string): { + code: string; + } | undefined; + tsdownConfig(config: SyncEngineConfig): void; +}; +//#endregion +export { debugWrapper, sha256, syncEngineTransform, testKit }; \ No newline at end of file diff --git a/packages/plugin/dist/index-g3mTMY1u.spec.d.ts b/packages/plugin/dist/index-g3mTMY1u.spec.d.ts new file mode 100644 index 00000000..f8dc8ee8 --- /dev/null +++ b/packages/plugin/dist/index-g3mTMY1u.spec.d.ts @@ -0,0 +1,560 @@ +import { App, ListedFiles, RequestUrlParam, Stat } from "obsidian"; +//#region ../shared/src/e2e-utils.spec.d.ts +type General = any; +//#endregion +//#region ../shared/src/binary.d.ts +type Binary = Uint8Array; +//#endregion +//#region src/types.d.ts +type MaybePromise = Promise | T; +type TogglableValue = { + enabled: boolean; + value: T; +}; +type FileStat = { + isDir: false; + key: string; + mtime: number; + size: number; + uid: string; +}; +type FolderStat = { + isDir: true; + key: string; +}; +type Stat$1 = FileStat | FolderStat; +type RecordStat = { + isDir: false; + local: string; + remote: string; +} | { + isDir: true; +}; +type StatsMap = Map; +type RecordStatsMap = Map; +type GlobMatchRule = { + expr: string; + caseSensitive: boolean; +}; +type Progress = { + total: number; + completed: number; + current?: T; +}; +//#endregion +//#region src/fs/interface.d.ts +/** + * All keys use unified format: + * - root: `/` + * - file: `note.md`, `folder/note.md` + * - folder: `folder/`, `folder/nested/` + */ +type RootFs = { + getUid(): string; + read(key: string, stat: FileStat): MaybePromise; + readStream(key: string, stat: FileStat): MaybePromise>; + write(key: string, value: Binary, stat: FileStat): MaybePromise; + writeStream(key: string, value: ReadableStream, stat: FileStat): MaybePromise; + delete(key: string): MaybePromise; + move(oldKey: string, newKey: string): MaybePromise; + mkdir(key: string, recursive?: boolean): MaybePromise; + stat(key: string): MaybePromise; + exists(key: string): MaybePromise; + list(key: string, reporter: ListReporter): MaybePromise>; +}; +type ListReporter = (progress: Required) => MaybePromise<'include' | 'exclude' | 'advance'>; +type WrappedFs = RootFs & { + original: Fs; +}; +type Fs = WrappedFs | RootFs; +type WriteAtom = { + type: 'write'; + key: string; + execute: () => MaybePromise; + resolve: (uid: string) => void; + reject: (err: Error) => void; +}; +type DeleteAtom = { + type: 'delete'; + key: string; + execute: () => MaybePromise; + resolve: () => void; + reject: (err: Error) => void; +}; +type MoveAtom = { + type: 'move'; + oldKey: string; + newKey: string; + execute: () => MaybePromise; + resolve: () => void; + reject: (err: Error) => void; +}; +type MkdirAtom = { + type: 'mkdir'; + key: string; + execute: () => MaybePromise; + resolve: () => void; + reject: (err: Error) => void; +}; +type InputAtom = WriteAtom | DeleteAtom | MoveAtom | MkdirAtom; +type CustomAtom = { + type: 'custom'; + execute: () => MaybePromise; +}; +type OutputAtom = InputAtom | CustomAtom; +type OptimizerInput = { + atoms: Array; + fs: Fs; + executeAtom: (atom: OutputAtom) => Promise; +}; +type OptimizerOutput = Array; +type BatchOptimizer = (input: OptimizerInput) => OptimizerOutput; +//#endregion +//#region ../../node_modules/.bun/uni-kv@..+..+uni-kv.tgz/node_modules/uni-kv/dist/interface.d.ts +//#region src/interface.d.ts +type Database, M extends Record, F extends boolean> = { + getStore(name: K): Store; + getStoreNames(): IsPromise, F>; + deleteStore(name: string): IsPromise; + clearStores(): IsPromise; + getMeta(key: T): IsPromise; + setMeta(key: T, value: M[T]): IsPromise; + dispose(): IsPromise; +}; +type Store = { + get(key: string): IsPromise; + set(key: string, value: T): IsPromise; + delete(key: string): IsPromise; + clear(): IsPromise; + keys(): IsPromise, F>; + values(): IsPromise, F>; + entries(): IsPromise, F>; + batch(operations: Array>): IsPromise>, F>; +}; +type StoreSync = Store; +type StoreAsync = Store; +type DatabaseSync = Record, M extends Record = {}> = Database; +type DatabaseAsync = Record, M extends Record = {}> = Database; +type GetOperation = { + type: 'get'; + key: string; +}; +type GetResult = { + key: string; + value: T | undefined; +}; +type SetOperation = { + type: 'set'; + key: string; + value: T; +}; +type DeleteOperation = { + type: 'delete'; + key: string; +}; +type StoreOperations = GetOperation | SetOperation | DeleteOperation; +type IsPromise = F extends true ? Promise : T; +//#endregion +//#region src/modules/Storage.d.ts +type RecordStore = StoreAsync; +declare class Storage { + private readonly ctx; + private readonly memoryDB; + private readonly indexedDB; + constructor(ctx: { + getNamespace: () => string; + }); + private readonly getRecordStore; + private readonly deleteRecordStore; + private readonly clearRecordStores; + private readonly recordStoreExists; + readonly root: { + clearRecordStores: () => Promise; + deleteRecordStore: (namespace?: string) => MaybePromise; + getRecordStore: (namespace?: string) => { + get(key: string): Promise; + set(key: string, value: RecordStat): Promise; + delete(key: string): Promise; + clear(): Promise; + keys(): Promise; + values(): Promise; + entries(): Promise<[string, RecordStat][]>; + batch(operations: StoreOperations[]): Promise[]>; + }; + indexedDB: DatabaseAsync; + memoryDB: { + getStore(name: K): { + get(key: string): any; + set(key: string, value: any): void; + delete(key: string): void; + clear(): void; + keys(): string[]; + values(): any[]; + entries(): [string, any][]; + batch(operations: StoreOperations[]): GetResult[]; + }; + getStoreNames(): string[]; + deleteStore(name: string): void; + clearStores(): void; + getMeta(key: T): any; + setMeta(key: T, value: any): void; + dispose(): void; + }; + recordStoreExists: (namespace?: string) => MaybePromise; + }; + readonly dispose: () => void; +} +//#endregion +//#region src/sync/tasks/interface.d.ts +type BaseTaskOptions = { + localFs: Fs; + remoteFs: Fs; + record: RecordStore; +}; +type TaskNames = 'addRecord' | 'removeRecord' | 'createLocalDir' | 'createRemoteDir' | 'download' | 'resolveConflict' | 'removeLocal' | 'removeRemote' | 'upload' | 'moveLocal' | 'moveRemote'; +type ConflictResolverPayload = { + local: FileStat; + remote: FileStat; + key: string; + localFs: Fs; + remoteFs: Fs; + record: RecordStore; +}; +type ConflictResolver = (payload: ConflictResolverPayload) => MaybePromise; +declare abstract class BaseTask { + readonly options: BaseTaskOptions & T; + constructor(options: BaseTaskOptions & T); + protected readonly remoteFs: Fs; + protected readonly localFs: Fs; + protected readonly record: RecordStore; + name: TaskNames; + prettyName: string; + readonly key: string; + readonly local: (BaseTaskOptions & T)['local']; + readonly remote: (BaseTaskOptions & T)['remote']; + abstract exec(): MaybePromise; +} +//#endregion +//#region src/sync/tasks/AddRecord.d.ts +declare class AddRecord extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/CreateRemoteDir.d.ts +declare class CreateRemoteDir extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/Download.d.ts +declare class Download extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/MoveLocal.d.ts +declare class MoveLocal extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/MoveRemote.d.ts +declare class MoveRemote extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/RemoveLocal.d.ts +declare class RemoveLocal extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/RemoveRecord.d.ts +declare class RemoveRecord extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/RemoveRemote.d.ts +declare class RemoveRemote extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/tasks/ResolveConflict.d.ts +declare class ResolveConflict extends BaseTask { + exec: () => MaybePromise; +} +//#endregion +//#region src/sync/tasks/Upload.d.ts +declare class Upload extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/sync/decision/interface.d.ts +type TaskOptions = { + key: string; + remote?: Stat$1; + local?: Stat$1; +}; +type OptionsWithRemoteFileStat = { + remote: FileStat; +} & TaskOptions; +type OptionsWithLocalFileStat = { + local: FileStat; +} & TaskOptions; +type OptionsWithRemoteFolderStat = { + remote: FolderStat; +} & TaskOptions; +type OptionsWithLocalFolderStat = { + local: FolderStat; +} & TaskOptions; +type OptionsWithLocalStat = { + local: Stat$1; +} & TaskOptions; +type OptionsWithRemoteStat = { + remote: Stat$1; +} & TaskOptions; +type OptionsWithBothStats = { + local: Stat$1; + remote: Stat$1; +} & TaskOptions; +type OptionsWithBothFileStats = { + local: FileStat; + remote: FileStat; +} & TaskOptions; +type OptionsWithLocalStatAndOldKey = { + local: Stat$1; + oldKey: string; +} & TaskOptions; +type OptionsWithRemoteStatAndOldKey = { + remote: Stat$1; + oldKey: string; +} & TaskOptions; +type TaskOptionsMap = { + download: OptionsWithRemoteFileStat; + upload: OptionsWithLocalFileStat; + resolveConflict: OptionsWithBothFileStats; + removeLocal: OptionsWithLocalStat; + removeRemote: OptionsWithRemoteStat; + createLocalDir: OptionsWithRemoteFolderStat; + createRemoteDir: OptionsWithLocalFolderStat; + removeRecord: TaskOptions; + addRecord: OptionsWithBothStats; + moveLocal: OptionsWithRemoteStatAndOldKey; + moveRemote: OptionsWithLocalStatAndOldKey; +}; +declare const taskMap: { + readonly addRecord: typeof AddRecord; + readonly createLocalDir: typeof CreateLocalDir; + readonly createRemoteDir: typeof CreateRemoteDir; + readonly download: typeof Download; + readonly moveLocal: typeof MoveLocal; + readonly moveRemote: typeof MoveRemote; + readonly removeLocal: typeof RemoveLocal; + readonly removeRecord: typeof RemoveRecord; + readonly removeRemote: typeof RemoveRemote; + readonly resolveConflict: typeof ResolveConflict; + readonly upload: typeof Upload; +}; +type TaskFactory = (name: N, options: TaskOptionsMap[N]) => InstanceType<(typeof taskMap)[N]>; +type Decider = (input: DeciderInput) => Array; +type DeciderInput = { + localStats: StatsMap; + remoteStats: StatsMap; + records: RecordStatsMap; + taskFactory: TaskFactory; + logger: (log: string) => void; +}; +//#endregion +//#region src/sync/tasks/CreateLocalDir.d.ts +declare class CreateLocalDir extends BaseTask { + exec(): Promise; +} +//#endregion +//#region src/modules/Registrar.d.ts +type RejectableWrapper = (value: T) => T | undefined; +type OrderedWrapperEntry = { + priority: number; + apply: RejectableWrapper; +}; +type RemoteRequestMiddlewareEntry = OrderedWrapperEntry; +type LocalRequestMiddlewareEntry = OrderedWrapperEntry; +type FsWrapperEntry = OrderedWrapperEntry; +type CheckConnectionResult = { + success: true; +} | { + success: false; + reason: string; +}; +type RemoteFsEntry = { + instantiate: (request: Request) => RootFs; + prettyName: () => string; + checkConnection: (request: Request) => MaybePromise; +}; +type DeciderEntry = { + decider: Decider; + prettyName: () => string; +}; +type ConflictResolverEntry = { + prettyName: () => string; + resolver: ConflictResolver; +}; +type GeneralFn = (...args: ReadonlyArray) => unknown; +type RejectableApply = (...input: Parameters) => ReturnType | undefined; +type OrderedApplyEntry = { + apply: RejectableApply; + priority: number; +}; +type RemoteLister = (info: Infras & { + trigger: string; + reporter: ListReporter; +}) => MaybePromise>; +type RemoteListerEntry = OrderedApplyEntry; +type OptimizerEntry = OrderedApplyEntry; +type RequestParam = Omit & { + body?: string | Binary; +}; +type RequestResponse = { + text: () => string; + bytes: () => Binary; + json: () => General; + headers: Record; + status: number; +}; +type Request = (params: RequestParam | string) => Promise; +type Infras = { + localFs: Fs; + remoteFs: Fs; + record: RecordStore; +}; +declare class Registrar { + private readonly ctx; + private readonly cleanupCallbacks; + private readonly localFsWrapperRegistry; + private readonly remoteFsWrapperRegistry; + private readonly localOptimizerRegistry; + private readonly remoteOptimizerRegistry; + private readonly remoteListerRegistry; + private readonly remoteRequestMiddlewareRegistry; + private readonly localRequestMiddlewareRegistry; + private readonly remoteFsRegistry; + private readonly deciderRegistry; + private readonly conflictResolverRegistry; + readonly settings: { + remoteFs: string; + decider: string; + conflictResolver: string; + }; + constructor(ctx: { + app: App; + getRecordStore: (namespace?: string) => StoreAsync; + }); + private readonly getVaultRequest; + private readonly createLocalFs; + private readonly createRemoteFs; + private readonly getRequest; + private readonly getCheckConnection; + private readonly getDecider; + private readonly optimizeLocal; + private readonly optimizeRemote; + private readonly listRemote; + private readonly getConflictResolver; + private readonly getNamespace; + private readonly initializeSync; + root: { + conflictResolverRegistry: Map; + createLocalFs: () => Fs; + createRemoteFs: (remoteFs?: string) => Fs; + deciderRegistry: Map; + getCheckConnection: (remoteFs?: string) => () => MaybePromise; + getConflictResolver: () => ConflictResolver; + getDecider: () => Decider; + getNamespace: (localFs?: Fs, remoteFs?: Fs) => string; + getRequest: () => Request; + getVaultRequest: () => VaultRequest; + initializeSync: () => Infras; + listRemote: RemoteLister; + optimizeLocal: BatchOptimizer; + optimizeRemote: BatchOptimizer; + registerConflictResolver: (key: string, entry: ConflictResolverEntry) => () => boolean; + registerCss: (css: string) => () => void; + registerDecider: (key: string, entry: DeciderEntry) => () => boolean; + registerLocalFsWrapper: (entry: FsWrapperEntry) => () => boolean; + registerLocalOptimizer: (entry: OptimizerEntry) => () => boolean; + registerLocalRequestMiddleware: (entry: LocalRequestMiddlewareEntry) => () => boolean; + registerRemoteFs: (key: string, entry: RemoteFsEntry) => () => boolean; + registerRemoteFsWrapper: (entry: FsWrapperEntry) => () => boolean; + registerRemoteLister: (entry: RemoteListerEntry) => () => boolean; + registerRemoteOptimizer: (entry: OptimizerEntry) => () => boolean; + registerRemoteRequestMiddleware: (entry: RemoteRequestMiddlewareEntry) => () => boolean; + remoteFsRegistry: Map; + }; + readonly dispose: () => void; +} +//#endregion +//#region src/fs/vault/request.d.ts +type VaultRequestParam = { + method: 'GET'; + key: string; +} | { + method: 'GET_STREAM'; + key: string; +} | { + method: 'PUT'; + key: string; + value: Binary; + headers?: { + mtime?: number; + ctime?: number; + }; +} | { + method: 'APPEND'; + key: string; + value: Binary; + headers?: { + mtime?: number; + ctime?: number; + }; +} | { + method: 'DELETE'; + key: string; + headers?: { + permanent?: boolean; + }; +} | { + method: 'MOVE'; + key: string; + headers: { + destination: string; + }; +} | { + method: 'MKDIR'; + key: string; +} | { + method: 'EXISTS'; + key: string; +} | { + method: 'STAT'; + key: string; + headers?: { + cached?: boolean; + }; +} | { + method: 'LIST'; + key: string; + headers?: { + cached?: boolean; + }; +}; +type VaultRequestResponseMap = { + GET: Binary; + GET_STREAM: ReadableStream; + PUT: void; + APPEND: void; + DELETE: void; + MOVE: void; + MKDIR: void; + EXISTS: boolean; + STAT: Stat; + LIST: ListedFiles; +}; +type VaultRequest = (params: T) => Promise; +//#endregion +export { RootFs as $, AddRecord as A, StoreOperations as B, RemoveRemote as C, MoveLocal as D, MoveRemote as E, RecordStore as F, Fs as G, BatchOptimizer as H, Storage as I, MkdirAtom as J, InputAtom as K, DatabaseAsync as L, ConflictResolver as M, ConflictResolverPayload as N, Download as O, TaskNames as P, OutputAtom as Q, DatabaseSync as R, ResolveConflict as S, RemoveLocal as T, CustomAtom as U, StoreSync as V, DeleteAtom as W, OptimizerInput as X, MoveAtom as Y, OptimizerOutput as Z, CreateLocalDir as _, FsWrapperEntry as a, MaybePromise as at, TaskFactory as b, OptimizerEntry as c, RecordStatsMap as ct, RemoteLister as d, TogglableValue as dt, WrappedFs as et, RemoteListerEntry as f, Binary as ft, RequestResponse as g, RequestParam as h, DeciderEntry as i, GlobMatchRule as it, BaseTask as j, CreateRemoteDir as k, Registrar as l, Stat$1 as lt, Request as m, CheckConnectionResult as n, FileStat as nt, Infras as o, Progress as ot, RemoteRequestMiddlewareEntry as p, General as pt, ListReporter as q, ConflictResolverEntry as r, FolderStat as rt, LocalRequestMiddlewareEntry as s, RecordStat as st, VaultRequest as t, WriteAtom as tt, RemoteFsEntry as u, StatsMap as ut, Decider as v, RemoveRecord as w, Upload as x, DeciderInput as y, StoreAsync as z }; \ No newline at end of file diff --git a/packages/plugin/dist/index.spec.d.ts b/packages/plugin/dist/index.spec.d.ts new file mode 100644 index 00000000..3ed5a981 --- /dev/null +++ b/packages/plugin/dist/index.spec.d.ts @@ -0,0 +1,797 @@ +import { $ as RootFs, A as AddRecord, B as StoreOperations, C as RemoveRemote, D as MoveLocal, E as MoveRemote, F as RecordStore, G as Fs, H as BatchOptimizer, I as Storage, J as MkdirAtom, K as InputAtom, L as DatabaseAsync, M as ConflictResolver, N as ConflictResolverPayload, O as Download, P as TaskNames, Q as OutputAtom, R as DatabaseSync, S as ResolveConflict, T as RemoveLocal, U as CustomAtom, V as StoreSync, W as DeleteAtom, X as OptimizerInput, Y as MoveAtom, Z as OptimizerOutput, _ as CreateLocalDir, a as FsWrapperEntry, at as MaybePromise, b as TaskFactory, c as OptimizerEntry, ct as RecordStatsMap, d as RemoteLister, dt as TogglableValue, et as WrappedFs, f as RemoteListerEntry, ft as Binary, g as RequestResponse, h as RequestParam, i as DeciderEntry, it as GlobMatchRule, j as BaseTask, k as CreateRemoteDir, l as Registrar, lt as Stat, m as Request, n as CheckConnectionResult, nt as FileStat, o as Infras, ot as Progress, p as RemoteRequestMiddlewareEntry, pt as General$1, q as ListReporter, r as ConflictResolverEntry, rt as FolderStat, s as LocalRequestMiddlewareEntry, st as RecordStat, t as VaultRequest, tt as WriteAtom, u as RemoteFsEntry, ut as StatsMap, v as Decider, w as RemoveRecord, x as Upload, y as DeciderInput, z as StoreAsync } from "./index-g3mTMY1u.spec.js"; +import { App, Command, EventRef, IconName, Modal, Plugin, Setting, SettingDefinition, SettingDefinitionGroup, SettingDefinitionItem, SettingDefinitionList, SettingDefinitionPage, ToggleComponent } from "obsidian"; +//#region ../../node_modules/.bun/synthkernel@.+synthkernel.tgz/node_modules/synthkernel/dist/context.d.ts +//#region src/context.d.ts +type General = any; +type GeneralConstructor = new (...args: Array) => General; +type ModuleConstructor = new (context: C) => General; +type GeneralModuleInput = ReadonlyArray | ReadonlyArray; +type IsPlainObject = T extends object ? T extends Function | Date | RegExp | Array | Map | Set ? false : true : false; +type ShallowMerge = IsPlainObject extends true ? (IsPlainObject extends true ? Omit & B : B) : B; +type Keys = T extends General ? keyof T : never; +type InstanceEach = T extends ReadonlyArray ? { [K in keyof T]: InstanceType; } : T; +type PickEach, K extends PropertyKey> = { [I in keyof T]: Pick>; }; +type RootValue = RootKey extends keyof T ? Extract : {}; +type MergeRootEach> = { [I in keyof T]: ShallowMerge, RootValue>; }; +type ExtractKeyEach, K extends Keys> = { [I in keyof T]: K extends keyof T[I] ? T[I][K] : never; }; +type MergeObjects, O extends ReadonlyArray = MergeRootEach> = { [P in Keys]: MergeValues>; }; +type MergeSingleKey[number]>> = MergeValues, K>>; +type MergePair = [A] extends [never] ? B : [B] extends [never] ? A : ShallowMerge; +type MergeValues> = T extends readonly [infer First, ...infer Rest] ? [First] extends [never] ? MergeValues : Rest extends ReadonlyArray ? Rest['length'] extends 0 ? First : MergePair> : never : never; +type MergeResult[number]>, Pr extends object, Po extends object> = MergeObjects<[Pr, ...PickEach, K>, Po]>; +type Context$1[number]>, Pr extends object = {}, Po extends object = {}> = MergeResult & { + __modules__: WeakMap[number]>; + __getModule__: InstanceEach[number]>(ctor: C) => InstanceType; + __addModule__: >>(newModule: N) => Context$1<[...M, N], K, Pr, Po>; + __assign__: (obj: Partial>) => Context$1; +}; +declare const ROOT_KEY = "root"; +type RootKey = typeof ROOT_KEY; +//#endregion +//#region ../../node_modules/.bun/synthkernel@.+synthkernel.tgz/node_modules/synthkernel/dist/reactive.d.ts +//#region src/reactive.d.ts +type RefMatchingFunc = (newValue: T, oldValue: T) => unknown; +type Ref = { + (): T; + (newValue: T): void; + subscribe(func: RefMatchingFunc, options?: { + immediate?: boolean; + }): () => void; + unsubscribe(func: RefMatchingFunc): void; + clear(): void; +}; +//#endregion +//#region src/modules/EventBus.d.ts +type Dispatch = (...[key, payload]: undefined extends O[K] ? [K] : [K, O[K]]) => void; +type On = (key: K, callback: (payload: O[K]) => void) => () => void; +declare class EventBus { + readonly events: { + logSync: string; + logGeneral: string; + errorSync: string; + errorGeneral: string; + }; + private readonly cleanupCallbacks; + private readonly isIdle; + private readonly syncLogs; + private readonly generalLogs; + constructor(); + private readonly getThisSync; + private readonly putSyncLog; + private readonly putGeneralLog; + private readonly subscribers; + private readonly on; + private readonly dispatch; + private readonly getLogs; + readonly dispose: () => void; + readonly root: { + dispatch: Dispatch; + getLogs: () => string; + isIdle: Ref; + on: On; + }; +} +//#endregion +//#region src/modules/I18n.d.ts +type ObsidianLanguageCode = 'en' | 'af' | 'am' | 'ar' | 'az' | 'be' | 'bg' | 'bn' | 'ca' | 'cs' | 'da' | 'de' | 'dv' | 'el' | 'en-GB' | 'eo' | 'es' | 'eu' | 'fa' | 'fi' | 'fr' | 'ga' | 'gl' | 'he' | 'hi' | 'hr' | 'hu' | 'id' | 'it' | 'ja' | 'ka' | 'kh' | 'kn' | 'ko' | 'ky' | 'la' | 'lt' | 'lv' | 'ml' | 'ms' | 'nan-TW' | 'ne' | 'nl' | 'nn' | 'no' | 'oc' | 'or' | 'pl' | 'pt' | 'pt-BR' | 'ro' | 'ru' | 'sa' | 'si' | 'sk' | 'sl' | 'sq' | 'sr' | 'sv' | 'sw' | 'ta' | 'te' | 'th' | 'tl' | 'tr' | 'tt' | 'uk' | 'ur' | 'uz' | 'vi' | 'zh' | 'zh-TW'; +type Primitive = string | number | boolean | null | undefined; +type Fragment = (frag: DocumentFragment, args: A) => void; +type TranslationResource = Record>; +type InterpolationValues = Record; +type TranslateParams | string> = R extends Fragment ? ([undefined] extends [A] ? [] : [A]) : [] | [InterpolationValues]; +type Translate = (key: K, ...args: TranslateParams) => O[K] extends string ? string : DocumentFragment; +declare class I18n { + private readonly targetLangs; + readonly i18n: {}; + private readonly registerI18n; + private readonly translate; + root: { + registerI18n: (code: ObsidianLanguageCode, resource: TranslationResource) => void; + translate: Translate; + }; +} +//#endregion +//#region src/modules/Sync.d.ts +type SyncTerminateReason = { + result: 'cancelled'; +} | { + result: 'completed'; +} | { + result: 'failed'; + error: string; +} | { + result: 'noop'; +}; +type TaskInfo = { + name: TaskNames; + key: string; + prettyName: string; + isDir: boolean; +}; +type FailedTaskInfo = TaskInfo & { + error: string; +}; +declare class Sync { + private readonly ctx; + dispatch: Dispatch; + on: On; + constructor(ctx: { + dispatch: Dispatch; + initializeSync: () => Infras; + getDecider: () => Decider; + on: On; + translate: Translate; + listRemote: RemoteLister; + getConflictResolver: () => ConflictResolver; + }); + readonly events: { + syncStarted: { + isCancelled: Ref; + trigger: string; + }; + remoteWalkProgress: Progress; + syncTerminated: SyncTerminateReason; + requestConfirmDelete: Array; + requestConfirmTasks: Array; + syncCanceled: undefined; + taskCompleted: TaskInfo; + taskFailed: FailedTaskInfo; + executionStarted: Array; + }; + readonly settings: { + maxFileSize: TogglableValue; + exclusionRules: Array; + inclusionRules: Array; + confirmDeleteInAutoSync: boolean; + confirmTasksInSync: boolean; + }; + private readonly postProcess; + private readonly confirmTasks; + private readonly confirmDeletion; + private readonly executeSync; + private readonly convertDeleteToUpload; + root: { + executeSync: (trigger: string) => Promise<{ + result: "cancelled"; + } | { + result: "completed"; + } | { + result: "failed"; + error: string; + } | { + result: "noop"; + }>; + }; +} +//#endregion +//#region src/modules/Observability.d.ts +type SyncStage = 'none' | 'walkingRemote' | 'awaitingConfirmation' | 'executing' | 'completed' | 'completedNoop' | 'cancelled' | 'failed'; +type AddRibbonIcon = (icon: IconName, title: string, callback: (evt: MouseEvent) => void) => HTMLElement; +declare class Observability { + private readonly ctx; + private lastSyncTime; + private readonly sinceLastSyncText; + private readonly syncStage; + private readonly walkProgress; + private readonly executionProgress; + private readonly cleanupCallbacks; + private readonly t; + private readonly progressText; + readonly settings: { + noticeStatusOnMobile: boolean; + exportLogsDirectory: string; + }; + readonly i18n: { + startSync: string; + startNonInteractiveSync: string; + stopSync: string; + showProgress: string; + exportLogsToFile: string; + exportLogsFailed: string; + idle: string; + }; + constructor(ctx: { + addStatusBarItem: () => HTMLElement; + on: On; + translate: Translate; + isIdle: Ref; + dispatch: Dispatch; + requestSync: (trigger: string) => Promise; + showProgress: () => void; + addCommand: (command: Command) => Command; + addRibbonIcon: AddRibbonIcon; + getLogs: () => string; + app: App; + }); + readonly start: () => void; + private readonly setupStatus; + private readonly setupCommands; + private readonly exportLogs; + readonly dispose: () => void; + root: { + executionProgress: Ref>; + exportLogs: () => Promise; + syncStage: Ref; + walkProgress: Ref; + }; +} +//#endregion +//#region src/components/file-tree/index.d.ts +type FileTreeTranslations = { + selectAll: string; + xSelected: string; +}; +//#endregion +//#region src/modules/Extensibility.d.ts +type ModuleInstance = { + moduleSettings: object; + dispose?: () => void; + start?: () => void; +}; +type ModuleCtor = new (ctx: object) => ModuleInstance; +type ModuleMeta = { + id: string; + name: string; + version: string; + description: string; + main: string; + icon?: string; + minPluginVersion?: string; + integrity: string; +}; +type AugmentedModuleMeta = ModuleMeta & { + enabled: boolean; + source: string; + icon: string; +}; +declare class Extensibility { + private readonly ctx; + private readonly moduleDir; + private readonly sourceCache; + private readonly discoveredModules; + private readonly loadedModules; + private readonly moduleStore; + private autoUpdateTimeout?; + readonly settings: { + moduleSources: Array; + moduleAutoUpdate: boolean; + modules: Record; + }; + readonly i18n: { + failedToLoadModule: string; + failedToDownloadModule: string; + failedToFetchSource: string; + }; + readonly events: { + moduleLoaded: string; + moduleUnloaded: string; + }; + constructor(ctx: { + app: App; + __addModule__: Context['__addModule__']; + __getModule__: Context['__getModule__']; + dispatch: Dispatch; + translate: Translate; + allModules: Set; + isIdle: Ref; + saveSettings: () => Promise; + indexedDB: DatabaseAsync>; + }); + readonly start: () => void; + private readonly createOperationFactory; + private readonly loadAllModules; + private readonly loadModule; + private readonly unloadModule; + private readonly downloadModule; + private readonly deleteModule; + private readonly fetchSources; + private readonly updateModules; + private readonly updateModuleMeta; + private readonly enableModule; + private readonly disableModule; + private readonly getModulePath; + private readonly parseModulePath; + readonly dispose: () => void; + readonly root: { + deleteModule: (id: string) => Promise; + disableModule: (id: string) => void; + discoveredModules: Map; + downloadModule: (meta: AugmentedModuleMeta, waitIdle?: boolean) => Promise; + enableModule: (id: string) => Promise; + fetchSources: (manual?: boolean) => Promise; + loadAllModules: () => Promise; + loadModule: (meta: AugmentedModuleMeta, start?: boolean, module?: string) => Promise; + loadedModules: Map; + pluginOutdated: boolean; + unloadModule: (id: string) => void; + updateModuleMeta: (meta: AugmentedModuleMeta) => Promise; + updateModules: () => Promise; + }; +} +//#endregion +//#region src/components/ModuleEditorModal.d.ts +type ModuleEditorTranslations = { + editModuleInformation: string; + enable: string; + name: string; + namePlaceholder: string; + description: string; + descriptionPlaceholder: string; + icon: string; + iconDescription: Fragment; + iconPlaceholder: string; + updateSource: string; + updateSourceDescription: string; + updateSourcePlaceholder: string; + invalidValue: string; + integrityVerification: string; + integrityVerificationDescription: Fragment; + save: string; + cancel: string; +}; +//#endregion +//#region src/components/UnknownModuleModal.d.ts +type FileInfo = { + path: string; + size: string; + mtime: string; + ctime: string; + fileName: string; +}; +type UnknownModuleTranslations = { + unknownModule: string; + unknownModuleDescription: Fragment; + delete: string; + configure: string; +}; +//#endregion +//#region src/modules/Setting.d.ts +type SettingTree = { + (self: SettingTree): SettingDefinitionItem; + [key: number]: SettingTree; +}; +type NestedCallableTree = { + (self: SettingTree): SettingDefinitionItem; + [key: number]: CallableOrObjectTree; +}; +type CallableOrObjectTree = NestedCallableTree | { + [key: number]: CallableOrObjectTree; +}; +type SettingEntry = { + priority: number; + apply: CallableOrObjectTree; +}; +declare class Setting$1 { + private readonly ctx; + private readonly cleanupCallbacks; + private settingTab?; + private readonly settingRegistry; + readonly i18n: { + match: string; + matchLabelDescription: string; + speed: string; + speedLabelDescription: string; + }; + constructor(ctx: { + on: On; + translate: Translate; + registerSetting: (entry: SettingEntry) => () => boolean; + }); + readonly start: () => void; + private readonly matchLabel; + private readonly speedLabel; + private readonly addSettingTab; + private readonly rerenderSettingTab; + private readonly refreshSettingTab; + root: { + addSettingTab: (plugin: Plugin) => void; + matchLabel: () => { + text: string; + tooltip: string; + }; + refreshSettingTab: () => void | undefined; + registerSetting: (entry: SettingEntry) => () => boolean; + rerenderSettingTab: () => void | undefined; + speedLabel: () => { + color: string; + text: string; + textColor: string; + tooltip: string; + }; + }; + readonly dispose: () => void; +} +//#endregion +//#region src/settings/utils.d.ts +type AugmentedSettingDefinitionItem = SettingDefinitionGroup | SettingDefinitionList | (SettingDefinitionPage & { + labels?: Array; +}) | (SettingDefinition & { + labels?: Array; +}); +type LabelDefinition = { + text: string; + tooltip: string; + color?: string; + textColor?: string; +}; +declare function s(parent: (self: SettingTree) => AugmentedSettingDefinitionItem, children?: CallableOrObjectTree): CallableOrObjectTree; +//#endregion +//#region src/settings/controls.d.ts +type ControlsSettingTranslations = { + controls: string; + maxFileSize: string; + maxFileSizeDescription: string; + maxFileSizePlaceholder: string; + maxRequestConcurrency: string; + minRequestInterval: string; + minRequestIntervalDescription: string; + minRequestIntervalPlaceholder: string; + maxRequestConcurrencyPlaceholder: string; + maxRequestConcurrencyDescription: string; + maxMemoryConsumption: string; + maxMemoryConsumptionDescription: string; + maxMemoryConsumptionPlaceholder: string; +}; +//#endregion +//#region src/settings/development.d.ts +type DevelopmentSettingTranslations = { + development: string; + clearRecords: string; + recordsCleared: string; + clear: string; + clearRecordsDescription: string; + export: string; + exportLogsDescription: string; + exportLogsDirectoryPlaceholder: string; + exportLogsToFile: string; + moduleSources: string; + moduleSourcesDescription: string; + edit: string; + xConfigured: string; + addSource: string; + noSourceConfigured: string; + moduleSourcePlaceholder: string; +}; +//#endregion +//#region src/components/MigrationModal.d.ts +type MigrationModalTranslations = { + cancel: string; + remoteMigration: string; + migrationProcess: string; + startMigration: string; + migrationDescription: string; + migrationPhase1Description: string; + migrationPhase2Description: string; + migrationPhase3Description: string; + toggleWithoutMigration: string; + migrationFailed: string; + completed: string; + hide: string; + done: string; +}; +type MigrationEvents = { + migrationProgress: Progress; + migrationFailed: string; +}; +type MigrationContext = { + app: App; + on: On; + dispatch: Dispatch; + translate: Translate; + requestSync: (trigger: string) => Promise; + initializeSync: () => Infras; + memoryDB: ExistingMemoryDB; +}; +declare function setNeedMigration(ctx: MigrationContext, { toggle, needMigration, content, apply }: { + toggle: ToggleComponent; + needMigration?: (value: boolean) => MaybePromise; + content: (value: boolean) => string | DocumentFragment; + apply: (value: boolean) => MaybePromise; +}): void; +//#endregion +//#region src/settings/features.d.ts +type FeaturesSettingTranslations = { + features: string; + realtimeSyncFastMode: string; + realtimeSyncFastModeDescription: string; + realtimeSync: string; + realtimeSyncDescription: string; + realtimeSyncPlaceholder: string; + startupSync: string; + startupSyncDescription: string; + startupSyncPlaceholder: string; + scheduledSync: string; + scheduledSyncDescription: string; + scheduledSyncPlaceholder: string; + asymmetricStorage: string; + asymmetricStorageDescription: Fragment; + asymmetricStorageMigration: Fragment<'enable' | 'disable'>; +} & MigrationModalTranslations; +//#endregion +//#region src/settings/filter.d.ts +type FilterSettingTranslations = { + filterRules: string; + inclusionRules: string; + inclusionRulesDescription: Fragment; + exclusionRules: string; + exclusionRulesDescription: Fragment; + xConfigured: string; + addInclusionRule: string; + addExclusionRule: string; + noRuleConfigured: string; + filterPlaceholder: string; + caseSensitive: string; +}; +//#endregion +//#region src/settings/head.d.ts +type HeadSettingTranslations = { + moduleAutoUpdate: string; + moduleAutoUpdateDescription: string; + moduleManagement: string; + moduleManagementDescription: string; + backend: string; + backendDescription: string; + syncStrategy: string; + syncStrategyDescription: string; + checkConnectionFailed: string; + checkConnectionSuccess: string; + checkConnection: string; + conflictResolveStrategy: string; + conflictResolveStrategyDescription: string; + xEnabled: string; + settingTips: Fragment<{ + labels: Array; + addLabel: typeof addLabel; + }>; +}; +declare function addLabel(element: Element, { text, tooltip, color, textColor }: LabelDefinition): HTMLSpanElement; +//#endregion +//#region src/settings/miscellaneous.d.ts +type MiscellaneousSettingTranslations = { + miscellaneous: string; + diffMatchPatch: string; + keepLocal: string; + keepRemote: string; + skip: string; + noticeStatusOnMobile: string; + noticeStatusOnMobileDescription: string; + confirmTasksInSync: string; + confirmTasksInSyncDescription: string; + confirmDeleteInAutoSync: string; + confirmDeleteInAutoSyncDescription: string; + customHeaders: string; + customHeadersDescription: string; + edit: string; + xConfigured: string; + addHeader: string; + noHeaderConfigured: string; + headerKeyPlaceholder: string; + headerValuePlaceholder: string; + addSecretHeader: string; +}; +//#endregion +//#region src/components/module-management/index.d.ts +type ModuleManagementTranslations = { + disableModule: string; + downloadModule: string; + enableModule: string; + installed: string; + loadingModules: string; + noInstalledModulesFound: string; + noMatchingModulesFound: string; + noModulesAvailable: string; + updateAvailable: string; + updateModule: string; + deleteModule: string; + editModuleInformation: string; + official: string; + someModulesHidden: string; +}; +//#endregion +//#region src/settings/module-management.d.ts +type ModulesTranslations = ModuleManagementTranslations & { + searchModules: string; + moduleManagement: string; + showInstalledOnly: string; +}; +//#endregion +//#region src/modules/Bootstrap.d.ts +type CustomHeaders = Array<{ + type: 'plaintext' | 'secret'; + value: string; + key: string; +}>; +type ExistingMemoryDB = DatabaseSync<{ + localContext20000: Stat; + remoteContext10000: Stat; + remoteContext20000: Stat; +}, { + localContext20000Marker: string; + remoteContext10000Marker: string; + remoteContext20000Marker: string; +}>; +declare class Bootstrap { + private readonly ctx; + private readonly cleanupCallbacks; + private readonly memoryStates; + private isCancelled?; + private readonly localPool; + private readonly remotePool; + private localFs?; + private remoteFs?; + readonly i18n: { + bidirectional: string; + mirrorLocal: string; + mirrorRemote: string; + latestSurvive: string; + keepLocal: string; + keepRemote: string; + renameAndKeepBoth: string; + skip: string; + } & ControlsSettingTranslations & DevelopmentSettingTranslations & FeaturesSettingTranslations & FilterSettingTranslations & HeadSettingTranslations & MiscellaneousSettingTranslations & UnknownModuleTranslations & ModuleEditorTranslations & FileTreeTranslations & ModulesTranslations; + readonly settings: { + maxMemoryConsumption: TogglableValue; + maxRequestConcurrency: TogglableValue; + minRequestInterval: TogglableValue; + realtimeSyncFastMode: boolean; + asymmetricStorage: boolean; + customHeaders: CustomHeaders; + }; + constructor(ctx: { + app: App; + registerI18n: (code: ObsidianLanguageCode, resource: TranslationResource) => void; + on: On; + dispatch: Dispatch; + memoryDB: ExistingMemoryDB; + registerDecider: (id: string, entry: DeciderEntry) => void; + registerLocalFsWrapper: (entry: FsWrapperEntry) => void; + registerRemoteFs: (id: string, entry: RemoteFsEntry) => void; + registerRemoteFsWrapper: (entry: FsWrapperEntry) => void; + translate: Translate; + optimizeLocal: BatchOptimizer; + optimizeRemote: BatchOptimizer; + registerLocalOptimizer: (optimizer: OptimizerEntry) => void; + registerRemoteOptimizer: (optimizer: OptimizerEntry) => void; + registerRemoteLister: (entry: RemoteListerEntry) => () => boolean; + registerConflictResolver: (id: string, entry: ConflictResolverEntry) => void; + registerRemoteRequestMiddleware: (entry: RemoteRequestMiddlewareEntry) => void; + registerLocalRequestMiddleware: (entry: LocalRequestMiddlewareEntry) => void; + }); + readonly start: () => void; + readonly dispose: () => void; +} +//#endregion +//#region src/modules/ProgressModal.d.ts +type DeleteConfirmReturn = { + delete: Array; + reupload: Array; +}; +type TaskCounts = { + total: number; + deleteLocal: number; + deleteRemote: number; + conflict: number; +}; +declare class ProgressModal extends Modal { + private readonly ctx; + private readonly moduleCleanupCallbacks; + private readonly t; + private opening; + private readonly modalCleanupCallbacks; + private readonly dispatch; + private description?; + private detailContainer?; + private controls?; + constructor(ctx: { + app: App; + translate: Translate; + on: On; + dispatch: Dispatch; + syncStage: Ref; + walkProgress: Ref; + executionProgress: Ref>; + }); + readonly events: { + tasksConfirmed: Array; + deleteConfirmed: DeleteConfirmReturn; + }; + readonly i18n: { + syncProgress: string; + completed: string; + failedTasksDescription: string; + confirmDeleteDescription: string; + confirmTasksDescription: Fragment; + hide: string; + confirm: string; + cancel: string; + done: string; + stopSync: string; + } & Record; + private readonly renderHideStop; + private readonly renderConfirmCancel; + private readonly renderDone; + private readonly showDetails; + private readonly hideDetails; + onOpen(): void; + root: { + hideProgress: { + (): void; + (): void; + }; + showProgress: () => void; + }; + onClose(): void; + dispose(): void; +} +//#endregion +//#region src/modules/Scheduler.d.ts +declare class Scheduler { + private readonly ctx; + private readonly pendingRequests; + private isScheduling; + private realtimeSyncTimer?; + private scheduledSyncTimer?; + private startupSyncTimer?; + constructor(ctx: { + syncStage: Ref; + executeSync: (trigger: string) => Promise; + registerEvent: (ref: EventRef) => void; + app: App; + isIdle: Ref; + }); + settings: { + startupSync: TogglableValue; + scheduledSync: TogglableValue; + realtimeSync: TogglableValue; + exclusionRules: Array; + inclusionRules: Array; + }; + private readonly requestSync; + start: () => void; + dispose: () => void; + private readonly startScheduledSync; + private readonly stopScheduledSync; + private readonly onChange; + private readonly scheduleFlush; + private readonly flush; + root: { + requestSync: (trigger: string) => Promise; + startScheduledSync: () => void; + stopScheduledSync: () => void; + }; +} +//#endregion +//#region src/index.d.ts +declare const internalModules: readonly [typeof EventBus, typeof I18n, typeof Storage, typeof Extensibility, typeof Setting$1, typeof Registrar, typeof Sync, typeof Observability, typeof Scheduler, typeof ProgressModal, typeof Bootstrap]; +type InternalModules = typeof internalModules; +type MergeKeys = 'settings' | 'root' | 'events' | 'i18n'; +type Context = Context$1 Command; + registerEvent: (ref: EventRef) => void; + addRibbonIcon: AddRibbonIcon; + addStatusBarItem: () => HTMLElement; + saveSettings: () => Promise; +}>; +type Events = MergeSingleKey; +type Settings = MergeSingleKey; +type Translations = MergeSingleKey; +//#endregion +//#region src/sdk/prefix.d.ts +declare function prefixWrapper(original: Fs, prefix: string): WrappedFs; +//#endregion +//#region src/utils/pipe.d.ts +declare function pipe({ from, to, stat, key }: { + from: Fs; + to: Fs; + key: string; + stat: FileStat; +}): Promise; +declare function readWithSize(fs: Fs, key: string, stat: FileStat): Promise | undefined>; +declare function writeWithValue(fs: Fs, key: string, value: Binary | ReadableStream, stat: FileStat): MaybePromise; +//#endregion +//#region src/sdk/index.d.ts +declare function digOriginal(wrapped: Fs): RootFs; +type SelectFromContext = Context extends O ? O : never; +//#endregion +export { type AddRecord, type AugmentedModuleMeta, type BaseTask, type BatchOptimizer, type Binary, type CallableOrObjectTree, type CheckConnectionResult, type ConflictResolver, type ConflictResolverEntry, type ConflictResolverPayload, type Context, type CreateLocalDir, type CreateRemoteDir, type CustomAtom, type DatabaseAsync, type DatabaseSync, type Decider, type DeciderEntry, type DeciderInput, type DeleteAtom, type Dispatch, type Download, type Events, type ExistingMemoryDB, type FileStat, type FolderStat, type Fragment, type Fs, type FsWrapperEntry, type InputAtom, type LabelDefinition, type ListReporter, type LocalRequestMiddlewareEntry, type MaybePromise, type MkdirAtom, type ModuleMeta, type MoveAtom, type MoveLocal, type MoveRemote, type ObsidianLanguageCode, type On, type OptimizerEntry, type OptimizerInput, type OptimizerOutput, type OutputAtom, type Progress, type RecordStat, type RecordStatsMap, type RecordStore, type RemoteFsEntry, type RemoteLister, type RemoteListerEntry, type RemoteRequestMiddlewareEntry, type RemoveLocal, type RemoveRecord, type RemoveRemote, type Request, type RequestParam, type RequestResponse, type ResolveConflict, type RootFs, SelectFromContext, type SettingEntry, type Settings, type Stat, type StatsMap, type StoreAsync, type StoreOperations, type StoreSync, type SyncTerminateReason, type TaskFactory, type TaskNames, type Translate, type TranslationResource, type Translations, type Upload, type VaultRequest, type WrappedFs, type WriteAtom, digOriginal, pipe, prefixWrapper, readWithSize, s, setNeedMigration, writeWithValue }; \ No newline at end of file