zen-fs-config 0.5.40 → 0.5.42

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.
@@ -9,7 +9,7 @@ import {
9
9
  registerBackend,
10
10
  unregisterBackend,
11
11
  wrapZenFSFileSystem
12
- } from "./chunk-NSEXSKVW.mjs";
12
+ } from "./chunk-S2S3XBK2.mjs";
13
13
  export {
14
14
  createBackend,
15
15
  getAccountFields,
@@ -277,9 +277,9 @@ registerBackend("GitHub", async (options) => {
277
277
  registerBackend("Gitee", async (options) => {
278
278
  const _gt = await importOptionalBackend("zen-fs-gitee");
279
279
  const Gitee = _gt?.Gitee ?? _gt?.default;
280
- if (typeof Gitee !== "function") {
280
+ if (!Gitee || typeof Gitee !== "function" && typeof Gitee.create !== "function") {
281
281
  throw new Error(
282
- `Backend package "zen-fs-gitee" loaded, but its Gitee export is not a constructor (typeof=${typeof Gitee}). Load its UMD bundle so it exposes the global "ZenFSGitee".`
282
+ `Backend package "zen-fs-gitee" loaded, but its Gitee export is not a usable backend (typeof=${typeof Gitee}). Load its UMD bundle so it exposes the global "ZenFSGitee".`
283
283
  );
284
284
  }
285
285
  return wrapZenFSFileSystem({
@@ -306,6 +306,39 @@ registerBackend("Gitee", async (options) => {
306
306
  // identity = the Git repo location
307
307
  identityFields: ["owner", "repo", "branch", "baseUrl"]
308
308
  });
309
+ async function resolveRemoteStorageHref(href) {
310
+ const raw = String(href ?? "").trim();
311
+ if (!raw) throw new Error("RemoteStorage href is required.");
312
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) return raw.replace(/\/+$/, "");
313
+ const match = raw.match(/^(?:acct:)?([^@/]+)@([^@/]+)$/);
314
+ if (!match) {
315
+ throw new Error(
316
+ `RemoteStorage href "${raw}" is neither an absolute URL nor a user address (user@domain).`
317
+ );
318
+ }
319
+ const user = match[1];
320
+ const domain = match[2];
321
+ const webfingerUrl = `https://${domain}/.well-known/webfinger?resource=acct:${encodeURIComponent(user)}@${encodeURIComponent(domain)}`;
322
+ let response;
323
+ try {
324
+ response = await globalThis.fetch(webfingerUrl, {
325
+ headers: { Accept: "application/jrd+json, application/json" }
326
+ });
327
+ } catch (err) {
328
+ throw new Error(
329
+ `RemoteStorage WebFinger request failed (${webfingerUrl}): ${err instanceof Error ? err.message : String(err)}`
330
+ );
331
+ }
332
+ if (!response.ok) {
333
+ throw new Error(`RemoteStorage WebFinger lookup failed (HTTP ${response.status}): ${webfingerUrl}`);
334
+ }
335
+ const jrd = await response.json();
336
+ const link = (jrd?.links ?? []).find(
337
+ (item) => item && item.rel === "http://tools.ietf.org/id/draft-dejong-remotestorage" && item.href
338
+ );
339
+ if (!link) throw new Error(`WebFinger response has no RemoteStorage link: ${webfingerUrl}`);
340
+ return String(link.href).replace(/\/+$/, "");
341
+ }
309
342
  registerBackend("RemoteStorage", async (options) => {
310
343
  const _rs = await importOptionalBackend("zen-fs-remotestoragejs");
311
344
  const RemoteStorageFileSystem = _rs?.RemoteStorageFileSystem ?? _rs?.default ?? (typeof _rs === "function" ? _rs : void 0);
@@ -315,7 +348,7 @@ registerBackend("RemoteStorage", async (options) => {
315
348
  );
316
349
  }
317
350
  return new RemoteStorageFileSystem({
318
- href: options.href,
351
+ href: await resolveRemoteStorageHref(options.href),
319
352
  token: options.token,
320
353
  basePath: options.basePath || void 0,
321
354
  preciseMtime: true,
@@ -326,7 +359,7 @@ registerBackend("RemoteStorage", async (options) => {
326
359
  label: "RemoteStorage",
327
360
  icon: "\u{1F4E1}",
328
361
  fields: [
329
- { key: "href", label: "User Address (href)", type: "text", placeholder: "user@5apps.com", required: true },
362
+ { key: "href", label: "User Address / Storage URL (href)", type: "text", placeholder: "user@5apps.com \u6216 https://storage.5apps.com/user", required: true },
330
363
  { key: "token", label: "Bearer Token", type: "password", placeholder: "rs-xxxxxxxx", required: true },
331
364
  { key: "basePath", label: "Base Path", type: "text", placeholder: "/zen-fs-config/" }
332
365
  ],
package/dist/index.js CHANGED
@@ -215,6 +215,39 @@ async function importOptionalBackend(pkg) {
215
215
  );
216
216
  }
217
217
  }
218
+ async function resolveRemoteStorageHref(href) {
219
+ const raw = String(href ?? "").trim();
220
+ if (!raw) throw new Error("RemoteStorage href is required.");
221
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) return raw.replace(/\/+$/, "");
222
+ const match = raw.match(/^(?:acct:)?([^@/]+)@([^@/]+)$/);
223
+ if (!match) {
224
+ throw new Error(
225
+ `RemoteStorage href "${raw}" is neither an absolute URL nor a user address (user@domain).`
226
+ );
227
+ }
228
+ const user = match[1];
229
+ const domain = match[2];
230
+ const webfingerUrl = `https://${domain}/.well-known/webfinger?resource=acct:${encodeURIComponent(user)}@${encodeURIComponent(domain)}`;
231
+ let response;
232
+ try {
233
+ response = await globalThis.fetch(webfingerUrl, {
234
+ headers: { Accept: "application/jrd+json, application/json" }
235
+ });
236
+ } catch (err) {
237
+ throw new Error(
238
+ `RemoteStorage WebFinger request failed (${webfingerUrl}): ${err instanceof Error ? err.message : String(err)}`
239
+ );
240
+ }
241
+ if (!response.ok) {
242
+ throw new Error(`RemoteStorage WebFinger lookup failed (HTTP ${response.status}): ${webfingerUrl}`);
243
+ }
244
+ const jrd = await response.json();
245
+ const link = (jrd?.links ?? []).find(
246
+ (item) => item && item.rel === "http://tools.ietf.org/id/draft-dejong-remotestorage" && item.href
247
+ );
248
+ if (!link) throw new Error(`WebFinger response has no RemoteStorage link: ${webfingerUrl}`);
249
+ return String(link.href).replace(/\/+$/, "");
250
+ }
218
251
  var registry, metadataRegistry, inMemoryCounter, _memCache, OPTIONAL_BACKEND_GLOBALS;
219
252
  var init_backend_registry = __esm({
220
253
  "src/backend-registry.ts"() {
@@ -326,9 +359,9 @@ var init_backend_registry = __esm({
326
359
  registerBackend("Gitee", async (options) => {
327
360
  const _gt = await importOptionalBackend("zen-fs-gitee");
328
361
  const Gitee = _gt?.Gitee ?? _gt?.default;
329
- if (typeof Gitee !== "function") {
362
+ if (!Gitee || typeof Gitee !== "function" && typeof Gitee.create !== "function") {
330
363
  throw new Error(
331
- `Backend package "zen-fs-gitee" loaded, but its Gitee export is not a constructor (typeof=${typeof Gitee}). Load its UMD bundle so it exposes the global "ZenFSGitee".`
364
+ `Backend package "zen-fs-gitee" loaded, but its Gitee export is not a usable backend (typeof=${typeof Gitee}). Load its UMD bundle so it exposes the global "ZenFSGitee".`
332
365
  );
333
366
  }
334
367
  return wrapZenFSFileSystem({
@@ -364,7 +397,7 @@ var init_backend_registry = __esm({
364
397
  );
365
398
  }
366
399
  return new RemoteStorageFileSystem({
367
- href: options.href,
400
+ href: await resolveRemoteStorageHref(options.href),
368
401
  token: options.token,
369
402
  basePath: options.basePath || void 0,
370
403
  preciseMtime: true,
@@ -375,7 +408,7 @@ var init_backend_registry = __esm({
375
408
  label: "RemoteStorage",
376
409
  icon: "\u{1F4E1}",
377
410
  fields: [
378
- { key: "href", label: "User Address (href)", type: "text", placeholder: "user@5apps.com", required: true },
411
+ { key: "href", label: "User Address / Storage URL (href)", type: "text", placeholder: "user@5apps.com \u6216 https://storage.5apps.com/user", required: true },
379
412
  { key: "token", label: "Bearer Token", type: "password", placeholder: "rs-xxxxxxxx", required: true },
380
413
  { key: "basePath", label: "Base Path", type: "text", placeholder: "/zen-fs-config/" }
381
414
  ],
@@ -1394,6 +1427,8 @@ var APP_DATA_GROUPS_DIR = `${META_DIR}/app-data-groups`;
1394
1427
  var CONFLICTS_DIR = `${META_DIR}/.conflicts`;
1395
1428
  var DELETIONS_DIR = `${META_DIR}/.deleted`;
1396
1429
  var NODES_DIR = "/nodes";
1430
+ var SHARED_DIR = "/shared";
1431
+ var CONFIG_ONLY_PREFIXES = [META_DIR, NODES_DIR, SHARED_DIR];
1397
1432
  var LOCAL_IDB_BACKEND_ID = "local-idb";
1398
1433
  function tombstoneFileName(filePath) {
1399
1434
  return filePath.replace(/^\//, "").replace(/\//g, "__").replace(/\./g, "++") + ".json";
@@ -1418,6 +1453,12 @@ function identityOptions(type, options) {
1418
1453
  for (const f of fields) {
1419
1454
  if (options && options[f] !== void 0) subset[f] = options[f];
1420
1455
  }
1456
+ if (type === "Gitee" || type === "GitHub") {
1457
+ const defaultEndpoint = type === "Gitee" ? "https://gitee.com/api/v5" : "https://api.github.com";
1458
+ const raw = options && options.baseUrl;
1459
+ const value = typeof raw === "string" && raw.trim() !== "" ? raw : defaultEndpoint;
1460
+ subset["baseUrl"] = value.replace(/\/+$/, "");
1461
+ }
1421
1462
  return subset;
1422
1463
  }
1423
1464
  function backendDedupKey(desc) {
@@ -2808,10 +2849,15 @@ var ConfigRepo = class {
2808
2849
  }
2809
2850
  const descPath = this.appDataGroupFilePath(id);
2810
2851
  try {
2811
- await this.cachedFS.unlink(descPath);
2812
- } catch {
2852
+ await this.deleteFile(descPath);
2853
+ } catch (err) {
2854
+ log2.log(`[ConfigRepo] removeAppDataGroup: deleteFile failed for "${id}":`, err);
2855
+ try {
2856
+ await this.cachedFS.unlink(descPath);
2857
+ } catch {
2858
+ }
2859
+ await this.unlinkVersionSidecar(this.cachedFS, descPath);
2813
2860
  }
2814
- await this.unlinkVersionSidecar(this.cachedFS, descPath);
2815
2861
  log2.log(`[ConfigRepo] removeAppDataGroup: "${id}" removed`);
2816
2862
  }
2817
2863
  async listAccountBackends() {
@@ -2901,7 +2947,8 @@ var AppDataGroupImpl = class {
2901
2947
  {
2902
2948
  direction: import_zen_fs_sync.SyncDirection.BiDirectional,
2903
2949
  conflictStrategy: "source-wins",
2904
- pollIntervalMs: this._pollIntervalMs
2950
+ pollIntervalMs: this._pollIntervalMs,
2951
+ filter: { excludePrefixes: CONFIG_ONLY_PREFIXES }
2905
2952
  },
2906
2953
  "/"
2907
2954
  );
@@ -2947,7 +2994,8 @@ var AppDataGroupImpl = class {
2947
2994
  {
2948
2995
  direction: import_zen_fs_sync.SyncDirection.BiDirectional,
2949
2996
  conflictStrategy: "source-wins",
2950
- pollIntervalMs: this._pollIntervalMs
2997
+ pollIntervalMs: this._pollIntervalMs,
2998
+ filter: { excludePrefixes: CONFIG_ONLY_PREFIXES }
2951
2999
  },
2952
3000
  "/"
2953
3001
  );
@@ -3194,12 +3242,25 @@ async function connect(appId, options = {}) {
3194
3242
  onConflict: options.onConflict,
3195
3243
  syncPollIntervalMs: options.syncPollIntervalMs
3196
3244
  });
3197
- const dataGroup2 = await repo2.createAppDataGroup("default", []);
3245
+ const appDataGroups2 = [];
3246
+ const descriptors2 = await repo2.listAppDataGroups();
3247
+ for (const d of descriptors2) {
3248
+ try {
3249
+ appDataGroups2.push(await repo2.getAppDataGroup(d.id));
3250
+ } catch (err) {
3251
+ log3(`connect: failed to load app data group "${d.id}":`, err);
3252
+ }
3253
+ }
3254
+ let dataGroup2 = appDataGroups2[0];
3255
+ if (!dataGroup2) {
3256
+ dataGroup2 = await repo2.createAppDataGroup("default", []);
3257
+ appDataGroups2.push(dataGroup2);
3258
+ }
3198
3259
  return {
3199
3260
  groupType: options.groupType ?? "config-sync",
3200
3261
  repo: repo2,
3201
3262
  dataGroup: dataGroup2,
3202
- appDataGroups: [dataGroup2]
3263
+ appDataGroups: appDataGroups2
3203
3264
  };
3204
3265
  }
3205
3266
  const { type, options: backendOptions } = options.backendInfo;
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  registerBackend,
10
10
  unregisterBackend,
11
11
  wrapZenFSFileSystem
12
- } from "./chunk-NSEXSKVW.mjs";
12
+ } from "./chunk-S2S3XBK2.mjs";
13
13
 
14
14
  // src/config-repo.ts
15
15
  import {
@@ -351,7 +351,7 @@ function registerFolderBackend() {
351
351
  const pathMod = await import("path");
352
352
  const dir = options.path;
353
353
  const store = new FolderStore({ path: dir, label: options.label, fs, pathMod });
354
- return (await import("./backend-registry-ZFTXH537.mjs")).wrapZenFSFileSystem({ backend: FolderBackend, path: dir, label: options.label });
354
+ return (await import("./backend-registry-RBKWNJZI.mjs")).wrapZenFSFileSystem({ backend: FolderBackend, path: dir, label: options.label });
355
355
  },
356
356
  {
357
357
  type: "Folder",
@@ -887,6 +887,8 @@ var APP_DATA_GROUPS_DIR = `${META_DIR}/app-data-groups`;
887
887
  var CONFLICTS_DIR = `${META_DIR}/.conflicts`;
888
888
  var DELETIONS_DIR = `${META_DIR}/.deleted`;
889
889
  var NODES_DIR = "/nodes";
890
+ var SHARED_DIR = "/shared";
891
+ var CONFIG_ONLY_PREFIXES = [META_DIR, NODES_DIR, SHARED_DIR];
890
892
  var LOCAL_IDB_BACKEND_ID = "local-idb";
891
893
  function tombstoneFileName(filePath) {
892
894
  return filePath.replace(/^\//, "").replace(/\//g, "__").replace(/\./g, "++") + ".json";
@@ -911,6 +913,12 @@ function identityOptions(type, options) {
911
913
  for (const f of fields) {
912
914
  if (options && options[f] !== void 0) subset[f] = options[f];
913
915
  }
916
+ if (type === "Gitee" || type === "GitHub") {
917
+ const defaultEndpoint = type === "Gitee" ? "https://gitee.com/api/v5" : "https://api.github.com";
918
+ const raw = options && options.baseUrl;
919
+ const value = typeof raw === "string" && raw.trim() !== "" ? raw : defaultEndpoint;
920
+ subset["baseUrl"] = value.replace(/\/+$/, "");
921
+ }
914
922
  return subset;
915
923
  }
916
924
  function backendDedupKey(desc) {
@@ -2301,10 +2309,15 @@ var ConfigRepo = class {
2301
2309
  }
2302
2310
  const descPath = this.appDataGroupFilePath(id);
2303
2311
  try {
2304
- await this.cachedFS.unlink(descPath);
2305
- } catch {
2312
+ await this.deleteFile(descPath);
2313
+ } catch (err) {
2314
+ log2.log(`[ConfigRepo] removeAppDataGroup: deleteFile failed for "${id}":`, err);
2315
+ try {
2316
+ await this.cachedFS.unlink(descPath);
2317
+ } catch {
2318
+ }
2319
+ await this.unlinkVersionSidecar(this.cachedFS, descPath);
2306
2320
  }
2307
- await this.unlinkVersionSidecar(this.cachedFS, descPath);
2308
2321
  log2.log(`[ConfigRepo] removeAppDataGroup: "${id}" removed`);
2309
2322
  }
2310
2323
  async listAccountBackends() {
@@ -2394,7 +2407,8 @@ var AppDataGroupImpl = class {
2394
2407
  {
2395
2408
  direction: SyncDirection.BiDirectional,
2396
2409
  conflictStrategy: "source-wins",
2397
- pollIntervalMs: this._pollIntervalMs
2410
+ pollIntervalMs: this._pollIntervalMs,
2411
+ filter: { excludePrefixes: CONFIG_ONLY_PREFIXES }
2398
2412
  },
2399
2413
  "/"
2400
2414
  );
@@ -2440,7 +2454,8 @@ var AppDataGroupImpl = class {
2440
2454
  {
2441
2455
  direction: SyncDirection.BiDirectional,
2442
2456
  conflictStrategy: "source-wins",
2443
- pollIntervalMs: this._pollIntervalMs
2457
+ pollIntervalMs: this._pollIntervalMs,
2458
+ filter: { excludePrefixes: CONFIG_ONLY_PREFIXES }
2444
2459
  },
2445
2460
  "/"
2446
2461
  );
@@ -2686,12 +2701,25 @@ async function connect(appId, options = {}) {
2686
2701
  onConflict: options.onConflict,
2687
2702
  syncPollIntervalMs: options.syncPollIntervalMs
2688
2703
  });
2689
- const dataGroup2 = await repo2.createAppDataGroup("default", []);
2704
+ const appDataGroups2 = [];
2705
+ const descriptors2 = await repo2.listAppDataGroups();
2706
+ for (const d of descriptors2) {
2707
+ try {
2708
+ appDataGroups2.push(await repo2.getAppDataGroup(d.id));
2709
+ } catch (err) {
2710
+ log3(`connect: failed to load app data group "${d.id}":`, err);
2711
+ }
2712
+ }
2713
+ let dataGroup2 = appDataGroups2[0];
2714
+ if (!dataGroup2) {
2715
+ dataGroup2 = await repo2.createAppDataGroup("default", []);
2716
+ appDataGroups2.push(dataGroup2);
2717
+ }
2690
2718
  return {
2691
2719
  groupType: options.groupType ?? "config-sync",
2692
2720
  repo: repo2,
2693
2721
  dataGroup: dataGroup2,
2694
- appDataGroups: [dataGroup2]
2722
+ appDataGroups: appDataGroups2
2695
2723
  };
2696
2724
  }
2697
2725
  const { type, options: backendOptions } = options.backendInfo;
@@ -24528,6 +24528,39 @@ var ZenFSConfig = (() => {
24528
24528
  );
24529
24529
  }
24530
24530
  }
24531
+ async function resolveRemoteStorageHref(href) {
24532
+ const raw = String(href ?? "").trim();
24533
+ if (!raw) throw new Error("RemoteStorage href is required.");
24534
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) return raw.replace(/\/+$/, "");
24535
+ const match = raw.match(/^(?:acct:)?([^@/]+)@([^@/]+)$/);
24536
+ if (!match) {
24537
+ throw new Error(
24538
+ `RemoteStorage href "${raw}" is neither an absolute URL nor a user address (user@domain).`
24539
+ );
24540
+ }
24541
+ const user = match[1];
24542
+ const domain = match[2];
24543
+ const webfingerUrl = `https://${domain}/.well-known/webfinger?resource=acct:${encodeURIComponent(user)}@${encodeURIComponent(domain)}`;
24544
+ let response;
24545
+ try {
24546
+ response = await globalThis.fetch(webfingerUrl, {
24547
+ headers: { Accept: "application/jrd+json, application/json" }
24548
+ });
24549
+ } catch (err2) {
24550
+ throw new Error(
24551
+ `RemoteStorage WebFinger request failed (${webfingerUrl}): ${err2 instanceof Error ? err2.message : String(err2)}`
24552
+ );
24553
+ }
24554
+ if (!response.ok) {
24555
+ throw new Error(`RemoteStorage WebFinger lookup failed (HTTP ${response.status}): ${webfingerUrl}`);
24556
+ }
24557
+ const jrd = await response.json();
24558
+ const link5 = (jrd?.links ?? []).find(
24559
+ (item) => item && item.rel === "http://tools.ietf.org/id/draft-dejong-remotestorage" && item.href
24560
+ );
24561
+ if (!link5) throw new Error(`WebFinger response has no RemoteStorage link: ${webfingerUrl}`);
24562
+ return String(link5.href).replace(/\/+$/, "");
24563
+ }
24531
24564
  var registry, metadataRegistry, inMemoryCounter, _memCache, OPTIONAL_BACKEND_GLOBALS;
24532
24565
  var init_backend_registry = __esm({
24533
24566
  "src/backend-registry.ts"() {
@@ -24639,9 +24672,9 @@ var ZenFSConfig = (() => {
24639
24672
  registerBackend("Gitee", async (options) => {
24640
24673
  const _gt = await importOptionalBackend("zen-fs-gitee");
24641
24674
  const Gitee = _gt?.Gitee ?? _gt?.default;
24642
- if (typeof Gitee !== "function") {
24675
+ if (!Gitee || typeof Gitee !== "function" && typeof Gitee.create !== "function") {
24643
24676
  throw new Error(
24644
- `Backend package "zen-fs-gitee" loaded, but its Gitee export is not a constructor (typeof=${typeof Gitee}). Load its UMD bundle so it exposes the global "ZenFSGitee".`
24677
+ `Backend package "zen-fs-gitee" loaded, but its Gitee export is not a usable backend (typeof=${typeof Gitee}). Load its UMD bundle so it exposes the global "ZenFSGitee".`
24645
24678
  );
24646
24679
  }
24647
24680
  return wrapZenFSFileSystem({
@@ -24677,7 +24710,7 @@ var ZenFSConfig = (() => {
24677
24710
  );
24678
24711
  }
24679
24712
  return new RemoteStorageFileSystem({
24680
- href: options.href,
24713
+ href: await resolveRemoteStorageHref(options.href),
24681
24714
  token: options.token,
24682
24715
  basePath: options.basePath || void 0,
24683
24716
  preciseMtime: true,
@@ -24688,7 +24721,7 @@ var ZenFSConfig = (() => {
24688
24721
  label: "RemoteStorage",
24689
24722
  icon: "\u{1F4E1}",
24690
24723
  fields: [
24691
- { key: "href", label: "User Address (href)", type: "text", placeholder: "user@5apps.com", required: true },
24724
+ { key: "href", label: "User Address / Storage URL (href)", type: "text", placeholder: "user@5apps.com \u6216 https://storage.5apps.com/user", required: true },
24692
24725
  { key: "token", label: "Bearer Token", type: "password", placeholder: "rs-xxxxxxxx", required: true },
24693
24726
  { key: "basePath", label: "Base Path", type: "text", placeholder: "/zen-fs-config/" }
24694
24727
  ],
@@ -27327,6 +27360,8 @@ var ZenFSConfig = (() => {
27327
27360
  var CONFLICTS_DIR = `${META_DIR}/.conflicts`;
27328
27361
  var DELETIONS_DIR = `${META_DIR}/.deleted`;
27329
27362
  var NODES_DIR = "/nodes";
27363
+ var SHARED_DIR = "/shared";
27364
+ var CONFIG_ONLY_PREFIXES = [META_DIR, NODES_DIR, SHARED_DIR];
27330
27365
  var LOCAL_IDB_BACKEND_ID = "local-idb";
27331
27366
  function tombstoneFileName(filePath) {
27332
27367
  return filePath.replace(/^\//, "").replace(/\//g, "__").replace(/\./g, "++") + ".json";
@@ -27351,6 +27386,12 @@ var ZenFSConfig = (() => {
27351
27386
  for (const f of fields) {
27352
27387
  if (options && options[f] !== void 0) subset[f] = options[f];
27353
27388
  }
27389
+ if (type === "Gitee" || type === "GitHub") {
27390
+ const defaultEndpoint = type === "Gitee" ? "https://gitee.com/api/v5" : "https://api.github.com";
27391
+ const raw = options && options.baseUrl;
27392
+ const value = typeof raw === "string" && raw.trim() !== "" ? raw : defaultEndpoint;
27393
+ subset["baseUrl"] = value.replace(/\/+$/, "");
27394
+ }
27354
27395
  return subset;
27355
27396
  }
27356
27397
  function backendDedupKey(desc) {
@@ -28741,10 +28782,15 @@ var ZenFSConfig = (() => {
28741
28782
  }
28742
28783
  const descPath = this.appDataGroupFilePath(id);
28743
28784
  try {
28744
- await this.cachedFS.unlink(descPath);
28745
- } catch {
28785
+ await this.deleteFile(descPath);
28786
+ } catch (err2) {
28787
+ log6.log(`[ConfigRepo] removeAppDataGroup: deleteFile failed for "${id}":`, err2);
28788
+ try {
28789
+ await this.cachedFS.unlink(descPath);
28790
+ } catch {
28791
+ }
28792
+ await this.unlinkVersionSidecar(this.cachedFS, descPath);
28746
28793
  }
28747
- await this.unlinkVersionSidecar(this.cachedFS, descPath);
28748
28794
  log6.log(`[ConfigRepo] removeAppDataGroup: "${id}" removed`);
28749
28795
  }
28750
28796
  async listAccountBackends() {
@@ -28834,7 +28880,8 @@ var ZenFSConfig = (() => {
28834
28880
  {
28835
28881
  direction: SyncDirection.BiDirectional,
28836
28882
  conflictStrategy: "source-wins",
28837
- pollIntervalMs: this._pollIntervalMs
28883
+ pollIntervalMs: this._pollIntervalMs,
28884
+ filter: { excludePrefixes: CONFIG_ONLY_PREFIXES }
28838
28885
  },
28839
28886
  "/"
28840
28887
  );
@@ -28880,7 +28927,8 @@ var ZenFSConfig = (() => {
28880
28927
  {
28881
28928
  direction: SyncDirection.BiDirectional,
28882
28929
  conflictStrategy: "source-wins",
28883
- pollIntervalMs: this._pollIntervalMs
28930
+ pollIntervalMs: this._pollIntervalMs,
28931
+ filter: { excludePrefixes: CONFIG_ONLY_PREFIXES }
28884
28932
  },
28885
28933
  "/"
28886
28934
  );
@@ -29127,12 +29175,25 @@ var ZenFSConfig = (() => {
29127
29175
  onConflict: options.onConflict,
29128
29176
  syncPollIntervalMs: options.syncPollIntervalMs
29129
29177
  });
29130
- const dataGroup2 = await repo2.createAppDataGroup("default", []);
29178
+ const appDataGroups2 = [];
29179
+ const descriptors2 = await repo2.listAppDataGroups();
29180
+ for (const d of descriptors2) {
29181
+ try {
29182
+ appDataGroups2.push(await repo2.getAppDataGroup(d.id));
29183
+ } catch (err2) {
29184
+ log7(`connect: failed to load app data group "${d.id}":`, err2);
29185
+ }
29186
+ }
29187
+ let dataGroup2 = appDataGroups2[0];
29188
+ if (!dataGroup2) {
29189
+ dataGroup2 = await repo2.createAppDataGroup("default", []);
29190
+ appDataGroups2.push(dataGroup2);
29191
+ }
29131
29192
  return {
29132
29193
  groupType: options.groupType ?? "config-sync",
29133
29194
  repo: repo2,
29134
29195
  dataGroup: dataGroup2,
29135
- appDataGroups: [dataGroup2]
29196
+ appDataGroups: appDataGroups2
29136
29197
  };
29137
29198
  }
29138
29199
  const { type, options: backendOptions } = options.backendInfo;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zen-fs-config",
3
- "version": "0.5.40",
3
+ "version": "0.5.42",
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",