@sparkelf/dsh-plugin-backup 0.1.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ //#region lib/types/invariant.js
2
+ /** Package invariant companion for `@sparkelf/dsh-plugin-backup`. */
3
+ const PACKAGE_NAME = "@sparkelf/dsh-plugin-backup";
4
+ const name = "plus-backup-invariant";
5
+ const inject = ["invariants"];
6
+ /**
7
+ * No runtime invariant: WebServer owns route registration, Workspace owns its
8
+ * durable/cache relation, and the browser settings slot has no Host projection.
9
+ */
10
+ const install = () => {};
11
+ /**
12
+ * Register this package's invariant companion.
13
+ * @param ctx - Host context carrying the invariant registry.
14
+ * @returns the registration disposer.
15
+ */
16
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
17
+ //#endregion
18
+ export { apply, inject, name };
@@ -0,0 +1,63 @@
1
+ /**
2
+ * User data backup core for the web settings Backup section. Export scans one
3
+ * stable file plan, reads and compresses bounded chunks, and publishes source-
4
+ * byte progress. Import validates before mutation, then writes bounded chunks
5
+ * while publishing restored-byte progress.
6
+ */
7
+ import type { BackupProgressReporter } from './protocol.ts';
8
+ /**
9
+ * Pack the harness home's user configuration and data into a zip archive,
10
+ * publishing scan and source-byte compression progress. A failed export removes
11
+ * its partial archive.
12
+ * @param dshHome - harness user data directory (settings.yaml parent).
13
+ * @param targetPath - absolute file path the archive is written to.
14
+ * @param signal - caller or response cancellation.
15
+ * @param report - ordered progress writer.
16
+ * @returns the number of zip entries including the manifest marker.
17
+ */
18
+ export declare function writeUserBackup(dshHome: string, targetPath: string, signal: AbortSignal, report: BackupProgressReporter): Promise<{
19
+ entries: number;
20
+ }>;
21
+ /** One validated archive entry staged outside the harness home. */
22
+ type ValidatedBackupEntry = {
23
+ kind: 'directory';
24
+ relativePath: string;
25
+ } | {
26
+ kind: 'file';
27
+ relativePath: string;
28
+ size: number;
29
+ };
30
+ /** An archive fully validated and extracted to a temporary directory before user-data mutation. */
31
+ export interface ValidatedUserBackup {
32
+ /** Temporary extraction root containing every validated regular file. */
33
+ stagingRoot: string;
34
+ /** Validated portable entries in archive order. */
35
+ entries: ValidatedBackupEntry[];
36
+ /** Number of zip entries including the manifest marker. */
37
+ count: number;
38
+ /** Total regular-file bytes restored into the harness home. */
39
+ totalBytes: number;
40
+ }
41
+ /**
42
+ * Validate and extract one staged zip without retaining archive or entry bodies in memory.
43
+ * @param archivePath - disk-staged raw upload.
44
+ * @param stagingRoot - temporary extraction root outside the harness home.
45
+ * @param maxExpandedBytes - aggregate expanded-byte limit shared with upload admission.
46
+ * @param signal - response cancellation honored until DSH-home mutation begins.
47
+ * @returns the validated staged entry plan.
48
+ */
49
+ export declare function validateUserBackup(archivePath: string, stagingRoot: string, maxExpandedBytes: number, signal: AbortSignal): Promise<ValidatedUserBackup>;
50
+ /**
51
+ * Write a validated staged archive over the harness home while publishing restored bytes.
52
+ * Once file mutation begins the operation completes rather than honoring a late response
53
+ * cancellation, so user data is not left half-written by closing a page.
54
+ * @param validated - validateUserBackup result.
55
+ * @param dshHome - harness user data directory.
56
+ * @param report - ordered progress writer; a disconnected response may ignore updates.
57
+ * @returns the restored entry count.
58
+ */
59
+ export declare function restoreUserBackup(validated: ValidatedUserBackup, dshHome: string, report: BackupProgressReporter): Promise<{
60
+ entries: number;
61
+ }>;
62
+ export {};
63
+ //# sourceMappingURL=archive.d.ts.map
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Backup settings section: exact Host routes stream archive bytes and progress;
3
+ * the slot store survives settings-driven component remounts.
4
+ */
5
+ import type { ReactNode } from 'react';
6
+ import type { InjectFace, PropsLocale, PropsRuntime, PropsStore } from '@deepseek-ai/dsh-client-ui-slots';
7
+ import type { BackupSectionStore } from './store.ts';
8
+ import type { BackupSectionProgress } from './types.ts';
9
+ /** Registration-side business face for the two streamed backup operations. */
10
+ export interface BackupSectionInjected {
11
+ /**
12
+ * Prepare a fresh export while reporting real source-byte progress.
13
+ * @param report - receives ordered progress updates.
14
+ * @returns the single-use browser download URL and entry count.
15
+ */
16
+ exportArchive(report: (progress: BackupSectionProgress) => void): Promise<{
17
+ downloadUrl: string;
18
+ entries: number;
19
+ }>;
20
+ /**
21
+ * Upload and restore one picked archive while reporting transport and Host progress.
22
+ * @param file - browser-selected backup archive.
23
+ * @param report - receives ordered progress updates.
24
+ * @returns the restored entry count.
25
+ */
26
+ importArchive(file: File, report: (progress: BackupSectionProgress) => void): Promise<{
27
+ entries: number;
28
+ }>;
29
+ /** Cancel the active operation while its current phase still permits cancellation. */
30
+ cancelOperation(): void;
31
+ /** Reload the browser so it fetches restored session and workspace baselines. */
32
+ reloadPage(): void;
33
+ }
34
+ /** Full component props. */
35
+ export type BackupSectionProps = PropsRuntime<'settings.section'> & PropsLocale<'settingsBackup'> & PropsStore<BackupSectionStore> & InjectFace<BackupSectionInjected>;
36
+ /**
37
+ * The Backup section body.
38
+ * @param props - runtime owner props, locale, store seat, and streamed operation callbacks.
39
+ * @returns the section tree.
40
+ */
41
+ export declare function BackupSection(props: BackupSectionProps): ReactNode;
42
+ //# sourceMappingURL=BackupSection.d.ts.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Settings Backup section plugin, browser half. Archive bytes use exact Host
3
+ * routes; preparation and restore state arrive as validated NDJSON progress
4
+ * lines, outside the unary RPC carrier.
5
+ */
6
+ import type { Context } from '@deepseek-ai/cordis';
7
+ import { type SettingsBackupKey } from './locales.ts';
8
+ declare module '@deepseek-ai/dsh-client-ui-slots' {
9
+ interface LocaleNamespaceMap {
10
+ /** Backup section copy. */
11
+ settingsBackup: SettingsBackupKey;
12
+ }
13
+ }
14
+ export declare const inject: string[];
15
+ /** Register the Backup settings section and its exact-route transport callbacks. */
16
+ export declare function apply(ctx: Context): void;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,34 @@
1
+ /** Settings Backup section dictionaries (zh product copy, en twin). */
2
+ export declare const zh: {
3
+ readonly nav: "备份";
4
+ readonly title: "备份与恢复";
5
+ readonly desc: "把用户设置和数据导出为一个 zip 压缩包,或从备份压缩包恢复。";
6
+ readonly exportButton: "导出备份压缩包";
7
+ readonly importButton: "选择压缩包并导入";
8
+ readonly busyExport: "正在生成备份…";
9
+ readonly busyImport: "正在导入备份…";
10
+ readonly cancelButton: "取消";
11
+ readonly cancellingButton: "正在取消…";
12
+ readonly exportScan: "正在计算备份数据量…";
13
+ readonly exportCompress: "正在生成备份";
14
+ readonly exportProgressLabel: "备份生成进度";
15
+ readonly importUpload: "正在上传备份";
16
+ readonly importValidate: "正在校验备份完整性…";
17
+ readonly importRestore: "正在恢复备份";
18
+ readonly importReload: "正在加载会话与工作区…";
19
+ readonly importProgressLabel: "备份恢复进度";
20
+ readonly progressDetail: "数据较多时可能需要几分钟,请保持此页面打开。";
21
+ readonly exported: "备份已生成,浏览器已开始下载。";
22
+ readonly imported: "备份已导入。重新加载页面后,会话和工作区将使用恢复后的数据。";
23
+ readonly reloadButton: "重新加载页面";
24
+ readonly notBackup: "所选压缩包不是 DeepSeek Harness 备份文件。";
25
+ readonly unsafe: "备份压缩包包含不安全的条目路径。";
26
+ readonly exportFailed: "备份导出失败,请重试;若持续失败,请检查可用磁盘空间。";
27
+ readonly importFailed: "备份导入失败,请检查所选压缩包后重试。";
28
+ readonly warning: "备份压缩包包含 API 密钥等敏感信息,请妥善保管。";
29
+ };
30
+ /** English twin of the `zh` dictionary. */
31
+ export declare const en: Record<SettingsBackupKey, string>;
32
+ /** Dictionary keys of the `settingsBackup` locale namespace. */
33
+ export type SettingsBackupKey = keyof typeof zh;
34
+ //# sourceMappingURL=locales.d.ts.map
@@ -0,0 +1,20 @@
1
+ /** Remount-surviving state for the Settings Backup slot registration. */
2
+ import { type EngineStoreHandle } from '@deepseek-ai/dsh-client-store';
3
+ import type { BackupErrorKey, BackupOperation, BackupSectionState, BackupStatusKey } from './types.ts';
4
+ type BackupSectionActions = {
5
+ begin: (draft: BackupSectionState, operation: BackupOperation) => void;
6
+ progress: (draft: BackupSectionState, operation: BackupOperation) => void;
7
+ requestCancel: (draft: BackupSectionState) => void;
8
+ cancelled: (draft: BackupSectionState) => void;
9
+ complete: (draft: BackupSectionState, status: BackupStatusKey) => void;
10
+ fail: (draft: BackupSectionState, error: BackupErrorKey) => void;
11
+ };
12
+ /** Store handle shared by each remount of the root-scoped Backup section. */
13
+ export type BackupSectionStore = EngineStoreHandle<BackupSectionState, BackupSectionActions>;
14
+ /**
15
+ * Declare the Backup section operation and result state.
16
+ * @returns the root-scoped store handle.
17
+ */
18
+ export declare function createBackupSectionStore(): BackupSectionStore;
19
+ export {};
20
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1,29 @@
1
+ /** Browser presentation progress after parsing Host lines or upload events. */
2
+ export type BackupSectionProgress = {
3
+ /** Phase without a measurable byte total. */
4
+ phase: 'scan' | 'validate' | 'reload';
5
+ } | {
6
+ /** Phase with a stable byte total. */
7
+ phase: 'compress' | 'upload' | 'restore';
8
+ /** Bytes completed in the current phase. */
9
+ completedBytes: number;
10
+ /** Stable byte total for the current phase. */
11
+ totalBytes: number;
12
+ };
13
+ /** One active backup operation rendered by the Settings section. */
14
+ export type BackupOperation = {
15
+ kind: 'export' | 'import';
16
+ progress: BackupSectionProgress;
17
+ };
18
+ /** Successful operation copy selected by the current locale. */
19
+ export type BackupStatusKey = 'exported' | 'imported';
20
+ /** Failed operation copy selected by the current locale. */
21
+ export type BackupErrorKey = 'notBackup' | 'unsafe' | 'exportFailed' | 'importFailed';
22
+ /** Remount-surviving presentation state owned by the Backup slot registration. */
23
+ export type BackupSectionState = {
24
+ operation: BackupOperation | null;
25
+ status: BackupStatusKey | null;
26
+ error: BackupErrorKey | null;
27
+ cancelling: boolean;
28
+ };
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,19 @@
1
+ /** Full-stack Plus user-data Backup Host plugin. */
2
+ import Schema from '@deepseek-ai/schemastery';
3
+ import { type BackupHostContext } from './routes.ts';
4
+ export declare const name = "plus-backup";
5
+ export declare const inject: string[];
6
+ /** Backup Host resource policy. */
7
+ export interface Config {
8
+ /** Maximum uploaded ZIP bytes written to Host disk. @default 2147483648 */
9
+ maxUploadBytes?: number;
10
+ }
11
+ /** Validate Backup Host resource policy. */
12
+ export declare const Config: Schema<Config>;
13
+ /**
14
+ * Register authenticated archive routes against a file-backed DSH home.
15
+ * @param ctx - Host services plus the temporary patched Workspace restore operation.
16
+ * @param config - Upload resource policy resolved by Cordis.
17
+ */
18
+ export declare function apply(ctx: BackupHostContext, config?: Config): void;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,11 @@
1
+ /** Package invariant companion for `@sparkelf/dsh-plugin-backup`. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ export declare const name = "plus-backup-invariant";
4
+ export declare const inject: string[];
5
+ /**
6
+ * Register this package's invariant companion.
7
+ * @param ctx - Host context carrying the invariant registry.
8
+ * @returns the registration disposer.
9
+ */
10
+ export declare const apply: (ctx: Context) => Promise<() => void>;
11
+ //# sourceMappingURL=invariant.d.ts.map
@@ -0,0 +1,32 @@
1
+ /** Host progress and terminal records for Plus user-data Backup routes. */
2
+ /** Progress without a stable byte total while scanning, validating, or reloading. */
3
+ type BackupOpenProgress = {
4
+ phase: 'scan' | 'validate' | 'reload';
5
+ };
6
+ /** Progress with a stable byte total while compressing or restoring. */
7
+ type BackupMeasuredProgress = {
8
+ phase: 'compress' | 'restore';
9
+ completedBytes: number;
10
+ totalBytes: number;
11
+ };
12
+ /** Host-authored progress emitted by one Backup operation. */
13
+ export type BackupHostProgress = BackupOpenProgress | BackupMeasuredProgress;
14
+ /** Ordered progress writer; archive work waits for response backpressure. */
15
+ export type BackupProgressReporter = (progress: BackupHostProgress) => Promise<void>;
16
+ /** One NDJSON progress or terminal line sent to the Client. */
17
+ export type BackupProgressLine = {
18
+ type: 'progress';
19
+ progress: BackupHostProgress;
20
+ } | {
21
+ type: 'export-ready';
22
+ downloadUrl: string;
23
+ entries: number;
24
+ } | {
25
+ type: 'import-complete';
26
+ entries: number;
27
+ } | {
28
+ type: 'error';
29
+ message: string;
30
+ };
31
+ export {};
32
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1,20 @@
1
+ /** Authenticated Host routes for streamed user-data Backup export and import. */
2
+ import type { Context } from '@deepseek-ai/cordis';
3
+ /** Official Host context plus the one temporary Workspace operation supplied by the source patch. */
4
+ export type BackupHostContext = Context & {
5
+ workspaceRegistry: Context['workspaceRegistry'] & {
6
+ withStorageRestore<T>(restore: () => Promise<T>): Promise<T>;
7
+ };
8
+ };
9
+ /** Backup route resource policy. */
10
+ export interface BackupRouteConfig {
11
+ maxUploadBytes: number;
12
+ }
13
+ /**
14
+ * Register the complete authenticated Backup route set and its temp-file lifecycle.
15
+ * @param ctx - Host services and the patched Workspace restore operation.
16
+ * @param config - Upload resource policy.
17
+ * @param dshHome - File-backed DSH home whose user data is archived.
18
+ */
19
+ export declare function registerBackupRoutes(ctx: BackupHostContext, config: BackupRouteConfig, dshHome: string): void;
20
+ //# sourceMappingURL=routes.d.ts.map
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "dependencies": {
3
+ "@deepseek-ai/schemastery": ">=3.18.1",
4
+ "fflate": "^0.8.2",
5
+ "yauzl": "^3.2.0"
6
+ },
7
+ "description": "Full-stack Plus user-data Backup plugin with streamed Host archive routes and Settings UI",
8
+ "devDependencies": {
9
+ "@deepseek-ai/cordis": "^4.0.1",
10
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-alpha.1",
11
+ "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.1",
12
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.1",
13
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-alpha.1",
14
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.1",
15
+ "@deepseek-ai/dsh-host-webserver": "^0.1.2-alpha.1",
16
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.1",
17
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.1",
18
+ "@deepseek-ai/dsh-workspace": "^0.1.2-alpha.1",
19
+ "@types/react": "~18.3.1",
20
+ "@types/yauzl": "^2.10.3",
21
+ "react": "^18.2.0"
22
+ },
23
+ "dsh": {
24
+ "client": {
25
+ "inject": [
26
+ "@deepseek-ai/dsh-client-locale",
27
+ "@deepseek-ai/dsh-client-ui-settings",
28
+ "@deepseek-ai/dsh-client-ui-renderer"
29
+ ],
30
+ "platform": "web"
31
+ }
32
+ },
33
+ "exports": {
34
+ ".": {
35
+ "default": "./lib/index.js",
36
+ "types": "./lib/types/index.d.ts"
37
+ },
38
+ "./client": {
39
+ "default": "./lib/client.js",
40
+ "types": "./lib/types/client/index.d.ts"
41
+ },
42
+ "./invariant": {
43
+ "default": "./lib/invariant.js",
44
+ "types": "./lib/types/invariant.d.ts"
45
+ },
46
+ "./package.json": "./package.json"
47
+ },
48
+ "files": [
49
+ "lib/index.js",
50
+ "lib/invariant.js",
51
+ "lib/client.js",
52
+ "lib/types/**/*.d.ts"
53
+ ],
54
+ "license": "MIT",
55
+ "main": "lib/index.js",
56
+ "name": "@sparkelf/dsh-plugin-backup",
57
+ "peerDependencies": {
58
+ "@deepseek-ai/cordis": ">=4.0.1",
59
+ "@deepseek-ai/dsh-client-locale": ">=0.1.2-alpha.1",
60
+ "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.2-alpha.1",
61
+ "@deepseek-ai/dsh-client-ui-settings": ">=0.1.2-alpha.1",
62
+ "@deepseek-ai/dsh-client-ui-slots": ">=0.1.2-alpha.1",
63
+ "@deepseek-ai/dsh-host-webserver": ">=0.1.2-alpha.1",
64
+ "@deepseek-ai/dsh-invariants": ">=0.1.2-alpha.1",
65
+ "@deepseek-ai/dsh-settings": ">=0.1.2-alpha.1",
66
+ "@deepseek-ai/dsh-workspace": ">=0.1.2-alpha.1"
67
+ },
68
+ "publishConfig": {
69
+ "access": "public"
70
+ },
71
+ "repository": {
72
+ "directory": "packages/plus/backup",
73
+ "type": "git",
74
+ "url": "git+https://github.com/SparkElf/deepseek-harness-plus.git"
75
+ },
76
+ "scripts": {
77
+ "bundle": "tsdown",
78
+ "watch": "tsdown --watch"
79
+ },
80
+ "type": "module",
81
+ "types": "lib/types/index.d.ts",
82
+ "version": "0.1.0-rc.10"
83
+ }