target-supabase-sdk 0.1.9 → 0.2.1
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.
- package/README.md +184 -1
- package/dist/browser.d.ts +60 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +6 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunks/create-logger-DyH3mZ8p.js +1028 -0
- package/dist/chunks/create-logger-DyH3mZ8p.js.map +1 -0
- package/dist/chunks/enable-log-persist-C_bSw6Kx.js +1362 -0
- package/dist/chunks/enable-log-persist-C_bSw6Kx.js.map +1 -0
- package/dist/chunks/word.interface-DLgRobKV.js +1973 -0
- package/dist/chunks/word.interface-DLgRobKV.js.map +1 -0
- package/dist/command/command.api.d.ts +1 -1
- package/dist/command/command.api.d.ts.map +1 -1
- package/dist/command/command.interface.d.ts +1 -1
- package/dist/command/command.interface.d.ts.map +1 -1
- package/dist/core.api.d.ts +10 -6
- package/dist/core.api.d.ts.map +1 -1
- package/dist/core.interface.d.ts +3 -2
- package/dist/core.interface.d.ts.map +1 -1
- package/dist/core.utils.d.ts +1 -1
- package/dist/core.utils.d.ts.map +1 -1
- package/dist/idea/idea.interface.d.ts +1 -1
- package/dist/idea/idea.interface.d.ts.map +1 -1
- package/dist/index.d.ts +2 -48
- package/dist/index.d.ts.map +1 -1
- package/dist/link/link.api.d.ts +1 -1
- package/dist/link/link.api.d.ts.map +1 -1
- package/dist/link/link.interface.d.ts +3 -3
- package/dist/link/link.interface.d.ts.map +1 -1
- package/dist/list/list.api.d.ts +3 -1
- package/dist/list/list.api.d.ts.map +1 -1
- package/dist/list/list.interface.d.ts +2 -2
- package/dist/list/list.interface.d.ts.map +1 -1
- package/dist/node/env/env-parsers.d.ts +19 -0
- package/dist/node/env/env-parsers.d.ts.map +1 -0
- package/dist/node/env/index.d.ts +11 -0
- package/dist/node/env/index.d.ts.map +1 -0
- package/dist/node/env/init-supabase-from-env.d.ts +17 -0
- package/dist/node/env/init-supabase-from-env.d.ts.map +1 -0
- package/dist/node/env/load-env.d.ts +20 -0
- package/dist/node/env/load-env.d.ts.map +1 -0
- package/dist/node/env/project-root.d.ts +11 -0
- package/dist/node/env/project-root.d.ts.map +1 -0
- package/dist/node/env/public-base-url.d.ts +10 -0
- package/dist/node/env/public-base-url.d.ts.map +1 -0
- package/dist/node/env/require-env.d.ts +3 -0
- package/dist/node/env/require-env.d.ts.map +1 -0
- package/dist/node/fs/json-state-store.d.ts +19 -0
- package/dist/node/fs/json-state-store.d.ts.map +1 -0
- package/dist/node/fs/read-source-file.d.ts +19 -0
- package/dist/node/fs/read-source-file.d.ts.map +1 -0
- package/dist/node/node-liveness.d.ts +30 -0
- package/dist/node/node-liveness.d.ts.map +1 -0
- package/dist/node/node-runtime.base.d.ts +60 -0
- package/dist/node/node-runtime.base.d.ts.map +1 -0
- package/dist/node/node.api.d.ts +4 -4
- package/dist/node/node.api.d.ts.map +1 -1
- package/dist/node/node.interface.d.ts +1 -6
- package/dist/node/node.interface.d.ts.map +1 -1
- package/dist/node/preload/run-service-preload.d.ts +14 -0
- package/dist/node/preload/run-service-preload.d.ts.map +1 -0
- package/dist/node/preload/service-preload.interface.d.ts +15 -0
- package/dist/node/preload/service-preload.interface.d.ts.map +1 -0
- package/dist/node/process/index.d.ts +5 -0
- package/dist/node/process/index.d.ts.map +1 -0
- package/dist/node/process/managed-child-processes.d.ts +37 -0
- package/dist/node/process/managed-child-processes.d.ts.map +1 -0
- package/dist/node/process/process-spawn.d.ts +27 -0
- package/dist/node/process/process-spawn.d.ts.map +1 -0
- package/dist/node/readiness/index.d.ts +9 -0
- package/dist/node/readiness/index.d.ts.map +1 -0
- package/dist/node/readiness/poll-until.d.ts +11 -0
- package/dist/node/readiness/poll-until.d.ts.map +1 -0
- package/dist/node/readiness/readiness-checks.d.ts +22 -0
- package/dist/node/readiness/readiness-checks.d.ts.map +1 -0
- package/dist/node/readiness/readiness.types.d.ts +12 -0
- package/dist/node/readiness/readiness.types.d.ts.map +1 -0
- package/dist/node/readiness/run-readiness-checks.d.ts +4 -0
- package/dist/node/readiness/run-readiness-checks.d.ts.map +1 -0
- package/dist/node/readiness/service-ready-gate.d.ts +26 -0
- package/dist/node/readiness/service-ready-gate.d.ts.map +1 -0
- package/dist/node.d.ts +36 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +2483 -0
- package/dist/node.js.map +1 -0
- package/dist/parcel/chunk-fetch-registry.d.ts +14 -0
- package/dist/parcel/chunk-fetch-registry.d.ts.map +1 -0
- package/dist/parcel/chunk-url.utils.d.ts +9 -0
- package/dist/parcel/chunk-url.utils.d.ts.map +1 -0
- package/dist/parcel/parcel-manager.d.ts +44 -20
- package/dist/parcel/parcel-manager.d.ts.map +1 -1
- package/dist/parcel/parcel.api.d.ts +306 -0
- package/dist/parcel/parcel.api.d.ts.map +1 -0
- package/dist/parcel/parcel.interface.d.ts +26 -5
- package/dist/parcel/parcel.interface.d.ts.map +1 -1
- package/dist/parcel/parcel.service.d.ts +38 -0
- package/dist/parcel/parcel.service.d.ts.map +1 -0
- package/dist/parcel/storage-provider-registry.d.ts +17 -0
- package/dist/parcel/storage-provider-registry.d.ts.map +1 -0
- package/dist/parcel/storage-provider.types.d.ts +31 -0
- package/dist/parcel/storage-provider.types.d.ts.map +1 -0
- package/dist/preload.d.ts +7 -0
- package/dist/preload.d.ts.map +1 -0
- package/dist/preload.js +47 -0
- package/dist/preload.js.map +1 -0
- package/dist/repo/repo-context.utils.d.ts.map +1 -1
- package/dist/repo/repo-manager.d.ts +14 -3
- package/dist/repo/repo-manager.d.ts.map +1 -1
- package/dist/repo/repo.api.d.ts +1 -1
- package/dist/repo/repo.api.d.ts.map +1 -1
- package/dist/repo/repo.interface.d.ts +1 -1
- package/dist/repo/repo.interface.d.ts.map +1 -1
- package/dist/repo/repo.script-loader.d.ts +5 -5
- package/dist/repo/repo.script-loader.d.ts.map +1 -1
- package/dist/service/base.interface.d.ts +54 -57
- package/dist/service/base.interface.d.ts.map +1 -1
- package/dist/service/index.d.ts +21 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/service.api.d.ts +503 -0
- package/dist/service/service.api.d.ts.map +1 -0
- package/dist/service/service.interface.d.ts +36 -9
- package/dist/service/service.interface.d.ts.map +1 -1
- package/dist/shared/http/fetch-retry.d.ts +21 -0
- package/dist/shared/http/fetch-retry.d.ts.map +1 -0
- package/dist/shared/log/create-logger.d.ts +27 -0
- package/dist/shared/log/create-logger.d.ts.map +1 -0
- package/dist/shared/log/enable-log-persist.d.ts +28 -0
- package/dist/shared/log/enable-log-persist.d.ts.map +1 -0
- package/dist/shared/log/index.d.ts +10 -0
- package/dist/shared/log/index.d.ts.map +1 -0
- package/dist/shared/log/log-manager.d.ts +37 -60
- package/dist/shared/log/log-manager.d.ts.map +1 -1
- package/dist/shared/log/log-persist-batch-id.d.ts +13 -0
- package/dist/shared/log/log-persist-batch-id.d.ts.map +1 -0
- package/dist/shared/log/log-persist-flush.d.ts +8 -0
- package/dist/shared/log/log-persist-flush.d.ts.map +1 -0
- package/dist/shared/log/log-persist-hook.d.ts +6 -0
- package/dist/shared/log/log-persist-hook.d.ts.map +1 -0
- package/dist/shared/log/log-persist-logger.d.ts +15 -0
- package/dist/shared/log/log-persist-logger.d.ts.map +1 -0
- package/dist/shared/log/log-persist-registry.d.ts +17 -0
- package/dist/shared/log/log-persist-registry.d.ts.map +1 -0
- package/dist/shared/log/log-persist.config.d.ts +10 -0
- package/dist/shared/log/log-persist.config.d.ts.map +1 -0
- package/dist/shared/log/log-persist.d.ts +55 -0
- package/dist/shared/log/log-persist.d.ts.map +1 -0
- package/dist/shared/log/log-persist.interface.d.ts +116 -0
- package/dist/shared/log/log-persist.interface.d.ts.map +1 -0
- package/dist/shared/log/log-scope.d.ts +56 -0
- package/dist/shared/log/log-scope.d.ts.map +1 -0
- package/dist/shared/utils/fetch-url.d.ts +3 -0
- package/dist/shared/utils/fetch-url.d.ts.map +1 -0
- package/dist/shared/utils/network-error.d.ts +14 -0
- package/dist/shared/utils/network-error.d.ts.map +1 -0
- package/dist/shared/utils/safe-file-name.d.ts +14 -0
- package/dist/shared/utils/safe-file-name.d.ts.map +1 -0
- package/dist/shared/utils/sha256.d.ts +3 -0
- package/dist/shared/utils/sha256.d.ts.map +1 -0
- package/dist/supabase.d.ts +7 -2
- package/dist/supabase.d.ts.map +1 -1
- package/dist/task/index.d.ts +16 -0
- package/dist/task/index.d.ts.map +1 -0
- package/dist/task/local-task-registry.d.ts +11 -1
- package/dist/task/local-task-registry.d.ts.map +1 -1
- package/dist/task/task-manager.d.ts +21 -11
- package/dist/task/task-manager.d.ts.map +1 -1
- package/dist/task/task-node.d.ts +19 -0
- package/dist/task/task-node.d.ts.map +1 -0
- package/dist/task/task-post-validated.api.d.ts +19 -0
- package/dist/task/task-post-validated.api.d.ts.map +1 -0
- package/dist/task/task-post.api.d.ts +54 -0
- package/dist/task/task-post.api.d.ts.map +1 -0
- package/dist/task/task-queue.d.ts +7 -0
- package/dist/task/task-queue.d.ts.map +1 -0
- package/dist/task/task-repo-context.d.ts +2 -0
- package/dist/task/task-repo-context.d.ts.map +1 -1
- package/dist/task/task-repo-validation.d.ts +46 -0
- package/dist/task/task-repo-validation.d.ts.map +1 -0
- package/dist/task/task.api.d.ts +5 -47
- package/dist/task/task.api.d.ts.map +1 -1
- package/dist/task/task.constant.d.ts +4 -0
- package/dist/task/task.constant.d.ts.map +1 -0
- package/dist/task/task.interface.d.ts +3 -1
- package/dist/task/task.interface.d.ts.map +1 -1
- package/dist/trigger/trigger-manager.d.ts +25 -0
- package/dist/trigger/trigger-manager.d.ts.map +1 -0
- package/dist/trigger/trigger-node.d.ts +23 -0
- package/dist/trigger/trigger-node.d.ts.map +1 -0
- package/dist/trigger/trigger.api.d.ts +140 -0
- package/dist/trigger/trigger.api.d.ts.map +1 -0
- package/dist/trigger/trigger.constant.d.ts +8 -0
- package/dist/trigger/trigger.constant.d.ts.map +1 -0
- package/dist/trigger/trigger.interface.d.ts +87 -0
- package/dist/trigger/trigger.interface.d.ts.map +1 -0
- package/dist/trigger/trigger.utils.d.ts +6 -0
- package/dist/trigger/trigger.utils.d.ts.map +1 -0
- package/dist/word/word.api.d.ts +1 -1
- package/dist/word/word.api.d.ts.map +1 -1
- package/dist/word/word.interface.d.ts +2 -2
- package/dist/word/word.interface.d.ts.map +1 -1
- package/package.json +91 -61
- package/src/browser.ts +165 -0
- package/src/command/command.api.ts +20 -18
- package/src/command/command.interface.ts +2 -3
- package/src/core.api.ts +466 -477
- package/src/core.interface.ts +63 -62
- package/src/core.utils.ts +64 -64
- package/src/idea/idea.interface.ts +3 -3
- package/src/index.ts +2 -79
- package/src/link/link.api.ts +28 -30
- package/src/link/link.interface.ts +4 -5
- package/src/list/list.api.ts +50 -29
- package/src/list/list.interface.ts +3 -4
- package/src/node/env/env-parsers.ts +77 -0
- package/src/node/env/index.ts +10 -0
- package/src/node/env/init-supabase-from-env.ts +38 -0
- package/src/node/env/load-env.ts +67 -0
- package/src/node/env/project-root.ts +34 -0
- package/src/node/env/public-base-url.ts +18 -0
- package/src/node/env/require-env.ts +15 -0
- package/src/node/fs/json-state-store.ts +97 -0
- package/src/node/fs/read-source-file.ts +75 -0
- package/src/node/node-liveness.ts +80 -0
- package/src/node/node-runtime.base.ts +481 -0
- package/src/node/node.api.ts +12 -11
- package/src/node/node.interface.ts +1 -8
- package/src/node/node.utils.ts +1 -1
- package/src/node/preload/run-service-preload.ts +48 -0
- package/src/node/preload/service-preload.interface.ts +14 -0
- package/src/node/process/index.ts +8 -0
- package/src/node/process/managed-child-processes.ts +121 -0
- package/src/node/process/process-spawn.ts +61 -0
- package/src/node/readiness/index.ts +20 -0
- package/src/node/readiness/poll-until.ts +27 -0
- package/src/node/readiness/readiness-checks.ts +79 -0
- package/src/node/readiness/readiness.types.ts +13 -0
- package/src/node/readiness/run-readiness-checks.ts +20 -0
- package/src/node/readiness/service-ready-gate.ts +65 -0
- package/src/node.ts +153 -0
- package/src/parcel/chunk-fetch-registry.ts +96 -0
- package/src/parcel/chunk-url.utils.ts +30 -0
- package/src/parcel/parcel-manager.ts +431 -173
- package/src/parcel/parcel.api.ts +103 -0
- package/src/parcel/parcel.interface.ts +44 -23
- package/src/parcel/parcel.service.ts +79 -0
- package/src/parcel/storage-provider-registry.ts +49 -0
- package/src/parcel/storage-provider.types.ts +45 -0
- package/src/preload.ts +7 -0
- package/src/repo/repo-context.utils.ts +3 -4
- package/src/repo/repo-manager.ts +54 -39
- package/src/repo/repo.api.ts +5 -5
- package/src/repo/repo.interface.ts +1 -2
- package/src/repo/repo.script-loader.ts +16 -20
- package/src/service/base.interface.ts +81 -90
- package/src/service/index.ts +173 -0
- package/src/service/service.api.ts +294 -0
- package/src/service/service.interface.ts +49 -17
- package/src/shared/http/fetch-retry.ts +145 -0
- package/src/shared/log/create-logger.ts +51 -0
- package/src/shared/log/enable-log-persist.ts +225 -0
- package/src/shared/log/index.ts +31 -0
- package/src/shared/log/log-manager.ts +112 -121
- package/src/shared/log/log-persist-batch-id.ts +43 -0
- package/src/shared/log/log-persist-flush.ts +128 -0
- package/src/shared/log/log-persist-hook.ts +13 -0
- package/src/shared/log/log-persist-logger.ts +33 -0
- package/src/shared/log/log-persist-registry.ts +109 -0
- package/src/shared/log/log-persist.config.ts +97 -0
- package/src/shared/log/log-persist.interface.ts +132 -0
- package/src/shared/log/log-persist.ts +704 -0
- package/src/shared/log/log-scope.ts +123 -0
- package/src/shared/utils/config-path.utils.ts +1 -1
- package/src/shared/utils/fetch-url.ts +13 -0
- package/src/shared/utils/network-error.ts +152 -0
- package/src/shared/utils/safe-file-name.ts +37 -0
- package/src/shared/utils/sha256.ts +15 -0
- package/src/supabase.ts +125 -119
- package/src/task/index.ts +45 -0
- package/src/task/local-task-registry.ts +115 -36
- package/src/task/task-manager.ts +101 -113
- package/src/task/task-node.ts +302 -0
- package/src/task/task-post-validated.api.ts +47 -0
- package/src/task/task-post.api.ts +99 -0
- package/src/task/task-queue.ts +18 -0
- package/src/task/task-repo-context.ts +4 -1
- package/src/task/task-repo-validation.ts +169 -0
- package/src/task/task.api.ts +68 -92
- package/src/task/task.constant.ts +4 -0
- package/src/task/task.interface.ts +6 -7
- package/src/trigger/trigger-manager.ts +287 -0
- package/src/trigger/trigger-node.ts +80 -0
- package/src/trigger/trigger.api.ts +166 -0
- package/src/trigger/trigger.constant.ts +10 -0
- package/src/trigger/trigger.interface.ts +100 -0
- package/src/trigger/trigger.utils.ts +56 -0
- package/src/word/word.api.ts +28 -30
- package/src/word/word.interface.ts +3 -4
- package/dist/auth/auth.api.d.ts +0 -28
- package/dist/auth/auth.api.d.ts.map +0 -1
- package/dist/auth/auth.api.js +0 -51
- package/dist/auth/auth.api.js.map +0 -1
- package/dist/command/command.api.js +0 -58
- package/dist/command/command.api.js.map +0 -1
- package/dist/command/command.interface.js +0 -9
- package/dist/command/command.interface.js.map +0 -1
- package/dist/core.api.js +0 -412
- package/dist/core.api.js.map +0 -1
- package/dist/core.interface.js +0 -46
- package/dist/core.interface.js.map +0 -1
- package/dist/core.utils.js +0 -81
- package/dist/core.utils.js.map +0 -1
- package/dist/feed/feed.interface.d.ts +0 -27
- package/dist/feed/feed.interface.d.ts.map +0 -1
- package/dist/feed/feed.interface.js +0 -17
- package/dist/feed/feed.interface.js.map +0 -1
- package/dist/file/file-manager.d.ts +0 -24
- package/dist/file/file-manager.d.ts.map +0 -1
- package/dist/file/file-manager.js +0 -109
- package/dist/file/file-manager.js.map +0 -1
- package/dist/file/file.api.d.ts +0 -15
- package/dist/file/file.api.d.ts.map +0 -1
- package/dist/file/file.api.js +0 -30
- package/dist/file/file.api.js.map +0 -1
- package/dist/file/file.interface.d.ts +0 -25
- package/dist/file/file.interface.d.ts.map +0 -1
- package/dist/file/file.interface.js +0 -9
- package/dist/file/file.interface.js.map +0 -1
- package/dist/file-list/file-list.api.d.ts +0 -15
- package/dist/file-list/file-list.api.d.ts.map +0 -1
- package/dist/file-list/file-list.api.js +0 -54
- package/dist/file-list/file-list.api.js.map +0 -1
- package/dist/file-list/file-list.interface.d.ts +0 -22
- package/dist/file-list/file-list.interface.d.ts.map +0 -1
- package/dist/file-list/file-list.interface.js +0 -5
- package/dist/file-list/file-list.interface.js.map +0 -1
- package/dist/idea/idea.interface.js +0 -15
- package/dist/idea/idea.interface.js.map +0 -1
- package/dist/index.js +0 -42
- package/dist/index.js.map +0 -1
- package/dist/link/link.api.js +0 -30
- package/dist/link/link.api.js.map +0 -1
- package/dist/link/link.interface.js +0 -7
- package/dist/link/link.interface.js.map +0 -1
- package/dist/list/list.api.js +0 -30
- package/dist/list/list.api.js.map +0 -1
- package/dist/list/list.interface.js +0 -6
- package/dist/list/list.interface.js.map +0 -1
- package/dist/node/node-manager.d.ts +0 -48
- package/dist/node/node-manager.d.ts.map +0 -1
- package/dist/node/node-manager.js +0 -619
- package/dist/node/node-manager.js.map +0 -1
- package/dist/node/node-task.preset.d.ts +0 -1
- package/dist/node/node-task.preset.d.ts.map +0 -1
- package/dist/node/node-task.preset.js +0 -14
- package/dist/node/node-task.preset.js.map +0 -1
- package/dist/node/node.api.js +0 -100
- package/dist/node/node.api.js.map +0 -1
- package/dist/node/node.interface.js +0 -19
- package/dist/node/node.interface.js.map +0 -1
- package/dist/node/node.utils.js +0 -36
- package/dist/node/node.utils.js.map +0 -1
- package/dist/parcel/parcel-manager.js +0 -156
- package/dist/parcel/parcel-manager.js.map +0 -1
- package/dist/parcel/parcel.interface.js +0 -11
- package/dist/parcel/parcel.interface.js.map +0 -1
- package/dist/question-list/question-list.api.d.ts +0 -13
- package/dist/question-list/question-list.api.d.ts.map +0 -1
- package/dist/question-list/question-list.api.js +0 -35
- package/dist/question-list/question-list.api.js.map +0 -1
- package/dist/question-list/question-list.interface.d.ts +0 -18
- package/dist/question-list/question-list.interface.d.ts.map +0 -1
- package/dist/question-list/question-list.interface.js +0 -5
- package/dist/question-list/question-list.interface.js.map +0 -1
- package/dist/repo/repo-context.utils.js +0 -81
- package/dist/repo/repo-context.utils.js.map +0 -1
- package/dist/repo/repo-manager.js +0 -156
- package/dist/repo/repo-manager.js.map +0 -1
- package/dist/repo/repo.api.js +0 -40
- package/dist/repo/repo.api.js.map +0 -1
- package/dist/repo/repo.interface.js +0 -8
- package/dist/repo/repo.interface.js.map +0 -1
- package/dist/repo/repo.script-loader.js +0 -108
- package/dist/repo/repo.script-loader.js.map +0 -1
- package/dist/review/review.api.d.ts +0 -14
- package/dist/review/review.api.d.ts.map +0 -1
- package/dist/review/review.api.js +0 -133
- package/dist/review/review.api.js.map +0 -1
- package/dist/review/review.interface.d.ts +0 -24
- package/dist/review/review.interface.d.ts.map +0 -1
- package/dist/review/review.interface.js +0 -10
- package/dist/review/review.interface.js.map +0 -1
- package/dist/review-v2/apis/post-review-setting.api.d.ts +0 -12
- package/dist/review-v2/apis/post-review-setting.api.d.ts.map +0 -1
- package/dist/review-v2/apis/post-review-setting.api.js +0 -27
- package/dist/review-v2/apis/post-review-setting.api.js.map +0 -1
- package/dist/review-v2/apis/post-review.api.d.ts +0 -13
- package/dist/review-v2/apis/post-review.api.d.ts.map +0 -1
- package/dist/review-v2/apis/post-review.api.js +0 -46
- package/dist/review-v2/apis/post-review.api.js.map +0 -1
- package/dist/review-v2/review-setting.interface.d.ts +0 -23
- package/dist/review-v2/review-setting.interface.d.ts.map +0 -1
- package/dist/review-v2/review-setting.interface.js +0 -5
- package/dist/review-v2/review-setting.interface.js.map +0 -1
- package/dist/review-v2/review.interface.d.ts +0 -20
- package/dist/review-v2/review.interface.d.ts.map +0 -1
- package/dist/review-v2/review.interface.js +0 -5
- package/dist/review-v2/review.interface.js.map +0 -1
- package/dist/service/api.interface.d.ts +0 -35
- package/dist/service/api.interface.d.ts.map +0 -1
- package/dist/service/api.interface.js +0 -12
- package/dist/service/api.interface.js.map +0 -1
- package/dist/service/base.interface.js +0 -7
- package/dist/service/base.interface.js.map +0 -1
- package/dist/service/service.interface.js +0 -11
- package/dist/service/service.interface.js.map +0 -1
- package/dist/shared/log/create-api-logger.d.ts +0 -17
- package/dist/shared/log/create-api-logger.d.ts.map +0 -1
- package/dist/shared/log/create-api-logger.js +0 -15
- package/dist/shared/log/create-api-logger.js.map +0 -1
- package/dist/shared/log/log-manager.js +0 -218
- package/dist/shared/log/log-manager.js.map +0 -1
- package/dist/shared/utils/config-path.utils.js +0 -85
- package/dist/shared/utils/config-path.utils.js.map +0 -1
- package/dist/shared/utils/error.utils.js +0 -15
- package/dist/shared/utils/error.utils.js.map +0 -1
- package/dist/shared/utils/id.utils.js +0 -5
- package/dist/shared/utils/id.utils.js.map +0 -1
- package/dist/supabase.js +0 -100
- package/dist/supabase.js.map +0 -1
- package/dist/task/local-task-registry.js +0 -153
- package/dist/task/local-task-registry.js.map +0 -1
- package/dist/task/task-manager.js +0 -217
- package/dist/task/task-manager.js.map +0 -1
- package/dist/task/task-repo-context.js +0 -12
- package/dist/task/task-repo-context.js.map +0 -1
- package/dist/task/task.api.js +0 -351
- package/dist/task/task.api.js.map +0 -1
- package/dist/task/task.interface.js +0 -36
- package/dist/task/task.interface.js.map +0 -1
- package/dist/task/task.utils.js +0 -2
- package/dist/task/task.utils.js.map +0 -1
- package/dist/word/word.api.js +0 -30
- package/dist/word/word.api.js.map +0 -1
- package/dist/word/word.interface.js +0 -6
- package/dist/word/word.interface.js.map +0 -1
- package/src/auth/auth.api.ts +0 -87
- package/src/feed/feed.interface.ts +0 -33
- package/src/file/file-manager.ts +0 -145
- package/src/file/file.api.ts +0 -43
- package/src/file/file.interface.ts +0 -30
- package/src/file-list/file-list.api.ts +0 -64
- package/src/file-list/file-list.interface.ts +0 -24
- package/src/node/node-manager.ts +0 -673
- package/src/node/node-task.preset.ts +0 -13
- package/src/question-list/question-list.api.ts +0 -42
- package/src/question-list/question-list.interface.ts +0 -21
- package/src/review/review.api.ts +0 -145
- package/src/review/review.interface.ts +0 -26
- package/src/review-v2/apis/post-review-setting.api.ts +0 -35
- package/src/review-v2/apis/post-review.api.ts +0 -59
- package/src/review-v2/review-setting.interface.ts +0 -26
- package/src/review-v2/review.interface.ts +0 -23
- package/src/service/api.interface.ts +0 -47
- package/src/shared/log/create-api-logger.ts +0 -25
|
@@ -1,209 +1,467 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TargetDraft } from "../core.interface";
|
|
2
|
+
import { sha256Hex } from "../shared/utils/sha256";
|
|
3
|
+
import { CategoryParcel, type Chunk, type Parcel, type ParcelCrypto, type ParcelDetails } from "./parcel.interface";
|
|
2
4
|
|
|
3
5
|
const MANIFEST_VERSION = 1;
|
|
4
|
-
const DEFAULT_CHUNK_SIZE =
|
|
6
|
+
const DEFAULT_CHUNK_SIZE = 2 * 1024 * 1024; // 2MB - fallback for empty input only
|
|
7
|
+
const MB = 1024 * 1024;
|
|
8
|
+
/** Source files at or below this size use at most 2 chunks */
|
|
9
|
+
const SMALL_FILE_MAX_BYTES = 50 * MB;
|
|
10
|
+
/** Target per-chunk size for larger files */
|
|
11
|
+
const PREFERRED_CHUNK_BYTES = 16 * MB;
|
|
12
|
+
/** Cap chunk count for very large files */
|
|
13
|
+
const MAX_CHUNK_COUNT = 64;
|
|
14
|
+
const AES_GCM_ALGORITHM = "AES-GCM-256";
|
|
15
|
+
const KEY_DERIVATION_PBKDF2 = "PBKDF2-SHA256";
|
|
16
|
+
const PBKDF2_ITERATIONS = 100_000;
|
|
5
17
|
const AES_GCM_IV_LENGTH = 12;
|
|
6
18
|
const AES_GCM_TAG_LENGTH = 128;
|
|
19
|
+
/** Auth tag bytes Web Crypto appends to AES-GCM ciphertext */
|
|
20
|
+
const AES_GCM_AUTH_TAG_BYTES = AES_GCM_TAG_LENGTH / 8;
|
|
7
21
|
|
|
8
|
-
/** IV
|
|
9
|
-
const
|
|
22
|
+
/** @deprecated Legacy IV in Target.extra - read only for old parcels */
|
|
23
|
+
const LEGACY_EXTRA_IV_KEY = "iv";
|
|
10
24
|
|
|
11
|
-
/**
|
|
25
|
+
/** Pluggable storage backend; chunks are round-robin distributed across adapters */
|
|
12
26
|
export interface StorageAdapter {
|
|
13
|
-
|
|
14
|
-
|
|
27
|
+
/** Written to {@link Chunk.provider} (e.g. `"s3"`, `"ipfs"`) */
|
|
28
|
+
provider?: string;
|
|
29
|
+
upload(data: ArrayBuffer, pathOrKey: string): Promise<{ url: string }>;
|
|
15
30
|
}
|
|
16
31
|
|
|
17
|
-
interface CreateOptions {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
export interface CreateOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Bytes per chunk after split (plaintext or ciphertext).
|
|
35
|
+
* When omitted, derived from source file size — see {@link resolveChunkSize}.
|
|
36
|
+
*/
|
|
37
|
+
chunkSize?: number;
|
|
38
|
+
/**
|
|
39
|
+
* When `true`, encrypt the whole file before chunking.
|
|
40
|
+
* Default `false` — plaintext shards across platforms (anti single-platform review).
|
|
41
|
+
*/
|
|
42
|
+
encrypt?: boolean;
|
|
43
|
+
/** User passphrase (e.g. `"apple"`); derives AES key via PBKDF2 when `encrypt` is true */
|
|
44
|
+
passphrase?: string;
|
|
45
|
+
/** Raw AES-GCM key; mutually exclusive with `passphrase` */
|
|
46
|
+
key?: CryptoKey;
|
|
22
47
|
}
|
|
23
48
|
|
|
24
|
-
interface
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/** Base64 编码的 IV,需在 save 时写入 Parcel.extra 供 reassembly 使用 */
|
|
30
|
-
ivBase64: string;
|
|
31
|
-
/** 若 create 时未传 key,则返回此处,调用方需妥善保存 */
|
|
32
|
-
key?: CryptoKey;
|
|
49
|
+
export interface ReassembleOptions {
|
|
50
|
+
/** Raw AES-GCM key (parcels without passphrase-based KDF) */
|
|
51
|
+
key?: CryptoKey;
|
|
52
|
+
/** Passphrase when `details.crypto.keyDerivation` is PBKDF2 */
|
|
53
|
+
passphrase?: string;
|
|
33
54
|
}
|
|
34
55
|
|
|
35
|
-
|
|
36
|
-
|
|
56
|
+
export interface CreateResult {
|
|
57
|
+
details: ParcelDetails;
|
|
58
|
+
/** Chunk payloads to upload (plaintext or ciphertext per `details.crypto`) */
|
|
59
|
+
chunks: ArrayBuffer[];
|
|
60
|
+
/** Present when `encrypt` and key was generated — caller must persist */
|
|
61
|
+
key?: CryptoKey;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Identity fields for {@link save} — `id` / `created_at` come from {@link postParcel}. */
|
|
65
|
+
export interface ParcelSaveInput {
|
|
66
|
+
name: string;
|
|
67
|
+
value: string;
|
|
68
|
+
tagList?: string[];
|
|
69
|
+
}
|
|
37
70
|
|
|
38
71
|
function getCrypto(): Crypto {
|
|
39
|
-
|
|
40
|
-
|
|
72
|
+
if (typeof globalThis !== "undefined" && globalThis.crypto) return globalThis.crypto;
|
|
73
|
+
throw new Error("ParcelManager: crypto not available");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function bytesToBase64(bytes: Uint8Array): string {
|
|
77
|
+
return btoa(String.fromCharCode(...bytes));
|
|
41
78
|
}
|
|
42
79
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const crypto = getCrypto();
|
|
46
|
-
const hash = await crypto.subtle.digest("SHA-256", buffer);
|
|
47
|
-
return Array.from(new Uint8Array(hash))
|
|
48
|
-
.map((b) => b.toString(16).padStart(2, "0"))
|
|
49
|
-
.join("");
|
|
80
|
+
function base64ToBytes(base64: string): Uint8Array {
|
|
81
|
+
return Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
|
|
50
82
|
}
|
|
51
83
|
|
|
52
|
-
/** AES-GCM 加密 */
|
|
53
84
|
async function encrypt(data: ArrayBuffer, key: CryptoKey, iv: Uint8Array): Promise<ArrayBuffer> {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return crypto.subtle.encrypt({ name: "AES-GCM", iv: ivCopy, tagLength: AES_GCM_TAG_LENGTH }, key, data);
|
|
85
|
+
const crypto = getCrypto();
|
|
86
|
+
return crypto.subtle.encrypt({ name: "AES-GCM", iv: new Uint8Array(iv), tagLength: AES_GCM_TAG_LENGTH }, key, data);
|
|
57
87
|
}
|
|
58
88
|
|
|
59
|
-
/** AES-GCM 解密 */
|
|
60
89
|
async function decrypt(data: ArrayBuffer, key: CryptoKey, iv: Uint8Array): Promise<ArrayBuffer> {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
90
|
+
const crypto = getCrypto();
|
|
91
|
+
return crypto.subtle.decrypt({ name: "AES-GCM", iv: new Uint8Array(iv), tagLength: AES_GCM_TAG_LENGTH }, key, data);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function isDecryptAuthFailure(error: unknown): boolean {
|
|
95
|
+
if (error instanceof DOMException && error.name === "OperationError") {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
if (error instanceof Error) {
|
|
99
|
+
return /operation failed|operation-specific|decrypt|OperationError/i.test(error.message);
|
|
100
|
+
}
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function decryptPayload(
|
|
105
|
+
data: ArrayBuffer,
|
|
106
|
+
key: CryptoKey,
|
|
107
|
+
iv: Uint8Array,
|
|
108
|
+
usedPassphrase: boolean,
|
|
109
|
+
): Promise<ArrayBuffer> {
|
|
110
|
+
try {
|
|
111
|
+
return await decrypt(data, key, iv);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
if (isDecryptAuthFailure(error)) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
usedPassphrase
|
|
116
|
+
? "ParcelManager.reassemble: 解密失败,口令错误或密文已损坏"
|
|
117
|
+
: "ParcelManager.reassemble: 解密失败,密钥错误或密文已损坏",
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
64
122
|
}
|
|
65
123
|
|
|
66
|
-
/** 生成 AES-GCM 密钥(256 位) */
|
|
67
124
|
async function generateKey(): Promise<CryptoKey> {
|
|
68
|
-
|
|
69
|
-
|
|
125
|
+
const crypto = getCrypto();
|
|
126
|
+
return crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"]);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function deriveKeyFromPassphrase(passphrase: string, salt: Uint8Array, iterations: number): Promise<CryptoKey> {
|
|
130
|
+
const crypto = getCrypto();
|
|
131
|
+
const keyMaterial = await crypto.subtle.importKey("raw", new TextEncoder().encode(passphrase), "PBKDF2", false, [
|
|
132
|
+
"deriveKey",
|
|
133
|
+
]);
|
|
134
|
+
return crypto.subtle.deriveKey(
|
|
135
|
+
{
|
|
136
|
+
name: "PBKDF2",
|
|
137
|
+
salt: new Uint8Array(salt),
|
|
138
|
+
iterations,
|
|
139
|
+
hash: "SHA-256",
|
|
140
|
+
},
|
|
141
|
+
keyMaterial,
|
|
142
|
+
{ name: "AES-GCM", length: 256 },
|
|
143
|
+
false,
|
|
144
|
+
["encrypt", "decrypt"],
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function usesPassphraseDerivation(crypto: ParcelCrypto): boolean {
|
|
149
|
+
return crypto.keyDerivation === KEY_DERIVATION_PBKDF2;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function resolveDecryptionKey(crypto: ParcelCrypto, options: ReassembleOptions): Promise<CryptoKey> {
|
|
153
|
+
if (usesPassphraseDerivation(crypto)) {
|
|
154
|
+
if (options.passphrase == null || options.passphrase === "") {
|
|
155
|
+
throw new Error("ParcelManager.reassemble: 口令加密 Parcel 需要提供 passphrase");
|
|
156
|
+
}
|
|
157
|
+
if (crypto.salt == null || crypto.salt === "") {
|
|
158
|
+
throw new Error("ParcelManager.reassemble: 缺少 details.crypto.salt");
|
|
159
|
+
}
|
|
160
|
+
const iterations = crypto.pbkdf2Iterations ?? PBKDF2_ITERATIONS;
|
|
161
|
+
const salt = base64ToBytes(crypto.salt);
|
|
162
|
+
return deriveKeyFromPassphrase(options.passphrase, salt, iterations);
|
|
163
|
+
}
|
|
164
|
+
if (options.key != null) {
|
|
165
|
+
return options.key;
|
|
166
|
+
}
|
|
167
|
+
throw new Error("ParcelManager.reassemble: 加密 Parcel 需要提供 key");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function buildChunkList(
|
|
171
|
+
payload: ArrayBuffer,
|
|
172
|
+
chunkSize: number,
|
|
173
|
+
): Promise<{ chunks: ArrayBuffer[]; chunkList: Chunk[] }> {
|
|
174
|
+
const chunks: ArrayBuffer[] = [];
|
|
175
|
+
const chunkList: Chunk[] = [];
|
|
176
|
+
let offset = 0;
|
|
177
|
+
let index = 0;
|
|
178
|
+
|
|
179
|
+
while (offset < payload.byteLength) {
|
|
180
|
+
const end = Math.min(offset + chunkSize, payload.byteLength);
|
|
181
|
+
const chunkBuffer = payload.slice(offset, end);
|
|
182
|
+
const checksum = await sha256Hex(chunkBuffer);
|
|
183
|
+
chunks.push(chunkBuffer);
|
|
184
|
+
chunkList.push({
|
|
185
|
+
index,
|
|
186
|
+
size: chunkBuffer.byteLength,
|
|
187
|
+
checksum,
|
|
188
|
+
url: "",
|
|
189
|
+
});
|
|
190
|
+
offset = end;
|
|
191
|
+
index += 1;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return { chunks, chunkList };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Derive per-chunk byte size from the buffer that will be split.
|
|
199
|
+
*
|
|
200
|
+
* | Payload size | Policy |
|
|
201
|
+
* |--------------|--------|
|
|
202
|
+
* | ≤50 MB | At most **2** chunks (`ceil(size / 2)` per chunk) |
|
|
203
|
+
* | > 50 MB | Target ~16 MB per chunk; chunk count capped at **64** |
|
|
204
|
+
*
|
|
205
|
+
* For encrypted parcels, pass plaintext size + {@link AES_GCM_AUTH_TAG_BYTES}
|
|
206
|
+
* (GCM auth tag is appended before split).
|
|
207
|
+
*
|
|
208
|
+
* Explicit `chunkSize` in {@link CreateOptions} overrides this table.
|
|
209
|
+
*/
|
|
210
|
+
function resolveChunkSize(fileSize: number, override?: number): number {
|
|
211
|
+
if (override != null) {
|
|
212
|
+
if (!Number.isFinite(override) || override <= 0) {
|
|
213
|
+
throw new Error("ParcelManager.create: chunkSize must be a positive number");
|
|
214
|
+
}
|
|
215
|
+
return override;
|
|
216
|
+
}
|
|
217
|
+
if (fileSize <= 0) {
|
|
218
|
+
return DEFAULT_CHUNK_SIZE;
|
|
219
|
+
}
|
|
220
|
+
if (fileSize <= SMALL_FILE_MAX_BYTES) {
|
|
221
|
+
return Math.ceil(fileSize / 2);
|
|
222
|
+
}
|
|
223
|
+
const targetChunks = Math.min(MAX_CHUNK_COUNT, Math.max(2, Math.ceil(fileSize / PREFERRED_CHUNK_BYTES)));
|
|
224
|
+
return Math.ceil(fileSize / targetChunks);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function concatBuffers(buffers: ArrayBuffer[]): ArrayBuffer {
|
|
228
|
+
const total = buffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
|
|
229
|
+
const merged = new Uint8Array(total);
|
|
230
|
+
let offset = 0;
|
|
231
|
+
for (const buffer of buffers) {
|
|
232
|
+
merged.set(new Uint8Array(buffer), offset);
|
|
233
|
+
offset += buffer.byteLength;
|
|
234
|
+
}
|
|
235
|
+
return merged.buffer;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function isEncryptionEnabled(details: ParcelDetails, parcelExtra?: string): boolean {
|
|
239
|
+
if (details.crypto != null) {
|
|
240
|
+
return details.crypto.enabled === true;
|
|
241
|
+
}
|
|
242
|
+
if (parcelExtra == null || parcelExtra.trim() === "") {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
const legacy = JSON.parse(parcelExtra) as Record<string, unknown>;
|
|
247
|
+
return typeof legacy[LEGACY_EXTRA_IV_KEY] === "string";
|
|
248
|
+
} catch {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
70
251
|
}
|
|
71
252
|
|
|
72
|
-
|
|
253
|
+
function resolveCrypto(details: ParcelDetails, parcelExtra?: string): ParcelCrypto | null {
|
|
254
|
+
if (details.crypto?.enabled === true) {
|
|
255
|
+
return details.crypto;
|
|
256
|
+
}
|
|
257
|
+
if (parcelExtra == null || parcelExtra.trim() === "") {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
try {
|
|
261
|
+
const legacy = JSON.parse(parcelExtra) as Record<string, unknown>;
|
|
262
|
+
const iv = legacy[LEGACY_EXTRA_IV_KEY];
|
|
263
|
+
if (typeof iv !== "string" || iv === "") {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
return { enabled: true, algorithm: AES_GCM_ALGORITHM, iv };
|
|
267
|
+
} catch {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Split a file into chunks. Default: plaintext shards; optional whole-file AES-GCM before split.
|
|
274
|
+
*/
|
|
73
275
|
async function create(file: ArrayBuffer, options: CreateOptions = {}): Promise<CreateResult> {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
276
|
+
const encryptEnabled = options.encrypt === true;
|
|
277
|
+
const splitPayloadSize = encryptEnabled ? file.byteLength + AES_GCM_AUTH_TAG_BYTES : file.byteLength;
|
|
278
|
+
const chunkSize = resolveChunkSize(splitPayloadSize, options.chunkSize);
|
|
279
|
+
const plaintextChecksum = await sha256Hex(file);
|
|
280
|
+
|
|
281
|
+
if (!encryptEnabled) {
|
|
282
|
+
const { chunks, chunkList } = await buildChunkList(file, chunkSize);
|
|
283
|
+
return {
|
|
284
|
+
details: {
|
|
285
|
+
manifestVersion: MANIFEST_VERSION,
|
|
286
|
+
chunkList,
|
|
287
|
+
checksum: plaintextChecksum,
|
|
288
|
+
size: file.byteLength,
|
|
289
|
+
},
|
|
290
|
+
chunks,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (options.passphrase != null && options.key != null) {
|
|
295
|
+
throw new Error("ParcelManager.create: passphrase 与 key 不能同時指定");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const cryptoApi = getCrypto();
|
|
299
|
+
const iv = cryptoApi.getRandomValues(new Uint8Array(AES_GCM_IV_LENGTH));
|
|
300
|
+
let key: CryptoKey;
|
|
301
|
+
let generatedKey = false;
|
|
302
|
+
let cryptoMeta: ParcelCrypto;
|
|
303
|
+
|
|
304
|
+
if (options.passphrase != null && options.passphrase !== "") {
|
|
305
|
+
const salt = cryptoApi.getRandomValues(new Uint8Array(16));
|
|
306
|
+
key = await deriveKeyFromPassphrase(options.passphrase, salt, PBKDF2_ITERATIONS);
|
|
307
|
+
cryptoMeta = {
|
|
308
|
+
enabled: true,
|
|
309
|
+
algorithm: AES_GCM_ALGORITHM,
|
|
310
|
+
iv: bytesToBase64(iv),
|
|
311
|
+
keyDerivation: KEY_DERIVATION_PBKDF2,
|
|
312
|
+
salt: bytesToBase64(salt),
|
|
313
|
+
pbkdf2Iterations: PBKDF2_ITERATIONS,
|
|
314
|
+
};
|
|
315
|
+
} else if (options.key != null) {
|
|
316
|
+
key = options.key;
|
|
317
|
+
cryptoMeta = {
|
|
318
|
+
enabled: true,
|
|
319
|
+
algorithm: AES_GCM_ALGORITHM,
|
|
320
|
+
iv: bytesToBase64(iv),
|
|
321
|
+
};
|
|
322
|
+
} else {
|
|
323
|
+
key = await generateKey();
|
|
324
|
+
generatedKey = true;
|
|
325
|
+
cryptoMeta = {
|
|
326
|
+
enabled: true,
|
|
327
|
+
algorithm: AES_GCM_ALGORITHM,
|
|
328
|
+
iv: bytesToBase64(iv),
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const encrypted = await encrypt(file, key, iv);
|
|
333
|
+
const { chunks, chunkList } = await buildChunkList(encrypted, chunkSize);
|
|
334
|
+
|
|
335
|
+
const result: CreateResult = {
|
|
336
|
+
details: {
|
|
337
|
+
manifestVersion: MANIFEST_VERSION,
|
|
338
|
+
chunkList,
|
|
339
|
+
checksum: plaintextChecksum,
|
|
340
|
+
size: file.byteLength,
|
|
341
|
+
crypto: cryptoMeta,
|
|
342
|
+
},
|
|
343
|
+
chunks,
|
|
344
|
+
};
|
|
345
|
+
if (generatedKey) {
|
|
346
|
+
result.key = key;
|
|
347
|
+
}
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/** Upload chunks round-robin across storage adapters */
|
|
124
352
|
async function save(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
): Promise<Parcel
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
353
|
+
createResult: CreateResult,
|
|
354
|
+
fileSystems: StorageAdapter[],
|
|
355
|
+
input: ParcelSaveInput,
|
|
356
|
+
): Promise<TargetDraft<Parcel>> {
|
|
357
|
+
if (fileSystems.length === 0) {
|
|
358
|
+
throw new Error("ParcelManager.save: fileSystems 不能为空");
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const { details, chunks } = createResult;
|
|
362
|
+
const chunkListWithUrls: Chunk[] = [];
|
|
363
|
+
|
|
364
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
365
|
+
const adapter = fileSystems[i % fileSystems.length];
|
|
366
|
+
const pathOrKey = `chunk-${i}-${details.checksum.slice(0, 8)}`;
|
|
367
|
+
const { url } = await adapter.upload(chunks[i], pathOrKey);
|
|
368
|
+
chunkListWithUrls.push({
|
|
369
|
+
...details.chunkList[i],
|
|
370
|
+
url,
|
|
371
|
+
provider: adapter.provider,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
name: input.name,
|
|
377
|
+
value: input.value,
|
|
378
|
+
tagList: input.tagList ?? [],
|
|
379
|
+
category: CategoryParcel.PARCEL,
|
|
380
|
+
details: {
|
|
381
|
+
...details,
|
|
382
|
+
chunkList: chunkListWithUrls,
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async function downloadAndVerifyChunks(chunkList: Chunk[]): Promise<ArrayBuffer[]> {
|
|
388
|
+
const sortedChunks = [...chunkList].sort((a, b) => a.index - b.index);
|
|
389
|
+
const buffers: ArrayBuffer[] = [];
|
|
390
|
+
|
|
391
|
+
for (const chunkMeta of sortedChunks) {
|
|
392
|
+
const res = await fetch(chunkMeta.url);
|
|
393
|
+
if (!res.ok) {
|
|
394
|
+
throw new Error(`ParcelManager.reassemble: 下载 chunk ${chunkMeta.index} 失败: ${res.status}`);
|
|
395
|
+
}
|
|
396
|
+
const chunkBuffer = await res.arrayBuffer();
|
|
397
|
+
const chunkChecksum = await sha256Hex(chunkBuffer);
|
|
398
|
+
if (chunkChecksum !== chunkMeta.checksum) {
|
|
399
|
+
throw new Error(`ParcelManager.reassemble: chunk ${chunkMeta.index} 校验失败 (checksum 不一致`);
|
|
400
|
+
}
|
|
401
|
+
buffers.push(chunkBuffer);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return buffers;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
function verifyPlaintextSize(buffer: ArrayBuffer, details: ParcelDetails): void {
|
|
408
|
+
if (buffer.byteLength !== details.size) {
|
|
409
|
+
throw new Error(
|
|
410
|
+
`ParcelManager.reassemble: 重组后大小与 details.size 不一致(${buffer.byteLength} !== ${details.size})`,
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Fetch chunks from {@link Parcel.details.chunkList}, reassemble, optionally decrypt, verify checksum.
|
|
417
|
+
* Encrypted parcels: pass `{ passphrase }` for PBKDF2 parcels, or `{ key }` for raw-key parcels.
|
|
418
|
+
*/
|
|
419
|
+
async function reassemble(parcel: Parcel, options: ReassembleOptions = {}): Promise<ArrayBuffer> {
|
|
420
|
+
const { details } = parcel;
|
|
421
|
+
const encrypted = isEncryptionEnabled(details, parcel.extra);
|
|
422
|
+
|
|
423
|
+
const buffers = await downloadAndVerifyChunks(details.chunkList);
|
|
424
|
+
const merged = concatBuffers(buffers);
|
|
425
|
+
|
|
426
|
+
if (!encrypted) {
|
|
427
|
+
verifyPlaintextSize(merged, details);
|
|
428
|
+
const fileChecksum = await sha256Hex(merged);
|
|
429
|
+
if (fileChecksum !== details.checksum) {
|
|
430
|
+
throw new Error("ParcelManager.reassemble: 重组后文件校验失败 (sha256 与 details.checksum 不一致)");
|
|
431
|
+
}
|
|
432
|
+
return merged;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const cryptoMeta = resolveCrypto(details, parcel.extra);
|
|
436
|
+
if (cryptoMeta?.iv == null || cryptoMeta.iv === "") {
|
|
437
|
+
throw new Error("ParcelManager.reassemble: 加密 Parcel 缺少 details.crypto.iv");
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const iv = base64ToBytes(cryptoMeta.iv);
|
|
441
|
+
if (iv.length !== AES_GCM_IV_LENGTH) {
|
|
442
|
+
throw new Error("ParcelManager.reassemble: IV 长度无效");
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const key = await resolveDecryptionKey(cryptoMeta, options);
|
|
446
|
+
const usedPassphrase = usesPassphraseDerivation(cryptoMeta);
|
|
447
|
+
const decrypted = await decryptPayload(merged, key, iv, usedPassphrase);
|
|
448
|
+
verifyPlaintextSize(decrypted, details);
|
|
449
|
+
const fileChecksum = await sha256Hex(decrypted);
|
|
450
|
+
if (fileChecksum !== details.checksum) {
|
|
451
|
+
throw new Error(
|
|
452
|
+
usedPassphrase
|
|
453
|
+
? "ParcelManager.reassemble: 解密后校验失败,口令错误或数据已损坏"
|
|
454
|
+
: "ParcelManager.reassemble: 解密后文件校验失败 (sha256 与 details.checksum 不一致)",
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return decrypted;
|
|
201
459
|
}
|
|
202
460
|
|
|
203
461
|
const ParcelManager = {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
462
|
+
create,
|
|
463
|
+
save,
|
|
464
|
+
reassemble,
|
|
207
465
|
};
|
|
208
466
|
|
|
209
467
|
export { ParcelManager };
|