Step 2.5 in deploy.js was env-blind, so 'npm run deploy:dev' falsely
reported reusing the production KV while wrangler silently fell back to
the env binding. Combined with [env.development] inheriting top-level
routes, dev deploys could also hijack the production custom domain.
Make extractWorkerName / injectKvNamespaceId / findExistingKvId accept
an envName parameter, and preserve [env.development].routes across
Sync Upstream merges so 'routes = []' overrides survive upgrades.
Split bulk/Google-migration imports into 100-item chunks (shared via
LIMITS.BULK_IMPORT_CHUNK_SIZE) so large batches stay within rate limits
and avoid per-request timeouts.
Backend:
- batch.js accepts chunkIndex/chunkCount; only full, non-last chunks
skip the event-driven backup (prevents forged metadata from bypassing)
- shared.js skipBackup branch stages pending_backup_hash so cron can
compensate via hash comparison; on stage failure falls back to an
immediate backup so middle chunks are never left without coverage
- data-hash.js saveDataHash accepts backupStartedAt and clears pending
entries superseded by the just-committed backup, avoiding KV residue
from multi-chunk imports
- worker.js/backup.js thread backupStartedAt through both event-driven
and scheduled paths
Frontend:
- import/core.js + googleMigration.js chunk uploads and accumulate
success/failure across retries; resume picks up from remaining items
- Google migration failures re-open the preview modal (including the
first-round zero-success case) so users always have a retry entry
- New regression test (emitted-scripts-parse.test.js) parses every
generated UI script through new Function to catch template-literal
issues like real newlines in .join('\n')
Bump package manifests, logger/monitoring defaults, and README badges
to 1.4.0 covering the backup/export refactor and offline fallback.
Single-file release bundles now inject a timestamped
serviceWorkerVersion via esbuild define (previously fell back to
SW_VERSION='v1' and left PWA clients on stale caches), and the
generated DEPLOY.md lists the cache version plus the cloud-drive
OAuth secrets (ONEDRIVE_*, GOOGLE_DRIVE_*, OAUTH_REDIRECT_BASE_URL).
Restore PWA offline parity for standard TXT/JSON/CSV/HTML exports by
falling back to the local generator when the unified /api/secrets/export
endpoint is unreachable (network TypeError), returns 503 with
{offline:true} from the service worker, or rejects with 413. The local
OTPAuth path now preserves HOTP type and counter.
Add a dedicated /api/secrets/export route (api/secrets/export.js)
that streams the unified backup format (JSON/CSV/HTML/TXT) with size
and auth guards. Settings persist the preferred export format per
user; backup runs pick it up so generated files match the chosen
schema. The UI settings label/toast reads "导出偏好格式" to clarify
the preference applies to batch export and backup export. The
Service Worker passes through offline responses, utils/backup-format.js
is slimmed down after route consolidation, and unused createdAt is
dropped from the unified format and validation.
Centralize backup serialization in utils/backup-format.js with a
single createBackupEntry() path shared by scheduled backups, manual
backups and exports. Introduce utils/backup-index.js for KV key
listing/pruning and utils/data-hash.js for change detection,
replacing ad-hoc helpers scattered across api/secrets/backup.js,
restore.js and worker.js. UI backup/export modules consume the shared
format so HTML/JSON/CSV exports round-trip through the same schema.