Преминете към основното съдържание

Конвенции

Работен процес с Git​

  • Push само към main. Правете къмити директно в main; без функционални клонове (feature branches) и без pull request-и.
  • Conventional commits: feat: …, fix: …, docs: …, feat(agent): …, fix(api): ….
  • Всеки push към main се разгръща в продукция (Непрекъснато разгръщане), а промените в entrosity-axis-agent/, entrosity-axis-connector/ или entrosity-shared-go/ също доставят dev изграждане до агентите (Издания на агента).
  • Всяка промяна в кода обновява тази документация в същия къмит (Писане на документация).

Генериране на код​

Генерираният код се къмитва:

  • entrosity-axis.backend/internal/db/gen/ (sqlc),
  • entrosity-axis.backend/internal/http/gen/ (oapi-codegen),
  • src/api/schema.d.ts във всяко приложение (openapi-typescript, от къмитнатата моментна снимка api/openapi.yaml),
  • src/routeTree.gen.ts във всяко приложение (TanStack Router).

Никога не ги редактирайте. Променете .sql заявката, миграцията или entrosity-axis.backend/api/openapi.yaml и изпълнете make gen.

  • Добавете заявка в entrosity-axis.backend/db/queries/<domain>.sql със заглавен ред като -- name: ListDevicesByTenant :many.
  • Добавете крайна точка (endpoint) в openapi.yaml първо; обработчикът имплементира генерирания интерфейс. След това добавете правилото ѝ за достъп в entrosity-axis.backend/internal/http/portal/access.go и ред в теста на RBAC матрицата.

Go​

  • Стандартна структура с пакети в internal/; грешките се обвиват с %w; sentinel грешки за всеки домейн (device.ErrNotFound); контексти навсякъде; без глобално състояние освен конфигурацията.
  • Код, използван от повече от един сървър (бекенда на Axis и Entrosity Hub), се намира в модула shared, без достъп до база данни: entrosity-shared-go/apperr (грешки на домейна), entrosity-shared-go/reqctx (IP адрес на клиента, user agent, ID на заявката), entrosity-shared-go/secretbox (AES-GCM тайни в покой с ротация на ключове), entrosity-shared-go/authkit (argon2id пароли, политика за пароли, непрозрачни токени, помощни функции за TOTP, QR кодове) и entrosity-shared-go/mailkit (SMTP и рендиране на шаблони). Всеки сървър има собствена база данни, миграции и шаблони за имейли.
  • Обработчиците превеждат грешките на домейна в problem+json на едно място (internal/http/errors.go); грешките на домейна носят стабилен код (apperr.New(kind, "code", "message"), entrosity-shared-go/apperr). Новите кодове се добавят в Кодове на грешки.
  • Всеки метод на хранилище (repository), ограничен до тенант, приема tenantID като първи аргумент след ctx.
  • Всяко извикване на услуга, което променя данни, записва одитен запис в същата транзакция.

Портал​

  • Папки по функционалност: src/features/<feature>/{api.ts, keys.ts, components/}; ключовете на заявките са в keys.ts за всяка функционалност.
  • Без any. Формите използват react-hook-form + zod. Loader-ите на маршрутите зареждат данни предварително с queryClient.ensureQueryData.
  • Стилизиране: само utility класове на Tailwind, без вграден style, без CSS освен токените на темата.
  • Графиките използват компонента за графики на shadcn/ui (@entrosity/ui/chart: ChartContainer, ChartTooltip + ChartTooltipContent, ChartLegend + ChartLegendContent) около примитивите на Recharts. Всяка серия се декларира в ChartConfig с етикета и цвета си и се рисува с var(--color-<key>). Цветовете идват от цветовете на темата chart-1 … chart-10 чрез chartColor(i) (src/lib/chart.ts), така че графиките следват светлия и тъмния режим. Ключовете на сериите трябва да са валидни CSS идентификатори (буквите на дискове като C: получават безопасен ключ).
  • Споделеният UI се намира в entrosity-ui (@entrosity/ui) и се използва от всяко уеб приложение: примитивите на shadcn/ui (@entrosity/ui/button, …), споделените компоненти (@entrosity/ui/components/DataTable, BrandLogo, ConfirmDialog, PageHeader, …), cn() (@entrosity/ui/lib/utils), дизайн токените (@entrosity/ui/tokens.css, импортирани от src/index.css на приложението) и Tailwind preset-ът. Добавете компонент там, когато второ приложение се нуждае от него; компонентите, специфични за продукта, остават в приложението. Неговият README обяснява как се добавя примитив на shadcn/ui.
  • Състоянията се показват с @entrosity/ui/components/StatusBadge: една таблица (statusTones) дава цвета на всяко състояние (good: зелено, busy: синьо, warning: кехлибарено, bad: червено, neutral: сиво), приложението подава преведения етикет, а tone променя цвета, където състоянието означава друго. Новите състояния се добавят в statusTones, не като цветове в приложението.
  • Заглавната лента на всяко приложение има @entrosity/ui/components/BackButton, свързан с useCanGoBack() и router.history.back() на рутера.
  • Всеки видим за потребителя текст е преведен (английски, по подразбиране, и български). Текстовете са в пакети със съобщения до кода (src/features/<feature>/messages.ts), създадени с defineMessages({ en, bg }) от @entrosity/ui/lib/i18n; българската таблица трябва да има точно английските ключове, така че липсващ превод проваля проверката на типовете. Компонентите ги четат с useT(bundle) (@entrosity/ui/components/LocaleProvider), останалият код – с translate(bundle, key) в момента на извикване, никога при зареждане на модула. Множественото число използва key_one / key_other с числово count. Датите и числата минават през помощните функции в src/lib/format.ts, които следват езика на интерфейса. Терминологията следва българската документация. Изборът на език се пази в localStorage (entrosity.locale), общ за Hub и Axis; превключването монтира страницата наново.
  • Брандиране: знакът на Entrosity и името на продукта „Entrosity Axis“ (src/lib/brand.ts: словесната марка е „Entrosity“ плюс приглушено „Axis“); основен цвят — виолетовото на Entrosity #7b35f5 (акценти #4c17b8). Уеб приложенията и този сайт използват ръчно рисувания вид по-долу.

Ръчно рисуван вид (Ink & Strata)​

Всяко уеб приложение (сайтът, Hub, Axis, Edge, Matrix, Sphere) и този сайт с документация следват графиката на марката: сива хартия, неравни черни мастилени контури с неправилни ъгли, виолетови пластове от вълни, които навлизат от ъглите, драсканици # и //// и мек отблясък. @entrosity/ui (0.6.0 и по-нови) го реализира; приложенията само избират класовете и компонентите.

Токени (tokens.css, HSL тройки, използвани като hsl(var(--ink)); също цветовете на Tailwind ink и wave-1 … wave-6):

ТокенЗначение
--background, --cardХартията и по-светлата хартия на панелите
--inkЦветът на рисуваните контури (почти черен; тебешир в тъмния режим)
--shadow-inkТвърдите изместени сенки (мастило; тъмновиолетово в тъмния режим)
--wave-1 … --wave-6Пластовете, от 1 най-наситен до 6 най-блед
--wave-highlightСветлите щрихи върху вълните
--glareМекият кръгъл отблясък върху хартията

Тъмният режим е „мастило във виолетова нощ“: виолетово-черна хартия (#120d1f), тебеширено мастило и по-тъмни пластове. Шрифтът е Geist Variable. shadow-sm … shadow-xl на Tailwind са твърди мастилени отмествания (shadow е 3px 3px 0), никога размазани.

Класове (sketch.css):

КласУпотреба
sketchНеравен мастилен контур, рисуван от ::before; запазете класа border на елемента (прозрачен, за оформлението). Прави елемента position: relative
sketch-sm, sketch-lgНабори ъгли за малки контроли и етикети и за големи панели
sketch-doubleВтора, по-бледа изместена линия (::after) за карти и диалози
sketch-fieldПолета, текстови области и падащи списъци: истинска мастилена рамка 1,5px с неправилните ъгли
sketch-shapeСамо неправилните ъгли, за запълване при посочване и избор и за блокове с код
sketch-edge-r, -l, -t, -bЕдин ръчно начертан мастилен ръб (странични ленти, заглавни ленти); линия във фона, затова остава на превъртащи се панели
sketch-panelИстинска ръчно начертана мастилена рамка за панели, които се превъртат (диалози)
sketch-underlineРъчно рисувана вълнообразна линия под текст; sketch-underline-primary я рисува във виолетово, sketch-underline-hover я показва само при посочване и фокус
hatch-grid, hatch-tallyДрасканиците # и //// в цвета на мастилото
paperФонът на страницата: хартия плюс отблясъка

Компоненти:

  • SketchWaves (@entrosity/ui/components/SketchWaves): пластовете от ъгъл, corner="tr|tl|br|bl", bands 3–6, highlights. Запълва кутията, която му дава className, и е декоративен (aria-hidden).
  • HatchMark: една драсканица, variant="grid|tally", с размер и място от className.
  • SketchFrame: графиката като контейнер (хартия, двоен контур, вълни в горния десен и долния ляв ъгъл, драсканици) за страниците за вход и заглавни секции; waves="sm|md|lg", hatches, contentClassName.
  • SketchDefs: SVG филтрите, които правят контурите неравни; поставя и sketch-ready на <html>, което включва неравността (без него контурите са прави). ThemeProvider го монтира; монтирайте го сами само без ThemeProvider.
  • BrandLogo с underline рисува ръчната линия под словесната марка.
  • SketchIllustration (0.7.0): малки илюстрации в стила на рисунката, name="empty|not-found|error|search|devices|shield|camera|network|done"; декоративни, освен ако имат title.
  • EmptyState (0.7.0): илюстрация, заглавие, описание и действие за празни списъци, липса на резултати и страници 404; compact в карти.
  • DatePicker (@entrosity/ui/date-picker, 0.7.0): ръчно начертан календар в изскачащ панел, с withTime за дата и час. Чете и записва същите низове като <input type="date"> и type="datetime-local" и ги заменя във всички приложения. Обикновените полета type="time" остават стандартни.
  • Графиките в ChartContainer са начертани в същия стил (баровете и секторите с мастилен контур, неравни линии, молив за мрежата); палитрата започва с виолетовото на пластовете (--chart-1), после зелено, кехлибарено, синьо и червено.

Button, Card, Dialog, Sheet, Popover, DropdownMenu, Select, Tabs, Tooltip, Toast, Badge, StatusBadge, Table, DataTable, PageHeader и контролите на формите от библиотеката вече използват този вид.

Правила:

  • Никога не слагайте sketch на <input>, <textarea>, <select> или <img>: те не могат да имат ::before. За полетата използвайте sketch-field; изображенията оставете или очертайте контейнера им.
  • Не комбинирайте sketch, sketch-field или sketch-shape с rounded-*: utility класът заменя неправилните ъгли. Кръглите точки (rounded-full) остават както са.
  • Сенките са твърди мастилени отмествания (shadow-sm, shadow, …); не добавяйте размазани или цветни сенки.
  • Панелите, писани на ръка, са sketch border … (sketch-double за големи карти, sketch-sm за етикети), не rounded-md border ….
  • Всяка страница работи от 320px ширина нагоре: без хоризонтално превъртане на страницата, широките таблици се превъртат в собствената си кутия, филтрите и формите се подреждат един под друг на телефон, мрежите минават на една колона, диалозите се побират на екрана и се превъртат отвътре.
  • Празните списъци, липсата на резултати и страниците 404 използват EmptyState; полетата за дата използват DatePicker.
  • Филтърът за неравни линии се включва изрично (sketch-wobble, @entrosity/ui 0.7.2) и само за единични елементи като SketchFrame: SVG филтър върху всеки контрол, графика или ред от списък се преизчислява при всяко прерисуване и забавя натоварените страници. По същата причина без backdrop-blur на залепващи заглавни ленти.
  • Вълните и драсканиците са украса: без текст върху вълните без плътен фон, и запазете пръстените на фокуса. В режим с висок контраст на Windows рисуваното мастило се скрива и се показват обикновени рамки.
  • Този сайт копира токените и правилата в src/css/custom.css и филтрите в src/theme/Root.tsx (не зависи от @entrosity/ui); вълните на началната страница са static/img/waves.svg и waves-dark.svg. Поддържайте ги в съответствие с библиотеката.