Backend API и интеграция с hooks
ExtensionBackendHostApis.entityFields
Доступно в ctx.hostApis при backend setup (extension-host.ts):
ts
await ctx.hostApis?.entityFields?.setValues(
'space',
spaceId,
{ 'my-ext.strictMode': 'true' },
{ spaceId }, // optional: для ability check в mutation path
);
const values = await ctx.hostApis?.entityFields?.getValues('artifact', artifactId);
// => Record<string, string>
await ctx.hostApis?.entityFields?.deleteValue('space', spaceId, 'my-ext.strictMode');
await ctx.hostApis?.entityFields?.assertValid('space', {
'my-ext.strictMode': 'true',
});assertValid проверяет: ключ зарегистрирован в registry, maxLength, optional validate() из definition.
Сервисный слой
entity-fields/value.service.ts— CRUD EAVentity-fields/registry.ts—backend.entityFieldsentity-fields/validation.service.ts— assert patch
Entity hooks: поле fields
Runner автоматически подгружает EAV для текущей entity в hook context:
ts
ctx.registerEntityHook('artifact', 'beforeCreate', async (hookCtx) => {
const strict = hookCtx.fields['my-ext.strictMode'] === 'true';
if (strict && !hookCtx.input?.name?.startsWith('REQ-')) {
return {
type: 'abort',
code: 'STRICT_NAME',
message: 'Name must start with REQ-',
};
}
});fields — все ключи для entity, не только поля текущего extension.
Feathers / internal mutations
Предпочтительно hostApis.entityFields из extension setup. Для host-internal кода — setEntityFieldValues / getEntityFieldValues напрямую.
GraphQL read (для UI)
graphql
query {
resolvedEntityFieldValues(entityType: "space", entityId: "…")
}Возвращает [{ key, value }] (JSON array).