@reformer/builder 3.0.0-beta.6 → 3.0.0-beta.8
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 +32 -198
- package/bin/reformer-builder.d.mts +7 -9
- package/bin/reformer-builder.mjs +43 -54
- package/dist/assets/css/index-CHjtwIsF.css +1 -0
- package/dist/assets/css/monaco-runtime-Ch4loDnq.css +1 -0
- package/dist/assets/i18n/en-uNov8AYL.js +1 -0
- package/dist/assets/i18n/ru-BNkTKaU6.js +1 -0
- package/dist/assets/js/index-C4LjLCAZ.js +57 -0
- package/dist/assets/monaco/html-DT-eqvPn.js +1 -0
- package/dist/assets/monaco/javascript-CIJHG94Q.js +1 -0
- package/dist/assets/monaco/jsonMode-rEmNPnut.js +12 -0
- package/dist/assets/monaco/monaco-runtime-Dqtu7Dpv.js +924 -0
- package/dist/assets/monaco/typescript-Bp6doald.js +1 -0
- package/dist/assets/monaco/xml-D8D5UF1F.js +1 -0
- package/dist/assets/monaco/yaml-DsiyZy1w.js +1 -0
- package/dist/assets/plugins/ai-CFoGZBd-.js +178 -0
- package/dist/assets/{byok-D0ncJaTq.js → plugins/ai-byok-a7JlkizL.js} +55 -55
- package/dist/assets/plugins/ai-knowledge-docs-BcbN7Ar1.js +1 -0
- package/dist/assets/plugins/ai-knowledge-index-CncxmxEf.js +1 -0
- package/dist/assets/plugins/codegen-DPh2ynzq.js +520 -0
- package/dist/assets/{MarkdownPreview-DXY3eJ1Z.js → plugins/editor-markdown-MarkdownPreview-CjVpNIV5.js} +20 -20
- package/dist/assets/plugins/editor-markdown-McTrLzET.js +2 -0
- package/dist/assets/plugins/editor-monaco-7BM478IS.js +14 -0
- package/dist/assets/plugins/editor-schema-DOoRcy16.js +4 -0
- package/dist/assets/plugins/files-WhQya3nC.js +2 -0
- package/dist/assets/plugins/plain-4ISpXJVh.js +78 -0
- package/dist/assets/plugins/plugin-manager-Ek0Ph0Jj.js +1 -0
- package/dist/assets/plugins/preview-BSh_puVw.js +1 -0
- package/dist/assets/plugins/preview-runtime-B8NzDg53.js +3 -0
- package/dist/assets/plugins/templates-BE9B0S3J.js +2 -0
- package/dist/assets/vendor/ajv-N5zGp_lm.js +8 -0
- package/dist/assets/vendor/calendar-base-BW48REpD-BYc4qqRC.js +1 -0
- package/dist/assets/vendor/carousel-BDyy29mt.js +1 -0
- package/dist/assets/vendor/chart-Cbp9J5YJ.js +52 -0
- package/dist/assets/vendor/collapsible-base-DZxAKbAF-DtQ4867U.js +1 -0
- package/dist/assets/vendor/drawer-BdLrIIeu.js +3 -0
- package/dist/assets/vendor/highlight.js/common-B96EybDa.js +5 -0
- package/dist/assets/vendor/index-BTAoX623.js +6 -0
- package/dist/assets/vendor/index-D8ACoUqy.js +51 -0
- package/dist/assets/vendor/input-otp-BoPlZ6dt.js +20 -0
- package/dist/assets/vendor/lucide-react/arrow-left-BlVPt6Ag.js +1 -0
- package/dist/assets/vendor/lucide-react/arrow-right-I5ntlq0-.js +1 -0
- package/dist/assets/vendor/lucide-react/calendar-L-57WZlQ.js +1 -0
- package/dist/assets/vendor/lucide-react/eye-DVTIIHcH.js +1 -0
- package/dist/assets/vendor/lucide-react/file-code-corner-DUfMS_yi.js +1 -0
- package/dist/assets/vendor/lucide-react/folder-tree-COyCkaDl.js +1 -0
- package/dist/assets/vendor/lucide-react/minus-zJRYKuAo.js +1 -0
- package/dist/assets/vendor/lucide-react/plus-B0WG2JcM.js +1 -0
- package/dist/assets/vendor/lucide-react/rotate-ccw-BSYk0mux.js +1 -0
- package/dist/assets/vendor/lucide-react/wrench-mybFdWHD.js +1 -0
- package/dist/assets/vendor/message-base-B5jT1FuY-BvDKjuSs.js +1 -0
- package/dist/assets/vendor/message-scroller-B2tlOtxT.js +1 -0
- package/dist/assets/vendor/reformer-builder-stack-reformer/node-token-VfZdCqcs.js +1 -0
- package/dist/assets/vendor/reformer-builder-stack-reformer/paths-DeGLVPUt.js +1 -0
- package/dist/assets/vendor/reformer-builder-stack-reformer/rules-CQSVDlmo.js +1 -0
- package/dist/assets/vendor/reformer-builder-stack-reformer/selectors-CjNSFsK9.js +1 -0
- package/dist/assets/vendor/reformer-builder-toolkit/marker-DiOaKX-e.js +4 -0
- package/dist/assets/vendor/reformer-builder-toolkit/naming-9aaM0Wbc.js +1 -0
- package/dist/assets/vendor/reformer-cdk/define-steps-CyGUrx9p-vcI1WbRz.js +1 -0
- package/dist/assets/vendor/reformer-cdk/file-upload-D8FOieMN.js +1 -0
- package/dist/assets/vendor/reformer-cdk/form-array-DlFEb40E.js +1 -0
- package/dist/assets/vendor/reformer-cdk/form-wizard-DDLs_-Ya.js +1 -0
- package/dist/assets/vendor/reformer-cdk/index-CeCSv2Go.js +1 -0
- package/dist/assets/vendor/reformer-cdk/list-DkqJWU70.js +1 -0
- package/dist/assets/vendor/reformer-form-registry/index-DflpiFcm.js +1 -0
- package/dist/assets/vendor/reformer-form-registry/loader-BK2c_fCA-BtIEWzon.js +2 -0
- package/dist/assets/vendor/reformer-form-registry/react-BiEQRau3.js +1 -0
- package/dist/assets/vendor/reformer-form-registry/storage-BbhnRE7V.js +1 -0
- package/dist/assets/vendor/reformer-form-registry/types-DoMH_n1U-BSN9tyeo.js +1 -0
- package/dist/assets/vendor/reformer-renderer-json/validate-DXzHWMfT.js +8 -0
- package/dist/assets/vendor/reformer-ui-kit/alert-base-WOl_V-qI-2ZIfaT1o.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/calendar-Bm2DDJDU.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/calendar-base.props-CqesU7CZ-tpDaVQbq.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/combobox-Dm4bFCVg.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/combobox-tree.props-BEQhnapq-DQmsBcYk.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/component-catalog-BEv0Zf-R.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/date-picker-CkVXt6Uh.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/date-picker-base.props-WBloFrDq-QhVYMCMG.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/input-otp-base.props-D1xRJiuO-DBKxHsz1.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/meta-YyKXxsBK.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/sidebar-CMzt3bAb.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/skeleton-base-C-lIzi0D-BjmjAmE9.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/toggle-group-multi.props-7kNpujN6-jLENMOcN.js +1 -0
- package/dist/assets/vendor/reformer-ui-kit/tree-node-schema-xHyN0QCr-CLbM_Aw_.js +1 -0
- package/dist/assets/vendor/render-DutGx1TC.js +46 -0
- package/dist/assets/vendor/sheet-base-Bdh947IC-CH2UsjIt.js +1 -0
- package/dist/assets/{typescript-BuFxP6n6.js → vendor/typescript/typescript-BejA4q8A.js} +1 -1
- package/dist/index.html +4 -4
- package/package.json +19 -18
- package/runtime-config.schema.json +32 -53
- package/dist/assets/App-DRJnHAjE.js +0 -1137
- package/dist/assets/BootError-CiPUX-Tr.js +0 -1
- package/dist/assets/ChatPanel-CnU7eT8N.js +0 -82
- package/dist/assets/CodeEditor-Wv0NRzV8.js +0 -1
- package/dist/assets/RawJsonEditor-c354H_pY.js +0 -1
- package/dist/assets/abap-DLDM7-KI.js +0 -1
- package/dist/assets/apex-DNDY2TF8.js +0 -1
- package/dist/assets/azcli-Y6nb8tq_.js +0 -1
- package/dist/assets/bat-BwHxbl9M.js +0 -1
- package/dist/assets/bicep-CFznDFnq.js +0 -2
- package/dist/assets/boot-5_JU0zay.js +0 -2
- package/dist/assets/cameligo-Bf6VGUru.js +0 -1
- package/dist/assets/clojure-Dnu-v4kV.js +0 -1
- package/dist/assets/coffee-Bd8akH9Z.js +0 -1
- package/dist/assets/cpp-BbWJElDN.js +0 -1
- package/dist/assets/csharp-Co3qMtFm.js +0 -1
- package/dist/assets/csp-D-4FJmMZ.js +0 -1
- package/dist/assets/cypher-cTPe9QuQ.js +0 -1
- package/dist/assets/dart-BOtBlQCF.js +0 -1
- package/dist/assets/dockerfile-BG73LgW2.js +0 -1
- package/dist/assets/ecl-BEgZUVRK.js +0 -1
- package/dist/assets/editor-BzOv8av-.css +0 -1
- package/dist/assets/editor.api-CMCnIB-P.js +0 -865
- package/dist/assets/elixir-BkW5O-1t.js +0 -1
- package/dist/assets/flow9-BeJ5waoc.js +0 -1
- package/dist/assets/freemarker2-C645vQBx.js +0 -3
- package/dist/assets/fsharp-PahG7c26.js +0 -1
- package/dist/assets/go-acbASCJo.js +0 -1
- package/dist/assets/graphql-BxJiqAUM.js +0 -1
- package/dist/assets/handlebars-B5DnoJkq.js +0 -1
- package/dist/assets/hcl-DtV1sZF8.js +0 -1
- package/dist/assets/html-TNLrm0oH.js +0 -1
- package/dist/assets/index--0tYkbnz.js +0 -3
- package/dist/assets/index-BKc-soqk.css +0 -1
- package/dist/assets/index-BLGbxQaR.js +0 -104
- package/dist/assets/index-Bb-H-IRh.js +0 -1
- package/dist/assets/index-BivFj4xA.js +0 -10
- package/dist/assets/index-C_YSTVSM.js +0 -68
- package/dist/assets/index-Crsub4wy.js +0 -5028
- package/dist/assets/index-D2vdVqoN.js +0 -11
- package/dist/assets/index-DBBur3Kg.js +0 -4709
- package/dist/assets/index-DzAasWzr.css +0 -1
- package/dist/assets/ini-Kd9XrMLS.js +0 -1
- package/dist/assets/java-CXBNlu9o.js +0 -1
- package/dist/assets/javascript-YmJoSFNK.js +0 -1
- package/dist/assets/jsonMode-BgHFRVOe.css +0 -1
- package/dist/assets/jsonMode-CUyarZ9Q.js +0 -70
- package/dist/assets/julia-cl7-CwDS.js +0 -1
- package/dist/assets/kotlin-s7OhZKlX.js +0 -1
- package/dist/assets/less-9HpZscsL.js +0 -2
- package/dist/assets/lexon-OrD6JF1K.js +0 -1
- package/dist/assets/liquid-CsrVJLkL.js +0 -1
- package/dist/assets/load-DahhU28W.js +0 -11
- package/dist/assets/lua-Cyyb5UIc.js +0 -1
- package/dist/assets/m3-B8OfTtLu.js +0 -1
- package/dist/assets/mdx-DDXJg3VI.js +0 -1
- package/dist/assets/mips-CiqrrVzr.js +0 -1
- package/dist/assets/monaco-languages-CfiXabIS.js +0 -2
- package/dist/assets/monaco-setup-DPehMZ7o.js +0 -12
- package/dist/assets/msdax-DmeGPVcC.js +0 -1
- package/dist/assets/mysql-C_tMU-Nz.js +0 -1
- package/dist/assets/objective-c-BDtDVThU.js +0 -1
- package/dist/assets/pascal-vHIfCaH5.js +0 -1
- package/dist/assets/pascaligo-DtZ0uQbO.js +0 -1
- package/dist/assets/perl-Ub6l9XKa.js +0 -1
- package/dist/assets/pgsql-BlNEE0v7.js +0 -1
- package/dist/assets/php-BBUBE1dy.js +0 -1
- package/dist/assets/pla-DSh2-awV.js +0 -1
- package/dist/assets/postiats-CocnycG-.js +0 -1
- package/dist/assets/powerquery-tScXyioY.js +0 -1
- package/dist/assets/powershell-COWaemsV.js +0 -1
- package/dist/assets/protobuf-Brw8urJB.js +0 -2
- package/dist/assets/pug-8SOpv6rk.js +0 -1
- package/dist/assets/python-DpnOD9VM.js +0 -1
- package/dist/assets/qsharp-Bw9ernYp.js +0 -1
- package/dist/assets/r-j7ic8hl3.js +0 -1
- package/dist/assets/razor-BsF1GcFZ.js +0 -1
- package/dist/assets/redis-Bu5POkcn.js +0 -1
- package/dist/assets/redshift-Bs9aos_-.js +0 -1
- package/dist/assets/reformer-ui-kit-11-Bml4F8Os.js +0 -1
- package/dist/assets/reformer-ui-kit-BWUaVvO0.js +0 -1
- package/dist/assets/restructuredtext-CqXO7rUv.js +0 -1
- package/dist/assets/ruby-zBfavPgS.js +0 -1
- package/dist/assets/rust-BzKRNQWT.js +0 -1
- package/dist/assets/sb-BBc9UKZt.js +0 -1
- package/dist/assets/scala-D9hQfWCl.js +0 -1
- package/dist/assets/scheme-BPhDTwHR.js +0 -1
- package/dist/assets/scss-CBJaRo0y.js +0 -3
- package/dist/assets/shell-DiJ1NA_G.js +0 -1
- package/dist/assets/solidity-Db0IVjzk.js +0 -1
- package/dist/assets/sophia-CnS9iZB_.js +0 -1
- package/dist/assets/sparql-CJmd_6j2.js +0 -1
- package/dist/assets/sql-ClhHkBeG.js +0 -1
- package/dist/assets/st-CHwy0fLd.js +0 -1
- package/dist/assets/swift-CnmFD0ga.js +0 -1
- package/dist/assets/systemverilog-Bs9z6M-B.js +0 -1
- package/dist/assets/tcl-Dm6ycUr_.js +0 -1
- package/dist/assets/twig-Csy3S7wG.js +0 -1
- package/dist/assets/typescript-D7ER-DvA.js +0 -1
- package/dist/assets/typespec-Btyra-wh.js +0 -1
- package/dist/assets/useFormField-BLbvmpme-CM4hze15.js +0 -1
- package/dist/assets/vb-Db0cS2oM.js +0 -1
- package/dist/assets/wgsl-BTesnYfV.js +0 -298
- package/dist/assets/xml-5MzZ4-DY.js +0 -1
- package/dist/assets/yaml-Ch0E2rII.js +0 -1
- /package/dist/assets/{codicon-Brq4_Ui5.ttf → fonts/codicon-Brq4_Ui5.ttf} +0 -0
- /package/dist/assets/{css-DdJfP1eB.js → monaco/css-DdJfP1eB.js} +0 -0
- /package/dist/assets/{editor.worker-CRaYpIdo.js → monaco/editor.worker-CRaYpIdo.js} +0 -0
- /package/dist/assets/{json.worker-C5PEkLU0.js → monaco/json.worker-C5PEkLU0.js} +0 -0
- /package/dist/assets/{markdown-BFxVWTOG.js → monaco/markdown-BFxVWTOG.js} +0 -0
package/README.md
CHANGED
|
@@ -1,219 +1,53 @@
|
|
|
1
1
|
# @reformer/builder
|
|
2
2
|
|
|
3
|
-
Визуальный
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
## Установка
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm i -D @reformer/builder
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
> До первого стабильного релиза устанавливайте beta-канал: `npm i -D @reformer/builder@develop`.
|
|
3
|
+
Визуальный конструктор форм ReFormer. Пакет несёт уже собранный офлайн-SPA
|
|
4
|
+
в `dist/` и zero-dependency лаунчер: `npx reformer-builder` поднимает локальный сервер
|
|
5
|
+
и открывает браузер. Серверной логики нет — файлы проекта билдер читает и пишет прямо
|
|
6
|
+
из браузера через File System Access API (нужен Chromium: Chrome/Edge/Arc/Brave).
|
|
15
7
|
|
|
16
8
|
## Запуск
|
|
17
9
|
|
|
18
10
|
```bash
|
|
19
|
-
npx reformer-builder
|
|
20
|
-
npx reformer-builder --port 5000
|
|
21
|
-
npx reformer-builder --no-open # не открывать браузер автоматически
|
|
22
|
-
|
|
23
|
-
# локальная кастомизация клиента: свой каталог компонентов и/или конфиг билдера
|
|
24
|
-
npx reformer-builder --catalog ./component-catalog.json --config ./reformer-builder.config.json
|
|
11
|
+
npx reformer-builder [--port 4321] [--host 127.0.0.1] [--no-open] [--config <path>]
|
|
25
12
|
```
|
|
26
13
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```json
|
|
30
|
-
{
|
|
31
|
-
"scripts": {
|
|
32
|
-
"builder": "reformer-builder"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
npm run builder
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
### Опции CLI
|
|
42
|
-
|
|
43
|
-
| Опция | По умолчанию | Описание |
|
|
44
|
-
| ------------------ | ------------ | --------------------------------------------------- |
|
|
45
|
-
| `-p, --port <n>` | `4321` | Порт (если занят — берётся следующий свободный) |
|
|
46
|
-
| `--host <h>` | `127.0.0.1` | Хост |
|
|
47
|
-
| `--no-open` | — | Не открывать браузер автоматически |
|
|
48
|
-
| `--catalog <path>` | — | JSON-каталог компонентов (замещает вшитый) |
|
|
49
|
-
| `--config <path>` | — | JSON-конфиг билдера (палитра, UI, брендинг, проект) |
|
|
50
|
-
| `-h, --help` | — | Справка |
|
|
51
|
-
| `-v, --version` | — | Версия |
|
|
52
|
-
|
|
53
|
-
Без `--catalog`/`--config` билдер пытается подхватить `component-catalog.json` и
|
|
54
|
-
`reformer-builder.config.json` из текущей папки; если их нет — работает на вшитых дефолтах.
|
|
55
|
-
|
|
56
|
-
## Режимы работы
|
|
57
|
-
|
|
58
|
-
- **Mode B (основной)** — открыть папку своего проекта прямо в браузере, найти в ней JSON-схемы форм,
|
|
59
|
-
редактировать их визуально и записывать обратно в исходники (dev-сервер подхватит изменения через HMR).
|
|
60
|
-
Использует **File System Access API**, поэтому работает **только в Chromium-браузерах** (Chrome, Edge,
|
|
61
|
-
Arc, Brave).
|
|
62
|
-
- **Mode A** — создать новую схему с нуля и выгрузить/скопировать JSON или сгенерированный код.
|
|
63
|
-
|
|
64
|
-
## Ассистент
|
|
65
|
-
|
|
66
|
-
Ассистент живёт в правой панели наравне с инспектором: вкладки «Свойства» и «Ассистент» на правом
|
|
67
|
-
рейле переключают зону, `⌘/Ctrl+Shift+K` открывает ассистента, `⌥⌘B` сворачивает зону целиком.
|
|
68
|
-
Он правит форму по описанию на обычном языке: «добавь email», «сделай телефон обязательным»,
|
|
69
|
-
«поставь имя и фамилию в одну строку».
|
|
14
|
+
## Конфигурация — каталог `.ui_builder/`
|
|
70
15
|
|
|
71
|
-
|
|
16
|
+
Один конвенционный каталог на два момента чтения:
|
|
72
17
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
18
|
+
| Что | Где | Когда читается |
|
|
19
|
+
| -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `config.json` — брендинг, дефолты UI | каталог запуска (`--config` переопределяет) | лаунчером при старте |
|
|
21
|
+
| `config.json` | открытый проект | при каждом открытии проекта; перекрывает уровень запуска по полю (`defaults` действуют только на уровне запуска) |
|
|
22
|
+
| `plugins/<id>/` — плагины: `manifest.json`, `main.js` (собранный) или `main.ts` (в разработке — транспиляция на лету, авто-перезагрузка по правке) | открытый проект | при открытии; включение — явное действие человека |
|
|
23
|
+
| `templates/<slug>/` — шаблоны форм | открытый проект | службой шаблонов |
|
|
24
|
+
| `codegen/*.eta` — свои цели генерации | открытый проект | плагином кодогенерации |
|
|
80
25
|
|
|
81
|
-
|
|
26
|
+
Запустили `npx reformer-builder` в корне проекта и его же открыли — вся конфигурация
|
|
27
|
+
в одном `.ui_builder/`, без дублей.
|
|
82
28
|
|
|
83
|
-
|
|
29
|
+
`config.json` (все секции опциональны; `$schema` даёт автодополнение в IDE):
|
|
84
30
|
|
|
85
|
-
|
|
86
|
-
| ---------------------------- | ------------------------------- | --------------- |
|
|
87
|
-
| Anthropic | напрямую из браузера | ваш |
|
|
88
|
-
| OpenAI | напрямую из браузера | ваш |
|
|
89
|
-
| Локальный OpenAI-совместимый | `localhost` (Ollama, LM Studio) | обычно не нужен |
|
|
90
|
-
|
|
91
|
-
Список моделей запрашивается у провайдера — вшитого списка нет, устаревать нечему.
|
|
92
|
-
|
|
93
|
-
**О безопасности честно.** В облачных каналах запрос идёт из браузера напрямую к провайдеру, и ключ
|
|
94
|
-
доступен странице. Это приемлемо для локального инструмента с вашим собственным ключом (Anthropic
|
|
95
|
-
описывает такой сценарий явно — отсюда заголовок `anthropic-dangerous-direct-browser-access`), но
|
|
96
|
-
для публичного стенда — нет. Используйте ключ с ограниченным бюджетом. Для Ollama потребуется
|
|
97
|
-
разрешить обращение со страницы: `OLLAMA_ORIGINS`.
|
|
98
|
-
|
|
99
|
-
**Содержимое формы — данные, а не команды.** Подписи и тексты внутри схемы могут содержать текст,
|
|
100
|
-
похожий на инструкцию агенту; ассистент их не исполняет.
|
|
101
|
-
|
|
102
|
-
Без настроенного канала панель объясняет, чего не хватает, а остальной редактор работает как
|
|
103
|
-
обычно. Ни SDK, ни сама панель не попадают в первый чанк: за ассистента не платит размером тот,
|
|
104
|
-
кто им не пользуется.
|
|
105
|
-
|
|
106
|
-
## Шаблоны форм
|
|
107
|
-
|
|
108
|
-
Новая форма создаётся из **шаблона** — набора файлов с плейсхолдерами вместо имени формы. Панель
|
|
109
|
-
«Шаблоны» в левом сайдбаре показывает все доступные шаблоны, генерация — ПКМ в дереве файлов →
|
|
110
|
-
«Сгенерировать → Выбрать шаблон…» (имя формы, шаблон и какие его файлы создать).
|
|
111
|
-
|
|
112
|
-
Три источника шаблонов:
|
|
113
|
-
|
|
114
|
-
- **встроенные** — «Простая форма» (одна страница полей) и «Пошаговая форма» (визард на два шага с
|
|
115
|
-
адаптером к ui-kit `FormWizard`). Оба дают полный набор: модель, схема, валидация, поведение формы
|
|
116
|
-
и UI, реестр, страница-компонент — она тянет остальные файлы, без них не соберётся;
|
|
117
|
-
- **проект** — папки в `.reformer/templates/<slug>/` (каталог переопределяется
|
|
118
|
-
`project.templatesDir`). Обычные файлы + `template.json` с именем и описанием: шаблон едет в git,
|
|
119
|
-
правится руками в IDE и работает у всей команды;
|
|
120
|
-
- **локальный** — сохранённый в IndexedDB браузера, доступен и без открытого проекта.
|
|
121
|
-
|
|
122
|
-
Свой шаблон делается из готовой формы: выделить её файлы в дереве (⌘/Ctrl+клик — добавить к выбору,
|
|
123
|
-
⇧+клик — диапазон) → ПКМ → «Создать шаблон…». Имя формы-источника (базовое имя) заменяется
|
|
124
|
-
плейсхолдерами во всех написаниях, чтобы при генерации подставлялось имя новой формы:
|
|
125
|
-
|
|
126
|
-
| Плейсхолдер | Форма `user-profile` |
|
|
127
|
-
| --------------- | -------------------- |
|
|
128
|
-
| `__FormName__` | `UserProfile` |
|
|
129
|
-
| `__formName__` | `userProfile` |
|
|
130
|
-
| `__form-name__` | `user-profile` |
|
|
131
|
-
| `__form_name__` | `user_profile` |
|
|
132
|
-
|
|
133
|
-
Плейсхолдеры работают и в именах файлов (`__form-name__.css`), поэтому шаблон переживает любое имя
|
|
134
|
-
новой формы. Бинарные файлы (картинки, шрифты) в шаблон не попадают.
|
|
135
|
-
|
|
136
|
-
## Каталог компонентов (`@reformer/ui-kit/catalog`)
|
|
137
|
-
|
|
138
|
-
Палитра билдера строится из **каталога компонентов** `@reformer/ui-kit` — это
|
|
139
|
-
сгенерированный JSON-файл (`component-catalog.json`), который `@reformer/ui-kit` отдаёт
|
|
140
|
-
через subpath-экспорт `@reformer/ui-kit/catalog`. Для каждого компонента в нём описаны имя,
|
|
141
|
-
роль (поле / контейнер / массив) и JSON-схема props — из этого билдер собирает список
|
|
142
|
-
доступных компонентов и инспектор свойств.
|
|
143
|
-
|
|
144
|
-
Каталог **вшивается в бандл на этапе сборки** билдера (Vite инлайнит импорт
|
|
145
|
-
`@reformer/ui-kit/catalog`), поэтому опубликованный `@reformer/builder` самодостаточен и
|
|
146
|
-
показывает набор компонентов той версии `@reformer/ui-kit`, с которой был собран. Этот вшитый
|
|
147
|
-
каталог можно **переопределить при локальном старте** флагом `--catalog` (см. ниже) — без
|
|
148
|
-
пересборки билдера.
|
|
149
|
-
|
|
150
|
-
`@reformer/ui-kit` — не единственный вариант: билдер держит несколько китов и версий, активный
|
|
151
|
-
выбирается в переключателе тулбара. Как подключить свой кит — другую версию, форк или стороннюю
|
|
152
|
-
дизайн-систему — см. [docs/instructions/add-ui-kit.md](docs/instructions/add-ui-kit.md).
|
|
153
|
-
|
|
154
|
-
## Локальная кастомизация (`--catalog` / `--config`)
|
|
155
|
-
|
|
156
|
-
Клиент может передать при локальном старте два JSON-файла — они читаются launcher'ом и
|
|
157
|
-
применяются в браузере на бутстрапе. Оба **опциональны**: если файла нет — берутся встроенные
|
|
158
|
-
дефолты (билдер стартует и работает как обычно). Если переданный файл невалиден — билдер
|
|
159
|
-
показывает экран с ошибкой валидации (не запускается с частичной конфигурацией).
|
|
160
|
-
|
|
161
|
-
- **`--catalog <path>`** — JSON-каталог компонентов по тому же контракту, что
|
|
162
|
-
`@reformer/ui-kit/catalog` (`{ version, components: [{ name, role, propsSchema, category? }] }`).
|
|
163
|
-
Замещает вшитый каталог: палитра и инспектор строятся из него.
|
|
164
|
-
- **`--config <path>`** — конфиг поведения самого билдера. Все секции опциональны:
|
|
165
|
-
|
|
166
|
-
```jsonc
|
|
31
|
+
```json
|
|
167
32
|
{
|
|
168
33
|
"$schema": "./node_modules/@reformer/builder/runtime-config.schema.json",
|
|
169
|
-
"
|
|
170
|
-
|
|
171
|
-
"branding": {
|
|
172
|
-
"productName": "Acme Forms",
|
|
173
|
-
"title": "Acme Builder",
|
|
174
|
-
"logoUrl": "data:image/svg+xml;...",
|
|
175
|
-
},
|
|
176
|
-
// Палитра: категории, порядок разделов, свёрнутые по умолчанию, глифы-бейджи
|
|
177
|
-
"palette": {
|
|
178
|
-
"categoryByName": { "AcmeRating": "Поля ввода" },
|
|
179
|
-
"order": ["Поля ввода", "Выбор и переключатели", "Контейнеры", "Действия"],
|
|
180
|
-
"collapsedByDefault": ["HTML", "Типографика"],
|
|
181
|
-
"glyphs": { "AcmeRating": "Ar" },
|
|
182
|
-
},
|
|
183
|
-
// Доступные компоненты: whitelist/blacklist + тоглы синтетических записей билдера
|
|
184
|
-
"components": {
|
|
185
|
-
"exclude": ["Chart", "Carousel"],
|
|
186
|
-
"synthetic": {
|
|
187
|
-
"html": true,
|
|
188
|
-
"htmlTags": ["div", "section", "fieldset"],
|
|
189
|
-
"formArray": true,
|
|
190
|
-
"wizard": false,
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
// Дефолты интерфейса при старте
|
|
194
|
-
"ui": { "theme": "light", "leftPanel": "palette", "rightOpen": true, "preview": "wire" },
|
|
195
|
-
// Работа с проектом (Mode B discovery), каталог шаблонов + стартовая схема Mode A (null — пустая форма)
|
|
196
|
-
"project": {
|
|
197
|
-
"ignoreDirs": ["fixtures"],
|
|
198
|
-
"templatesDir": ".reformer/templates",
|
|
199
|
-
"seedSchema": null,
|
|
200
|
-
},
|
|
34
|
+
"branding": { "title": "Формы Acme" },
|
|
35
|
+
"defaults": { "locale": "ru", "theme": "system" }
|
|
201
36
|
}
|
|
202
37
|
```
|
|
203
38
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
встроенные; `palette.order`, `palette.collapsedByDefault`, `components.*`, `ui.*`, `branding.*` —
|
|
207
|
-
**замещают** дефолт, если заданы. JSON Schema контракта конфига публикуется в пакете как
|
|
208
|
-
`@reformer/builder/runtime-config.schema.json` (для автодополнения в редакторе через `$schema`).
|
|
39
|
+
Сторонний ui-kit встраивается плагином (плагин привозит и каталог компонентов, и код),
|
|
40
|
+
а не файлом данных — механизм в работе.
|
|
209
41
|
|
|
210
|
-
|
|
211
|
-
> резолвился у внешних потребителей, `component-catalog.json` обязан входить в поле `files`
|
|
212
|
-
> пакета `@reformer/ui-kit` — иначе файла нет в npm-тарболе и импорт падает. Для самого
|
|
213
|
-
> билдера это некритично (каталог уже вшит в его `dist`), но важно для CI-проверки
|
|
214
|
-
> `check:subpaths` и для любых Node-ESM-потребителей этого subpath (импортировать JSON в
|
|
215
|
-
> Node ESM нужно с атрибутом `with { type: 'json' }`).
|
|
42
|
+
## Отличия от 2.x
|
|
216
43
|
|
|
217
|
-
|
|
44
|
+
Версия 3 — переписанный билдер, и контракт запуска у него другой:
|
|
218
45
|
|
|
219
|
-
|
|
46
|
+
- **флага `--catalog` больше нет.** Сторонний ui-kit подключается плагином из
|
|
47
|
+
`.ui_builder/plugins/`: плагин привозит и каталог компонентов, и их код — файлом данных
|
|
48
|
+
превью нечем рисовать;
|
|
49
|
+
- **конфиг переехал** из `reformer-builder.config.json` рядом с запуском в
|
|
50
|
+
`.ui_builder/config.json` (или `--config <path>`), и в нём остались брендинг и дефолты UI:
|
|
51
|
+
палитра, набор компонентов и раскладка настраиваются плагинами;
|
|
52
|
+
- **битый конфиг больше не роняет билдер**: приложение открывается, а каждая проблема
|
|
53
|
+
называется в уведомлении.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Типы для тестируемых экспортов
|
|
3
|
-
* деклараций).
|
|
2
|
+
* Типы для тестируемых экспортов лаунчера (`reformer-builder.mjs` — zero-dependency JS без
|
|
3
|
+
* деклараций). Позволяют `.ts`-тестам импортировать хелперы без implicit-any (TS7016).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
export interface LauncherOpts {
|
|
@@ -9,24 +9,22 @@ export interface LauncherOpts {
|
|
|
9
9
|
open: boolean;
|
|
10
10
|
help: boolean;
|
|
11
11
|
version: boolean;
|
|
12
|
-
/** Путь к
|
|
13
|
-
catalog: string | null;
|
|
14
|
-
/** Путь к конфигу билдера (`--config`) или `null` (авто-детект в cwd). */
|
|
12
|
+
/** Путь к конфигу билдера (`--config`) или `null` (авто-детект `.ui_builder/config.json` в cwd). */
|
|
15
13
|
config: string | null;
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
export interface RuntimeBundleResult {
|
|
19
|
-
payload: {
|
|
20
|
-
sources: {
|
|
17
|
+
payload: { config: unknown };
|
|
18
|
+
sources: { config: string | null };
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
/** URL раздачи
|
|
21
|
+
/** URL раздачи конфига запуска. */
|
|
24
22
|
export const RUNTIME_BUNDLE_URL: string;
|
|
25
23
|
|
|
26
24
|
export function parseArgs(argv: string[]): LauncherOpts;
|
|
27
25
|
|
|
28
26
|
export function loadRuntimeBundle(
|
|
29
|
-
opts: {
|
|
27
|
+
opts: { config: string | null },
|
|
30
28
|
cwd: string
|
|
31
29
|
): Promise<RuntimeBundleResult>;
|
|
32
30
|
|
package/bin/reformer-builder.mjs
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* reformer-builder — локальный запуск визуального билдера ReFormer
|
|
3
|
+
* reformer-builder — локальный запуск визуального билдера ReFormer.
|
|
4
4
|
*
|
|
5
|
-
* Опубликованный пакет несёт УЖЕ собранный SPA в `dist
|
|
6
|
-
*
|
|
7
|
-
* поднимает `dist/` на localhost и открывает браузер. Серверной
|
|
8
|
-
* файлами проекта идёт в браузере через File System Access
|
|
5
|
+
* Опубликованный пакет несёт УЖЕ собранный SPA в `dist/`. Этот скрипт — zero-dependency
|
|
6
|
+
* статик-сервер на встроенных модулях Node (перенесён из первой версии билдера, она же
|
|
7
|
+
* в истории git): поднимает `dist/` на localhost и открывает браузер. Серверной
|
|
8
|
+
* логики у билдера нет — вся работа с файлами проекта идёт в браузере через File System Access
|
|
9
|
+
* (нужен Chromium-браузер).
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Конфигурация уровня запуска — ОДИН файл: конфиг билдера (брендинг, дефолты UI). Launcher
|
|
12
|
+
* читает его с диска и отдаёт SPA по `/__reformer-builder/runtime.json`; без флага `--config`
|
|
13
|
+
* пытается авто-подхватить `<cwd>/.ui_builder/config.json` — тот же конвенционный каталог,
|
|
14
|
+
* в котором живут плагины, шаблоны и цели кодогена открытого проекта. Частый случай «запустил
|
|
15
|
+
* в корне проекта и его же открыл» даёт один каталог конфигурации без дублей.
|
|
16
|
+
*
|
|
17
|
+
* Каталога компонентов (`--catalog` первой версии) здесь НЕТ намеренно: сторонний ui-kit
|
|
18
|
+
* встраивается плагином (`.ui_builder/plugins/`), а не файлом данных — плагин привозит
|
|
19
|
+
* и каталог, и код компонентов.
|
|
14
20
|
*
|
|
15
21
|
* Использование:
|
|
16
|
-
* npx reformer-builder [--port <n>] [--host <h>] [--no-open] [--
|
|
22
|
+
* npx reformer-builder [--port <n>] [--host <h>] [--no-open] [--config <path>]
|
|
17
23
|
*/
|
|
18
24
|
|
|
19
25
|
import { createServer } from 'node:http';
|
|
@@ -22,12 +28,11 @@ import { spawn } from 'node:child_process';
|
|
|
22
28
|
import { fileURLToPath } from 'node:url';
|
|
23
29
|
import { extname, join, normalize, resolve, sep } from 'node:path';
|
|
24
30
|
|
|
25
|
-
/** URL, по которому SPA забирает
|
|
31
|
+
/** URL, по которому SPA забирает конфиг (совпадает с RUNTIME_BUNDLE_PATH в shell/boot/runtime-config). */
|
|
26
32
|
export const RUNTIME_BUNDLE_URL = '/__reformer-builder/runtime.json';
|
|
27
33
|
|
|
28
|
-
/**
|
|
29
|
-
const
|
|
30
|
-
const DEFAULT_CONFIG_FILE = 'reformer-builder.config.json';
|
|
34
|
+
/** Путь авто-детекта конфига в cwd, если флаг `--config` не задан. */
|
|
35
|
+
const DEFAULT_CONFIG_FILE = join('.ui_builder', 'config.json');
|
|
31
36
|
|
|
32
37
|
// Без хвостового разделителя: иначе `distDir + sep` даёт двойной слэш и проверка
|
|
33
38
|
// границы каталога в resolveFsPath() никогда не совпадает (все запросы → 400).
|
|
@@ -64,61 +69,53 @@ async function readVersion() {
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
/**
|
|
67
|
-
* Прочитать и распарсить
|
|
68
|
-
*
|
|
69
|
-
* (
|
|
70
|
-
*
|
|
72
|
+
* Прочитать и распарсить конфиг. Явно переданный (`--config`) файл обязателен — при ошибке
|
|
73
|
+
* чтения/парсинга завершаемся с сообщением. Авто-детект: отсутствие файла — тихий пропуск
|
|
74
|
+
* (вшитые дефолты); присутствует, но битый JSON — ошибка: файл явно предназначен
|
|
75
|
+
* к использованию, и молча проигнорировать его значило бы обмануть положившего.
|
|
71
76
|
*/
|
|
72
|
-
async function readRuntimeFile(path, { explicit
|
|
77
|
+
async function readRuntimeFile(path, { explicit }) {
|
|
73
78
|
let text;
|
|
74
79
|
try {
|
|
75
80
|
text = await readFile(path, 'utf8');
|
|
76
81
|
} catch (err) {
|
|
77
82
|
if (explicit) {
|
|
78
|
-
console.error(`reformer-builder: не удалось прочитать
|
|
83
|
+
console.error(`reformer-builder: не удалось прочитать конфиг "${path}": ${err.message}`);
|
|
79
84
|
process.exit(1);
|
|
80
85
|
}
|
|
81
|
-
return null;
|
|
86
|
+
return null;
|
|
82
87
|
}
|
|
83
88
|
try {
|
|
84
89
|
return JSON.parse(text);
|
|
85
90
|
} catch (err) {
|
|
86
|
-
console.error(`reformer-builder: невалидный JSON в
|
|
91
|
+
console.error(`reformer-builder: невалидный JSON в конфиге "${path}": ${err.message}`);
|
|
87
92
|
process.exit(1);
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
/**
|
|
92
|
-
* Собрать runtime-bundle для SPA
|
|
93
|
-
*
|
|
94
|
-
* здесь ловим только
|
|
97
|
+
* Собрать runtime-bundle для SPA. Путь берётся из флага, иначе — авто-детект
|
|
98
|
+
* `<cwd>/.ui_builder/config.json`. Структурную валидацию делает SPA (точные сообщения
|
|
99
|
+
* о полях — его словарь); здесь ловим только отсутствие и JSON-синтаксис.
|
|
95
100
|
*/
|
|
96
101
|
export async function loadRuntimeBundle(opts, cwd) {
|
|
97
|
-
const catalogPath = resolve(cwd, opts.catalog ?? DEFAULT_CATALOG_FILE);
|
|
98
102
|
const configPath = resolve(cwd, opts.config ?? DEFAULT_CONFIG_FILE);
|
|
99
|
-
const
|
|
100
|
-
explicit: Boolean(opts.catalog),
|
|
101
|
-
label: 'каталог (--catalog)',
|
|
102
|
-
});
|
|
103
|
-
const config = await readRuntimeFile(configPath, {
|
|
104
|
-
explicit: Boolean(opts.config),
|
|
105
|
-
label: 'конфиг (--config)',
|
|
106
|
-
});
|
|
103
|
+
const config = await readRuntimeFile(configPath, { explicit: Boolean(opts.config) });
|
|
107
104
|
return {
|
|
108
|
-
payload: {
|
|
109
|
-
sources: {
|
|
105
|
+
payload: { config: config ?? null },
|
|
106
|
+
sources: { config: config === null ? null : configPath },
|
|
110
107
|
};
|
|
111
108
|
}
|
|
112
109
|
|
|
113
110
|
export function parseArgs(argv) {
|
|
114
111
|
const opts = {
|
|
112
|
+
// 4321 — исторический порт билдера: он записан в чужих package.json и в памяти людей.
|
|
115
113
|
port: 4321,
|
|
116
114
|
host: '127.0.0.1',
|
|
117
115
|
open: true,
|
|
118
116
|
help: false,
|
|
119
117
|
version: false,
|
|
120
|
-
|
|
121
|
-
catalog: null,
|
|
118
|
+
/** Явно переданный путь к конфигу (null — не задан, будет авто-детект в cwd). */
|
|
122
119
|
config: null,
|
|
123
120
|
};
|
|
124
121
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -131,8 +128,6 @@ export function parseArgs(argv) {
|
|
|
131
128
|
else if (a.startsWith('--port=')) opts.port = Number(a.slice('--port='.length));
|
|
132
129
|
else if (a === '--host') opts.host = String(argv[++i]);
|
|
133
130
|
else if (a.startsWith('--host=')) opts.host = a.slice('--host='.length);
|
|
134
|
-
else if (a === '--catalog') opts.catalog = String(argv[++i]);
|
|
135
|
-
else if (a.startsWith('--catalog=')) opts.catalog = a.slice('--catalog='.length);
|
|
136
131
|
else if (a === '--config') opts.config = String(argv[++i]);
|
|
137
132
|
else if (a.startsWith('--config=')) opts.config = a.slice('--config='.length);
|
|
138
133
|
else {
|
|
@@ -157,13 +152,13 @@ function printHelp() {
|
|
|
157
152
|
-p, --port <n> Порт (по умолчанию 4321; занят — берётся следующий свободный)
|
|
158
153
|
--host <h> Хост (по умолчанию 127.0.0.1)
|
|
159
154
|
--no-open Не открывать браузер автоматически
|
|
160
|
-
--
|
|
161
|
-
--config <path> Конфиг билдера (JSON): палитра, доступные компоненты, дефолты UI, брендинг
|
|
155
|
+
--config <path> Конфиг билдера (JSON): брендинг, дефолты UI, состав плагинов
|
|
162
156
|
-h, --help Показать эту справку
|
|
163
157
|
-v, --version Показать версию
|
|
164
158
|
|
|
165
|
-
Без --
|
|
166
|
-
|
|
159
|
+
Без --config билдер пытается подхватить .ui_builder/config.json из текущей папки;
|
|
160
|
+
если его нет — работает на вшитых дефолтах. Плагины, шаблоны форм и цели кодогена
|
|
161
|
+
живут в .ui_builder/ ОТКРЫТОГО проекта и читаются самим приложением.
|
|
167
162
|
|
|
168
163
|
Примечание: режим «открыть папку проекта» (File System Access API) работает только в
|
|
169
164
|
Chromium-браузерах (Chrome/Edge/Arc/Brave).`);
|
|
@@ -201,7 +196,6 @@ function resolveFsPath(pathname) {
|
|
|
201
196
|
} catch {
|
|
202
197
|
return null;
|
|
203
198
|
}
|
|
204
|
-
// Отбрасываем query/hash уже сделано вызывающим; нормализуем и запрещаем выход за distDir.
|
|
205
199
|
const rel = normalize(decoded).replace(/^(\.\.(\/|\\|$))+/, '');
|
|
206
200
|
const full = join(distDir, rel);
|
|
207
201
|
if (full !== distDir && !full.startsWith(distDir + sep)) return null;
|
|
@@ -227,7 +221,7 @@ export function createRequestHandler(indexHtmlPath, runtimeBundleBody) {
|
|
|
227
221
|
return;
|
|
228
222
|
}
|
|
229
223
|
const pathname = (req.url || '/').split('?')[0].split('#')[0];
|
|
230
|
-
//
|
|
224
|
+
// Конфиг уровня запуска — отдаём ДО резолва static/dist.
|
|
231
225
|
if (pathname === RUNTIME_BUNDLE_URL) {
|
|
232
226
|
res.writeHead(200, {
|
|
233
227
|
'Content-Type': 'application/json; charset=utf-8',
|
|
@@ -246,7 +240,6 @@ export function createRequestHandler(indexHtmlPath, runtimeBundleBody) {
|
|
|
246
240
|
try {
|
|
247
241
|
const info = await stat(target);
|
|
248
242
|
if (info.isDirectory()) {
|
|
249
|
-
// Каталог → отдаём его index.html, иначе SPA-fallback.
|
|
250
243
|
const dirIndex = join(target, 'index.html');
|
|
251
244
|
try {
|
|
252
245
|
await stat(dirIndex);
|
|
@@ -278,7 +271,7 @@ export function createRequestHandler(indexHtmlPath, runtimeBundleBody) {
|
|
|
278
271
|
|
|
279
272
|
/** Поднять сервер, при EADDRINUSE — попробовать следующий порт (до +20). */
|
|
280
273
|
function listenWithFallback(server, host, startPort, attemptsLeft = 20) {
|
|
281
|
-
return new Promise((
|
|
274
|
+
return new Promise((resolvePort, reject) => {
|
|
282
275
|
const tryPort = (port) => {
|
|
283
276
|
const onError = (err) => {
|
|
284
277
|
if (err.code === 'EADDRINUSE' && attemptsLeft > 0) {
|
|
@@ -291,7 +284,7 @@ function listenWithFallback(server, host, startPort, attemptsLeft = 20) {
|
|
|
291
284
|
server.once('error', onError);
|
|
292
285
|
server.listen(port, host, () => {
|
|
293
286
|
server.removeListener('error', onError);
|
|
294
|
-
|
|
287
|
+
resolvePort(port);
|
|
295
288
|
});
|
|
296
289
|
};
|
|
297
290
|
tryPort(startPort);
|
|
@@ -315,13 +308,11 @@ async function main() {
|
|
|
315
308
|
} catch {
|
|
316
309
|
console.error(
|
|
317
310
|
`reformer-builder: не найден собранный dist/ (ожидался ${indexHtmlPath}).\n` +
|
|
318
|
-
`Похоже, пакет установлен без бандла — переустановите
|
|
311
|
+
`Похоже, пакет установлен без бандла — переустановите его.`
|
|
319
312
|
);
|
|
320
313
|
process.exit(1);
|
|
321
314
|
}
|
|
322
315
|
|
|
323
|
-
// Клиентский конфиг/каталог из файлов (флаги или авто-детект в cwd). Отдаётся SPA по
|
|
324
|
-
// RUNTIME_BUNDLE_URL; отсутствие файлов ⇒ пустой bundle ⇒ билдер на вшитых дефолтах.
|
|
325
316
|
const runtime = await loadRuntimeBundle(opts, process.cwd());
|
|
326
317
|
const runtimeBundleBody = Buffer.from(JSON.stringify(runtime.payload));
|
|
327
318
|
|
|
@@ -338,7 +329,6 @@ async function main() {
|
|
|
338
329
|
const url = `http://${displayHost}:${port}/`;
|
|
339
330
|
console.log(`\n reformer-builder v${await readVersion()}`);
|
|
340
331
|
console.log(` Локальный сервер: ${url}`);
|
|
341
|
-
if (runtime.sources.catalog) console.log(` Каталог из файла: ${runtime.sources.catalog}`);
|
|
342
332
|
if (runtime.sources.config) console.log(` Конфиг из файла: ${runtime.sources.config}`);
|
|
343
333
|
console.log(` Режим «открыть папку проекта» требует Chromium-браузер (File System Access API).`);
|
|
344
334
|
console.log(` Остановить: Ctrl+C\n`);
|
|
@@ -347,7 +337,6 @@ async function main() {
|
|
|
347
337
|
|
|
348
338
|
const shutdown = () => {
|
|
349
339
|
server.close(() => process.exit(0));
|
|
350
|
-
// На случай зависших соединений — жёсткий выход.
|
|
351
340
|
setTimeout(() => process.exit(0), 500).unref();
|
|
352
341
|
};
|
|
353
342
|
process.on('SIGINT', shutdown);
|