@retailcrm/embed-ui 0.9.16 → 0.9.18
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/CHANGELOG.md +11 -0
- package/package.json +5 -5
- package/.actrc +0 -3
- package/.docker/act/Dockerfile +0 -20
- package/.versionrc.json +0 -12
- package/.yarnrc.dist.yml +0 -15
- package/.yarnrc.yml +0 -15
- package/AGENTS.md +0 -110
- package/ARCHITECTURE.md +0 -143
- package/Makefile +0 -245
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -5899
- package/coverage/coverage-final.json +0 -206
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -1106
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/skills/commit-workflow/SKILL.md +0 -78
- package/skills/local-ci-simulation/SKILL.md +0 -46
- package/skills/local-ci-simulation/agents/openai.yaml +0 -4
- package/skills/sync-remote-host-registry/SKILL.md +0 -62
- package/skills/yarn-lock-conflict-resolution/SKILL.md +0 -76
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
## [0.9.18](https://github.com/retailcrm/embed-ui/compare/v0.9.17...v0.9.18) (2026-04-06)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **v1-components:** Remote root component registry synchronized ([71f89d4](https://github.com/retailcrm/embed-ui/commit/71f89d4bff091c7ef4c9cfff3330d21fe340e45d))
|
|
9
|
+
## [0.9.17](https://github.com/retailcrm/embed-ui/compare/v0.9.16...v0.9.17) (2026-04-06)
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **v1-components:** UiSkeleton loading placeholder added ([635e331](https://github.com/retailcrm/embed-ui/commit/635e331833aa7a4a385553068bfc1d16060f1d3d))
|
|
14
|
+
* **v1-components:** Width modes for UiTextbox and UiSelect added ([895e1fe](https://github.com/retailcrm/embed-ui/commit/895e1febe6bc43329834897f94f57adcfceabd04))
|
|
4
15
|
## [0.9.16](https://github.com/retailcrm/embed-ui/compare/v0.9.15...v0.9.16) (2026-04-05)
|
|
5
16
|
|
|
6
17
|
### Features
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@retailcrm/embed-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.9.
|
|
4
|
+
"version": "0.9.18",
|
|
5
5
|
"description": "API and components for creating RetailCRM UI extensions",
|
|
6
6
|
"repository": "git@github.com:retailcrm/embed-ui.git",
|
|
7
7
|
"author": "RetailDriverLLC <integration@retailcrm.ru>",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"@omnicajs/symfony-router": "^1.0.0",
|
|
43
43
|
"@omnicajs/vue-remote": "^0.2.23",
|
|
44
44
|
"@remote-ui/rpc": "^1.4.5",
|
|
45
|
-
"@retailcrm/embed-ui-v1-components": "^0.9.
|
|
46
|
-
"@retailcrm/embed-ui-v1-contexts": "^0.9.
|
|
47
|
-
"@retailcrm/embed-ui-v1-types": "^0.9.
|
|
45
|
+
"@retailcrm/embed-ui-v1-components": "^0.9.18",
|
|
46
|
+
"@retailcrm/embed-ui-v1-contexts": "^0.9.18",
|
|
47
|
+
"@retailcrm/embed-ui-v1-types": "^0.9.18"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@eslint/eslintrc": "^3.3.3",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@modulify/git-toolkit": "^0.0.2",
|
|
53
53
|
"@modulify/pkg": "^1.0.1",
|
|
54
54
|
"@omnicajs/eslint-plugin-dependencies": "^0.0.2",
|
|
55
|
-
"@retailcrm/embed-ui-v1-testing": "^0.9.
|
|
55
|
+
"@retailcrm/embed-ui-v1-testing": "^0.9.18",
|
|
56
56
|
"@types/git-semver-tags": "^7.0.0",
|
|
57
57
|
"@types/node": "^22.19.2",
|
|
58
58
|
"@types/semver": "^7.7.1",
|
package/.actrc
DELETED
package/.docker/act/Dockerfile
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
FROM ubuntu:24.04
|
|
2
|
-
|
|
3
|
-
ARG DEBIAN_FRONTEND=noninteractive
|
|
4
|
-
ARG TARGETARCH
|
|
5
|
-
|
|
6
|
-
RUN apt-get update \
|
|
7
|
-
&& apt-get install -y --no-install-recommends ca-certificates curl tar git \
|
|
8
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
9
|
-
|
|
10
|
-
RUN set -eu; \
|
|
11
|
-
case "${TARGETARCH}" in \
|
|
12
|
-
amd64) ACT_ARCH="x86_64" ;; \
|
|
13
|
-
arm64) ACT_ARCH="arm64" ;; \
|
|
14
|
-
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
|
|
15
|
-
esac; \
|
|
16
|
-
curl -fsSL "https://github.com/nektos/act/releases/latest/download/act_Linux_${ACT_ARCH}.tar.gz" \
|
|
17
|
-
| tar -xz -C /usr/local/bin act; \
|
|
18
|
-
chmod +x /usr/local/bin/act
|
|
19
|
-
|
|
20
|
-
ENTRYPOINT ["act"]
|
package/.versionrc.json
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"types": [
|
|
3
|
-
{"type": "feat", "section": "Features"},
|
|
4
|
-
{"type": "fix", "section": "Fixes"},
|
|
5
|
-
{"type": "chore", "hidden": true},
|
|
6
|
-
{"type": "docs", "hidden": true},
|
|
7
|
-
{"type": "style", "hidden": true},
|
|
8
|
-
{"type": "refactor", "hidden": true},
|
|
9
|
-
{"type": "perf", "hidden": true},
|
|
10
|
-
{"type": "test", "hidden": true}
|
|
11
|
-
]
|
|
12
|
-
}
|
package/.yarnrc.dist.yml
DELETED
package/.yarnrc.yml
DELETED
package/AGENTS.md
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# AGENTS.md
|
|
2
|
-
|
|
3
|
-
## Goals
|
|
4
|
-
- Avoid clarification loops by proposing a concrete interpretation when details are missing.
|
|
5
|
-
- Default to the language of the user's initial message unless they explicitly request a different language.
|
|
6
|
-
- Match the tone and formality of the user's initial message unless they explicitly ask for a change.
|
|
7
|
-
- Treat a language switch in the user's message as an explicit request to respond in that language.
|
|
8
|
-
- If a message is mixed-language, reply in the dominant language unless the user specifies otherwise.
|
|
9
|
-
|
|
10
|
-
## Purpose
|
|
11
|
-
This file defines practical instructions for working in the `@retailcrm/embed-ui` repository.
|
|
12
|
-
|
|
13
|
-
## Repository Structure
|
|
14
|
-
- This project is a Yarn Workspaces monorepo.
|
|
15
|
-
- Workspace glob: `packages/*`.
|
|
16
|
-
- Current workspace folders:
|
|
17
|
-
- `v1-components`
|
|
18
|
-
- `v1-contexts`
|
|
19
|
-
- `v1-testing`
|
|
20
|
-
- `v1-types`
|
|
21
|
-
- Workspace package names may differ from folder names, but commit scopes in this repository are based on workspace folder names.
|
|
22
|
-
|
|
23
|
-
## Local Environment Prerequisites
|
|
24
|
-
- Yarn version is `4.12.0` (see `packageManager` in `package.json` and `yarnPath` in `.yarnrc.yml`).
|
|
25
|
-
- Package manager mode is `node-modules` (see `.yarnrc.yml`).
|
|
26
|
-
- Local Yarn config is generated from `.yarnrc.dist.yml` using:
|
|
27
|
-
```bash
|
|
28
|
-
make .yarnrc.yml
|
|
29
|
-
```
|
|
30
|
-
- Root install:
|
|
31
|
-
```bash
|
|
32
|
-
yarn install
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Running Checks
|
|
36
|
-
|
|
37
|
-
### Local Path (without Docker)
|
|
38
|
-
- Prepare Yarn config:
|
|
39
|
-
```bash
|
|
40
|
-
make .yarnrc.yml
|
|
41
|
-
```
|
|
42
|
-
- Install dependencies:
|
|
43
|
-
```bash
|
|
44
|
-
yarn install
|
|
45
|
-
```
|
|
46
|
-
- Build all workspaces:
|
|
47
|
-
```bash
|
|
48
|
-
yarn workspaces foreach -A --topological-dev run build
|
|
49
|
-
```
|
|
50
|
-
- Run lint:
|
|
51
|
-
```bash
|
|
52
|
-
yarn eslint
|
|
53
|
-
```
|
|
54
|
-
- Run tests:
|
|
55
|
-
```bash
|
|
56
|
-
yarn test
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Docker Path (Makefile)
|
|
60
|
-
- Install dependencies in container:
|
|
61
|
-
```bash
|
|
62
|
-
make node_modules
|
|
63
|
-
```
|
|
64
|
-
- Build all workspaces:
|
|
65
|
-
```bash
|
|
66
|
-
make build
|
|
67
|
-
```
|
|
68
|
-
- Run tests:
|
|
69
|
-
```bash
|
|
70
|
-
make tests
|
|
71
|
-
```
|
|
72
|
-
- Pass custom Vitest CLI arguments via Makefile:
|
|
73
|
-
```bash
|
|
74
|
-
make tests cli="-t outOfRangeErrorText"
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Related Commands
|
|
78
|
-
- Build root package only:
|
|
79
|
-
```bash
|
|
80
|
-
yarn build
|
|
81
|
-
```
|
|
82
|
-
- Build root code artifacts only:
|
|
83
|
-
```bash
|
|
84
|
-
yarn build:code
|
|
85
|
-
```
|
|
86
|
-
- Build root meta artifacts only:
|
|
87
|
-
```bash
|
|
88
|
-
yarn build:meta
|
|
89
|
-
```
|
|
90
|
-
- Build Storybook for `v1-components`:
|
|
91
|
-
```bash
|
|
92
|
-
yarn workspace @retailcrm/embed-ui-v1-components run storybook:build
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
## Commit Workflow
|
|
96
|
-
- Before creating commits, you must read `skills/commit-workflow/SKILL.md` and follow its rules.
|
|
97
|
-
|
|
98
|
-
## Skills
|
|
99
|
-
- Repository-local skills are available under `skills/`.
|
|
100
|
-
- If a skill conflicts with this file, follow `AGENTS.md`.
|
|
101
|
-
- Current local skills:
|
|
102
|
-
- `skills/commit-workflow/SKILL.md`
|
|
103
|
-
- `skills/sync-remote-host-registry/SKILL.md`
|
|
104
|
-
- `skills/yarn-lock-conflict-resolution/SKILL.md`
|
|
105
|
-
|
|
106
|
-
## Notes
|
|
107
|
-
- Do not assume legacy rules from other repositories (especially `omnica`) apply here.
|
|
108
|
-
- Keep imports grouped by type-only, external, internal alias, and relative blocks, separated from each other and alphabetized within each block: this improves scanability and reduces merge conflicts when multiple PRs add imports to the same file.
|
|
109
|
-
- When resolving lint issues, prefer running `eslint` with `--fix` first to avoid manual import reshuffling and unnecessary reading of repository-specific lint rules.
|
|
110
|
-
- If repository policy is unclear, ask a short clarifying question before making irreversible actions.
|
package/ARCHITECTURE.md
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
# Архитектура `@retailcrm/embed-ui`
|
|
2
|
-
|
|
3
|
-
## 1. Назначение
|
|
4
|
-
|
|
5
|
-
Репозиторий содержит библиотечный слой для JS-расширений RetailCRM:
|
|
6
|
-
|
|
7
|
-
- контракт и транспорт между `remote` (код расширения) и `host` (CRM-страница);
|
|
8
|
-
- UI-компоненты с разделением на remote-описания и host-реализации;
|
|
9
|
-
- реактивные контексты (предопределенные и пользовательские);
|
|
10
|
-
- вспомогательные типы и тестовые утилиты.
|
|
11
|
-
|
|
12
|
-
Ключевая идея: расширение не рендерит «реальный DOM» CRM напрямую.
|
|
13
|
-
Оно отправляет инструкции рендера и вызовов в host-часть через RPC/remote-runtime.
|
|
14
|
-
|
|
15
|
-
## 2. Структура монорепозитория
|
|
16
|
-
|
|
17
|
-
Монорепозиторий на Yarn Workspaces (`packages/*`), Yarn `4.12.0`, linker `node-modules`.
|
|
18
|
-
|
|
19
|
-
### `src/` (корневой пакет `@retailcrm/embed-ui`)
|
|
20
|
-
|
|
21
|
-
- точка входа SDK для расширений;
|
|
22
|
-
- `createWidgetEndpoint(widget, messenger)` поднимает endpoint и lifecycle `run/release`;
|
|
23
|
-
- создает remote-root с whitelist host-компонентов (`createRoot`);
|
|
24
|
-
- подключает Pinia + плагины доступа к контекстам (`injectEndpoint`, `injectAccessor`);
|
|
25
|
-
- экспортирует публичный API контекстов и composables (`useField`, `useCustomField`, `useHost`, `useRouter`).
|
|
26
|
-
|
|
27
|
-
### `packages/v1-components`
|
|
28
|
-
|
|
29
|
-
- UI-библиотека разделена на два entrypoint:
|
|
30
|
-
- `src/host.ts`: host-компоненты для реального рендера в CRM;
|
|
31
|
-
- `src/remote.ts`: remote-компоненты (описания/схемы для передачи в host).
|
|
32
|
-
- Storybook живет здесь и используется как витрина компонентов и сценариев.
|
|
33
|
-
|
|
34
|
-
### `packages/v1-contexts`
|
|
35
|
-
|
|
36
|
-
- слой реактивных контекстов и action-вызовов;
|
|
37
|
-
- `src/host.ts`: сборка host-accessor’ов (`createGetter`, `createSetter`, `createContextAccessor`, `createCustomContextAccessor`) и типизированные ошибки (`HostError`, `LogicalError`, `RuntimeError`);
|
|
38
|
-
- `src/remote.ts`: Pinia-обертки для предопределенных контекстов (`defineContext`) и инвокаций (`defineActions`);
|
|
39
|
-
- `src/remote/custom.ts`: доступ к пользовательским полям и словарям.
|
|
40
|
-
|
|
41
|
-
### `packages/v1-types`
|
|
42
|
-
|
|
43
|
-
- базовые TS-контракты (контексты, поля, отклонения, action-схемы и пр.);
|
|
44
|
-
- используется всеми остальными workspace.
|
|
45
|
-
|
|
46
|
-
### `packages/v1-testing`
|
|
47
|
-
|
|
48
|
-
- тестовые утилиты для runtime-сценариев (RPC/polyfill и хелперы событий).
|
|
49
|
-
|
|
50
|
-
## 3. Runtime-модель host/remote
|
|
51
|
-
|
|
52
|
-
### 3.1 Поток инициализации виджета
|
|
53
|
-
|
|
54
|
-
1. CRM (host) создает `messenger` и вызывает `createWidgetEndpoint(...)` из корневого SDK.
|
|
55
|
-
2. SDK поднимает RPC endpoint и экспортирует методы lifecycle: `run(channel, target)`, `release()`.
|
|
56
|
-
3. При `run(...)` создается remote-root с допустимыми host-компонентами, инициализируется Pinia с endpoint-плагинами контекстов, после чего вызывается `widget.run(createApp, root, pinia, target)`.
|
|
57
|
-
4. При `release()` вызывается destroy-функция виджета и освобождаются RPC-ресурсы.
|
|
58
|
-
|
|
59
|
-
### 3.2 Каналы ответственности
|
|
60
|
-
|
|
61
|
-
- `remote`: бизнес-логика расширения, декларативная сборка UI через remote-компоненты, чтение/запись контекстов через Pinia stores.
|
|
62
|
-
- `host`: фактический рендер, геометрия, DOM, popper/positioning, интерактивность, предоставление данных контекста и invokable-методов (`goTo`, `httpCall`, domain actions).
|
|
63
|
-
|
|
64
|
-
## 4. Архитектура компонентов
|
|
65
|
-
|
|
66
|
-
### 4.1 Общий паттерн
|
|
67
|
-
|
|
68
|
-
Для большинства компонентов сохраняется 1:1 соответствие:
|
|
69
|
-
|
|
70
|
-
- remote-компонент описывает схему и события;
|
|
71
|
-
- host-компонент выполняет фактический рендер.
|
|
72
|
-
|
|
73
|
-
Примеры: `UiButton`, `UiCheckbox`, `UiTooltip`.
|
|
74
|
-
|
|
75
|
-
### 4.2 Важный частный случай: `UiSelect`
|
|
76
|
-
|
|
77
|
-
`UiSelect` — первый явно композиционный пример, где соответствие не 1:1:
|
|
78
|
-
|
|
79
|
-
- remote-слой содержит семейство: `UiSelect`, `UiSelectOption`, `UiSelectOptionGroup`, `UiSelectOptionGroupHeader`;
|
|
80
|
-
- host-рендер опирается на `UiSelectTrigger` + `UiSelectPopper` + menu/popper-примитивы;
|
|
81
|
-
- состояние выбора/фильтрации и регистрация опций координируются через `provide/inject`-ключи.
|
|
82
|
-
|
|
83
|
-
Следствие: host-реестр компонентов должен отражать не только «публичные remote-компоненты», но и необходимые host-примитивы, из которых они фактически собираются.
|
|
84
|
-
|
|
85
|
-
### 4.3 Реестр host-компонентов: что в него входит
|
|
86
|
-
|
|
87
|
-
Реестр в `src/index.ts` должен содержать только те host-компоненты, которые достижимы из remote-схемы рендера.
|
|
88
|
-
|
|
89
|
-
- часть host-компонентов может быть внутренней (не remote-публичной) и потому не обязана попадать в реестр root SDK;
|
|
90
|
-
- обратный случай тоже возможен: один remote-компонент может требовать несколько host-примитивов;
|
|
91
|
-
- пример host-only компонента: `UiToolbar` экспортируется в `v1-components/host`, но не участвует в текущем remote render graph корневого SDK.
|
|
92
|
-
|
|
93
|
-
## 5. Контексты и данные
|
|
94
|
-
|
|
95
|
-
### 5.1 Предопределенные контексты
|
|
96
|
-
|
|
97
|
-
- контекст задается описанием схемы полей;
|
|
98
|
-
- remote-store инициализируется через `endpoint.call.get(context, '~')`;
|
|
99
|
-
- подписки на изменения поля устанавливаются через `endpoint.call.on('change:field', ...)`;
|
|
100
|
-
- запись идет через `endpoint.call.set(...)` с валидацией по schema.
|
|
101
|
-
|
|
102
|
-
### 5.2 Пользовательские контексты (custom fields)
|
|
103
|
-
|
|
104
|
-
- схема контекста запрашивается динамически у host;
|
|
105
|
-
- значения и типы полей становятся известны после `initialize()`;
|
|
106
|
-
- чтение/запись выполняются через `getCustomField/setCustomField`;
|
|
107
|
-
- словари грузятся отдельным каналом `getCustomDictionary`.
|
|
108
|
-
|
|
109
|
-
### 5.3 Ошибки и отклонения
|
|
110
|
-
|
|
111
|
-
- host-часть разделяет логические и runtime-ошибки;
|
|
112
|
-
- remote-часть может получать `Rejection` через callback `onReject`;
|
|
113
|
-
- в composables заданы безопасные обработчики по умолчанию (логирование в `console.error`).
|
|
114
|
-
|
|
115
|
-
## 6. Storybook как архитектурная песочница
|
|
116
|
-
|
|
117
|
-
`packages/v1-components/storybook` выполняет две роли:
|
|
118
|
-
|
|
119
|
-
- документация и интерактивная проверка host-компонентов;
|
|
120
|
-
- демонстрация host/remote-связки (сейчас явно показана в `UiSelect`-истории через worker + endpoint + HostedTree/provider/receiver).
|
|
121
|
-
|
|
122
|
-
Текущее состояние: bridge-механика визуально раскрыта не во всех историях, что усложняет onboarding для новых участников.
|
|
123
|
-
|
|
124
|
-
## 7. Сборка, релиз, CI
|
|
125
|
-
|
|
126
|
-
- сборка корня: `vite build` + генерация meta (`scripts/build.meta.ts`);
|
|
127
|
-
- workspace-сборка в CI: `yarn workspaces foreach -A --topological-dev run build`;
|
|
128
|
-
- тестовый workflow: Node `22.x` и `24.x`, шаги build + eslint + test;
|
|
129
|
-
- release workflow: build/lint/test, bump/release scripts, публикация npm, деплой Storybook (`version` + обновление `latest`).
|
|
130
|
-
|
|
131
|
-
## 8. Дальнейшее развитие качества
|
|
132
|
-
|
|
133
|
-
Следующий этап развития проекта направлен на усиление автоматизированного контроля качества и формализацию ключевых архитектурных инвариантов.
|
|
134
|
-
|
|
135
|
-
## 9. Планы по усилению контроля качества
|
|
136
|
-
|
|
137
|
-
Ближайшие шаги:
|
|
138
|
-
|
|
139
|
-
1. Ввести обязательный typecheck в локальный и CI-пайплайн.
|
|
140
|
-
2. Расширить тесты на ключевые контракты host/remote и на синхронизацию реестров компонентов.
|
|
141
|
-
3. Добавить автоматические проверки целостности render graph (минимум smoke/contract test).
|
|
142
|
-
4. Расширить Storybook-документацию: явно показывать host/remote-binding не только для `UiSelect`.
|
|
143
|
-
5. После стабилизации перейти к автоматизации registry/provider (кодогенерация) как к следующему этапу эволюции.
|
package/Makefile
DELETED
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
.DEFAULT_GOAL := help
|
|
2
|
-
|
|
3
|
-
TARGET_HEADER=@echo -e '===== \e[34m' $@ '\e[0m'
|
|
4
|
-
TARGET_OK=@echo -e '\e[32mOK\e[0m'
|
|
5
|
-
COMPOSE=$(shell if command -v docker-compose >/dev/null 2>&1; then echo "docker-compose"; elif command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then echo "docker compose"; fi)
|
|
6
|
-
YARN=$(COMPOSE) run --rm node yarn
|
|
7
|
-
|
|
8
|
-
.PHONY: .require-compose
|
|
9
|
-
.require-compose:
|
|
10
|
-
@if [ -z "$(COMPOSE)" ]; then \
|
|
11
|
-
echo "docker compose is unavailable (need 'docker compose' or 'docker-compose')"; \
|
|
12
|
-
exit 1; \
|
|
13
|
-
fi
|
|
14
|
-
|
|
15
|
-
.PHONY: .yarnrc.yml
|
|
16
|
-
.yarnrc.yml: ## [Setup][local] Generates yarn configuration
|
|
17
|
-
$(TARGET_HEADER)
|
|
18
|
-
cp .yarnrc.dist.yml .yarnrc.yml
|
|
19
|
-
$(TARGET_OK)
|
|
20
|
-
|
|
21
|
-
.PHONY: node_modules
|
|
22
|
-
node_modules: .require-compose package.json yarn.lock ## [Setup][docker][heavy] Installs dependencies
|
|
23
|
-
$(TARGET_HEADER)
|
|
24
|
-
@$(COMPOSE) run --rm node yarn install --silent
|
|
25
|
-
$(TARGET_OK)
|
|
26
|
-
|
|
27
|
-
.PHONY: build
|
|
28
|
-
build: .require-compose ## [Build][docker][heavy] Builds all workspaces
|
|
29
|
-
$(TARGET_HEADER)
|
|
30
|
-
$(YARN) workspaces foreach -A --topological-dev run build
|
|
31
|
-
$(TARGET_OK)
|
|
32
|
-
|
|
33
|
-
.PHONY: storybook.build
|
|
34
|
-
storybook.build: .require-compose ## [Build][docker][heavy] Builds Storybook for v1-components
|
|
35
|
-
$(TARGET_HEADER)
|
|
36
|
-
$(YARN) workspace @retailcrm/embed-ui-v1-components run storybook:build
|
|
37
|
-
$(TARGET_OK)
|
|
38
|
-
|
|
39
|
-
.PHONY: storybook.serve
|
|
40
|
-
storybook.serve: .require-compose ## [Build][docker] Runs Storybook for v1-components
|
|
41
|
-
$(TARGET_HEADER)
|
|
42
|
-
$(COMPOSE) up v1-components
|
|
43
|
-
|
|
44
|
-
.PHONY: storybook.shot
|
|
45
|
-
storybook.shot: .require-compose ## [Research][docker] Captures a Storybook screenshot for v1-components docs/story page
|
|
46
|
-
$(TARGET_HEADER)
|
|
47
|
-
@$(COMPOSE) up -d v1-components
|
|
48
|
-
@UID=$$(id -u) GID=$$(id -g) $(COMPOSE) run --rm playwright \
|
|
49
|
-
yarn workspace @retailcrm/embed-ui-v1-components run storybook:shot \
|
|
50
|
-
--base-url http://v1-components:6006 \
|
|
51
|
-
--path "$(if $(story_path),$(story_path),/iframe.html?viewMode=docs&id=components-uitable--docs)" \
|
|
52
|
-
--output "$(if $(output),$(output),artifacts/storybook/UiTable.docs.png)" \
|
|
53
|
-
--wait-for-selector "$(if $(wait_for),$(wait_for),#storybook-docs)" \
|
|
54
|
-
--settle-ms "$(if $(settle_ms),$(settle_ms),2500)" \
|
|
55
|
-
--timeout-ms "$(if $(timeout_ms),$(timeout_ms),60000)" \
|
|
56
|
-
--viewport-width "$(if $(viewport_width),$(viewport_width),1600)" \
|
|
57
|
-
--viewport-height "$(if $(viewport_height),$(viewport_height),1600)"
|
|
58
|
-
$(TARGET_OK)
|
|
59
|
-
|
|
60
|
-
.PHONY: prepare
|
|
61
|
-
prepare: .require-compose ## [Build][docker][heavy] Runs prepare in all workspaces
|
|
62
|
-
$(TARGET_HEADER)
|
|
63
|
-
$(YARN) workspaces foreach -A --topological-dev run prepare
|
|
64
|
-
$(TARGET_OK)
|
|
65
|
-
|
|
66
|
-
.PHONY: release
|
|
67
|
-
release: .require-compose ## [Release][docker][heavy][network] Bumps version and creates tag
|
|
68
|
-
$(TARGET_HEADER)
|
|
69
|
-
ifdef as
|
|
70
|
-
$(YARN) release:$(as)
|
|
71
|
-
else
|
|
72
|
-
$(YARN) release
|
|
73
|
-
endif
|
|
74
|
-
$(TARGET_OK)
|
|
75
|
-
|
|
76
|
-
.PHONY: tests
|
|
77
|
-
tests: .require-compose ## [Tests][docker] Runs autotests
|
|
78
|
-
$(TARGET_HEADER)
|
|
79
|
-
ifdef cli
|
|
80
|
-
$(YARN) test $(cli) --passWithNoTests
|
|
81
|
-
else
|
|
82
|
-
$(YARN) test
|
|
83
|
-
endif
|
|
84
|
-
$(TARGET_OK)
|
|
85
|
-
|
|
86
|
-
.PHONY: tests-coverage
|
|
87
|
-
tests-coverage: .require-compose ## [Tests][docker][heavy] Runs autotests with coverage report
|
|
88
|
-
$(TARGET_HEADER)
|
|
89
|
-
ifdef cli
|
|
90
|
-
$(YARN) vitest --run --coverage $(cli) --passWithNoTests
|
|
91
|
-
else
|
|
92
|
-
$(YARN) test:coverage
|
|
93
|
-
endif
|
|
94
|
-
$(TARGET_OK)
|
|
95
|
-
|
|
96
|
-
.PHONY: tests-typecheck-contexts
|
|
97
|
-
tests-typecheck-contexts: .require-compose ## [Tests][docker] Runs typecheck tests (test-d.ts) for v1-contexts
|
|
98
|
-
$(TARGET_HEADER)
|
|
99
|
-
ifdef cli
|
|
100
|
-
$(YARN) vitest run -c packages/v1-contexts/vitest.config.ts --typecheck.only --typecheck.checker tsc --typecheck.tsconfig packages/v1-contexts/tsconfig.json $(cli)
|
|
101
|
-
else
|
|
102
|
-
$(YARN) vitest run -c packages/v1-contexts/vitest.config.ts --typecheck.only --typecheck.checker tsc --typecheck.tsconfig packages/v1-contexts/tsconfig.json
|
|
103
|
-
endif
|
|
104
|
-
$(TARGET_OK)
|
|
105
|
-
|
|
106
|
-
.PHONY: tests-typecheck-v1-contexts
|
|
107
|
-
tests-typecheck-v1-contexts: tests-typecheck-contexts ## [Tests][alias] Alias for tests-typecheck-contexts
|
|
108
|
-
|
|
109
|
-
.PHONY: tests-typecheck
|
|
110
|
-
tests-typecheck: tests-typecheck-contexts ## [Tests][alias] Runs typecheck tests (currently v1-contexts)
|
|
111
|
-
|
|
112
|
-
.PHONY: ci-actionlint
|
|
113
|
-
ci-actionlint: ## [CI][docker] Lints GitHub Actions workflows locally (actionlint binary or docker image)
|
|
114
|
-
$(TARGET_HEADER)
|
|
115
|
-
@if command -v actionlint >/dev/null 2>&1; then \
|
|
116
|
-
actionlint; \
|
|
117
|
-
elif [ -n "$(COMPOSE)" ]; then \
|
|
118
|
-
$(COMPOSE) run --rm actionlint; \
|
|
119
|
-
elif command -v docker >/dev/null 2>&1; then \
|
|
120
|
-
docker run --rm -v "$$(pwd):/repo" -w /repo rhysd/actionlint:latest; \
|
|
121
|
-
else \
|
|
122
|
-
echo "actionlint is not installed and docker/docker-compose is unavailable"; \
|
|
123
|
-
exit 1; \
|
|
124
|
-
fi
|
|
125
|
-
$(TARGET_OK)
|
|
126
|
-
|
|
127
|
-
.PHONY: ci-act-plan
|
|
128
|
-
ci-act-plan: ## [CI][docker] Shows act execution plan for tests workflow without running jobs
|
|
129
|
-
$(TARGET_HEADER)
|
|
130
|
-
@if command -v act >/dev/null 2>&1; then \
|
|
131
|
-
act -n pull_request -W .github/workflows/tests.yml; \
|
|
132
|
-
elif [ -n "$(COMPOSE)" ]; then \
|
|
133
|
-
$(COMPOSE) run --rm --build act -n pull_request -W .github/workflows/tests.yml; \
|
|
134
|
-
else \
|
|
135
|
-
echo "act is not installed and docker compose is unavailable"; \
|
|
136
|
-
exit 1; \
|
|
137
|
-
fi
|
|
138
|
-
$(TARGET_OK)
|
|
139
|
-
|
|
140
|
-
.PHONY: ci-act-tests
|
|
141
|
-
ci-act-tests: ## [CI][docker][heavy][network] Runs tests workflow locally via act
|
|
142
|
-
$(TARGET_HEADER)
|
|
143
|
-
@if command -v act >/dev/null 2>&1; then \
|
|
144
|
-
act pull_request -W .github/workflows/tests.yml -j workflow-lint -j eslint -j tests; \
|
|
145
|
-
elif [ -n "$(COMPOSE)" ]; then \
|
|
146
|
-
$(COMPOSE) run --rm --build act pull_request -W .github/workflows/tests.yml -j workflow-lint -j eslint -j tests; \
|
|
147
|
-
else \
|
|
148
|
-
echo "act is not installed and docker compose is unavailable"; \
|
|
149
|
-
exit 1; \
|
|
150
|
-
fi
|
|
151
|
-
$(TARGET_OK)
|
|
152
|
-
|
|
153
|
-
.PHONY: help
|
|
154
|
-
help: ## [General] Shows grouped command help
|
|
155
|
-
@set -eu; \
|
|
156
|
-
if [ -t 1 ] && [ -z "$${CI:-}" ] && [ -z "$${NO_COLOR:-}" ]; then \
|
|
157
|
-
C_HEAD="$$(printf '\033[1;36m')"; \
|
|
158
|
-
C_TGT="$$(printf '\033[36m')"; \
|
|
159
|
-
C_TAG="$$(printf '\033[33m')"; \
|
|
160
|
-
C_WARN="$$(printf '\033[33m')"; \
|
|
161
|
-
C_RST="$$(printf '\033[0m')"; \
|
|
162
|
-
else \
|
|
163
|
-
C_HEAD=''; C_TGT=''; C_TAG=''; C_WARN=''; C_RST=''; \
|
|
164
|
-
fi; \
|
|
165
|
-
FILTER="$$(printf '%s' "$(value filter)" | tr '[:upper:]' '[:lower:]')"; \
|
|
166
|
-
SHOW_INTERNAL="$(value show_internal)"; \
|
|
167
|
-
awk -v filter="$$FILTER" -v show_internal="$$SHOW_INTERNAL" '\
|
|
168
|
-
function trim(s){ sub(/^[ \t\r\n]+/, "", s); sub(/[ \t\r\n]+$$/, "", s); return s } \
|
|
169
|
-
function group_order(g){ \
|
|
170
|
-
if (g=="General") return 1; \
|
|
171
|
-
if (g=="Setup") return 2; \
|
|
172
|
-
if (g=="Build") return 3; \
|
|
173
|
-
if (g=="Tests") return 4; \
|
|
174
|
-
if (g=="CI") return 5; \
|
|
175
|
-
if (g=="Release") return 6; \
|
|
176
|
-
return 99; \
|
|
177
|
-
} \
|
|
178
|
-
/^[a-zA-Z0-9_.-]+:.*##[[:space:]]+/ { \
|
|
179
|
-
target = $$1; sub(/:.*/, "", target); \
|
|
180
|
-
if (show_internal != "1" && target ~ /^\./) next; \
|
|
181
|
-
desc = $$0; sub(/^.*##[[:space:]]*/, "", desc); \
|
|
182
|
-
group = "Other"; tags = ""; \
|
|
183
|
-
if (match(desc, /^\[[^]]+\]/)) { \
|
|
184
|
-
group = substr(desc, 2, RLENGTH - 2); \
|
|
185
|
-
desc = substr(desc, RLENGTH + 1); \
|
|
186
|
-
} \
|
|
187
|
-
while (match(desc, /^[[:space:]]*\[[^]]+\]/)) { \
|
|
188
|
-
sub(/^[[:space:]]*/, "", desc); \
|
|
189
|
-
rb = index(desc, "]"); \
|
|
190
|
-
if (rb == 0) break; \
|
|
191
|
-
tags = tags "[" substr(desc, 2, rb - 2) "]"; \
|
|
192
|
-
desc = substr(desc, rb + 1); \
|
|
193
|
-
} \
|
|
194
|
-
desc = trim(desc); \
|
|
195
|
-
hay = tolower(target " " group " " tags " " desc); \
|
|
196
|
-
if (filter != "" && index(hay, filter) == 0) next; \
|
|
197
|
-
printf "%02d\t%s\t%s\t%s\t%s\n", group_order(group), group, target, tags, desc; \
|
|
198
|
-
} \
|
|
199
|
-
' $(MAKEFILE_LIST) \
|
|
200
|
-
| sort -t "$$(printf '\t')" -k1,1n -k3,3 \
|
|
201
|
-
| awk -F '\t' -v c_head="$$C_HEAD" -v c_tgt="$$C_TGT" -v c_tag="$$C_TAG" -v c_rst="$$C_RST" '\
|
|
202
|
-
BEGIN { current = ""; count = 0 } \
|
|
203
|
-
{ \
|
|
204
|
-
if ($$2 != current) { \
|
|
205
|
-
if (current != "") print ""; \
|
|
206
|
-
printf "%s%s%s\n", c_head, $$2, c_rst; \
|
|
207
|
-
current = $$2; \
|
|
208
|
-
} \
|
|
209
|
-
printf " %s%-30s%s %s", c_tgt, $$3, c_rst, $$5; \
|
|
210
|
-
if ($$4 != "") printf " %s%s%s", c_tag, $$4, c_rst; \
|
|
211
|
-
printf "\n"; \
|
|
212
|
-
count++; \
|
|
213
|
-
} \
|
|
214
|
-
END { if (count == 0) print "No targets matched the current filter." }'; \
|
|
215
|
-
echo ""; \
|
|
216
|
-
printf "%sQuick Start%s\n" "$$C_HEAD" "$$C_RST"; \
|
|
217
|
-
printf " make ci-actionlint\n"; \
|
|
218
|
-
printf " make tests\n"; \
|
|
219
|
-
printf " make tests-coverage\n"; \
|
|
220
|
-
printf " make ci-act-plan\n"; \
|
|
221
|
-
echo ""; \
|
|
222
|
-
printf "%sExamples%s\n" "$$C_HEAD" "$$C_RST"; \
|
|
223
|
-
printf " make help filter=ci\n"; \
|
|
224
|
-
printf " make help show_internal=1\n"; \
|
|
225
|
-
printf " make tests cli='tests/scenarios/customer/phone.test.ts'\n"; \
|
|
226
|
-
printf " make release as=beta\n"; \
|
|
227
|
-
dup_targets="$$(awk -F: '/^[a-zA-Z0-9_.-]+:/ && $$1 != ".PHONY" {print $$1}' $(MAKEFILE_LIST) | sort | uniq -d | tr '\n' ' ')"; \
|
|
228
|
-
dup_phony="$$(awk '/^\.PHONY:[[:space:]]*/ {for (i=2; i<=NF; i++) print $$i}' $(MAKEFILE_LIST) | sort | uniq -d | tr '\n' ' ')"; \
|
|
229
|
-
if [ -n "$$dup_targets$$dup_phony" ]; then \
|
|
230
|
-
echo ""; \
|
|
231
|
-
printf "%sWarnings%s\n" "$$C_WARN" "$$C_RST"; \
|
|
232
|
-
if [ -n "$$dup_targets" ]; then printf " duplicate targets: %s\n" "$$dup_targets"; fi; \
|
|
233
|
-
if [ -n "$$dup_phony" ]; then printf " duplicate .PHONY entries: %s\n" "$$dup_phony"; fi; \
|
|
234
|
-
fi
|
|
235
|
-
|
|
236
|
-
# Colors
|
|
237
|
-
$(call computable,CC_BLACK,$(shell tput -Txterm setaf 0 2>/dev/null))
|
|
238
|
-
$(call computable,CC_RED,$(shell tput -Txterm setaf 1 2>/dev/null))
|
|
239
|
-
$(call computable,CC_GREEN,$(shell tput -Txterm setaf 2 2>/dev/null))
|
|
240
|
-
$(call computable,CC_YELLOW,$(shell tput -Txterm setaf 3 2>/dev/null))
|
|
241
|
-
$(call computable,CC_BLUE,$(shell tput -Txterm setaf 4 2>/dev/null))
|
|
242
|
-
$(call computable,CC_MAGENTA,$(shell tput -Txterm setaf 5 2>/dev/null))
|
|
243
|
-
$(call computable,CC_CYAN,$(shell tput -Txterm setaf 6 2>/dev/null))
|
|
244
|
-
$(call computable,CC_WHITE,$(shell tput -Txterm setaf 7 2>/dev/null))
|
|
245
|
-
$(call computable,CC_END,$(shell tput -Txterm sgr0 2>/dev/null))
|