@sanity-labs/client-fake-for-test 0.13.0 → 0.14.0
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/README.md +3 -1
- package/dist/index.cjs +142 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +142 -75
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1183,8 +1183,8 @@ export declare interface TestClientAccessControl {
|
|
|
1183
1183
|
*/
|
|
1184
1184
|
aclPath?: string;
|
|
1185
1185
|
/**
|
|
1186
|
-
* Access API entries, keyed `"<access type>:<id>"` — `"
|
|
1187
|
-
* `"media-library:<id>"`, `"canvas:<id>"`, `"dashboard:<id>"`. See {@link ResourceAccess}.
|
|
1186
|
+
* Access API entries, keyed `"<access type>:<id>"` — `"organization:<id>"`,
|
|
1187
|
+
* `"project:<projectId>"`, `"media-library:<id>"`, `"canvas:<id>"`, `"dashboard:<id>"`. See {@link ResourceAccess}.
|
|
1188
1188
|
*/
|
|
1189
1189
|
access?: Record<string, ResourceAccess>;
|
|
1190
1190
|
}
|
|
@@ -1225,10 +1225,10 @@ export declare interface TestClientIdentity {
|
|
|
1225
1225
|
/** Grants served at the ACL path and enforced on reads/writes. */
|
|
1226
1226
|
grants: Grant[];
|
|
1227
1227
|
/**
|
|
1228
|
-
* Access API entries, keyed `"<access type>:<id>"` (`"
|
|
1229
|
-
* `"
|
|
1230
|
-
* non-
|
|
1231
|
-
* there. Project membership needs no entry: every identity is a member of
|
|
1228
|
+
* Access API entries, keyed `"<access type>:<id>"` (`"organization:<id>"`,
|
|
1229
|
+
* `"media-library:<id>"`, `"canvas:<id>"`, `"dashboard:<id>"`,
|
|
1230
|
+
* `"project:<projectId>"`). On a non-project resource, an entry with
|
|
1231
|
+
* `roles` makes the identity a member there. Project membership needs no entry: every identity is a member of
|
|
1232
1232
|
* every project with its project-scoped roles.
|
|
1233
1233
|
*/
|
|
1234
1234
|
access?: Record<string, ResourceAccess>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1183,8 +1183,8 @@ export declare interface TestClientAccessControl {
|
|
|
1183
1183
|
*/
|
|
1184
1184
|
aclPath?: string;
|
|
1185
1185
|
/**
|
|
1186
|
-
* Access API entries, keyed `"<access type>:<id>"` — `"
|
|
1187
|
-
* `"media-library:<id>"`, `"canvas:<id>"`, `"dashboard:<id>"`. See {@link ResourceAccess}.
|
|
1186
|
+
* Access API entries, keyed `"<access type>:<id>"` — `"organization:<id>"`,
|
|
1187
|
+
* `"project:<projectId>"`, `"media-library:<id>"`, `"canvas:<id>"`, `"dashboard:<id>"`. See {@link ResourceAccess}.
|
|
1188
1188
|
*/
|
|
1189
1189
|
access?: Record<string, ResourceAccess>;
|
|
1190
1190
|
}
|
|
@@ -1225,10 +1225,10 @@ export declare interface TestClientIdentity {
|
|
|
1225
1225
|
/** Grants served at the ACL path and enforced on reads/writes. */
|
|
1226
1226
|
grants: Grant[];
|
|
1227
1227
|
/**
|
|
1228
|
-
* Access API entries, keyed `"<access type>:<id>"` (`"
|
|
1229
|
-
* `"
|
|
1230
|
-
* non-
|
|
1231
|
-
* there. Project membership needs no entry: every identity is a member of
|
|
1228
|
+
* Access API entries, keyed `"<access type>:<id>"` (`"organization:<id>"`,
|
|
1229
|
+
* `"media-library:<id>"`, `"canvas:<id>"`, `"dashboard:<id>"`,
|
|
1230
|
+
* `"project:<projectId>"`). On a non-project resource, an entry with
|
|
1231
|
+
* `roles` makes the identity a member there. Project membership needs no entry: every identity is a member of
|
|
1232
1232
|
* every project with its project-scoped roles.
|
|
1233
1233
|
*/
|
|
1234
1234
|
access?: Record<string, ResourceAccess>;
|
package/dist/index.js
CHANGED
|
@@ -102,7 +102,7 @@ function accessApiError(args) {
|
|
|
102
102
|
...request,
|
|
103
103
|
statusCode,
|
|
104
104
|
statusMessage,
|
|
105
|
-
body: { statusCode, message }
|
|
105
|
+
body: { statusCode, error: statusMessage, message }
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
108
|
const noPermission = (request) => accessApiError({
|
|
@@ -185,14 +185,7 @@ const RESOURCE_CAPABILITIES = {
|
|
|
185
185
|
history: "served",
|
|
186
186
|
actions: "served",
|
|
187
187
|
refusedActions: {},
|
|
188
|
-
access: {
|
|
189
|
-
type: "project",
|
|
190
|
-
id: (id) => datasetParts(id).projectId,
|
|
191
|
-
roles: "served",
|
|
192
|
-
users: "served",
|
|
193
|
-
// Every registered identity is a member of every project, with its project roles.
|
|
194
|
-
memberRoles: ({ identity, id }) => (identity.usersByProject?.[id] ?? identity.user).roles ?? []
|
|
195
|
-
}
|
|
188
|
+
access: { type: "project", id: (id) => datasetParts(id).projectId }
|
|
196
189
|
},
|
|
197
190
|
"media-library": {
|
|
198
191
|
label: (id) => `media library "${id}"`,
|
|
@@ -204,15 +197,7 @@ const RESOURCE_CAPABILITIES = {
|
|
|
204
197
|
history: "served",
|
|
205
198
|
actions: "served",
|
|
206
199
|
refusedActions: { "sanity.action.release.create": releaseLimitExceeded },
|
|
207
|
-
access: {
|
|
208
|
-
type: "media-library",
|
|
209
|
-
id: (id) => id,
|
|
210
|
-
// Unproven on staging (no token held roles read): refused like a missing permission.
|
|
211
|
-
roles: noPermission,
|
|
212
|
-
users: "served",
|
|
213
|
-
unknownId: notFound("Media library"),
|
|
214
|
-
memberRoles: accessEntryRoles("media-library")
|
|
215
|
-
}
|
|
200
|
+
access: { type: "media-library", id: (id) => id }
|
|
216
201
|
},
|
|
217
202
|
canvas: {
|
|
218
203
|
label: (id) => `canvas "${id}"`,
|
|
@@ -224,15 +209,7 @@ const RESOURCE_CAPABILITIES = {
|
|
|
224
209
|
history: "served",
|
|
225
210
|
actions: notMounted,
|
|
226
211
|
refusedActions: {},
|
|
227
|
-
access: {
|
|
228
|
-
type: "canvas",
|
|
229
|
-
id: (id) => id,
|
|
230
|
-
// Unproven on staging (no canvas roles/members permission exists to grant).
|
|
231
|
-
roles: noPermission,
|
|
232
|
-
users: noPermission,
|
|
233
|
-
unknownId: notFound("Canvas"),
|
|
234
|
-
memberRoles: accessEntryRoles("canvas")
|
|
235
|
-
}
|
|
212
|
+
access: { type: "canvas", id: (id) => id }
|
|
236
213
|
},
|
|
237
214
|
dashboard: {
|
|
238
215
|
label: (id) => `dashboard "${id}"`,
|
|
@@ -244,19 +221,11 @@ const RESOURCE_CAPABILITIES = {
|
|
|
244
221
|
history: notMounted,
|
|
245
222
|
actions: notMounted,
|
|
246
223
|
refusedActions: {},
|
|
247
|
-
access: {
|
|
248
|
-
type: "dashboard",
|
|
249
|
-
id: (id) => id,
|
|
250
|
-
// Unproven on staging, as for canvas.
|
|
251
|
-
roles: noPermission,
|
|
252
|
-
users: noPermission,
|
|
253
|
-
unknownId: notFound("Dashboard"),
|
|
254
|
-
memberRoles: accessEntryRoles("dashboard")
|
|
255
|
-
}
|
|
224
|
+
access: { type: "dashboard", id: (id) => id }
|
|
256
225
|
}
|
|
257
226
|
};
|
|
258
227
|
function capabilitiesOf(type) {
|
|
259
|
-
const row = RESOURCE_CAPABILITIES[type];
|
|
228
|
+
const row = Object.hasOwn(RESOURCE_CAPABILITIES, type) ? RESOURCE_CAPABILITIES[type] : void 0;
|
|
260
229
|
if (row === void 0)
|
|
261
230
|
throw fakeError(
|
|
262
231
|
`Unsupported resource type ${JSON.stringify(type)}. The fake serves ${Object.keys(RESOURCE_CAPABILITIES).map((t) => `"${t}"`).join(", ")}.`
|
|
@@ -278,9 +247,76 @@ function matchResourcePath(path) {
|
|
|
278
247
|
return { resource: { type, id: match.id }, rest: match.rest };
|
|
279
248
|
}
|
|
280
249
|
}
|
|
281
|
-
function
|
|
282
|
-
|
|
283
|
-
|
|
250
|
+
function accessResourceOf(resource) {
|
|
251
|
+
const { access } = capabilitiesOf(resource.type);
|
|
252
|
+
return { type: access.type, id: access.id(resource.id) };
|
|
253
|
+
}
|
|
254
|
+
function holdsResource(type) {
|
|
255
|
+
return (registry, id) => registry.resources().some((resource) => {
|
|
256
|
+
const access = accessResourceOf(resource);
|
|
257
|
+
return access.type === type && access.id === id;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
const ACCESS_CAPABILITIES = {
|
|
261
|
+
organization: {
|
|
262
|
+
// Proven on staging, but outside what the fake serves: refused like a missing permission.
|
|
263
|
+
roles: noPermission,
|
|
264
|
+
users: "served",
|
|
265
|
+
user: "served",
|
|
266
|
+
// Granted by the built-in organization `member` role.
|
|
267
|
+
usersPermission: "sanity.organization.members.read",
|
|
268
|
+
unknown: {
|
|
269
|
+
holds: (registry, id) => id === registry.organizationId,
|
|
270
|
+
refusal: notFound("Organization")
|
|
271
|
+
},
|
|
272
|
+
memberRoles: accessEntryRoles("organization"),
|
|
273
|
+
// Every resource of the family belongs to its organization (see `organizationId`).
|
|
274
|
+
owns: (registry) => {
|
|
275
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
276
|
+
for (const resource of registry.resources()) {
|
|
277
|
+
const access = accessResourceOf(resource);
|
|
278
|
+
byKey.set(accessKey(access.type, access.id), access);
|
|
279
|
+
}
|
|
280
|
+
return [...byKey.values()];
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
project: {
|
|
284
|
+
roles: "served",
|
|
285
|
+
users: "served",
|
|
286
|
+
// Single-user reads are served only where the fake checks members read (the
|
|
287
|
+
// organization); elsewhere they refuse rather than answer unchecked.
|
|
288
|
+
user: noPermission,
|
|
289
|
+
// Every registered identity is a member of every project, with its project roles.
|
|
290
|
+
memberRoles: ({ identity, id }) => (identity.usersByProject?.[id] ?? identity.user).roles ?? []
|
|
291
|
+
},
|
|
292
|
+
"media-library": {
|
|
293
|
+
// Unproven on staging (no token held roles read): refused like a missing permission.
|
|
294
|
+
roles: noPermission,
|
|
295
|
+
users: "served",
|
|
296
|
+
// Unproven on staging (only the listing was probed); refused as on `project`.
|
|
297
|
+
user: noPermission,
|
|
298
|
+
unknown: { holds: holdsResource("media-library"), refusal: notFound("Media library") },
|
|
299
|
+
memberRoles: accessEntryRoles("media-library")
|
|
300
|
+
},
|
|
301
|
+
canvas: {
|
|
302
|
+
// Unproven on staging (no canvas roles/members permission exists to grant).
|
|
303
|
+
roles: noPermission,
|
|
304
|
+
users: noPermission,
|
|
305
|
+
user: noPermission,
|
|
306
|
+
unknown: { holds: holdsResource("canvas"), refusal: notFound("Canvas") },
|
|
307
|
+
memberRoles: accessEntryRoles("canvas")
|
|
308
|
+
},
|
|
309
|
+
dashboard: {
|
|
310
|
+
// Unproven on staging, as for canvas.
|
|
311
|
+
roles: noPermission,
|
|
312
|
+
users: noPermission,
|
|
313
|
+
user: noPermission,
|
|
314
|
+
unknown: { holds: holdsResource("dashboard"), refusal: notFound("Dashboard") },
|
|
315
|
+
memberRoles: accessEntryRoles("dashboard")
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
function accessCapabilitiesOf(type) {
|
|
319
|
+
return Object.hasOwn(ACCESS_CAPABILITIES, type) ? ACCESS_CAPABILITIES[type] : void 0;
|
|
284
320
|
}
|
|
285
321
|
function dataUrl(args) {
|
|
286
322
|
const { resource, dataset, operation, path } = args;
|
|
@@ -294,10 +330,14 @@ function dataUrl(args) {
|
|
|
294
330
|
const base = `/${operation}/${dataset}`;
|
|
295
331
|
return `/data${path !== void 0 ? `${base}/${path}` : base}`.replace(/\/($|\?)/, "$1");
|
|
296
332
|
}
|
|
297
|
-
const ACCESS_PATH = /^\/access\/([^/]+)\/([^/]+)(\/.*)?$/, DATA_HISTORY_PATH = /^\/data\/history\/([^/]+)(\/.*)$/;
|
|
333
|
+
const ACCESS_PATH = /^\/access\/([^/]+)\/([^/]+)(\/.*)?$/, ACCESS_USER_PATH = /^\/users\/([^/]+)$/, DATA_HISTORY_PATH = /^\/data\/history\/([^/]+)(\/.*)$/;
|
|
298
334
|
function page(data) {
|
|
299
335
|
return { data, nextCursor: null };
|
|
300
336
|
}
|
|
337
|
+
function usersPage(data) {
|
|
338
|
+
return { ...page(data), totalCount: data.length };
|
|
339
|
+
}
|
|
340
|
+
const UNMODELLED_PROFILE = { provider: "sanity", createdAt: (/* @__PURE__ */ new Date(0)).toISOString() };
|
|
301
341
|
async function servePlatformRequest(ctx, url) {
|
|
302
342
|
const queryStart = url.indexOf("?"), path = queryStart === -1 ? url : url.slice(0, queryStart), query = new URLSearchParams(queryStart === -1 ? "" : url.slice(queryStart + 1)), request = { method: "GET", path }, access = path.match(ACCESS_PATH);
|
|
303
343
|
if (access !== null) {
|
|
@@ -367,20 +407,41 @@ async function readHistory(args) {
|
|
|
367
407
|
};
|
|
368
408
|
}
|
|
369
409
|
function serveAccess(args) {
|
|
370
|
-
const { ctx, request, type, id, rest, query } = args,
|
|
371
|
-
if (
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
410
|
+
const { ctx, request, type, id, rest, query } = args, row = accessCapabilitiesOf(type);
|
|
411
|
+
if (row === void 0) throw invalidAccessType(request, type);
|
|
412
|
+
const resource = { type, id }, registry = {
|
|
413
|
+
organizationId: ctx.organizationId,
|
|
414
|
+
resources: ctx.resources
|
|
415
|
+
}, permissions = ctx.actorAccess()?.[accessKey(resource.type, id)]?.permissions ?? [];
|
|
416
|
+
if (rest === "/user-permissions/me/check") {
|
|
417
|
+
const requested = query.getAll("permissions").flatMap((value) => value.split(","));
|
|
418
|
+
return {
|
|
419
|
+
value: { data: Object.fromEntries(requested.map((p) => [p, permissions.includes(p)])) }
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
if (row.unknown !== void 0 && !row.unknown.holds(registry, id))
|
|
423
|
+
throw row.unknown.refusal(request);
|
|
424
|
+
const users = (capability, serve) => serveCapability(capability, request, () => {
|
|
425
|
+
if (row.usersPermission !== void 0 && !permissions.includes(row.usersPermission))
|
|
426
|
+
throw noPermission(request);
|
|
427
|
+
return serve();
|
|
428
|
+
}), user = rest.match(ACCESS_USER_PATH);
|
|
429
|
+
if (user !== null)
|
|
430
|
+
return users(row.user, () => {
|
|
431
|
+
const sanityUserId = decodeURIComponent(user[1]), record = usersOn({ resource, registry, identities: ctx.identities() }).find(
|
|
432
|
+
(candidate) => candidate.sanityUserId === sanityUserId
|
|
433
|
+
);
|
|
434
|
+
if (record === void 0) throw notFound("User")(request);
|
|
435
|
+
return { value: record };
|
|
436
|
+
});
|
|
376
437
|
switch (rest) {
|
|
377
438
|
case "/roles":
|
|
378
|
-
return serveCapability(
|
|
379
|
-
value: page(rolesOn({
|
|
439
|
+
return serveCapability(row.roles, request, () => ({
|
|
440
|
+
value: page(rolesOn({ resource, identities: ctx.identities() }))
|
|
380
441
|
}));
|
|
381
442
|
case "/users":
|
|
382
|
-
return
|
|
383
|
-
value:
|
|
443
|
+
return users(row.users, () => ({
|
|
444
|
+
value: usersPage(usersOn({ resource, registry, identities: ctx.identities() }))
|
|
384
445
|
}));
|
|
385
446
|
case "/user-permissions/me":
|
|
386
447
|
return {
|
|
@@ -389,58 +450,64 @@ function serveAccess(args) {
|
|
|
389
450
|
const dot = permission.lastIndexOf(".");
|
|
390
451
|
return {
|
|
391
452
|
type: permission.slice(0, dot),
|
|
392
|
-
resourceType:
|
|
453
|
+
resourceType: resource.type,
|
|
393
454
|
resourceId: id,
|
|
394
455
|
action: permission.slice(dot + 1)
|
|
395
456
|
};
|
|
396
457
|
})
|
|
397
458
|
)
|
|
398
459
|
};
|
|
399
|
-
case "/user-permissions/me/check": {
|
|
400
|
-
const requested = query.getAll("permissions").flatMap((value) => value.split(","));
|
|
401
|
-
return {
|
|
402
|
-
value: {
|
|
403
|
-
data: Object.fromEntries(requested.map((p) => [p, permissions.includes(p)]))
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
460
|
default:
|
|
408
461
|
return;
|
|
409
462
|
}
|
|
410
463
|
}
|
|
411
464
|
function rolesOn(args) {
|
|
412
|
-
const byName = /* @__PURE__ */ new Map();
|
|
413
|
-
for (const identity of args.identities)
|
|
414
|
-
|
|
465
|
+
const { resource } = args, byName = /* @__PURE__ */ new Map();
|
|
466
|
+
for (const identity of args.identities) {
|
|
467
|
+
const roles = ACCESS_CAPABILITIES[resource.type].memberRoles({ identity, id: resource.id });
|
|
468
|
+
for (const role of roles ?? [])
|
|
415
469
|
byName.set(role.name, {
|
|
416
470
|
name: role.name,
|
|
417
471
|
...role.title !== void 0 ? { title: role.title } : {},
|
|
418
472
|
...role.description !== void 0 ? { description: role.description } : {}
|
|
419
473
|
});
|
|
474
|
+
}
|
|
420
475
|
return [...byName.values()].toSorted((a, b) => a.name.localeCompare(b.name));
|
|
421
476
|
}
|
|
477
|
+
function membershipOn(identity, resource) {
|
|
478
|
+
const roles = ACCESS_CAPABILITIES[resource.type].memberRoles({ identity, id: resource.id });
|
|
479
|
+
if (roles !== void 0)
|
|
480
|
+
return {
|
|
481
|
+
resourceType: resource.type,
|
|
482
|
+
resourceId: resource.id,
|
|
483
|
+
roleNames: roles.map((role) => role.name).toSorted()
|
|
484
|
+
};
|
|
485
|
+
}
|
|
422
486
|
function usersOn(args) {
|
|
423
|
-
const {
|
|
487
|
+
const { resource, registry, identities } = args, owned = ACCESS_CAPABILITIES[resource.type].owns?.(registry) ?? [], bySanityUserId = /* @__PURE__ */ new Map();
|
|
424
488
|
for (const identity of identities) {
|
|
425
|
-
const
|
|
426
|
-
if (
|
|
489
|
+
const own = membershipOn(identity, resource);
|
|
490
|
+
if (own === void 0) continue;
|
|
427
491
|
const user = identity.globalUser ?? identity.user, record = {
|
|
428
492
|
sanityUserId: user.id,
|
|
429
493
|
profile: {
|
|
494
|
+
id: user.id,
|
|
430
495
|
displayName: user.name ?? user.id,
|
|
431
|
-
|
|
496
|
+
email: user.email ?? "",
|
|
497
|
+
...UNMODELLED_PROFILE
|
|
432
498
|
},
|
|
433
499
|
memberships: [
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
500
|
+
own,
|
|
501
|
+
// A user is part of a resource only through a role on it.
|
|
502
|
+
...owned.flatMap((child) => {
|
|
503
|
+
const membership = membershipOn(identity, child);
|
|
504
|
+
return membership === void 0 || membership.roleNames.length === 0 ? [] : [membership];
|
|
505
|
+
})
|
|
439
506
|
]
|
|
440
507
|
}, existing = bySanityUserId.get(record.sanityUserId);
|
|
441
508
|
if (existing !== void 0 && JSON.stringify(existing) !== JSON.stringify(record))
|
|
442
509
|
throw fakeError(
|
|
443
|
-
`request(): two registered identities resolve to user "${record.sanityUserId}" on ${
|
|
510
|
+
`request(): two registered identities resolve to user "${record.sanityUserId}" on ${resource.type} "${resource.id}" with different records. Fix the identity registrations so duplicate ids carry identical records.`
|
|
444
511
|
);
|
|
445
512
|
bySanityUserId.set(record.sanityUserId, record);
|
|
446
513
|
}
|
|
@@ -602,7 +669,7 @@ function makeRequestImpl(ctx) {
|
|
|
602
669
|
const served = path === void 0 ? void 0 : await servePlatformRequest(platform, path);
|
|
603
670
|
if (served !== void 0) return served.value;
|
|
604
671
|
throw fakeError(
|
|
605
|
-
`request(): no handler for path "${path}". With access control configured, the fake serves "/users/me", the handle's ACL ("<data base>/acl"), "/projects/<projectId>" (members), "/projects/<projectId>/users/<ids>", the History API (client.getDataUrl("history", \u2026)), resource lookup ("/media-libraries/<id>", "/canvases/<id>", "/dashboards/<id>") and the Access API ("/access/<type>/<id>/roles | users | user-permissions/me[/check]"). For any other endpoint, register a stub (client.stub("request", fn)) or intercept the HTTP call with a tool like MSW.`
|
|
672
|
+
`request(): no handler for path "${path}". With access control configured, the fake serves "/users/me", the handle's ACL ("<data base>/acl"), "/projects/<projectId>" (members), "/projects/<projectId>/users/<ids>", the History API (client.getDataUrl("history", \u2026)), resource lookup ("/media-libraries/<id>", "/canvases/<id>", "/dashboards/<id>") and the Access API ("/access/<type>/<id>/roles | users[/<id>] | user-permissions/me[/check]"). For any other endpoint, register a stub (client.stub("request", fn)) or intercept the HTTP call with a tool like MSW.`
|
|
606
673
|
);
|
|
607
674
|
};
|
|
608
675
|
}
|
|
@@ -2033,7 +2100,7 @@ function makeHandle(handleArgs) {
|
|
|
2033
2100
|
} : void 0,
|
|
2034
2101
|
actorAccess: () => requireActiveAccess().access,
|
|
2035
2102
|
identities: () => [...backend.identities.values()],
|
|
2036
|
-
|
|
2103
|
+
resources: () => [...registry.values()].map((entry) => entry.resource)
|
|
2037
2104
|
}
|
|
2038
2105
|
})
|
|
2039
2106
|
} : {},
|