[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-jira-chto-takoe-forge-storage-api-i-custom-ui":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":18,"progress":19,"seo":20},1067,"chto-takoe-forge-storage-api-i-custom-ui",27,"jira","Jira","📋","Что такое Forge Storage API и Custom UI?","Forge Storage API — встроенное хранилище данных для Forge-приложений, позволяющее сохранять данные без собственной БД. Custom UI — возможность использовать полноценное React-приложение вместо декларативного UI Kit.\n\n### Типы хранилища\n\n| Тип | Лимит | Назначение |\n|---|---|---|\n| Key-Value (storage) | 32 KB на ключ | Конфигурация, маленькие данные |\n| Entity Storage | 32 KB на entity, queryable | Структурированные данные с поиском |\n| Secrets | 4 KB | Токены, пароли |\n\n### Key-Value Storage\n\n```typescript\nimport { storage } from '@forge\u002Fapi';\n\nawait storage.set('config:PROJ', { enabled: true, maxRetries: 3 });\nconst config = await storage.get('config:PROJ');\nawait storage.delete('config:PROJ');\n\n\u002F\u002F Список ключей (с пагинацией)\nconst result = await storage.query()\n    .where('key', startsWith('config:'))\n    .limit(20)\n    .getMany();\n```\n\n### Entity Storage (структурированное хранилище)\n\n```typescript\n\u002F\u002F Сохранение entity\nawait storage.entity('task-record').set('task-001', {\n    projectKey: 'PROJ',\n    status: 'active',\n    score: 85,\n    createdAt: Date.now()\n});\n\n\u002F\u002F Поиск по атрибутам\nconst activeTasks = await storage.entity('task-record')\n    .query()\n    .index('projectKey')\n    .where('projectKey', 'PROJ')\n    .sort('createdAt', 'DESC')\n    .limit(50)\n    .getMany();\n```\n\n### Custom UI (React-приложение)\n\n```typescript\n\u002F\u002F static\u002Fmy-custom-ui\u002Fsrc\u002FApp.tsx\nimport React, { useEffect, useState } from 'react';\nimport { invoke, view } from '@forge\u002Fbridge';\nimport Button from '@atlaskit\u002Fbutton';\n\nconst App: React.FC = () => {\n    const [details, setDetails] = useState(null);\n\n    useEffect(() => {\n        invoke('getIssueDetails').then(setDetails);\n    }, []);\n\n    return (\n        \u003Cdiv style={{ padding: '16px' }}>\n            \u003Ch3>{details?.summary}\u003C\u002Fh3>\n            \u003Cp>Статус: {details?.status}\u003C\u002Fp>\n            \u003CButton appearance=\"primary\" onClick={() => invoke('saveScore')}>\n                Сохранить\n            \u003C\u002FButton>\n        \u003C\u002Fdiv>\n    );\n};\n```\n\n### Bridge API (@forge\u002Fbridge)\n\n```typescript\nimport { invoke, view, router } from '@forge\u002Fbridge';\n\nconst result = await invoke('functionName', { param1: 'value' });\nconst context = await view.getContext();\nconst issueKey = context.extension.issue.key;\nawait router.navigate('\u002Fbrowse\u002FPROJ-123');\n```\n\n### Частые ошибки\n\n- Хранение большого объёма данных в Storage (>32KB) — ошибка при записи\n- Не использовать Entity Storage для данных, по которым нужен поиск — Key-Value не поддерживает query\n- Не собирать Custom UI перед forge deploy — забыть `npm run build` в static\u002F\n- Прямые вызовы Jira REST API из Custom UI (frontend) — нужно через resolver (backend)\n\n### Как используется в 2026\n\n- Entity Storage стал основным способом хранения данных в Forge\n- Custom UI + Atlaskit — стандарт для сложных UI\n- Forge Remote Backend — позволяет вызывать внешние серверы из Forge\n- Storage API получил улучшенные лимиты и возможности запросов\n\n> **На собеседовании:** разграничьте Key-Value (простое, без поиска) и Entity Storage (с индексами и query). Custom UI даёт полную свободу дизайна через React + Atlaskit, UI Kit проще для стандартных сценариев. Все вызовы API из Custom UI идут через resolver (backend), а не напрямую.","","middle",[15,16,17,7],"jira-forge","jira-cloud","data-persistence",[],null,{"title":21,"description":22,"ogTitle":23,"ogDescription":24,"keywords":25,"schemaAnswer":35,"featuredSnippetReady":36},"Forge Storage API и Custom UI — Gymterview","Forge Storage: Key-Value (32KB), Entity Storage (queryable), Secrets. Custom UI: React + Atlaskit, @forge\u002Fbridge, invoke\u002Fview\u002Frouter. Примеры кода.","Forge Storage API и Custom UI: хранение данных и React UI — Gymterview","Forge Storage: KV (32KB), Entity Storage (с индексами), Secrets. Custom UI: React + Atlaskit через @forge\u002Fbridge.",[26,27,28,29,30,31,32,33,34],"Forge Storage","Entity Storage","Key-Value","Custom UI","Atlaskit","@forge\u002Fbridge","React","Jira Cloud","Forge","Forge Storage — встроенное хранилище без собственной БД: Key-Value (32KB\u002Fключ, простые данные), Entity Storage (32KB\u002Fentity, с индексами и query), Secrets (4KB, зашифрованы). Custom UI — полноценное React-приложение вместо декларативного UI Kit, использует @forge\u002Fbridge (invoke для backend, view.getContext для контекста). Atlaskit — библиотека UI-компонентов Atlassian.",true]