zen-fs-config 0.5.44 → 0.5.45

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/dist/index.d.mts CHANGED
@@ -347,6 +347,20 @@ interface AppDataGroupDescriptor {
347
347
  groupType: 'data-sync';
348
348
  backends: AppDataBackendDescriptor[];
349
349
  }
350
+ /** Per-backend sync state of a data group. */
351
+ interface BackendSyncState {
352
+ backendId: string;
353
+ /** Pair id when the backend instance was created and paired successfully. */
354
+ pairId?: string;
355
+ /**
356
+ * Present when this descriptor could not be connected (e.g. a required
357
+ * option is missing), so no sync pair exists for it.
358
+ */
359
+ error?: {
360
+ message: string;
361
+ timestamp: number;
362
+ };
363
+ }
350
364
  /** Handle to a data-sync group, providing direct fs access. */
351
365
  interface AppDataGroup {
352
366
  readonly groupId: string;
@@ -355,6 +369,11 @@ interface AppDataGroup {
355
369
  readonly fs: typeof node_fs;
356
370
  /** Get sync status for this data group's sync pairs. */
357
371
  getSyncStatuses(): Map<string, SyncPairStatus>;
372
+ /**
373
+ * Per-backend sync state, including descriptors that failed to connect and
374
+ * therefore have no pair (they do not appear in getSyncStatuses()).
375
+ */
376
+ getBackendSyncStates(): Map<string, BackendSyncState>;
358
377
  /** Manually flush pending sync. */
359
378
  flush(): Promise<SyncResult[]>;
360
379
  /** Stop sync and release resources. */
@@ -1141,4 +1160,4 @@ declare function incrementVersion(fs: SyncableFS, configFilePath: string, newCon
1141
1160
  */
1142
1161
  declare function verifyOrRepairVersion(fs: SyncableFS, configFilePath: string, author: string): Promise<VersionMeta | null>;
1143
1162
 
1144
- export { type AppDataBackendDescriptor, type AppDataGroup, type AppDataGroupDescriptor, type BackendDescriptor, type BackendFactory, type BackendInstance, type BackendMetadata, type BackendParamDef, type BackendsMeta, type CacheOptions, ConfigRepo, type ConfigRepoOptions, type ConfigSerializer, type ConflictArchive, type ConflictInfo, type ConnectOptions, type ConnectResult, FolderStore, type IConfigRepo, type KeepPurgeResult, LOCAL_IDB_BACKEND_ID, type MigrateLocalFS, type MigrateReplicaFS, type MtimePurgeResult, type PurgeKeepOptions, type PurgeMtimeOptions, type PurgeableFS$1 as PurgeableFS, type SyncGroupType, type TombstoneMeta, type VersionMeta, type VersionMigrationOptions, type VersionMigrationResult, configKeyToFilePath, connect, createBackend, createConfigRepo, createSerializerChain, getAccountFields, getBackendMetadata, getExtension, hasBackend, incrementVersion, isBrowserEnv, isKeepFile, isMtimeSidecar, legacyVersionPathFor, listBackendMetadata, listBackends, localPrimaryType, mergeAccountFields, migrateVersionSidecars, purgeKeepFiles, purgeMtimeSidecars, readVersion, registerBackend, registerFolderBackend, resolveLocalPrimary, sha256, unregisterBackend, verifyOrRepairVersion, versionPathFor, wrapZenFSFileSystem, writeVersion };
1163
+ export { type AppDataBackendDescriptor, type AppDataGroup, type AppDataGroupDescriptor, type BackendDescriptor, type BackendFactory, type BackendInstance, type BackendMetadata, type BackendParamDef, type BackendSyncState, type BackendsMeta, type CacheOptions, ConfigRepo, type ConfigRepoOptions, type ConfigSerializer, type ConflictArchive, type ConflictInfo, type ConnectOptions, type ConnectResult, FolderStore, type IConfigRepo, type KeepPurgeResult, LOCAL_IDB_BACKEND_ID, type MigrateLocalFS, type MigrateReplicaFS, type MtimePurgeResult, type PurgeKeepOptions, type PurgeMtimeOptions, type PurgeableFS$1 as PurgeableFS, type SyncGroupType, type TombstoneMeta, type VersionMeta, type VersionMigrationOptions, type VersionMigrationResult, configKeyToFilePath, connect, createBackend, createConfigRepo, createSerializerChain, getAccountFields, getBackendMetadata, getExtension, hasBackend, incrementVersion, isBrowserEnv, isKeepFile, isMtimeSidecar, legacyVersionPathFor, listBackendMetadata, listBackends, localPrimaryType, mergeAccountFields, migrateVersionSidecars, purgeKeepFiles, purgeMtimeSidecars, readVersion, registerBackend, registerFolderBackend, resolveLocalPrimary, sha256, unregisterBackend, verifyOrRepairVersion, versionPathFor, wrapZenFSFileSystem, writeVersion };
package/dist/index.d.ts CHANGED
@@ -347,6 +347,20 @@ interface AppDataGroupDescriptor {
347
347
  groupType: 'data-sync';
348
348
  backends: AppDataBackendDescriptor[];
349
349
  }
350
+ /** Per-backend sync state of a data group. */
351
+ interface BackendSyncState {
352
+ backendId: string;
353
+ /** Pair id when the backend instance was created and paired successfully. */
354
+ pairId?: string;
355
+ /**
356
+ * Present when this descriptor could not be connected (e.g. a required
357
+ * option is missing), so no sync pair exists for it.
358
+ */
359
+ error?: {
360
+ message: string;
361
+ timestamp: number;
362
+ };
363
+ }
350
364
  /** Handle to a data-sync group, providing direct fs access. */
351
365
  interface AppDataGroup {
352
366
  readonly groupId: string;
@@ -355,6 +369,11 @@ interface AppDataGroup {
355
369
  readonly fs: typeof node_fs;
356
370
  /** Get sync status for this data group's sync pairs. */
357
371
  getSyncStatuses(): Map<string, SyncPairStatus>;
372
+ /**
373
+ * Per-backend sync state, including descriptors that failed to connect and
374
+ * therefore have no pair (they do not appear in getSyncStatuses()).
375
+ */
376
+ getBackendSyncStates(): Map<string, BackendSyncState>;
358
377
  /** Manually flush pending sync. */
359
378
  flush(): Promise<SyncResult[]>;
360
379
  /** Stop sync and release resources. */
@@ -1141,4 +1160,4 @@ declare function incrementVersion(fs: SyncableFS, configFilePath: string, newCon
1141
1160
  */
1142
1161
  declare function verifyOrRepairVersion(fs: SyncableFS, configFilePath: string, author: string): Promise<VersionMeta | null>;
1143
1162
 
1144
- export { type AppDataBackendDescriptor, type AppDataGroup, type AppDataGroupDescriptor, type BackendDescriptor, type BackendFactory, type BackendInstance, type BackendMetadata, type BackendParamDef, type BackendsMeta, type CacheOptions, ConfigRepo, type ConfigRepoOptions, type ConfigSerializer, type ConflictArchive, type ConflictInfo, type ConnectOptions, type ConnectResult, FolderStore, type IConfigRepo, type KeepPurgeResult, LOCAL_IDB_BACKEND_ID, type MigrateLocalFS, type MigrateReplicaFS, type MtimePurgeResult, type PurgeKeepOptions, type PurgeMtimeOptions, type PurgeableFS$1 as PurgeableFS, type SyncGroupType, type TombstoneMeta, type VersionMeta, type VersionMigrationOptions, type VersionMigrationResult, configKeyToFilePath, connect, createBackend, createConfigRepo, createSerializerChain, getAccountFields, getBackendMetadata, getExtension, hasBackend, incrementVersion, isBrowserEnv, isKeepFile, isMtimeSidecar, legacyVersionPathFor, listBackendMetadata, listBackends, localPrimaryType, mergeAccountFields, migrateVersionSidecars, purgeKeepFiles, purgeMtimeSidecars, readVersion, registerBackend, registerFolderBackend, resolveLocalPrimary, sha256, unregisterBackend, verifyOrRepairVersion, versionPathFor, wrapZenFSFileSystem, writeVersion };
1163
+ export { type AppDataBackendDescriptor, type AppDataGroup, type AppDataGroupDescriptor, type BackendDescriptor, type BackendFactory, type BackendInstance, type BackendMetadata, type BackendParamDef, type BackendSyncState, type BackendsMeta, type CacheOptions, ConfigRepo, type ConfigRepoOptions, type ConfigSerializer, type ConflictArchive, type ConflictInfo, type ConnectOptions, type ConnectResult, FolderStore, type IConfigRepo, type KeepPurgeResult, LOCAL_IDB_BACKEND_ID, type MigrateLocalFS, type MigrateReplicaFS, type MtimePurgeResult, type PurgeKeepOptions, type PurgeMtimeOptions, type PurgeableFS$1 as PurgeableFS, type SyncGroupType, type TombstoneMeta, type VersionMeta, type VersionMigrationOptions, type VersionMigrationResult, configKeyToFilePath, connect, createBackend, createConfigRepo, createSerializerChain, getAccountFields, getBackendMetadata, getExtension, hasBackend, incrementVersion, isBrowserEnv, isKeepFile, isMtimeSidecar, legacyVersionPathFor, listBackendMetadata, listBackends, localPrimaryType, mergeAccountFields, migrateVersionSidecars, purgeKeepFiles, purgeMtimeSidecars, readVersion, registerBackend, registerFolderBackend, resolveLocalPrimary, sha256, unregisterBackend, verifyOrRepairVersion, versionPathFor, wrapZenFSFileSystem, writeVersion };
package/dist/index.js CHANGED
@@ -2885,6 +2885,7 @@ var AppDataGroupImpl = class {
2885
2885
  syncEngine;
2886
2886
  localFS;
2887
2887
  dataBackends = /* @__PURE__ */ new Map();
2888
+ backendStates = /* @__PURE__ */ new Map();
2888
2889
  disposed = false;
2889
2890
  constructor(groupId, appId, backends, pollIntervalMs, parent) {
2890
2891
  this.groupId = groupId;
@@ -2957,8 +2958,14 @@ var AppDataGroupImpl = class {
2957
2958
  "/"
2958
2959
  );
2959
2960
  this.dataBackends.set(desc.id, { instance, syncable, pairId: pair.pairId, desc });
2961
+ this.backendStates.set(desc.id, { backendId: desc.id, pairId: pair.pairId });
2960
2962
  log2.log(`[AppDataGroup:${this.groupId}] backend ${desc.id} (${desc.type}) connected, pair=${pair.pairId}`);
2961
2963
  } catch (err) {
2964
+ const message = err instanceof Error ? err.message : String(err);
2965
+ this.backendStates.set(desc.id, {
2966
+ backendId: desc.id,
2967
+ error: { message, timestamp: Date.now() }
2968
+ });
2962
2969
  log2.error(`[AppDataGroup:${this.groupId}] Failed to create backend ${desc.id} (${desc.type}):`, err);
2963
2970
  }
2964
2971
  }
@@ -2983,6 +2990,9 @@ var AppDataGroupImpl = class {
2983
2990
  const results = await this.syncEngine.syncAll();
2984
2991
  return Array.from(results.values());
2985
2992
  }
2993
+ getBackendSyncStates() {
2994
+ return new Map(this.backendStates);
2995
+ }
2986
2996
  async addBackend(id, type, options, description) {
2987
2997
  if (this.disposed) throw new Error("DataSyncGroup has been disposed");
2988
2998
  if (this.dataBackends.has(id)) {
@@ -3005,6 +3015,8 @@ var AppDataGroupImpl = class {
3005
3015
  );
3006
3016
  const desc = { id, type, options, description, createdAt: Date.now() };
3007
3017
  this.dataBackends.set(id, { instance, syncable, pairId: pair.pairId, desc });
3018
+ this.backendStates.set(id, { backendId: id, pairId: pair.pairId });
3019
+ this._backends = [...this._backends.filter((b) => b.id !== id), desc];
3008
3020
  log2.log(`[AppDataGroup:${this.groupId}] addBackend: ${id} (${type}) connected, pair=${pair.pairId}`);
3009
3021
  try {
3010
3022
  await this.syncEngine.sync(pair.pairId);
@@ -3012,18 +3024,23 @@ var AppDataGroupImpl = class {
3012
3024
  log2.warn(`[AppDataGroup:${this.groupId}] addBackend: initial sync failed for ${id}:`, err);
3013
3025
  }
3014
3026
  this.syncEngine.watch(pair.pairId);
3015
- await this.parent.updateAppDataGroupDescriptor(this.groupId, this.listBackends());
3027
+ await this.parent.updateAppDataGroupDescriptor(this.groupId, this._backends);
3016
3028
  }
3017
3029
  async removeBackend(id) {
3018
3030
  if (this.disposed) throw new Error("DataSyncGroup has been disposed");
3019
3031
  const backend = this.dataBackends.get(id);
3020
- if (!backend) {
3032
+ const desc = this._backends.find((b) => b.id === id);
3033
+ if (!backend && !desc) {
3021
3034
  throw new Error(`Backend "${id}" not found in data group "${this.groupId}"`);
3022
3035
  }
3023
- this.syncEngine.removePair(backend.pairId);
3024
- this.dataBackends.delete(id);
3025
- await this.parent.updateAppDataGroupDescriptor(this.groupId, this.listBackends());
3026
- if (backend.instance?.dispose) {
3036
+ if (backend) {
3037
+ this.syncEngine.removePair(backend.pairId);
3038
+ this.dataBackends.delete(id);
3039
+ }
3040
+ this.backendStates.delete(id);
3041
+ this._backends = this._backends.filter((b) => b.id !== id);
3042
+ await this.parent.updateAppDataGroupDescriptor(this.groupId, this._backends);
3043
+ if (backend?.instance?.dispose) {
3027
3044
  await backend.instance.dispose();
3028
3045
  }
3029
3046
  log2.log(`[AppDataGroup:${this.groupId}] removeBackend: ${id} removed`);
package/dist/index.mjs CHANGED
@@ -2345,6 +2345,7 @@ var AppDataGroupImpl = class {
2345
2345
  syncEngine;
2346
2346
  localFS;
2347
2347
  dataBackends = /* @__PURE__ */ new Map();
2348
+ backendStates = /* @__PURE__ */ new Map();
2348
2349
  disposed = false;
2349
2350
  constructor(groupId, appId, backends, pollIntervalMs, parent) {
2350
2351
  this.groupId = groupId;
@@ -2417,8 +2418,14 @@ var AppDataGroupImpl = class {
2417
2418
  "/"
2418
2419
  );
2419
2420
  this.dataBackends.set(desc.id, { instance, syncable, pairId: pair.pairId, desc });
2421
+ this.backendStates.set(desc.id, { backendId: desc.id, pairId: pair.pairId });
2420
2422
  log2.log(`[AppDataGroup:${this.groupId}] backend ${desc.id} (${desc.type}) connected, pair=${pair.pairId}`);
2421
2423
  } catch (err) {
2424
+ const message = err instanceof Error ? err.message : String(err);
2425
+ this.backendStates.set(desc.id, {
2426
+ backendId: desc.id,
2427
+ error: { message, timestamp: Date.now() }
2428
+ });
2422
2429
  log2.error(`[AppDataGroup:${this.groupId}] Failed to create backend ${desc.id} (${desc.type}):`, err);
2423
2430
  }
2424
2431
  }
@@ -2443,6 +2450,9 @@ var AppDataGroupImpl = class {
2443
2450
  const results = await this.syncEngine.syncAll();
2444
2451
  return Array.from(results.values());
2445
2452
  }
2453
+ getBackendSyncStates() {
2454
+ return new Map(this.backendStates);
2455
+ }
2446
2456
  async addBackend(id, type, options, description) {
2447
2457
  if (this.disposed) throw new Error("DataSyncGroup has been disposed");
2448
2458
  if (this.dataBackends.has(id)) {
@@ -2465,6 +2475,8 @@ var AppDataGroupImpl = class {
2465
2475
  );
2466
2476
  const desc = { id, type, options, description, createdAt: Date.now() };
2467
2477
  this.dataBackends.set(id, { instance, syncable, pairId: pair.pairId, desc });
2478
+ this.backendStates.set(id, { backendId: id, pairId: pair.pairId });
2479
+ this._backends = [...this._backends.filter((b) => b.id !== id), desc];
2468
2480
  log2.log(`[AppDataGroup:${this.groupId}] addBackend: ${id} (${type}) connected, pair=${pair.pairId}`);
2469
2481
  try {
2470
2482
  await this.syncEngine.sync(pair.pairId);
@@ -2472,18 +2484,23 @@ var AppDataGroupImpl = class {
2472
2484
  log2.warn(`[AppDataGroup:${this.groupId}] addBackend: initial sync failed for ${id}:`, err);
2473
2485
  }
2474
2486
  this.syncEngine.watch(pair.pairId);
2475
- await this.parent.updateAppDataGroupDescriptor(this.groupId, this.listBackends());
2487
+ await this.parent.updateAppDataGroupDescriptor(this.groupId, this._backends);
2476
2488
  }
2477
2489
  async removeBackend(id) {
2478
2490
  if (this.disposed) throw new Error("DataSyncGroup has been disposed");
2479
2491
  const backend = this.dataBackends.get(id);
2480
- if (!backend) {
2492
+ const desc = this._backends.find((b) => b.id === id);
2493
+ if (!backend && !desc) {
2481
2494
  throw new Error(`Backend "${id}" not found in data group "${this.groupId}"`);
2482
2495
  }
2483
- this.syncEngine.removePair(backend.pairId);
2484
- this.dataBackends.delete(id);
2485
- await this.parent.updateAppDataGroupDescriptor(this.groupId, this.listBackends());
2486
- if (backend.instance?.dispose) {
2496
+ if (backend) {
2497
+ this.syncEngine.removePair(backend.pairId);
2498
+ this.dataBackends.delete(id);
2499
+ }
2500
+ this.backendStates.delete(id);
2501
+ this._backends = this._backends.filter((b) => b.id !== id);
2502
+ await this.parent.updateAppDataGroupDescriptor(this.groupId, this._backends);
2503
+ if (backend?.instance?.dispose) {
2487
2504
  await backend.instance.dispose();
2488
2505
  }
2489
2506
  log2.log(`[AppDataGroup:${this.groupId}] removeBackend: ${id} removed`);
@@ -28911,6 +28911,7 @@ var ZenFSConfig = (() => {
28911
28911
  __publicField(this, "syncEngine");
28912
28912
  __publicField(this, "localFS");
28913
28913
  __publicField(this, "dataBackends", /* @__PURE__ */ new Map());
28914
+ __publicField(this, "backendStates", /* @__PURE__ */ new Map());
28914
28915
  __publicField(this, "disposed", false);
28915
28916
  __publicField(this, "parent");
28916
28917
  __publicField(this, "_backends");
@@ -28982,8 +28983,14 @@ var ZenFSConfig = (() => {
28982
28983
  "/"
28983
28984
  );
28984
28985
  this.dataBackends.set(desc.id, { instance, syncable, pairId: pair.pairId, desc });
28986
+ this.backendStates.set(desc.id, { backendId: desc.id, pairId: pair.pairId });
28985
28987
  log6.log(`[AppDataGroup:${this.groupId}] backend ${desc.id} (${desc.type}) connected, pair=${pair.pairId}`);
28986
28988
  } catch (err2) {
28989
+ const message = err2 instanceof Error ? err2.message : String(err2);
28990
+ this.backendStates.set(desc.id, {
28991
+ backendId: desc.id,
28992
+ error: { message, timestamp: Date.now() }
28993
+ });
28987
28994
  log6.error(`[AppDataGroup:${this.groupId}] Failed to create backend ${desc.id} (${desc.type}):`, err2);
28988
28995
  }
28989
28996
  }
@@ -29008,6 +29015,9 @@ var ZenFSConfig = (() => {
29008
29015
  const results = await this.syncEngine.syncAll();
29009
29016
  return Array.from(results.values());
29010
29017
  }
29018
+ getBackendSyncStates() {
29019
+ return new Map(this.backendStates);
29020
+ }
29011
29021
  async addBackend(id, type, options, description) {
29012
29022
  if (this.disposed) throw new Error("DataSyncGroup has been disposed");
29013
29023
  if (this.dataBackends.has(id)) {
@@ -29030,6 +29040,8 @@ var ZenFSConfig = (() => {
29030
29040
  );
29031
29041
  const desc = { id, type, options, description, createdAt: Date.now() };
29032
29042
  this.dataBackends.set(id, { instance, syncable, pairId: pair.pairId, desc });
29043
+ this.backendStates.set(id, { backendId: id, pairId: pair.pairId });
29044
+ this._backends = [...this._backends.filter((b) => b.id !== id), desc];
29033
29045
  log6.log(`[AppDataGroup:${this.groupId}] addBackend: ${id} (${type}) connected, pair=${pair.pairId}`);
29034
29046
  try {
29035
29047
  await this.syncEngine.sync(pair.pairId);
@@ -29037,18 +29049,23 @@ var ZenFSConfig = (() => {
29037
29049
  log6.warn(`[AppDataGroup:${this.groupId}] addBackend: initial sync failed for ${id}:`, err2);
29038
29050
  }
29039
29051
  this.syncEngine.watch(pair.pairId);
29040
- await this.parent.updateAppDataGroupDescriptor(this.groupId, this.listBackends());
29052
+ await this.parent.updateAppDataGroupDescriptor(this.groupId, this._backends);
29041
29053
  }
29042
29054
  async removeBackend(id) {
29043
29055
  if (this.disposed) throw new Error("DataSyncGroup has been disposed");
29044
29056
  const backend = this.dataBackends.get(id);
29045
- if (!backend) {
29057
+ const desc = this._backends.find((b) => b.id === id);
29058
+ if (!backend && !desc) {
29046
29059
  throw new Error(`Backend "${id}" not found in data group "${this.groupId}"`);
29047
29060
  }
29048
- this.syncEngine.removePair(backend.pairId);
29049
- this.dataBackends.delete(id);
29050
- await this.parent.updateAppDataGroupDescriptor(this.groupId, this.listBackends());
29051
- if (backend.instance?.dispose) {
29061
+ if (backend) {
29062
+ this.syncEngine.removePair(backend.pairId);
29063
+ this.dataBackends.delete(id);
29064
+ }
29065
+ this.backendStates.delete(id);
29066
+ this._backends = this._backends.filter((b) => b.id !== id);
29067
+ await this.parent.updateAppDataGroupDescriptor(this.groupId, this._backends);
29068
+ if (backend?.instance?.dispose) {
29052
29069
  await backend.instance.dispose();
29053
29070
  }
29054
29071
  log6.log(`[AppDataGroup:${this.groupId}] removeBackend: ${id} removed`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zen-fs-config",
3
- "version": "0.5.44",
3
+ "version": "0.5.45",
4
4
  "description": "Distributed config management library built on ZenFS, zen-fs-cache, and zen-fs-sync",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",