zen-fs-config 0.5.45 → 0.5.46
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 +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +84 -0
- package/dist/index.mjs +84 -0
- package/dist/zen-fs-config.js +84 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -345,8 +345,16 @@ interface AppDataBackendDescriptor {
|
|
|
345
345
|
interface AppDataGroupDescriptor {
|
|
346
346
|
id: string;
|
|
347
347
|
groupType: 'data-sync';
|
|
348
|
+
/** User-editable display name. `id` is the stable identifier. */
|
|
349
|
+
name?: string;
|
|
348
350
|
backends: AppDataBackendDescriptor[];
|
|
349
351
|
}
|
|
352
|
+
/** Descriptor for the config-sync group itself (display metadata only). */
|
|
353
|
+
interface ConfigSyncGroupDescriptor {
|
|
354
|
+
groupType: 'config-sync';
|
|
355
|
+
/** User-editable display name. The group has no separate id. */
|
|
356
|
+
name?: string;
|
|
357
|
+
}
|
|
350
358
|
/** Per-backend sync state of a data group. */
|
|
351
359
|
interface BackendSyncState {
|
|
352
360
|
backendId: string;
|
|
@@ -555,6 +563,20 @@ interface IConfigRepo {
|
|
|
555
563
|
getAppDataGroup(id: string): Promise<AppDataGroup>;
|
|
556
564
|
/** List all data-sync group descriptors for this app. */
|
|
557
565
|
listAppDataGroups(): Promise<AppDataGroupDescriptor[]>;
|
|
566
|
+
/**
|
|
567
|
+
* Update a data-sync group's display name (descriptor-only; id, backends,
|
|
568
|
+
* local and remote data are untouched). Empty/oversized names are rejected.
|
|
569
|
+
*/
|
|
570
|
+
updateAppDataGroupName(id: string, name: string): Promise<void>;
|
|
571
|
+
/** Read the config-sync group's display descriptor (may be absent). */
|
|
572
|
+
getConfigSyncGroupDescriptor(): Promise<ConfigSyncGroupDescriptor | null>;
|
|
573
|
+
/**
|
|
574
|
+
* Update the config-sync group's display name (descriptor-only; backends,
|
|
575
|
+
* local store and remote data are untouched).
|
|
576
|
+
*/
|
|
577
|
+
updateConfigSyncGroupDescriptor(patch: {
|
|
578
|
+
name: string;
|
|
579
|
+
}): Promise<ConfigSyncGroupDescriptor>;
|
|
558
580
|
/** Remove a data-sync group (stops sync, removes descriptor). */
|
|
559
581
|
removeAppDataGroup(id: string): Promise<void>;
|
|
560
582
|
/**
|
|
@@ -1005,6 +1027,20 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
1005
1027
|
* authoritative source of the data group's backend topology (FR2.3).
|
|
1006
1028
|
*/
|
|
1007
1029
|
updateAppDataGroupDescriptor(id: string, backends: AppDataBackendDescriptor[]): Promise<void>;
|
|
1030
|
+
/**
|
|
1031
|
+
* Change a data-sync group's display name only. `id`, backends, local stores
|
|
1032
|
+
* and remote data are untouched, so existing sync pairs keep working.
|
|
1033
|
+
*/
|
|
1034
|
+
updateAppDataGroupName(id: string, name: string): Promise<void>;
|
|
1035
|
+
getConfigSyncGroupDescriptor(): Promise<ConfigSyncGroupDescriptor | null>;
|
|
1036
|
+
/**
|
|
1037
|
+
* Change the config-sync group's display name only. Backends, the local
|
|
1038
|
+
* store and remote data are untouched.
|
|
1039
|
+
*/
|
|
1040
|
+
updateConfigSyncGroupDescriptor(patch: {
|
|
1041
|
+
name: string;
|
|
1042
|
+
}): Promise<ConfigSyncGroupDescriptor>;
|
|
1043
|
+
private readAppDataGroupDescriptor;
|
|
1008
1044
|
getAppDataGroup(id: string): Promise<AppDataGroup>;
|
|
1009
1045
|
listAppDataGroups(): Promise<AppDataGroupDescriptor[]>;
|
|
1010
1046
|
removeAppDataGroup(id: string): Promise<void>;
|
|
@@ -1160,4 +1196,4 @@ declare function incrementVersion(fs: SyncableFS, configFilePath: string, newCon
|
|
|
1160
1196
|
*/
|
|
1161
1197
|
declare function verifyOrRepairVersion(fs: SyncableFS, configFilePath: string, author: string): Promise<VersionMeta | null>;
|
|
1162
1198
|
|
|
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 };
|
|
1199
|
+
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 ConfigSyncGroupDescriptor, 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
|
@@ -345,8 +345,16 @@ interface AppDataBackendDescriptor {
|
|
|
345
345
|
interface AppDataGroupDescriptor {
|
|
346
346
|
id: string;
|
|
347
347
|
groupType: 'data-sync';
|
|
348
|
+
/** User-editable display name. `id` is the stable identifier. */
|
|
349
|
+
name?: string;
|
|
348
350
|
backends: AppDataBackendDescriptor[];
|
|
349
351
|
}
|
|
352
|
+
/** Descriptor for the config-sync group itself (display metadata only). */
|
|
353
|
+
interface ConfigSyncGroupDescriptor {
|
|
354
|
+
groupType: 'config-sync';
|
|
355
|
+
/** User-editable display name. The group has no separate id. */
|
|
356
|
+
name?: string;
|
|
357
|
+
}
|
|
350
358
|
/** Per-backend sync state of a data group. */
|
|
351
359
|
interface BackendSyncState {
|
|
352
360
|
backendId: string;
|
|
@@ -555,6 +563,20 @@ interface IConfigRepo {
|
|
|
555
563
|
getAppDataGroup(id: string): Promise<AppDataGroup>;
|
|
556
564
|
/** List all data-sync group descriptors for this app. */
|
|
557
565
|
listAppDataGroups(): Promise<AppDataGroupDescriptor[]>;
|
|
566
|
+
/**
|
|
567
|
+
* Update a data-sync group's display name (descriptor-only; id, backends,
|
|
568
|
+
* local and remote data are untouched). Empty/oversized names are rejected.
|
|
569
|
+
*/
|
|
570
|
+
updateAppDataGroupName(id: string, name: string): Promise<void>;
|
|
571
|
+
/** Read the config-sync group's display descriptor (may be absent). */
|
|
572
|
+
getConfigSyncGroupDescriptor(): Promise<ConfigSyncGroupDescriptor | null>;
|
|
573
|
+
/**
|
|
574
|
+
* Update the config-sync group's display name (descriptor-only; backends,
|
|
575
|
+
* local store and remote data are untouched).
|
|
576
|
+
*/
|
|
577
|
+
updateConfigSyncGroupDescriptor(patch: {
|
|
578
|
+
name: string;
|
|
579
|
+
}): Promise<ConfigSyncGroupDescriptor>;
|
|
558
580
|
/** Remove a data-sync group (stops sync, removes descriptor). */
|
|
559
581
|
removeAppDataGroup(id: string): Promise<void>;
|
|
560
582
|
/**
|
|
@@ -1005,6 +1027,20 @@ declare class ConfigRepo implements IConfigRepo {
|
|
|
1005
1027
|
* authoritative source of the data group's backend topology (FR2.3).
|
|
1006
1028
|
*/
|
|
1007
1029
|
updateAppDataGroupDescriptor(id: string, backends: AppDataBackendDescriptor[]): Promise<void>;
|
|
1030
|
+
/**
|
|
1031
|
+
* Change a data-sync group's display name only. `id`, backends, local stores
|
|
1032
|
+
* and remote data are untouched, so existing sync pairs keep working.
|
|
1033
|
+
*/
|
|
1034
|
+
updateAppDataGroupName(id: string, name: string): Promise<void>;
|
|
1035
|
+
getConfigSyncGroupDescriptor(): Promise<ConfigSyncGroupDescriptor | null>;
|
|
1036
|
+
/**
|
|
1037
|
+
* Change the config-sync group's display name only. Backends, the local
|
|
1038
|
+
* store and remote data are untouched.
|
|
1039
|
+
*/
|
|
1040
|
+
updateConfigSyncGroupDescriptor(patch: {
|
|
1041
|
+
name: string;
|
|
1042
|
+
}): Promise<ConfigSyncGroupDescriptor>;
|
|
1043
|
+
private readAppDataGroupDescriptor;
|
|
1008
1044
|
getAppDataGroup(id: string): Promise<AppDataGroup>;
|
|
1009
1045
|
listAppDataGroups(): Promise<AppDataGroupDescriptor[]>;
|
|
1010
1046
|
removeAppDataGroup(id: string): Promise<void>;
|
|
@@ -1160,4 +1196,4 @@ declare function incrementVersion(fs: SyncableFS, configFilePath: string, newCon
|
|
|
1160
1196
|
*/
|
|
1161
1197
|
declare function verifyOrRepairVersion(fs: SyncableFS, configFilePath: string, author: string): Promise<VersionMeta | null>;
|
|
1162
1198
|
|
|
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 };
|
|
1199
|
+
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 ConfigSyncGroupDescriptor, 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
|
@@ -1424,10 +1424,25 @@ var GROUP_TYPE_FILE = `${META_DIR}/group-type`;
|
|
|
1424
1424
|
var BACKENDS_FILE = `${META_DIR}/backends.json`;
|
|
1425
1425
|
var BACKENDS_DIR = `${META_DIR}/backends`;
|
|
1426
1426
|
var APP_DATA_GROUPS_DIR = `${META_DIR}/app-data-groups`;
|
|
1427
|
+
var CONFIG_SYNC_GROUP_FILE = `${META_DIR}/config-sync-group.json`;
|
|
1428
|
+
var GROUP_NAME_MAX_LENGTH = 40;
|
|
1427
1429
|
var CONFLICTS_DIR = `${META_DIR}/.conflicts`;
|
|
1428
1430
|
var DELETIONS_DIR = `${META_DIR}/.deleted`;
|
|
1429
1431
|
var NODES_DIR = "/nodes";
|
|
1430
1432
|
var SHARED_DIR = "/shared";
|
|
1433
|
+
function normalizeGroupName(value) {
|
|
1434
|
+
if (typeof value !== "string") {
|
|
1435
|
+
throw new Error("Group name must be a string");
|
|
1436
|
+
}
|
|
1437
|
+
const name = value.trim();
|
|
1438
|
+
if (!name) {
|
|
1439
|
+
throw new Error("Group name must not be empty");
|
|
1440
|
+
}
|
|
1441
|
+
if (name.length > GROUP_NAME_MAX_LENGTH) {
|
|
1442
|
+
throw new Error(`Group name must be at most ${GROUP_NAME_MAX_LENGTH} characters`);
|
|
1443
|
+
}
|
|
1444
|
+
return name;
|
|
1445
|
+
}
|
|
1431
1446
|
var CONFIG_ONLY_PREFIXES = [META_DIR, NODES_DIR, SHARED_DIR];
|
|
1432
1447
|
var LOCAL_IDB_BACKEND_ID = "local-idb";
|
|
1433
1448
|
function tombstoneFileName(filePath) {
|
|
@@ -2783,9 +2798,11 @@ var ConfigRepo = class {
|
|
|
2783
2798
|
*/
|
|
2784
2799
|
async updateAppDataGroupDescriptor(id, backends) {
|
|
2785
2800
|
this.assertNotDisposed();
|
|
2801
|
+
const existing = await this.readAppDataGroupDescriptor(id);
|
|
2786
2802
|
const descriptor = {
|
|
2787
2803
|
id,
|
|
2788
2804
|
groupType: "data-sync",
|
|
2805
|
+
...existing?.name ? { name: existing.name } : {},
|
|
2789
2806
|
backends
|
|
2790
2807
|
};
|
|
2791
2808
|
const descPath = this.appDataGroupFilePath(id);
|
|
@@ -2796,6 +2813,73 @@ var ConfigRepo = class {
|
|
|
2796
2813
|
const version = await incrementVersion(this.fullFS, descPath, bytes, author);
|
|
2797
2814
|
await this.writeVersionSidecar(descPath, version);
|
|
2798
2815
|
}
|
|
2816
|
+
/**
|
|
2817
|
+
* Change a data-sync group's display name only. `id`, backends, local stores
|
|
2818
|
+
* and remote data are untouched, so existing sync pairs keep working.
|
|
2819
|
+
*/
|
|
2820
|
+
async updateAppDataGroupName(id, name) {
|
|
2821
|
+
this.assertNotDisposed();
|
|
2822
|
+
const normalized = normalizeGroupName(name);
|
|
2823
|
+
const existing = await this.readAppDataGroupDescriptor(id);
|
|
2824
|
+
if (!existing) {
|
|
2825
|
+
throw new Error(`App data group "${id}" not found`);
|
|
2826
|
+
}
|
|
2827
|
+
const descriptor = {
|
|
2828
|
+
...existing,
|
|
2829
|
+
id,
|
|
2830
|
+
groupType: "data-sync",
|
|
2831
|
+
name: normalized
|
|
2832
|
+
};
|
|
2833
|
+
const descPath = this.appDataGroupFilePath(id);
|
|
2834
|
+
await this.ensureDir(descPath);
|
|
2835
|
+
const bytes = new TextEncoder().encode(JSON.stringify(descriptor, null, 2));
|
|
2836
|
+
await this.cachedFS.writeFile(descPath, bytes);
|
|
2837
|
+
const author = `${this.appId}/${this.nodeId}`;
|
|
2838
|
+
const version = await incrementVersion(this.fullFS, descPath, bytes, author);
|
|
2839
|
+
await this.writeVersionSidecar(descPath, version);
|
|
2840
|
+
}
|
|
2841
|
+
async getConfigSyncGroupDescriptor() {
|
|
2842
|
+
this.assertNotDisposed();
|
|
2843
|
+
try {
|
|
2844
|
+
const raw = await this.cachedFS.readFile(CONFIG_SYNC_GROUP_FILE);
|
|
2845
|
+
const parsed = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
2846
|
+
if (parsed && parsed.groupType === "config-sync") {
|
|
2847
|
+
return parsed;
|
|
2848
|
+
}
|
|
2849
|
+
} catch {
|
|
2850
|
+
}
|
|
2851
|
+
return null;
|
|
2852
|
+
}
|
|
2853
|
+
/**
|
|
2854
|
+
* Change the config-sync group's display name only. Backends, the local
|
|
2855
|
+
* store and remote data are untouched.
|
|
2856
|
+
*/
|
|
2857
|
+
async updateConfigSyncGroupDescriptor(patch) {
|
|
2858
|
+
this.assertNotDisposed();
|
|
2859
|
+
const normalized = normalizeGroupName(patch?.name);
|
|
2860
|
+
const descriptor = {
|
|
2861
|
+
groupType: "config-sync",
|
|
2862
|
+
name: normalized
|
|
2863
|
+
};
|
|
2864
|
+
await this.ensureDir(CONFIG_SYNC_GROUP_FILE);
|
|
2865
|
+
const bytes = new TextEncoder().encode(JSON.stringify(descriptor, null, 2));
|
|
2866
|
+
await this.cachedFS.writeFile(CONFIG_SYNC_GROUP_FILE, bytes);
|
|
2867
|
+
const author = `${this.appId}/${this.nodeId}`;
|
|
2868
|
+
const version = await incrementVersion(this.fullFS, CONFIG_SYNC_GROUP_FILE, bytes, author);
|
|
2869
|
+
await this.writeVersionSidecar(CONFIG_SYNC_GROUP_FILE, version);
|
|
2870
|
+
return descriptor;
|
|
2871
|
+
}
|
|
2872
|
+
async readAppDataGroupDescriptor(id) {
|
|
2873
|
+
try {
|
|
2874
|
+
const raw = await this.cachedFS.readFile(this.appDataGroupFilePath(id));
|
|
2875
|
+
const parsed = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
2876
|
+
if (parsed && parsed.id === id && parsed.groupType === "data-sync") {
|
|
2877
|
+
return parsed;
|
|
2878
|
+
}
|
|
2879
|
+
} catch {
|
|
2880
|
+
}
|
|
2881
|
+
return null;
|
|
2882
|
+
}
|
|
2799
2883
|
async getAppDataGroup(id) {
|
|
2800
2884
|
this.assertNotDisposed();
|
|
2801
2885
|
const cached = this.appDataGroups.get(id);
|
package/dist/index.mjs
CHANGED
|
@@ -884,10 +884,25 @@ var GROUP_TYPE_FILE = `${META_DIR}/group-type`;
|
|
|
884
884
|
var BACKENDS_FILE = `${META_DIR}/backends.json`;
|
|
885
885
|
var BACKENDS_DIR = `${META_DIR}/backends`;
|
|
886
886
|
var APP_DATA_GROUPS_DIR = `${META_DIR}/app-data-groups`;
|
|
887
|
+
var CONFIG_SYNC_GROUP_FILE = `${META_DIR}/config-sync-group.json`;
|
|
888
|
+
var GROUP_NAME_MAX_LENGTH = 40;
|
|
887
889
|
var CONFLICTS_DIR = `${META_DIR}/.conflicts`;
|
|
888
890
|
var DELETIONS_DIR = `${META_DIR}/.deleted`;
|
|
889
891
|
var NODES_DIR = "/nodes";
|
|
890
892
|
var SHARED_DIR = "/shared";
|
|
893
|
+
function normalizeGroupName(value) {
|
|
894
|
+
if (typeof value !== "string") {
|
|
895
|
+
throw new Error("Group name must be a string");
|
|
896
|
+
}
|
|
897
|
+
const name = value.trim();
|
|
898
|
+
if (!name) {
|
|
899
|
+
throw new Error("Group name must not be empty");
|
|
900
|
+
}
|
|
901
|
+
if (name.length > GROUP_NAME_MAX_LENGTH) {
|
|
902
|
+
throw new Error(`Group name must be at most ${GROUP_NAME_MAX_LENGTH} characters`);
|
|
903
|
+
}
|
|
904
|
+
return name;
|
|
905
|
+
}
|
|
891
906
|
var CONFIG_ONLY_PREFIXES = [META_DIR, NODES_DIR, SHARED_DIR];
|
|
892
907
|
var LOCAL_IDB_BACKEND_ID = "local-idb";
|
|
893
908
|
function tombstoneFileName(filePath) {
|
|
@@ -2243,9 +2258,11 @@ var ConfigRepo = class {
|
|
|
2243
2258
|
*/
|
|
2244
2259
|
async updateAppDataGroupDescriptor(id, backends) {
|
|
2245
2260
|
this.assertNotDisposed();
|
|
2261
|
+
const existing = await this.readAppDataGroupDescriptor(id);
|
|
2246
2262
|
const descriptor = {
|
|
2247
2263
|
id,
|
|
2248
2264
|
groupType: "data-sync",
|
|
2265
|
+
...existing?.name ? { name: existing.name } : {},
|
|
2249
2266
|
backends
|
|
2250
2267
|
};
|
|
2251
2268
|
const descPath = this.appDataGroupFilePath(id);
|
|
@@ -2256,6 +2273,73 @@ var ConfigRepo = class {
|
|
|
2256
2273
|
const version = await incrementVersion(this.fullFS, descPath, bytes, author);
|
|
2257
2274
|
await this.writeVersionSidecar(descPath, version);
|
|
2258
2275
|
}
|
|
2276
|
+
/**
|
|
2277
|
+
* Change a data-sync group's display name only. `id`, backends, local stores
|
|
2278
|
+
* and remote data are untouched, so existing sync pairs keep working.
|
|
2279
|
+
*/
|
|
2280
|
+
async updateAppDataGroupName(id, name) {
|
|
2281
|
+
this.assertNotDisposed();
|
|
2282
|
+
const normalized = normalizeGroupName(name);
|
|
2283
|
+
const existing = await this.readAppDataGroupDescriptor(id);
|
|
2284
|
+
if (!existing) {
|
|
2285
|
+
throw new Error(`App data group "${id}" not found`);
|
|
2286
|
+
}
|
|
2287
|
+
const descriptor = {
|
|
2288
|
+
...existing,
|
|
2289
|
+
id,
|
|
2290
|
+
groupType: "data-sync",
|
|
2291
|
+
name: normalized
|
|
2292
|
+
};
|
|
2293
|
+
const descPath = this.appDataGroupFilePath(id);
|
|
2294
|
+
await this.ensureDir(descPath);
|
|
2295
|
+
const bytes = new TextEncoder().encode(JSON.stringify(descriptor, null, 2));
|
|
2296
|
+
await this.cachedFS.writeFile(descPath, bytes);
|
|
2297
|
+
const author = `${this.appId}/${this.nodeId}`;
|
|
2298
|
+
const version = await incrementVersion(this.fullFS, descPath, bytes, author);
|
|
2299
|
+
await this.writeVersionSidecar(descPath, version);
|
|
2300
|
+
}
|
|
2301
|
+
async getConfigSyncGroupDescriptor() {
|
|
2302
|
+
this.assertNotDisposed();
|
|
2303
|
+
try {
|
|
2304
|
+
const raw = await this.cachedFS.readFile(CONFIG_SYNC_GROUP_FILE);
|
|
2305
|
+
const parsed = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
2306
|
+
if (parsed && parsed.groupType === "config-sync") {
|
|
2307
|
+
return parsed;
|
|
2308
|
+
}
|
|
2309
|
+
} catch {
|
|
2310
|
+
}
|
|
2311
|
+
return null;
|
|
2312
|
+
}
|
|
2313
|
+
/**
|
|
2314
|
+
* Change the config-sync group's display name only. Backends, the local
|
|
2315
|
+
* store and remote data are untouched.
|
|
2316
|
+
*/
|
|
2317
|
+
async updateConfigSyncGroupDescriptor(patch) {
|
|
2318
|
+
this.assertNotDisposed();
|
|
2319
|
+
const normalized = normalizeGroupName(patch?.name);
|
|
2320
|
+
const descriptor = {
|
|
2321
|
+
groupType: "config-sync",
|
|
2322
|
+
name: normalized
|
|
2323
|
+
};
|
|
2324
|
+
await this.ensureDir(CONFIG_SYNC_GROUP_FILE);
|
|
2325
|
+
const bytes = new TextEncoder().encode(JSON.stringify(descriptor, null, 2));
|
|
2326
|
+
await this.cachedFS.writeFile(CONFIG_SYNC_GROUP_FILE, bytes);
|
|
2327
|
+
const author = `${this.appId}/${this.nodeId}`;
|
|
2328
|
+
const version = await incrementVersion(this.fullFS, CONFIG_SYNC_GROUP_FILE, bytes, author);
|
|
2329
|
+
await this.writeVersionSidecar(CONFIG_SYNC_GROUP_FILE, version);
|
|
2330
|
+
return descriptor;
|
|
2331
|
+
}
|
|
2332
|
+
async readAppDataGroupDescriptor(id) {
|
|
2333
|
+
try {
|
|
2334
|
+
const raw = await this.cachedFS.readFile(this.appDataGroupFilePath(id));
|
|
2335
|
+
const parsed = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
2336
|
+
if (parsed && parsed.id === id && parsed.groupType === "data-sync") {
|
|
2337
|
+
return parsed;
|
|
2338
|
+
}
|
|
2339
|
+
} catch {
|
|
2340
|
+
}
|
|
2341
|
+
return null;
|
|
2342
|
+
}
|
|
2259
2343
|
async getAppDataGroup(id) {
|
|
2260
2344
|
this.assertNotDisposed();
|
|
2261
2345
|
const cached = this.appDataGroups.get(id);
|
package/dist/zen-fs-config.js
CHANGED
|
@@ -27449,10 +27449,25 @@ var ZenFSConfig = (() => {
|
|
|
27449
27449
|
var BACKENDS_FILE = `${META_DIR}/backends.json`;
|
|
27450
27450
|
var BACKENDS_DIR = `${META_DIR}/backends`;
|
|
27451
27451
|
var APP_DATA_GROUPS_DIR = `${META_DIR}/app-data-groups`;
|
|
27452
|
+
var CONFIG_SYNC_GROUP_FILE = `${META_DIR}/config-sync-group.json`;
|
|
27453
|
+
var GROUP_NAME_MAX_LENGTH = 40;
|
|
27452
27454
|
var CONFLICTS_DIR = `${META_DIR}/.conflicts`;
|
|
27453
27455
|
var DELETIONS_DIR = `${META_DIR}/.deleted`;
|
|
27454
27456
|
var NODES_DIR = "/nodes";
|
|
27455
27457
|
var SHARED_DIR = "/shared";
|
|
27458
|
+
function normalizeGroupName(value) {
|
|
27459
|
+
if (typeof value !== "string") {
|
|
27460
|
+
throw new Error("Group name must be a string");
|
|
27461
|
+
}
|
|
27462
|
+
const name = value.trim();
|
|
27463
|
+
if (!name) {
|
|
27464
|
+
throw new Error("Group name must not be empty");
|
|
27465
|
+
}
|
|
27466
|
+
if (name.length > GROUP_NAME_MAX_LENGTH) {
|
|
27467
|
+
throw new Error(`Group name must be at most ${GROUP_NAME_MAX_LENGTH} characters`);
|
|
27468
|
+
}
|
|
27469
|
+
return name;
|
|
27470
|
+
}
|
|
27456
27471
|
var CONFIG_ONLY_PREFIXES = [META_DIR, NODES_DIR, SHARED_DIR];
|
|
27457
27472
|
var LOCAL_IDB_BACKEND_ID = "local-idb";
|
|
27458
27473
|
function tombstoneFileName(filePath) {
|
|
@@ -28808,9 +28823,11 @@ var ZenFSConfig = (() => {
|
|
|
28808
28823
|
*/
|
|
28809
28824
|
async updateAppDataGroupDescriptor(id, backends) {
|
|
28810
28825
|
this.assertNotDisposed();
|
|
28826
|
+
const existing = await this.readAppDataGroupDescriptor(id);
|
|
28811
28827
|
const descriptor = {
|
|
28812
28828
|
id,
|
|
28813
28829
|
groupType: "data-sync",
|
|
28830
|
+
...existing?.name ? { name: existing.name } : {},
|
|
28814
28831
|
backends
|
|
28815
28832
|
};
|
|
28816
28833
|
const descPath = this.appDataGroupFilePath(id);
|
|
@@ -28821,6 +28838,73 @@ var ZenFSConfig = (() => {
|
|
|
28821
28838
|
const version2 = await incrementVersion(this.fullFS, descPath, bytes, author);
|
|
28822
28839
|
await this.writeVersionSidecar(descPath, version2);
|
|
28823
28840
|
}
|
|
28841
|
+
/**
|
|
28842
|
+
* Change a data-sync group's display name only. `id`, backends, local stores
|
|
28843
|
+
* and remote data are untouched, so existing sync pairs keep working.
|
|
28844
|
+
*/
|
|
28845
|
+
async updateAppDataGroupName(id, name) {
|
|
28846
|
+
this.assertNotDisposed();
|
|
28847
|
+
const normalized = normalizeGroupName(name);
|
|
28848
|
+
const existing = await this.readAppDataGroupDescriptor(id);
|
|
28849
|
+
if (!existing) {
|
|
28850
|
+
throw new Error(`App data group "${id}" not found`);
|
|
28851
|
+
}
|
|
28852
|
+
const descriptor = {
|
|
28853
|
+
...existing,
|
|
28854
|
+
id,
|
|
28855
|
+
groupType: "data-sync",
|
|
28856
|
+
name: normalized
|
|
28857
|
+
};
|
|
28858
|
+
const descPath = this.appDataGroupFilePath(id);
|
|
28859
|
+
await this.ensureDir(descPath);
|
|
28860
|
+
const bytes = new TextEncoder().encode(JSON.stringify(descriptor, null, 2));
|
|
28861
|
+
await this.cachedFS.writeFile(descPath, bytes);
|
|
28862
|
+
const author = `${this.appId}/${this.nodeId}`;
|
|
28863
|
+
const version2 = await incrementVersion(this.fullFS, descPath, bytes, author);
|
|
28864
|
+
await this.writeVersionSidecar(descPath, version2);
|
|
28865
|
+
}
|
|
28866
|
+
async getConfigSyncGroupDescriptor() {
|
|
28867
|
+
this.assertNotDisposed();
|
|
28868
|
+
try {
|
|
28869
|
+
const raw = await this.cachedFS.readFile(CONFIG_SYNC_GROUP_FILE);
|
|
28870
|
+
const parsed = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
28871
|
+
if (parsed && parsed.groupType === "config-sync") {
|
|
28872
|
+
return parsed;
|
|
28873
|
+
}
|
|
28874
|
+
} catch {
|
|
28875
|
+
}
|
|
28876
|
+
return null;
|
|
28877
|
+
}
|
|
28878
|
+
/**
|
|
28879
|
+
* Change the config-sync group's display name only. Backends, the local
|
|
28880
|
+
* store and remote data are untouched.
|
|
28881
|
+
*/
|
|
28882
|
+
async updateConfigSyncGroupDescriptor(patch) {
|
|
28883
|
+
this.assertNotDisposed();
|
|
28884
|
+
const normalized = normalizeGroupName(patch?.name);
|
|
28885
|
+
const descriptor = {
|
|
28886
|
+
groupType: "config-sync",
|
|
28887
|
+
name: normalized
|
|
28888
|
+
};
|
|
28889
|
+
await this.ensureDir(CONFIG_SYNC_GROUP_FILE);
|
|
28890
|
+
const bytes = new TextEncoder().encode(JSON.stringify(descriptor, null, 2));
|
|
28891
|
+
await this.cachedFS.writeFile(CONFIG_SYNC_GROUP_FILE, bytes);
|
|
28892
|
+
const author = `${this.appId}/${this.nodeId}`;
|
|
28893
|
+
const version2 = await incrementVersion(this.fullFS, CONFIG_SYNC_GROUP_FILE, bytes, author);
|
|
28894
|
+
await this.writeVersionSidecar(CONFIG_SYNC_GROUP_FILE, version2);
|
|
28895
|
+
return descriptor;
|
|
28896
|
+
}
|
|
28897
|
+
async readAppDataGroupDescriptor(id) {
|
|
28898
|
+
try {
|
|
28899
|
+
const raw = await this.cachedFS.readFile(this.appDataGroupFilePath(id));
|
|
28900
|
+
const parsed = JSON.parse(new TextDecoder().decode(toUint8Array2(raw)));
|
|
28901
|
+
if (parsed && parsed.id === id && parsed.groupType === "data-sync") {
|
|
28902
|
+
return parsed;
|
|
28903
|
+
}
|
|
28904
|
+
} catch {
|
|
28905
|
+
}
|
|
28906
|
+
return null;
|
|
28907
|
+
}
|
|
28824
28908
|
async getAppDataGroup(id) {
|
|
28825
28909
|
this.assertNotDisposed();
|
|
28826
28910
|
const cached = this.appDataGroups.get(id);
|