@tinycloud/sdk-core 2.4.0-beta.6 → 2.4.0-beta.7

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.cjs CHANGED
@@ -1151,6 +1151,7 @@ var SpaceService = class {
1151
1151
  this._userDid = config.userDid;
1152
1152
  this.sharingService = config.sharingService;
1153
1153
  this.createDelegationFn = config.createDelegation;
1154
+ this.onSpaceRegisteredFn = config.onSpaceRegistered;
1154
1155
  }
1155
1156
  /**
1156
1157
  * Update the service configuration.
@@ -1166,6 +1167,7 @@ var SpaceService = class {
1166
1167
  if (config.userDid !== void 0) this._userDid = config.userDid;
1167
1168
  if (config.sharingService) this.sharingService = config.sharingService;
1168
1169
  if (config.createDelegation) this.createDelegationFn = config.createDelegation;
1170
+ if (config.onSpaceRegistered) this.onSpaceRegisteredFn = config.onSpaceRegistered;
1169
1171
  this.spaceCache.clear();
1170
1172
  this.infoCache.clear();
1171
1173
  }
@@ -1216,6 +1218,9 @@ var SpaceService = class {
1216
1218
  spaces.push(...delegatedSpaces);
1217
1219
  }
1218
1220
  const uniqueSpaces = this.deduplicateSpaces(spaces);
1221
+ for (const space of uniqueSpaces) {
1222
+ this.notifySpaceRegistered(space);
1223
+ }
1219
1224
  return (0, import_sdk_services2.ok)(uniqueSpaces);
1220
1225
  } catch (error) {
1221
1226
  return (0, import_sdk_services2.err)(
@@ -1413,6 +1418,7 @@ var SpaceService = class {
1413
1418
  permissions: ["*"]
1414
1419
  };
1415
1420
  this.infoCache.set(spaceInfo.id, { info: spaceInfo, cachedAt: Date.now() });
1421
+ this.notifySpaceRegistered(spaceInfo);
1416
1422
  return (0, import_sdk_services2.ok)(spaceInfo);
1417
1423
  } catch (error) {
1418
1424
  return (0, import_sdk_services2.err)(
@@ -1425,6 +1431,11 @@ var SpaceService = class {
1425
1431
  );
1426
1432
  }
1427
1433
  }
1434
+ notifySpaceRegistered(space) {
1435
+ if (!this.onSpaceRegisteredFn) return;
1436
+ void Promise.resolve(this.onSpaceRegisteredFn(space)).catch(() => {
1437
+ });
1438
+ }
1428
1439
  // ===========================================================================
1429
1440
  // Get Space
1430
1441
  // ===========================================================================
@@ -2965,12 +2976,20 @@ function withCapabilitiesReadForSpaces(resources) {
2965
2976
  ...[...spaces].map(capabilitiesReadPermission)
2966
2977
  ]);
2967
2978
  }
2968
- function accountRegistryPermission() {
2969
- return {
2979
+ function accountRegistryPermissions() {
2980
+ return [ACCOUNT_REGISTRY_PATH, "spaces/"].map((path) => ({
2970
2981
  service: "tinycloud.kv",
2971
2982
  space: ACCOUNT_REGISTRY_SPACE,
2972
- path: ACCOUNT_REGISTRY_PATH,
2983
+ path,
2973
2984
  actions: ["tinycloud.kv/get", "tinycloud.kv/put", "tinycloud.kv/list"]
2985
+ }));
2986
+ }
2987
+ function accountRegistryIndexPermission() {
2988
+ return {
2989
+ service: "tinycloud.sql",
2990
+ space: ACCOUNT_REGISTRY_SPACE,
2991
+ path: "account",
2992
+ actions: ["tinycloud.sql/read", "tinycloud.sql/write"]
2974
2993
  };
2975
2994
  }
2976
2995
  function composeManifestRequest(inputs, options = {}) {
@@ -2990,7 +3009,8 @@ function composeManifestRequest(inputs, options = {}) {
2990
3009
  }))
2991
3010
  );
2992
3011
  if (includeAccountRegistryPermissions) {
2993
- resources.push(accountRegistryPermission());
3012
+ resources.push(...accountRegistryPermissions());
3013
+ resources.push(accountRegistryIndexPermission());
2994
3014
  }
2995
3015
  const resourcesWithImplicitCapabilities = withCapabilitiesReadForSpaces(resources);
2996
3016
  const manifestsByAppId = /* @__PURE__ */ new Map();
@@ -3076,6 +3096,7 @@ function manifestAbilitiesUnion(resolved) {
3076
3096
  // src/account/AccountService.ts
3077
3097
  var SERVICE_NAME2 = "account";
3078
3098
  var ACCOUNT_INDEX_DB = "account";
3099
+ var ACCOUNT_SPACES_PATH = "spaces/";
3079
3100
  var AccountService = class {
3080
3101
  constructor(config) {
3081
3102
  this.config = config;
@@ -3119,14 +3140,28 @@ var AccountService = class {
3119
3140
  if (!kvResult.ok) return kvResult;
3120
3141
  let registered;
3121
3142
  for (const record of request.registryRecords) {
3143
+ const manifestHash = hashJson(record.manifests);
3144
+ if (await this.indexHasApplicationHash(record.app_id, manifestHash)) {
3145
+ registered = {
3146
+ appId: record.app_id,
3147
+ manifests: record.manifests,
3148
+ manifestHash,
3149
+ name: record.manifests[0]?.name,
3150
+ description: record.manifests[0]?.description
3151
+ };
3152
+ continue;
3153
+ }
3122
3154
  const stored = {
3123
3155
  app_id: record.app_id,
3124
3156
  manifests: record.manifests,
3157
+ manifest_hash: manifestHash,
3125
3158
  updated_at: (/* @__PURE__ */ new Date()).toISOString()
3126
3159
  };
3127
3160
  const written = await kvResult.data.put(record.key, stored);
3128
3161
  if (!written.ok) return accountErr(written.error);
3129
3162
  registered = applicationFromRecord(record.key, stored);
3163
+ const indexed = await this.upsertApplicationIndex(registered);
3164
+ if (!indexed.ok) return indexed;
3130
3165
  }
3131
3166
  return (0, import_sdk_services5.ok)(registered);
3132
3167
  },
@@ -3135,6 +3170,63 @@ var AccountService = class {
3135
3170
  if (!kvResult.ok) return kvResult;
3136
3171
  const removed = await kvResult.data.delete(applicationKey(appId));
3137
3172
  if (!removed.ok) return accountErr(removed.error);
3173
+ const indexed = await this.deleteApplicationIndex(appId);
3174
+ if (!indexed.ok) return indexed;
3175
+ return (0, import_sdk_services5.ok)(void 0);
3176
+ }
3177
+ };
3178
+ this.spaces = {
3179
+ list: async () => {
3180
+ const kvResult = this.accountKV();
3181
+ if (!kvResult.ok) return kvResult;
3182
+ const listed = await kvResult.data.list({ prefix: ACCOUNT_SPACES_PATH });
3183
+ if (!listed.ok) return accountErr(listed.error);
3184
+ const spaces = [];
3185
+ for (const key of listed.data.keys) {
3186
+ const loaded = await kvResult.data.get(key);
3187
+ if (!loaded.ok) return accountErr(loaded.error);
3188
+ spaces.push(spaceFromRecord(key, loaded.data.data));
3189
+ }
3190
+ spaces.sort((a, b) => a.name.localeCompare(b.name) || a.spaceId.localeCompare(b.spaceId));
3191
+ return (0, import_sdk_services5.ok)(spaces);
3192
+ },
3193
+ get: async (spaceId) => {
3194
+ const kvResult = this.accountKV();
3195
+ if (!kvResult.ok) return kvResult;
3196
+ const loaded = await kvResult.data.get(spaceKey(spaceId));
3197
+ if (!loaded.ok) return accountErr(loaded.error);
3198
+ return (0, import_sdk_services5.ok)(spaceFromRecord(spaceKey(spaceId), loaded.data.data));
3199
+ },
3200
+ register: async (space) => {
3201
+ await this.config.ensureAccountSpaceHosted?.();
3202
+ const kvResult = this.accountKV();
3203
+ if (!kvResult.ok) return kvResult;
3204
+ const stored = spaceRecordFromInput(space);
3205
+ const written = await kvResult.data.put(spaceKey(stored.space_id), stored);
3206
+ if (!written.ok) return accountErr(written.error);
3207
+ const registered = spaceFromRecord(spaceKey(stored.space_id), stored);
3208
+ const indexed = await this.upsertSpaceIndex(registered);
3209
+ if (!indexed.ok) return indexed;
3210
+ return (0, import_sdk_services5.ok)(registered);
3211
+ },
3212
+ syncAccessible: async () => {
3213
+ const listed = await this.config.getSpaces().list();
3214
+ if (!listed.ok) return accountErr(listed.error);
3215
+ const registered = [];
3216
+ for (const space of listed.data) {
3217
+ const result = await this.spaces.register(space);
3218
+ if (!result.ok) return result;
3219
+ registered.push(result.data);
3220
+ }
3221
+ return (0, import_sdk_services5.ok)(registered);
3222
+ },
3223
+ remove: async (spaceId) => {
3224
+ const kvResult = this.accountKV();
3225
+ if (!kvResult.ok) return kvResult;
3226
+ const removed = await kvResult.data.delete(spaceKey(spaceId));
3227
+ if (!removed.ok) return accountErr(removed.error);
3228
+ const indexed = await this.deleteSpaceIndex(spaceId);
3229
+ if (!indexed.ok) return indexed;
3138
3230
  return (0, import_sdk_services5.ok)(void 0);
3139
3231
  }
3140
3232
  };
@@ -3174,12 +3266,16 @@ var AccountService = class {
3174
3266
  if (!dbResult.ok) return dbResult;
3175
3267
  const applications = await this.applications.list();
3176
3268
  if (!applications.ok) return applications;
3269
+ const spaces = await this.spaces.list();
3270
+ if (!spaces.ok) return spaces;
3177
3271
  const delegations = await this.delegations.list();
3178
3272
  if (!delegations.ok) return delegations;
3179
3273
  const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
3180
3274
  const statements = [
3181
3275
  ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3182
3276
  { sql: "DELETE FROM applications" },
3277
+ { sql: "DELETE FROM application_state" },
3278
+ { sql: "DELETE FROM spaces" },
3183
3279
  { sql: "DELETE FROM delegations" },
3184
3280
  { sql: "DELETE FROM sync_state" },
3185
3281
  ...applications.data.map((app) => ({
@@ -3192,6 +3288,24 @@ var AccountService = class {
3192
3288
  JSON.stringify(app.manifests)
3193
3289
  ]
3194
3290
  })),
3291
+ ...applications.data.map((app) => ({
3292
+ sql: "INSERT OR REPLACE INTO application_state (app_id, manifest_hash, indexed_at) VALUES (?, ?, ?)",
3293
+ params: [app.appId, app.manifestHash ?? hashJson(app.manifests), syncedAt]
3294
+ })),
3295
+ ...spaces.data.map((space) => ({
3296
+ sql: "INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
3297
+ params: [
3298
+ space.spaceId,
3299
+ space.name,
3300
+ space.ownerDid,
3301
+ space.type,
3302
+ JSON.stringify(space.permissions),
3303
+ space.status,
3304
+ space.registeredAt ?? syncedAt,
3305
+ space.updatedAt ?? syncedAt,
3306
+ space.expiresAt?.toISOString() ?? null
3307
+ ]
3308
+ })),
3195
3309
  ...delegations.data.map((delegation) => ({
3196
3310
  sql: "INSERT INTO delegations (cid, direction, space_id, space_name, counterparty_did, delegate_did, delegator_did, path, actions_json, expiry, status, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
3197
3311
  params: [
@@ -3214,6 +3328,10 @@ var AccountService = class {
3214
3328
  sql: "INSERT INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
3215
3329
  params: ["applications", syncedAt, applications.data.length]
3216
3330
  },
3331
+ {
3332
+ sql: "INSERT INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
3333
+ params: ["spaces", syncedAt, spaces.data.length]
3334
+ },
3217
3335
  {
3218
3336
  sql: "INSERT INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
3219
3337
  params: ["delegations", syncedAt, delegations.data.length]
@@ -3224,6 +3342,7 @@ var AccountService = class {
3224
3342
  return (0, import_sdk_services5.ok)({
3225
3343
  database: ACCOUNT_INDEX_DB,
3226
3344
  applications: applications.data.length,
3345
+ spaces: spaces.data.length,
3227
3346
  delegations: delegations.data.length,
3228
3347
  syncedAt
3229
3348
  });
@@ -3233,12 +3352,23 @@ var AccountService = class {
3233
3352
  const dbResult = this.accountDb();
3234
3353
  if (!dbResult.ok) return dbResult;
3235
3354
  const queried = await dbResult.data.query(
3236
- "SELECT app_id, name, description, updated_at, manifest_json FROM applications ORDER BY app_id"
3355
+ "SELECT applications.app_id, name, description, updated_at, manifest_json, application_state.manifest_hash FROM applications LEFT JOIN application_state ON applications.app_id = application_state.app_id ORDER BY applications.app_id"
3237
3356
  );
3238
3357
  if (!queried.ok) return accountErr(queried.error);
3239
3358
  return (0, import_sdk_services5.ok)(queried.data.rows.map(indexedApplicationFromRow));
3240
3359
  }
3241
3360
  },
3361
+ spaces: {
3362
+ list: async () => {
3363
+ const dbResult = this.accountDb();
3364
+ if (!dbResult.ok) return dbResult;
3365
+ const queried = await dbResult.data.query(
3366
+ "SELECT space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at FROM spaces ORDER BY name, space_id"
3367
+ );
3368
+ if (!queried.ok) return accountErr(queried.error);
3369
+ return (0, import_sdk_services5.ok)(queried.data.rows.map(indexedSpaceFromRow));
3370
+ }
3371
+ },
3242
3372
  delegations: {
3243
3373
  list: async (options = {}) => {
3244
3374
  const dbResult = this.accountDb();
@@ -3267,6 +3397,22 @@ var AccountService = class {
3267
3397
  const queried = await dbResult.data.query(sql, params);
3268
3398
  if (!queried.ok) return accountErr(queried.error);
3269
3399
  return (0, import_sdk_services5.ok)(queried.data);
3400
+ },
3401
+ status: async () => {
3402
+ const dbResult = this.accountDb();
3403
+ if (!dbResult.ok) return dbResult;
3404
+ const queried = await dbResult.data.query(
3405
+ "SELECT source, synced_at, count FROM sync_state ORDER BY source"
3406
+ );
3407
+ if (!queried.ok) return accountErr(queried.error);
3408
+ return (0, import_sdk_services5.ok)({
3409
+ database: ACCOUNT_INDEX_DB,
3410
+ sources: queried.data.rows.map(([source, syncedAt, count]) => ({
3411
+ source,
3412
+ syncedAt,
3413
+ count
3414
+ }))
3415
+ });
3270
3416
  }
3271
3417
  };
3272
3418
  }
@@ -3275,12 +3421,15 @@ var AccountService = class {
3275
3421
  if (!apps.ok) return apps;
3276
3422
  const delegations = await this.delegations.list();
3277
3423
  if (!delegations.ok) return delegations;
3424
+ const spaces = await this.spaces.list();
3425
+ if (!spaces.ok) return spaces;
3278
3426
  return (0, import_sdk_services5.ok)({
3279
3427
  did: this.config.getDid(),
3280
3428
  host: this.config.getHost(),
3281
3429
  primarySpaceId: this.config.getPrimarySpaceId(),
3282
3430
  accountSpaceId: this.config.getAccountSpaceId(),
3283
3431
  applications: apps.data.length,
3432
+ spaces: spaces.data.length,
3284
3433
  grantedDelegations: delegations.data.filter((d) => d.direction === "granted").length,
3285
3434
  receivedDelegations: delegations.data.filter((d) => d.direction === "received").length
3286
3435
  });
@@ -3311,6 +3460,87 @@ var AccountService = class {
3311
3460
  }
3312
3461
  return (0, import_sdk_services5.ok)(db);
3313
3462
  }
3463
+ async indexHasApplicationHash(appId, manifestHash) {
3464
+ const dbResult = this.accountDb();
3465
+ if (!dbResult.ok) return false;
3466
+ const schema = await dbResult.data.batch(ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })));
3467
+ if (!schema.ok) return false;
3468
+ const queried = await dbResult.data.query(
3469
+ "SELECT 1 FROM application_state WHERE app_id = ? AND manifest_hash = ? LIMIT 1",
3470
+ [appId, manifestHash]
3471
+ );
3472
+ return queried.ok && queried.data.rows.length > 0;
3473
+ }
3474
+ async upsertApplicationIndex(app) {
3475
+ const dbResult = this.accountDb();
3476
+ if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3477
+ const updatedAt = app.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
3478
+ const manifestHash = app.manifestHash ?? hashJson(app.manifests);
3479
+ const written = await dbResult.data.batch([
3480
+ ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3481
+ {
3482
+ sql: "INSERT OR REPLACE INTO applications (app_id, name, description, updated_at, manifest_json) VALUES (?, ?, ?, ?, ?)",
3483
+ params: [
3484
+ app.appId,
3485
+ app.name ?? null,
3486
+ app.description ?? null,
3487
+ updatedAt,
3488
+ JSON.stringify(app.manifests)
3489
+ ]
3490
+ },
3491
+ {
3492
+ sql: "INSERT OR REPLACE INTO application_state (app_id, manifest_hash, indexed_at) VALUES (?, ?, ?)",
3493
+ params: [app.appId, manifestHash, updatedAt]
3494
+ }
3495
+ ]);
3496
+ if (!written.ok) return accountErr(written.error);
3497
+ return (0, import_sdk_services5.ok)(void 0);
3498
+ }
3499
+ async deleteApplicationIndex(appId) {
3500
+ const dbResult = this.accountDb();
3501
+ if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3502
+ const deleted = await dbResult.data.batch([
3503
+ ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3504
+ { sql: "DELETE FROM applications WHERE app_id = ?", params: [appId] },
3505
+ { sql: "DELETE FROM application_state WHERE app_id = ?", params: [appId] }
3506
+ ]);
3507
+ if (!deleted.ok) return accountErr(deleted.error);
3508
+ return (0, import_sdk_services5.ok)(void 0);
3509
+ }
3510
+ async upsertSpaceIndex(space) {
3511
+ const dbResult = this.accountDb();
3512
+ if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3513
+ const updatedAt = space.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
3514
+ const written = await dbResult.data.batch([
3515
+ ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3516
+ {
3517
+ sql: "INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
3518
+ params: [
3519
+ space.spaceId,
3520
+ space.name,
3521
+ space.ownerDid,
3522
+ space.type,
3523
+ JSON.stringify(space.permissions),
3524
+ space.status,
3525
+ space.registeredAt ?? updatedAt,
3526
+ updatedAt,
3527
+ space.expiresAt?.toISOString() ?? null
3528
+ ]
3529
+ }
3530
+ ]);
3531
+ if (!written.ok) return accountErr(written.error);
3532
+ return (0, import_sdk_services5.ok)(void 0);
3533
+ }
3534
+ async deleteSpaceIndex(spaceId) {
3535
+ const dbResult = this.accountDb();
3536
+ if (!dbResult.ok) return (0, import_sdk_services5.ok)(void 0);
3537
+ const deleted = await dbResult.data.batch([
3538
+ ...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
3539
+ { sql: "DELETE FROM spaces WHERE space_id = ?", params: [spaceId] }
3540
+ ]);
3541
+ if (!deleted.ok) return accountErr(deleted.error);
3542
+ return (0, import_sdk_services5.ok)(void 0);
3543
+ }
3314
3544
  async resolveSpace(space) {
3315
3545
  const listed = await this.config.getSpaces().list();
3316
3546
  if (!listed.ok) return accountErr(listed.error);
@@ -3331,6 +3561,22 @@ var ACCOUNT_INDEX_SCHEMA = [
3331
3561
  updated_at TEXT,
3332
3562
  manifest_json TEXT NOT NULL
3333
3563
  )`,
3564
+ `CREATE TABLE IF NOT EXISTS application_state (
3565
+ app_id TEXT PRIMARY KEY,
3566
+ manifest_hash TEXT NOT NULL,
3567
+ indexed_at TEXT NOT NULL
3568
+ )`,
3569
+ `CREATE TABLE IF NOT EXISTS spaces (
3570
+ space_id TEXT PRIMARY KEY,
3571
+ name TEXT NOT NULL,
3572
+ owner_did TEXT NOT NULL,
3573
+ type TEXT NOT NULL,
3574
+ permissions_json TEXT NOT NULL,
3575
+ status TEXT NOT NULL,
3576
+ registered_at TEXT,
3577
+ updated_at TEXT NOT NULL,
3578
+ expires_at TEXT
3579
+ )`,
3334
3580
  `CREATE TABLE IF NOT EXISTS delegations (
3335
3581
  cid TEXT PRIMARY KEY,
3336
3582
  direction TEXT NOT NULL,
@@ -3353,7 +3599,9 @@ var ACCOUNT_INDEX_SCHEMA = [
3353
3599
  )`,
3354
3600
  "CREATE INDEX IF NOT EXISTS idx_delegations_direction ON delegations(direction)",
3355
3601
  "CREATE INDEX IF NOT EXISTS idx_delegations_space ON delegations(space_id)",
3356
- "CREATE INDEX IF NOT EXISTS idx_delegations_counterparty ON delegations(counterparty_did)"
3602
+ "CREATE INDEX IF NOT EXISTS idx_delegations_counterparty ON delegations(counterparty_did)",
3603
+ "CREATE INDEX IF NOT EXISTS idx_spaces_owner ON spaces(owner_did)",
3604
+ "CREATE INDEX IF NOT EXISTS idx_spaces_type ON spaces(type)"
3357
3605
  ];
3358
3606
  function applicationKey(appId) {
3359
3607
  return `${ACCOUNT_REGISTRY_PATH}${appId}`;
@@ -3369,19 +3617,98 @@ function applicationFromRecord(key, record) {
3369
3617
  manifests,
3370
3618
  updatedAt: record.updated_at ?? record.updatedAt,
3371
3619
  name: first?.name,
3372
- description: first?.description
3620
+ description: first?.description,
3621
+ manifestHash: record.manifest_hash ?? record.manifestHash ?? hashJson(manifests)
3373
3622
  };
3374
3623
  }
3375
3624
  function indexedApplicationFromRow(row) {
3376
- const [appId, name, description, updatedAt, manifestJson] = row;
3625
+ const [appId, name, description, updatedAt, manifestJson, manifestHash] = row;
3377
3626
  return {
3378
3627
  appId,
3379
3628
  name: name ?? void 0,
3380
3629
  description: description ?? void 0,
3381
3630
  updatedAt: updatedAt ?? void 0,
3382
- manifests: JSON.parse(manifestJson)
3631
+ manifests: JSON.parse(manifestJson),
3632
+ manifestHash: manifestHash ?? void 0
3633
+ };
3634
+ }
3635
+ function spaceKey(spaceId) {
3636
+ return `${ACCOUNT_SPACES_PATH}${spaceId}`;
3637
+ }
3638
+ function spaceIdFromKey(key) {
3639
+ return key.startsWith(ACCOUNT_SPACES_PATH) ? key.slice(ACCOUNT_SPACES_PATH.length) : key;
3640
+ }
3641
+ function spaceRecordFromInput(space) {
3642
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3643
+ const accountSpace = "spaceId" in space ? space : {
3644
+ spaceId: space.id,
3645
+ name: space.name ?? space.id.split(":").pop() ?? space.id,
3646
+ ownerDid: space.owner ?? "",
3647
+ type: space.type ?? "discovered",
3648
+ permissions: space.permissions ?? [],
3649
+ status: "active",
3650
+ expiresAt: space.expiresAt
3651
+ };
3652
+ return {
3653
+ space_id: accountSpace.spaceId,
3654
+ name: accountSpace.name,
3655
+ owner_did: accountSpace.ownerDid,
3656
+ type: accountSpace.type,
3657
+ permissions: accountSpace.permissions,
3658
+ status: accountSpace.status,
3659
+ registered_at: accountSpace.registeredAt ?? now,
3660
+ updated_at: now,
3661
+ expires_at: accountSpace.expiresAt instanceof Date ? accountSpace.expiresAt.toISOString() : accountSpace.expiresAt
3383
3662
  };
3384
3663
  }
3664
+ function spaceFromRecord(key, record) {
3665
+ const expiresAt = record.expires_at ?? record.expiresAt;
3666
+ return {
3667
+ spaceId: record.space_id ?? record.spaceId ?? spaceIdFromKey(key),
3668
+ name: record.name ?? spaceIdFromKey(key).split(":").pop() ?? spaceIdFromKey(key),
3669
+ ownerDid: record.owner_did ?? record.ownerDid ?? record.owner ?? "",
3670
+ type: record.type ?? "discovered",
3671
+ permissions: Array.isArray(record.permissions) ? record.permissions : [],
3672
+ status: record.status ?? "active",
3673
+ registeredAt: record.registered_at ?? record.registeredAt,
3674
+ updatedAt: record.updated_at ?? record.updatedAt,
3675
+ expiresAt: expiresAt ? new Date(expiresAt) : void 0
3676
+ };
3677
+ }
3678
+ function indexedSpaceFromRow(row) {
3679
+ const [spaceId, name, ownerDid, type, permissionsJson, status, registeredAt, updatedAt, expiresAt] = row;
3680
+ return {
3681
+ spaceId,
3682
+ name,
3683
+ ownerDid,
3684
+ type,
3685
+ permissions: JSON.parse(permissionsJson),
3686
+ status,
3687
+ registeredAt: registeredAt ?? void 0,
3688
+ updatedAt,
3689
+ expiresAt: expiresAt ? new Date(expiresAt) : void 0
3690
+ };
3691
+ }
3692
+ function hashJson(value) {
3693
+ const input = stableJson(value);
3694
+ let hash = 0xcbf29ce484222325n;
3695
+ const prime = 0x100000001b3n;
3696
+ for (let index = 0; index < input.length; index += 1) {
3697
+ hash ^= BigInt(input.charCodeAt(index));
3698
+ hash = BigInt.asUintN(64, hash * prime);
3699
+ }
3700
+ return hash.toString(16).padStart(16, "0");
3701
+ }
3702
+ function stableJson(value) {
3703
+ if (value === null || typeof value !== "object") {
3704
+ return JSON.stringify(value);
3705
+ }
3706
+ if (Array.isArray(value)) {
3707
+ return `[${value.map(stableJson).join(",")}]`;
3708
+ }
3709
+ const object = value;
3710
+ return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableJson(object[key])}`).join(",")}}`;
3711
+ }
3385
3712
  function indexedDelegationFromRow(row) {
3386
3713
  const [
3387
3714
  cid,