@tinycloud/sdk-core 2.4.0-beta.6 → 2.4.0-beta.8
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 +336 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +336 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -970,6 +970,7 @@ var SpaceService = class {
|
|
|
970
970
|
this._userDid = config.userDid;
|
|
971
971
|
this.sharingService = config.sharingService;
|
|
972
972
|
this.createDelegationFn = config.createDelegation;
|
|
973
|
+
this.onSpaceRegisteredFn = config.onSpaceRegistered;
|
|
973
974
|
}
|
|
974
975
|
/**
|
|
975
976
|
* Update the service configuration.
|
|
@@ -985,6 +986,7 @@ var SpaceService = class {
|
|
|
985
986
|
if (config.userDid !== void 0) this._userDid = config.userDid;
|
|
986
987
|
if (config.sharingService) this.sharingService = config.sharingService;
|
|
987
988
|
if (config.createDelegation) this.createDelegationFn = config.createDelegation;
|
|
989
|
+
if (config.onSpaceRegistered) this.onSpaceRegisteredFn = config.onSpaceRegistered;
|
|
988
990
|
this.spaceCache.clear();
|
|
989
991
|
this.infoCache.clear();
|
|
990
992
|
}
|
|
@@ -1035,6 +1037,9 @@ var SpaceService = class {
|
|
|
1035
1037
|
spaces.push(...delegatedSpaces);
|
|
1036
1038
|
}
|
|
1037
1039
|
const uniqueSpaces = this.deduplicateSpaces(spaces);
|
|
1040
|
+
for (const space of uniqueSpaces) {
|
|
1041
|
+
this.notifySpaceRegistered(space);
|
|
1042
|
+
}
|
|
1038
1043
|
return ok(uniqueSpaces);
|
|
1039
1044
|
} catch (error) {
|
|
1040
1045
|
return err(
|
|
@@ -1232,6 +1237,7 @@ var SpaceService = class {
|
|
|
1232
1237
|
permissions: ["*"]
|
|
1233
1238
|
};
|
|
1234
1239
|
this.infoCache.set(spaceInfo.id, { info: spaceInfo, cachedAt: Date.now() });
|
|
1240
|
+
this.notifySpaceRegistered(spaceInfo);
|
|
1235
1241
|
return ok(spaceInfo);
|
|
1236
1242
|
} catch (error) {
|
|
1237
1243
|
return err(
|
|
@@ -1244,6 +1250,11 @@ var SpaceService = class {
|
|
|
1244
1250
|
);
|
|
1245
1251
|
}
|
|
1246
1252
|
}
|
|
1253
|
+
notifySpaceRegistered(space) {
|
|
1254
|
+
if (!this.onSpaceRegisteredFn) return;
|
|
1255
|
+
void Promise.resolve(this.onSpaceRegisteredFn(space)).catch(() => {
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1247
1258
|
// ===========================================================================
|
|
1248
1259
|
// Get Space
|
|
1249
1260
|
// ===========================================================================
|
|
@@ -2788,12 +2799,20 @@ function withCapabilitiesReadForSpaces(resources) {
|
|
|
2788
2799
|
...[...spaces].map(capabilitiesReadPermission)
|
|
2789
2800
|
]);
|
|
2790
2801
|
}
|
|
2791
|
-
function
|
|
2792
|
-
return {
|
|
2802
|
+
function accountRegistryPermissions() {
|
|
2803
|
+
return [ACCOUNT_REGISTRY_PATH, "spaces/"].map((path) => ({
|
|
2793
2804
|
service: "tinycloud.kv",
|
|
2794
2805
|
space: ACCOUNT_REGISTRY_SPACE,
|
|
2795
|
-
path
|
|
2806
|
+
path,
|
|
2796
2807
|
actions: ["tinycloud.kv/get", "tinycloud.kv/put", "tinycloud.kv/list"]
|
|
2808
|
+
}));
|
|
2809
|
+
}
|
|
2810
|
+
function accountRegistryIndexPermission() {
|
|
2811
|
+
return {
|
|
2812
|
+
service: "tinycloud.sql",
|
|
2813
|
+
space: ACCOUNT_REGISTRY_SPACE,
|
|
2814
|
+
path: "account",
|
|
2815
|
+
actions: ["tinycloud.sql/read", "tinycloud.sql/write", "tinycloud.sql/ddl"]
|
|
2797
2816
|
};
|
|
2798
2817
|
}
|
|
2799
2818
|
function composeManifestRequest(inputs, options = {}) {
|
|
@@ -2813,7 +2832,8 @@ function composeManifestRequest(inputs, options = {}) {
|
|
|
2813
2832
|
}))
|
|
2814
2833
|
);
|
|
2815
2834
|
if (includeAccountRegistryPermissions) {
|
|
2816
|
-
resources.push(
|
|
2835
|
+
resources.push(...accountRegistryPermissions());
|
|
2836
|
+
resources.push(accountRegistryIndexPermission());
|
|
2817
2837
|
}
|
|
2818
2838
|
const resourcesWithImplicitCapabilities = withCapabilitiesReadForSpaces(resources);
|
|
2819
2839
|
const manifestsByAppId = /* @__PURE__ */ new Map();
|
|
@@ -2899,6 +2919,7 @@ function manifestAbilitiesUnion(resolved) {
|
|
|
2899
2919
|
// src/account/AccountService.ts
|
|
2900
2920
|
var SERVICE_NAME2 = "account";
|
|
2901
2921
|
var ACCOUNT_INDEX_DB = "account";
|
|
2922
|
+
var ACCOUNT_SPACES_PATH = "spaces/";
|
|
2902
2923
|
var AccountService = class {
|
|
2903
2924
|
constructor(config) {
|
|
2904
2925
|
this.config = config;
|
|
@@ -2942,14 +2963,28 @@ var AccountService = class {
|
|
|
2942
2963
|
if (!kvResult.ok) return kvResult;
|
|
2943
2964
|
let registered;
|
|
2944
2965
|
for (const record of request.registryRecords) {
|
|
2966
|
+
const manifestHash = hashJson(record.manifests);
|
|
2967
|
+
if (await this.indexHasApplicationHash(record.app_id, manifestHash)) {
|
|
2968
|
+
registered = {
|
|
2969
|
+
appId: record.app_id,
|
|
2970
|
+
manifests: record.manifests,
|
|
2971
|
+
manifestHash,
|
|
2972
|
+
name: record.manifests[0]?.name,
|
|
2973
|
+
description: record.manifests[0]?.description
|
|
2974
|
+
};
|
|
2975
|
+
continue;
|
|
2976
|
+
}
|
|
2945
2977
|
const stored = {
|
|
2946
2978
|
app_id: record.app_id,
|
|
2947
2979
|
manifests: record.manifests,
|
|
2980
|
+
manifest_hash: manifestHash,
|
|
2948
2981
|
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
2949
2982
|
};
|
|
2950
2983
|
const written = await kvResult.data.put(record.key, stored);
|
|
2951
2984
|
if (!written.ok) return accountErr(written.error);
|
|
2952
2985
|
registered = applicationFromRecord(record.key, stored);
|
|
2986
|
+
const indexed = await this.upsertApplicationIndex(registered);
|
|
2987
|
+
if (!indexed.ok) return indexed;
|
|
2953
2988
|
}
|
|
2954
2989
|
return ok3(registered);
|
|
2955
2990
|
},
|
|
@@ -2958,6 +2993,63 @@ var AccountService = class {
|
|
|
2958
2993
|
if (!kvResult.ok) return kvResult;
|
|
2959
2994
|
const removed = await kvResult.data.delete(applicationKey(appId));
|
|
2960
2995
|
if (!removed.ok) return accountErr(removed.error);
|
|
2996
|
+
const indexed = await this.deleteApplicationIndex(appId);
|
|
2997
|
+
if (!indexed.ok) return indexed;
|
|
2998
|
+
return ok3(void 0);
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
this.spaces = {
|
|
3002
|
+
list: async () => {
|
|
3003
|
+
const kvResult = this.accountKV();
|
|
3004
|
+
if (!kvResult.ok) return kvResult;
|
|
3005
|
+
const listed = await kvResult.data.list({ prefix: ACCOUNT_SPACES_PATH });
|
|
3006
|
+
if (!listed.ok) return accountErr(listed.error);
|
|
3007
|
+
const spaces = [];
|
|
3008
|
+
for (const key of listed.data.keys) {
|
|
3009
|
+
const loaded = await kvResult.data.get(key);
|
|
3010
|
+
if (!loaded.ok) return accountErr(loaded.error);
|
|
3011
|
+
spaces.push(spaceFromRecord(key, loaded.data.data));
|
|
3012
|
+
}
|
|
3013
|
+
spaces.sort((a, b) => a.name.localeCompare(b.name) || a.spaceId.localeCompare(b.spaceId));
|
|
3014
|
+
return ok3(spaces);
|
|
3015
|
+
},
|
|
3016
|
+
get: async (spaceId) => {
|
|
3017
|
+
const kvResult = this.accountKV();
|
|
3018
|
+
if (!kvResult.ok) return kvResult;
|
|
3019
|
+
const loaded = await kvResult.data.get(spaceKey(spaceId));
|
|
3020
|
+
if (!loaded.ok) return accountErr(loaded.error);
|
|
3021
|
+
return ok3(spaceFromRecord(spaceKey(spaceId), loaded.data.data));
|
|
3022
|
+
},
|
|
3023
|
+
register: async (space) => {
|
|
3024
|
+
await this.config.ensureAccountSpaceHosted?.();
|
|
3025
|
+
const kvResult = this.accountKV();
|
|
3026
|
+
if (!kvResult.ok) return kvResult;
|
|
3027
|
+
const stored = spaceRecordFromInput(space);
|
|
3028
|
+
const written = await kvResult.data.put(spaceKey(stored.space_id), stored);
|
|
3029
|
+
if (!written.ok) return accountErr(written.error);
|
|
3030
|
+
const registered = spaceFromRecord(spaceKey(stored.space_id), stored);
|
|
3031
|
+
const indexed = await this.upsertSpaceIndex(registered);
|
|
3032
|
+
if (!indexed.ok) return indexed;
|
|
3033
|
+
return ok3(registered);
|
|
3034
|
+
},
|
|
3035
|
+
syncAccessible: async () => {
|
|
3036
|
+
const listed = await this.config.getSpaces().list();
|
|
3037
|
+
if (!listed.ok) return accountErr(listed.error);
|
|
3038
|
+
const registered = [];
|
|
3039
|
+
for (const space of listed.data) {
|
|
3040
|
+
const result = await this.spaces.register(space);
|
|
3041
|
+
if (!result.ok) return result;
|
|
3042
|
+
registered.push(result.data);
|
|
3043
|
+
}
|
|
3044
|
+
return ok3(registered);
|
|
3045
|
+
},
|
|
3046
|
+
remove: async (spaceId) => {
|
|
3047
|
+
const kvResult = this.accountKV();
|
|
3048
|
+
if (!kvResult.ok) return kvResult;
|
|
3049
|
+
const removed = await kvResult.data.delete(spaceKey(spaceId));
|
|
3050
|
+
if (!removed.ok) return accountErr(removed.error);
|
|
3051
|
+
const indexed = await this.deleteSpaceIndex(spaceId);
|
|
3052
|
+
if (!indexed.ok) return indexed;
|
|
2961
3053
|
return ok3(void 0);
|
|
2962
3054
|
}
|
|
2963
3055
|
};
|
|
@@ -2997,12 +3089,16 @@ var AccountService = class {
|
|
|
2997
3089
|
if (!dbResult.ok) return dbResult;
|
|
2998
3090
|
const applications = await this.applications.list();
|
|
2999
3091
|
if (!applications.ok) return applications;
|
|
3092
|
+
const spaces = await this.spaces.list();
|
|
3093
|
+
if (!spaces.ok) return spaces;
|
|
3000
3094
|
const delegations = await this.delegations.list();
|
|
3001
3095
|
if (!delegations.ok) return delegations;
|
|
3002
3096
|
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3003
3097
|
const statements = [
|
|
3004
3098
|
...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
|
|
3005
3099
|
{ sql: "DELETE FROM applications" },
|
|
3100
|
+
{ sql: "DELETE FROM application_state" },
|
|
3101
|
+
{ sql: "DELETE FROM spaces" },
|
|
3006
3102
|
{ sql: "DELETE FROM delegations" },
|
|
3007
3103
|
{ sql: "DELETE FROM sync_state" },
|
|
3008
3104
|
...applications.data.map((app) => ({
|
|
@@ -3015,6 +3111,24 @@ var AccountService = class {
|
|
|
3015
3111
|
JSON.stringify(app.manifests)
|
|
3016
3112
|
]
|
|
3017
3113
|
})),
|
|
3114
|
+
...applications.data.map((app) => ({
|
|
3115
|
+
sql: "INSERT OR REPLACE INTO application_state (app_id, manifest_hash, indexed_at) VALUES (?, ?, ?)",
|
|
3116
|
+
params: [app.appId, app.manifestHash ?? hashJson(app.manifests), syncedAt]
|
|
3117
|
+
})),
|
|
3118
|
+
...spaces.data.map((space) => ({
|
|
3119
|
+
sql: "INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
3120
|
+
params: [
|
|
3121
|
+
space.spaceId,
|
|
3122
|
+
space.name,
|
|
3123
|
+
space.ownerDid,
|
|
3124
|
+
space.type,
|
|
3125
|
+
JSON.stringify(space.permissions),
|
|
3126
|
+
space.status,
|
|
3127
|
+
space.registeredAt ?? syncedAt,
|
|
3128
|
+
space.updatedAt ?? syncedAt,
|
|
3129
|
+
space.expiresAt?.toISOString() ?? null
|
|
3130
|
+
]
|
|
3131
|
+
})),
|
|
3018
3132
|
...delegations.data.map((delegation) => ({
|
|
3019
3133
|
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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
3020
3134
|
params: [
|
|
@@ -3037,6 +3151,10 @@ var AccountService = class {
|
|
|
3037
3151
|
sql: "INSERT INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
|
|
3038
3152
|
params: ["applications", syncedAt, applications.data.length]
|
|
3039
3153
|
},
|
|
3154
|
+
{
|
|
3155
|
+
sql: "INSERT INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
|
|
3156
|
+
params: ["spaces", syncedAt, spaces.data.length]
|
|
3157
|
+
},
|
|
3040
3158
|
{
|
|
3041
3159
|
sql: "INSERT INTO sync_state (source, synced_at, count) VALUES (?, ?, ?)",
|
|
3042
3160
|
params: ["delegations", syncedAt, delegations.data.length]
|
|
@@ -3047,6 +3165,7 @@ var AccountService = class {
|
|
|
3047
3165
|
return ok3({
|
|
3048
3166
|
database: ACCOUNT_INDEX_DB,
|
|
3049
3167
|
applications: applications.data.length,
|
|
3168
|
+
spaces: spaces.data.length,
|
|
3050
3169
|
delegations: delegations.data.length,
|
|
3051
3170
|
syncedAt
|
|
3052
3171
|
});
|
|
@@ -3056,12 +3175,23 @@ var AccountService = class {
|
|
|
3056
3175
|
const dbResult = this.accountDb();
|
|
3057
3176
|
if (!dbResult.ok) return dbResult;
|
|
3058
3177
|
const queried = await dbResult.data.query(
|
|
3059
|
-
"SELECT app_id, name, description, updated_at, manifest_json FROM applications ORDER BY app_id"
|
|
3178
|
+
"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"
|
|
3060
3179
|
);
|
|
3061
3180
|
if (!queried.ok) return accountErr(queried.error);
|
|
3062
3181
|
return ok3(queried.data.rows.map(indexedApplicationFromRow));
|
|
3063
3182
|
}
|
|
3064
3183
|
},
|
|
3184
|
+
spaces: {
|
|
3185
|
+
list: async () => {
|
|
3186
|
+
const dbResult = this.accountDb();
|
|
3187
|
+
if (!dbResult.ok) return dbResult;
|
|
3188
|
+
const queried = await dbResult.data.query(
|
|
3189
|
+
"SELECT space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at FROM spaces ORDER BY name, space_id"
|
|
3190
|
+
);
|
|
3191
|
+
if (!queried.ok) return accountErr(queried.error);
|
|
3192
|
+
return ok3(queried.data.rows.map(indexedSpaceFromRow));
|
|
3193
|
+
}
|
|
3194
|
+
},
|
|
3065
3195
|
delegations: {
|
|
3066
3196
|
list: async (options = {}) => {
|
|
3067
3197
|
const dbResult = this.accountDb();
|
|
@@ -3090,6 +3220,22 @@ var AccountService = class {
|
|
|
3090
3220
|
const queried = await dbResult.data.query(sql, params);
|
|
3091
3221
|
if (!queried.ok) return accountErr(queried.error);
|
|
3092
3222
|
return ok3(queried.data);
|
|
3223
|
+
},
|
|
3224
|
+
status: async () => {
|
|
3225
|
+
const dbResult = this.accountDb();
|
|
3226
|
+
if (!dbResult.ok) return dbResult;
|
|
3227
|
+
const queried = await dbResult.data.query(
|
|
3228
|
+
"SELECT source, synced_at, count FROM sync_state ORDER BY source"
|
|
3229
|
+
);
|
|
3230
|
+
if (!queried.ok) return accountErr(queried.error);
|
|
3231
|
+
return ok3({
|
|
3232
|
+
database: ACCOUNT_INDEX_DB,
|
|
3233
|
+
sources: queried.data.rows.map(([source, syncedAt, count]) => ({
|
|
3234
|
+
source,
|
|
3235
|
+
syncedAt,
|
|
3236
|
+
count
|
|
3237
|
+
}))
|
|
3238
|
+
});
|
|
3093
3239
|
}
|
|
3094
3240
|
};
|
|
3095
3241
|
}
|
|
@@ -3098,12 +3244,15 @@ var AccountService = class {
|
|
|
3098
3244
|
if (!apps.ok) return apps;
|
|
3099
3245
|
const delegations = await this.delegations.list();
|
|
3100
3246
|
if (!delegations.ok) return delegations;
|
|
3247
|
+
const spaces = await this.spaces.list();
|
|
3248
|
+
if (!spaces.ok) return spaces;
|
|
3101
3249
|
return ok3({
|
|
3102
3250
|
did: this.config.getDid(),
|
|
3103
3251
|
host: this.config.getHost(),
|
|
3104
3252
|
primarySpaceId: this.config.getPrimarySpaceId(),
|
|
3105
3253
|
accountSpaceId: this.config.getAccountSpaceId(),
|
|
3106
3254
|
applications: apps.data.length,
|
|
3255
|
+
spaces: spaces.data.length,
|
|
3107
3256
|
grantedDelegations: delegations.data.filter((d) => d.direction === "granted").length,
|
|
3108
3257
|
receivedDelegations: delegations.data.filter((d) => d.direction === "received").length
|
|
3109
3258
|
});
|
|
@@ -3134,6 +3283,87 @@ var AccountService = class {
|
|
|
3134
3283
|
}
|
|
3135
3284
|
return ok3(db);
|
|
3136
3285
|
}
|
|
3286
|
+
async indexHasApplicationHash(appId, manifestHash) {
|
|
3287
|
+
const dbResult = this.accountDb();
|
|
3288
|
+
if (!dbResult.ok) return false;
|
|
3289
|
+
const schema = await dbResult.data.batch(ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })));
|
|
3290
|
+
if (!schema.ok) return false;
|
|
3291
|
+
const queried = await dbResult.data.query(
|
|
3292
|
+
"SELECT 1 FROM application_state WHERE app_id = ? AND manifest_hash = ? LIMIT 1",
|
|
3293
|
+
[appId, manifestHash]
|
|
3294
|
+
);
|
|
3295
|
+
return queried.ok && queried.data.rows.length > 0;
|
|
3296
|
+
}
|
|
3297
|
+
async upsertApplicationIndex(app) {
|
|
3298
|
+
const dbResult = this.accountDb();
|
|
3299
|
+
if (!dbResult.ok) return ok3(void 0);
|
|
3300
|
+
const updatedAt = app.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
3301
|
+
const manifestHash = app.manifestHash ?? hashJson(app.manifests);
|
|
3302
|
+
const written = await dbResult.data.batch([
|
|
3303
|
+
...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
|
|
3304
|
+
{
|
|
3305
|
+
sql: "INSERT OR REPLACE INTO applications (app_id, name, description, updated_at, manifest_json) VALUES (?, ?, ?, ?, ?)",
|
|
3306
|
+
params: [
|
|
3307
|
+
app.appId,
|
|
3308
|
+
app.name ?? null,
|
|
3309
|
+
app.description ?? null,
|
|
3310
|
+
updatedAt,
|
|
3311
|
+
JSON.stringify(app.manifests)
|
|
3312
|
+
]
|
|
3313
|
+
},
|
|
3314
|
+
{
|
|
3315
|
+
sql: "INSERT OR REPLACE INTO application_state (app_id, manifest_hash, indexed_at) VALUES (?, ?, ?)",
|
|
3316
|
+
params: [app.appId, manifestHash, updatedAt]
|
|
3317
|
+
}
|
|
3318
|
+
]);
|
|
3319
|
+
if (!written.ok) return accountErr(written.error);
|
|
3320
|
+
return ok3(void 0);
|
|
3321
|
+
}
|
|
3322
|
+
async deleteApplicationIndex(appId) {
|
|
3323
|
+
const dbResult = this.accountDb();
|
|
3324
|
+
if (!dbResult.ok) return ok3(void 0);
|
|
3325
|
+
const deleted = await dbResult.data.batch([
|
|
3326
|
+
...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
|
|
3327
|
+
{ sql: "DELETE FROM applications WHERE app_id = ?", params: [appId] },
|
|
3328
|
+
{ sql: "DELETE FROM application_state WHERE app_id = ?", params: [appId] }
|
|
3329
|
+
]);
|
|
3330
|
+
if (!deleted.ok) return accountErr(deleted.error);
|
|
3331
|
+
return ok3(void 0);
|
|
3332
|
+
}
|
|
3333
|
+
async upsertSpaceIndex(space) {
|
|
3334
|
+
const dbResult = this.accountDb();
|
|
3335
|
+
if (!dbResult.ok) return ok3(void 0);
|
|
3336
|
+
const updatedAt = space.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
3337
|
+
const written = await dbResult.data.batch([
|
|
3338
|
+
...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
|
|
3339
|
+
{
|
|
3340
|
+
sql: "INSERT OR REPLACE INTO spaces (space_id, name, owner_did, type, permissions_json, status, registered_at, updated_at, expires_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
|
3341
|
+
params: [
|
|
3342
|
+
space.spaceId,
|
|
3343
|
+
space.name,
|
|
3344
|
+
space.ownerDid,
|
|
3345
|
+
space.type,
|
|
3346
|
+
JSON.stringify(space.permissions),
|
|
3347
|
+
space.status,
|
|
3348
|
+
space.registeredAt ?? updatedAt,
|
|
3349
|
+
updatedAt,
|
|
3350
|
+
space.expiresAt?.toISOString() ?? null
|
|
3351
|
+
]
|
|
3352
|
+
}
|
|
3353
|
+
]);
|
|
3354
|
+
if (!written.ok) return accountErr(written.error);
|
|
3355
|
+
return ok3(void 0);
|
|
3356
|
+
}
|
|
3357
|
+
async deleteSpaceIndex(spaceId) {
|
|
3358
|
+
const dbResult = this.accountDb();
|
|
3359
|
+
if (!dbResult.ok) return ok3(void 0);
|
|
3360
|
+
const deleted = await dbResult.data.batch([
|
|
3361
|
+
...ACCOUNT_INDEX_SCHEMA.map((sql) => ({ sql })),
|
|
3362
|
+
{ sql: "DELETE FROM spaces WHERE space_id = ?", params: [spaceId] }
|
|
3363
|
+
]);
|
|
3364
|
+
if (!deleted.ok) return accountErr(deleted.error);
|
|
3365
|
+
return ok3(void 0);
|
|
3366
|
+
}
|
|
3137
3367
|
async resolveSpace(space) {
|
|
3138
3368
|
const listed = await this.config.getSpaces().list();
|
|
3139
3369
|
if (!listed.ok) return accountErr(listed.error);
|
|
@@ -3154,6 +3384,22 @@ var ACCOUNT_INDEX_SCHEMA = [
|
|
|
3154
3384
|
updated_at TEXT,
|
|
3155
3385
|
manifest_json TEXT NOT NULL
|
|
3156
3386
|
)`,
|
|
3387
|
+
`CREATE TABLE IF NOT EXISTS application_state (
|
|
3388
|
+
app_id TEXT PRIMARY KEY,
|
|
3389
|
+
manifest_hash TEXT NOT NULL,
|
|
3390
|
+
indexed_at TEXT NOT NULL
|
|
3391
|
+
)`,
|
|
3392
|
+
`CREATE TABLE IF NOT EXISTS spaces (
|
|
3393
|
+
space_id TEXT PRIMARY KEY,
|
|
3394
|
+
name TEXT NOT NULL,
|
|
3395
|
+
owner_did TEXT NOT NULL,
|
|
3396
|
+
type TEXT NOT NULL,
|
|
3397
|
+
permissions_json TEXT NOT NULL,
|
|
3398
|
+
status TEXT NOT NULL,
|
|
3399
|
+
registered_at TEXT,
|
|
3400
|
+
updated_at TEXT NOT NULL,
|
|
3401
|
+
expires_at TEXT
|
|
3402
|
+
)`,
|
|
3157
3403
|
`CREATE TABLE IF NOT EXISTS delegations (
|
|
3158
3404
|
cid TEXT PRIMARY KEY,
|
|
3159
3405
|
direction TEXT NOT NULL,
|
|
@@ -3176,7 +3422,9 @@ var ACCOUNT_INDEX_SCHEMA = [
|
|
|
3176
3422
|
)`,
|
|
3177
3423
|
"CREATE INDEX IF NOT EXISTS idx_delegations_direction ON delegations(direction)",
|
|
3178
3424
|
"CREATE INDEX IF NOT EXISTS idx_delegations_space ON delegations(space_id)",
|
|
3179
|
-
"CREATE INDEX IF NOT EXISTS idx_delegations_counterparty ON delegations(counterparty_did)"
|
|
3425
|
+
"CREATE INDEX IF NOT EXISTS idx_delegations_counterparty ON delegations(counterparty_did)",
|
|
3426
|
+
"CREATE INDEX IF NOT EXISTS idx_spaces_owner ON spaces(owner_did)",
|
|
3427
|
+
"CREATE INDEX IF NOT EXISTS idx_spaces_type ON spaces(type)"
|
|
3180
3428
|
];
|
|
3181
3429
|
function applicationKey(appId) {
|
|
3182
3430
|
return `${ACCOUNT_REGISTRY_PATH}${appId}`;
|
|
@@ -3192,19 +3440,98 @@ function applicationFromRecord(key, record) {
|
|
|
3192
3440
|
manifests,
|
|
3193
3441
|
updatedAt: record.updated_at ?? record.updatedAt,
|
|
3194
3442
|
name: first?.name,
|
|
3195
|
-
description: first?.description
|
|
3443
|
+
description: first?.description,
|
|
3444
|
+
manifestHash: record.manifest_hash ?? record.manifestHash ?? hashJson(manifests)
|
|
3196
3445
|
};
|
|
3197
3446
|
}
|
|
3198
3447
|
function indexedApplicationFromRow(row) {
|
|
3199
|
-
const [appId, name, description, updatedAt, manifestJson] = row;
|
|
3448
|
+
const [appId, name, description, updatedAt, manifestJson, manifestHash] = row;
|
|
3200
3449
|
return {
|
|
3201
3450
|
appId,
|
|
3202
3451
|
name: name ?? void 0,
|
|
3203
3452
|
description: description ?? void 0,
|
|
3204
3453
|
updatedAt: updatedAt ?? void 0,
|
|
3205
|
-
manifests: JSON.parse(manifestJson)
|
|
3454
|
+
manifests: JSON.parse(manifestJson),
|
|
3455
|
+
manifestHash: manifestHash ?? void 0
|
|
3456
|
+
};
|
|
3457
|
+
}
|
|
3458
|
+
function spaceKey(spaceId) {
|
|
3459
|
+
return `${ACCOUNT_SPACES_PATH}${spaceId}`;
|
|
3460
|
+
}
|
|
3461
|
+
function spaceIdFromKey(key) {
|
|
3462
|
+
return key.startsWith(ACCOUNT_SPACES_PATH) ? key.slice(ACCOUNT_SPACES_PATH.length) : key;
|
|
3463
|
+
}
|
|
3464
|
+
function spaceRecordFromInput(space) {
|
|
3465
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3466
|
+
const accountSpace = "spaceId" in space ? space : {
|
|
3467
|
+
spaceId: space.id,
|
|
3468
|
+
name: space.name ?? space.id.split(":").pop() ?? space.id,
|
|
3469
|
+
ownerDid: space.owner ?? "",
|
|
3470
|
+
type: space.type ?? "discovered",
|
|
3471
|
+
permissions: space.permissions ?? [],
|
|
3472
|
+
status: "active",
|
|
3473
|
+
expiresAt: space.expiresAt
|
|
3474
|
+
};
|
|
3475
|
+
return {
|
|
3476
|
+
space_id: accountSpace.spaceId,
|
|
3477
|
+
name: accountSpace.name,
|
|
3478
|
+
owner_did: accountSpace.ownerDid,
|
|
3479
|
+
type: accountSpace.type,
|
|
3480
|
+
permissions: accountSpace.permissions,
|
|
3481
|
+
status: accountSpace.status,
|
|
3482
|
+
registered_at: accountSpace.registeredAt ?? now,
|
|
3483
|
+
updated_at: now,
|
|
3484
|
+
expires_at: accountSpace.expiresAt instanceof Date ? accountSpace.expiresAt.toISOString() : accountSpace.expiresAt
|
|
3206
3485
|
};
|
|
3207
3486
|
}
|
|
3487
|
+
function spaceFromRecord(key, record) {
|
|
3488
|
+
const expiresAt = record.expires_at ?? record.expiresAt;
|
|
3489
|
+
return {
|
|
3490
|
+
spaceId: record.space_id ?? record.spaceId ?? spaceIdFromKey(key),
|
|
3491
|
+
name: record.name ?? spaceIdFromKey(key).split(":").pop() ?? spaceIdFromKey(key),
|
|
3492
|
+
ownerDid: record.owner_did ?? record.ownerDid ?? record.owner ?? "",
|
|
3493
|
+
type: record.type ?? "discovered",
|
|
3494
|
+
permissions: Array.isArray(record.permissions) ? record.permissions : [],
|
|
3495
|
+
status: record.status ?? "active",
|
|
3496
|
+
registeredAt: record.registered_at ?? record.registeredAt,
|
|
3497
|
+
updatedAt: record.updated_at ?? record.updatedAt,
|
|
3498
|
+
expiresAt: expiresAt ? new Date(expiresAt) : void 0
|
|
3499
|
+
};
|
|
3500
|
+
}
|
|
3501
|
+
function indexedSpaceFromRow(row) {
|
|
3502
|
+
const [spaceId, name, ownerDid, type, permissionsJson, status, registeredAt, updatedAt, expiresAt] = row;
|
|
3503
|
+
return {
|
|
3504
|
+
spaceId,
|
|
3505
|
+
name,
|
|
3506
|
+
ownerDid,
|
|
3507
|
+
type,
|
|
3508
|
+
permissions: JSON.parse(permissionsJson),
|
|
3509
|
+
status,
|
|
3510
|
+
registeredAt: registeredAt ?? void 0,
|
|
3511
|
+
updatedAt,
|
|
3512
|
+
expiresAt: expiresAt ? new Date(expiresAt) : void 0
|
|
3513
|
+
};
|
|
3514
|
+
}
|
|
3515
|
+
function hashJson(value) {
|
|
3516
|
+
const input = stableJson(value);
|
|
3517
|
+
let hash = 0xcbf29ce484222325n;
|
|
3518
|
+
const prime = 0x100000001b3n;
|
|
3519
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
3520
|
+
hash ^= BigInt(input.charCodeAt(index));
|
|
3521
|
+
hash = BigInt.asUintN(64, hash * prime);
|
|
3522
|
+
}
|
|
3523
|
+
return hash.toString(16).padStart(16, "0");
|
|
3524
|
+
}
|
|
3525
|
+
function stableJson(value) {
|
|
3526
|
+
if (value === null || typeof value !== "object") {
|
|
3527
|
+
return JSON.stringify(value);
|
|
3528
|
+
}
|
|
3529
|
+
if (Array.isArray(value)) {
|
|
3530
|
+
return `[${value.map(stableJson).join(",")}]`;
|
|
3531
|
+
}
|
|
3532
|
+
const object = value;
|
|
3533
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableJson(object[key])}`).join(",")}}`;
|
|
3534
|
+
}
|
|
3208
3535
|
function indexedDelegationFromRow(row) {
|
|
3209
3536
|
const [
|
|
3210
3537
|
cid,
|