@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.
Files changed (200) hide show
  1. package/README.md +32 -198
  2. package/bin/reformer-builder.d.mts +7 -9
  3. package/bin/reformer-builder.mjs +43 -54
  4. package/dist/assets/css/index-CHjtwIsF.css +1 -0
  5. package/dist/assets/css/monaco-runtime-Ch4loDnq.css +1 -0
  6. package/dist/assets/i18n/en-uNov8AYL.js +1 -0
  7. package/dist/assets/i18n/ru-BNkTKaU6.js +1 -0
  8. package/dist/assets/js/index-C4LjLCAZ.js +57 -0
  9. package/dist/assets/monaco/html-DT-eqvPn.js +1 -0
  10. package/dist/assets/monaco/javascript-CIJHG94Q.js +1 -0
  11. package/dist/assets/monaco/jsonMode-rEmNPnut.js +12 -0
  12. package/dist/assets/monaco/monaco-runtime-Dqtu7Dpv.js +924 -0
  13. package/dist/assets/monaco/typescript-Bp6doald.js +1 -0
  14. package/dist/assets/monaco/xml-D8D5UF1F.js +1 -0
  15. package/dist/assets/monaco/yaml-DsiyZy1w.js +1 -0
  16. package/dist/assets/plugins/ai-CFoGZBd-.js +178 -0
  17. package/dist/assets/{byok-D0ncJaTq.js → plugins/ai-byok-a7JlkizL.js} +55 -55
  18. package/dist/assets/plugins/ai-knowledge-docs-BcbN7Ar1.js +1 -0
  19. package/dist/assets/plugins/ai-knowledge-index-CncxmxEf.js +1 -0
  20. package/dist/assets/plugins/codegen-DPh2ynzq.js +520 -0
  21. package/dist/assets/{MarkdownPreview-DXY3eJ1Z.js → plugins/editor-markdown-MarkdownPreview-CjVpNIV5.js} +20 -20
  22. package/dist/assets/plugins/editor-markdown-McTrLzET.js +2 -0
  23. package/dist/assets/plugins/editor-monaco-7BM478IS.js +14 -0
  24. package/dist/assets/plugins/editor-schema-DOoRcy16.js +4 -0
  25. package/dist/assets/plugins/files-WhQya3nC.js +2 -0
  26. package/dist/assets/plugins/plain-4ISpXJVh.js +78 -0
  27. package/dist/assets/plugins/plugin-manager-Ek0Ph0Jj.js +1 -0
  28. package/dist/assets/plugins/preview-BSh_puVw.js +1 -0
  29. package/dist/assets/plugins/preview-runtime-B8NzDg53.js +3 -0
  30. package/dist/assets/plugins/templates-BE9B0S3J.js +2 -0
  31. package/dist/assets/vendor/ajv-N5zGp_lm.js +8 -0
  32. package/dist/assets/vendor/calendar-base-BW48REpD-BYc4qqRC.js +1 -0
  33. package/dist/assets/vendor/carousel-BDyy29mt.js +1 -0
  34. package/dist/assets/vendor/chart-Cbp9J5YJ.js +52 -0
  35. package/dist/assets/vendor/collapsible-base-DZxAKbAF-DtQ4867U.js +1 -0
  36. package/dist/assets/vendor/drawer-BdLrIIeu.js +3 -0
  37. package/dist/assets/vendor/highlight.js/common-B96EybDa.js +5 -0
  38. package/dist/assets/vendor/index-BTAoX623.js +6 -0
  39. package/dist/assets/vendor/index-D8ACoUqy.js +51 -0
  40. package/dist/assets/vendor/input-otp-BoPlZ6dt.js +20 -0
  41. package/dist/assets/vendor/lucide-react/arrow-left-BlVPt6Ag.js +1 -0
  42. package/dist/assets/vendor/lucide-react/arrow-right-I5ntlq0-.js +1 -0
  43. package/dist/assets/vendor/lucide-react/calendar-L-57WZlQ.js +1 -0
  44. package/dist/assets/vendor/lucide-react/eye-DVTIIHcH.js +1 -0
  45. package/dist/assets/vendor/lucide-react/file-code-corner-DUfMS_yi.js +1 -0
  46. package/dist/assets/vendor/lucide-react/folder-tree-COyCkaDl.js +1 -0
  47. package/dist/assets/vendor/lucide-react/minus-zJRYKuAo.js +1 -0
  48. package/dist/assets/vendor/lucide-react/plus-B0WG2JcM.js +1 -0
  49. package/dist/assets/vendor/lucide-react/rotate-ccw-BSYk0mux.js +1 -0
  50. package/dist/assets/vendor/lucide-react/wrench-mybFdWHD.js +1 -0
  51. package/dist/assets/vendor/message-base-B5jT1FuY-BvDKjuSs.js +1 -0
  52. package/dist/assets/vendor/message-scroller-B2tlOtxT.js +1 -0
  53. package/dist/assets/vendor/reformer-builder-stack-reformer/node-token-VfZdCqcs.js +1 -0
  54. package/dist/assets/vendor/reformer-builder-stack-reformer/paths-DeGLVPUt.js +1 -0
  55. package/dist/assets/vendor/reformer-builder-stack-reformer/rules-CQSVDlmo.js +1 -0
  56. package/dist/assets/vendor/reformer-builder-stack-reformer/selectors-CjNSFsK9.js +1 -0
  57. package/dist/assets/vendor/reformer-builder-toolkit/marker-DiOaKX-e.js +4 -0
  58. package/dist/assets/vendor/reformer-builder-toolkit/naming-9aaM0Wbc.js +1 -0
  59. package/dist/assets/vendor/reformer-cdk/define-steps-CyGUrx9p-vcI1WbRz.js +1 -0
  60. package/dist/assets/vendor/reformer-cdk/file-upload-D8FOieMN.js +1 -0
  61. package/dist/assets/vendor/reformer-cdk/form-array-DlFEb40E.js +1 -0
  62. package/dist/assets/vendor/reformer-cdk/form-wizard-DDLs_-Ya.js +1 -0
  63. package/dist/assets/vendor/reformer-cdk/index-CeCSv2Go.js +1 -0
  64. package/dist/assets/vendor/reformer-cdk/list-DkqJWU70.js +1 -0
  65. package/dist/assets/vendor/reformer-form-registry/index-DflpiFcm.js +1 -0
  66. package/dist/assets/vendor/reformer-form-registry/loader-BK2c_fCA-BtIEWzon.js +2 -0
  67. package/dist/assets/vendor/reformer-form-registry/react-BiEQRau3.js +1 -0
  68. package/dist/assets/vendor/reformer-form-registry/storage-BbhnRE7V.js +1 -0
  69. package/dist/assets/vendor/reformer-form-registry/types-DoMH_n1U-BSN9tyeo.js +1 -0
  70. package/dist/assets/vendor/reformer-renderer-json/validate-DXzHWMfT.js +8 -0
  71. package/dist/assets/vendor/reformer-ui-kit/alert-base-WOl_V-qI-2ZIfaT1o.js +1 -0
  72. package/dist/assets/vendor/reformer-ui-kit/calendar-Bm2DDJDU.js +1 -0
  73. package/dist/assets/vendor/reformer-ui-kit/calendar-base.props-CqesU7CZ-tpDaVQbq.js +1 -0
  74. package/dist/assets/vendor/reformer-ui-kit/combobox-Dm4bFCVg.js +1 -0
  75. package/dist/assets/vendor/reformer-ui-kit/combobox-tree.props-BEQhnapq-DQmsBcYk.js +1 -0
  76. package/dist/assets/vendor/reformer-ui-kit/component-catalog-BEv0Zf-R.js +1 -0
  77. package/dist/assets/vendor/reformer-ui-kit/date-picker-CkVXt6Uh.js +1 -0
  78. package/dist/assets/vendor/reformer-ui-kit/date-picker-base.props-WBloFrDq-QhVYMCMG.js +1 -0
  79. package/dist/assets/vendor/reformer-ui-kit/input-otp-base.props-D1xRJiuO-DBKxHsz1.js +1 -0
  80. package/dist/assets/vendor/reformer-ui-kit/meta-YyKXxsBK.js +1 -0
  81. package/dist/assets/vendor/reformer-ui-kit/sidebar-CMzt3bAb.js +1 -0
  82. package/dist/assets/vendor/reformer-ui-kit/skeleton-base-C-lIzi0D-BjmjAmE9.js +1 -0
  83. package/dist/assets/vendor/reformer-ui-kit/toggle-group-multi.props-7kNpujN6-jLENMOcN.js +1 -0
  84. package/dist/assets/vendor/reformer-ui-kit/tree-node-schema-xHyN0QCr-CLbM_Aw_.js +1 -0
  85. package/dist/assets/vendor/render-DutGx1TC.js +46 -0
  86. package/dist/assets/vendor/sheet-base-Bdh947IC-CH2UsjIt.js +1 -0
  87. package/dist/assets/{typescript-BuFxP6n6.js → vendor/typescript/typescript-BejA4q8A.js} +1 -1
  88. package/dist/index.html +4 -4
  89. package/package.json +19 -18
  90. package/runtime-config.schema.json +32 -53
  91. package/dist/assets/App-DRJnHAjE.js +0 -1137
  92. package/dist/assets/BootError-CiPUX-Tr.js +0 -1
  93. package/dist/assets/ChatPanel-CnU7eT8N.js +0 -82
  94. package/dist/assets/CodeEditor-Wv0NRzV8.js +0 -1
  95. package/dist/assets/RawJsonEditor-c354H_pY.js +0 -1
  96. package/dist/assets/abap-DLDM7-KI.js +0 -1
  97. package/dist/assets/apex-DNDY2TF8.js +0 -1
  98. package/dist/assets/azcli-Y6nb8tq_.js +0 -1
  99. package/dist/assets/bat-BwHxbl9M.js +0 -1
  100. package/dist/assets/bicep-CFznDFnq.js +0 -2
  101. package/dist/assets/boot-5_JU0zay.js +0 -2
  102. package/dist/assets/cameligo-Bf6VGUru.js +0 -1
  103. package/dist/assets/clojure-Dnu-v4kV.js +0 -1
  104. package/dist/assets/coffee-Bd8akH9Z.js +0 -1
  105. package/dist/assets/cpp-BbWJElDN.js +0 -1
  106. package/dist/assets/csharp-Co3qMtFm.js +0 -1
  107. package/dist/assets/csp-D-4FJmMZ.js +0 -1
  108. package/dist/assets/cypher-cTPe9QuQ.js +0 -1
  109. package/dist/assets/dart-BOtBlQCF.js +0 -1
  110. package/dist/assets/dockerfile-BG73LgW2.js +0 -1
  111. package/dist/assets/ecl-BEgZUVRK.js +0 -1
  112. package/dist/assets/editor-BzOv8av-.css +0 -1
  113. package/dist/assets/editor.api-CMCnIB-P.js +0 -865
  114. package/dist/assets/elixir-BkW5O-1t.js +0 -1
  115. package/dist/assets/flow9-BeJ5waoc.js +0 -1
  116. package/dist/assets/freemarker2-C645vQBx.js +0 -3
  117. package/dist/assets/fsharp-PahG7c26.js +0 -1
  118. package/dist/assets/go-acbASCJo.js +0 -1
  119. package/dist/assets/graphql-BxJiqAUM.js +0 -1
  120. package/dist/assets/handlebars-B5DnoJkq.js +0 -1
  121. package/dist/assets/hcl-DtV1sZF8.js +0 -1
  122. package/dist/assets/html-TNLrm0oH.js +0 -1
  123. package/dist/assets/index--0tYkbnz.js +0 -3
  124. package/dist/assets/index-BKc-soqk.css +0 -1
  125. package/dist/assets/index-BLGbxQaR.js +0 -104
  126. package/dist/assets/index-Bb-H-IRh.js +0 -1
  127. package/dist/assets/index-BivFj4xA.js +0 -10
  128. package/dist/assets/index-C_YSTVSM.js +0 -68
  129. package/dist/assets/index-Crsub4wy.js +0 -5028
  130. package/dist/assets/index-D2vdVqoN.js +0 -11
  131. package/dist/assets/index-DBBur3Kg.js +0 -4709
  132. package/dist/assets/index-DzAasWzr.css +0 -1
  133. package/dist/assets/ini-Kd9XrMLS.js +0 -1
  134. package/dist/assets/java-CXBNlu9o.js +0 -1
  135. package/dist/assets/javascript-YmJoSFNK.js +0 -1
  136. package/dist/assets/jsonMode-BgHFRVOe.css +0 -1
  137. package/dist/assets/jsonMode-CUyarZ9Q.js +0 -70
  138. package/dist/assets/julia-cl7-CwDS.js +0 -1
  139. package/dist/assets/kotlin-s7OhZKlX.js +0 -1
  140. package/dist/assets/less-9HpZscsL.js +0 -2
  141. package/dist/assets/lexon-OrD6JF1K.js +0 -1
  142. package/dist/assets/liquid-CsrVJLkL.js +0 -1
  143. package/dist/assets/load-DahhU28W.js +0 -11
  144. package/dist/assets/lua-Cyyb5UIc.js +0 -1
  145. package/dist/assets/m3-B8OfTtLu.js +0 -1
  146. package/dist/assets/mdx-DDXJg3VI.js +0 -1
  147. package/dist/assets/mips-CiqrrVzr.js +0 -1
  148. package/dist/assets/monaco-languages-CfiXabIS.js +0 -2
  149. package/dist/assets/monaco-setup-DPehMZ7o.js +0 -12
  150. package/dist/assets/msdax-DmeGPVcC.js +0 -1
  151. package/dist/assets/mysql-C_tMU-Nz.js +0 -1
  152. package/dist/assets/objective-c-BDtDVThU.js +0 -1
  153. package/dist/assets/pascal-vHIfCaH5.js +0 -1
  154. package/dist/assets/pascaligo-DtZ0uQbO.js +0 -1
  155. package/dist/assets/perl-Ub6l9XKa.js +0 -1
  156. package/dist/assets/pgsql-BlNEE0v7.js +0 -1
  157. package/dist/assets/php-BBUBE1dy.js +0 -1
  158. package/dist/assets/pla-DSh2-awV.js +0 -1
  159. package/dist/assets/postiats-CocnycG-.js +0 -1
  160. package/dist/assets/powerquery-tScXyioY.js +0 -1
  161. package/dist/assets/powershell-COWaemsV.js +0 -1
  162. package/dist/assets/protobuf-Brw8urJB.js +0 -2
  163. package/dist/assets/pug-8SOpv6rk.js +0 -1
  164. package/dist/assets/python-DpnOD9VM.js +0 -1
  165. package/dist/assets/qsharp-Bw9ernYp.js +0 -1
  166. package/dist/assets/r-j7ic8hl3.js +0 -1
  167. package/dist/assets/razor-BsF1GcFZ.js +0 -1
  168. package/dist/assets/redis-Bu5POkcn.js +0 -1
  169. package/dist/assets/redshift-Bs9aos_-.js +0 -1
  170. package/dist/assets/reformer-ui-kit-11-Bml4F8Os.js +0 -1
  171. package/dist/assets/reformer-ui-kit-BWUaVvO0.js +0 -1
  172. package/dist/assets/restructuredtext-CqXO7rUv.js +0 -1
  173. package/dist/assets/ruby-zBfavPgS.js +0 -1
  174. package/dist/assets/rust-BzKRNQWT.js +0 -1
  175. package/dist/assets/sb-BBc9UKZt.js +0 -1
  176. package/dist/assets/scala-D9hQfWCl.js +0 -1
  177. package/dist/assets/scheme-BPhDTwHR.js +0 -1
  178. package/dist/assets/scss-CBJaRo0y.js +0 -3
  179. package/dist/assets/shell-DiJ1NA_G.js +0 -1
  180. package/dist/assets/solidity-Db0IVjzk.js +0 -1
  181. package/dist/assets/sophia-CnS9iZB_.js +0 -1
  182. package/dist/assets/sparql-CJmd_6j2.js +0 -1
  183. package/dist/assets/sql-ClhHkBeG.js +0 -1
  184. package/dist/assets/st-CHwy0fLd.js +0 -1
  185. package/dist/assets/swift-CnmFD0ga.js +0 -1
  186. package/dist/assets/systemverilog-Bs9z6M-B.js +0 -1
  187. package/dist/assets/tcl-Dm6ycUr_.js +0 -1
  188. package/dist/assets/twig-Csy3S7wG.js +0 -1
  189. package/dist/assets/typescript-D7ER-DvA.js +0 -1
  190. package/dist/assets/typespec-Btyra-wh.js +0 -1
  191. package/dist/assets/useFormField-BLbvmpme-CM4hze15.js +0 -1
  192. package/dist/assets/vb-Db0cS2oM.js +0 -1
  193. package/dist/assets/wgsl-BTesnYfV.js +0 -298
  194. package/dist/assets/xml-5MzZ4-DY.js +0 -1
  195. package/dist/assets/yaml-Ch0E2rII.js +0 -1
  196. /package/dist/assets/{codicon-Brq4_Ui5.ttf → fonts/codicon-Brq4_Ui5.ttf} +0 -0
  197. /package/dist/assets/{css-DdJfP1eB.js → monaco/css-DdJfP1eB.js} +0 -0
  198. /package/dist/assets/{editor.worker-CRaYpIdo.js → monaco/editor.worker-CRaYpIdo.js} +0 -0
  199. /package/dist/assets/{json.worker-C5PEkLU0.js → monaco/json.worker-C5PEkLU0.js} +0 -0
  200. /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
- Визуальный билдер JSON-схем форм для экосистемы **ReFormer**. Это самодостаточный офлайн-SPA: вы
4
- запускаете его локально через `npx`, собираете форму мышкой из компонентов `@reformer/ui-kit`, и билдер
5
- отдаёт готовую схему / код. Каталог компонентов `@reformer/ui-kit` вшит в бандл устанавливать сам ui-kit
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
- Или добавьте скрипт в свой `package.json`:
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
- - **Модель не пишет JSON.** Она вызывает операции редактора (вставить узел, задать свойство,
74
- перенести, сгруппировать), а схему собирает сам билдер — теми же функциями, что палитра и
75
- инспектор. Имена компонентов модель обязана брать из каталога; выдуманное имя отклоняется.
76
- - **Изменения показываются до применения.** Ход агента правит копию схемы; вы видите список
77
- изменений и решаете, применять ли. Применённый ход отменяется **одним** `Ctrl+Z`.
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
- "version": "1.0",
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
- Семантика слияния: карты (`palette.categoryByName`, `palette.glyphs`) и списки безопасных
205
- дефолтов (`project.ignoreDirs`, `project.skipFiles`, `project.formSchemaMarkers`) **дополняют**
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
- > **Требование к упаковке `@reformer/ui-kit`:** чтобы subpath `@reformer/ui-kit/catalog`
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
- MIT © Alexandr Bukhtatyy
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
- * Типы для тестируемых экспортов launcher'а (`reformer-builder.mjs` — zero-dependency JS без
3
- * деклараций). Позволяет `.ts`-тестам импортировать хелперы без implicit-any (TS7016).
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
- /** Путь к каталогу компонентов (`--catalog`) или `null` (авто-детект в cwd). */
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: { catalog: unknown; config: unknown };
20
- sources: { catalog: string | null; config: string | null };
17
+ payload: { config: unknown };
18
+ sources: { config: string | null };
21
19
  }
22
20
 
23
- /** URL раздачи клиентского bundle. */
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: { catalog: string | null; config: string | null },
27
+ opts: { config: string | null },
30
28
  cwd: string
31
29
  ): Promise<RuntimeBundleResult>;
32
30
 
@@ -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/` (каталог компонентов @reformer/ui-kit вшит
6
- * в бандл на этапе сборки). Этот скрипт zero-dependency статик-сервер на встроенных модулях Node:
7
- * поднимает `dist/` на localhost и открывает браузер. Серверной логики у билдера нет — вся работа с
8
- * файлами проекта идёт в браузере через File System Access API (нужен Chromium-браузер).
5
+ * Опубликованный пакет несёт УЖЕ собранный SPA в `dist/`. Этот скрипт — zero-dependency
6
+ * статик-сервер на встроенных модулях Node (перенесён из первой версии билдера, она же
7
+ * в истории git): поднимает `dist/` на localhost и открывает браузер. Серверной
8
+ * логики у билдера нет — вся работа с файлами проекта идёт в браузере через File System Access
9
+ * (нужен Chromium-браузер).
9
10
  *
10
- * Клиент может передать 2 JSON-файла для локальной кастомизации: каталог компонентов (--catalog)
11
- * и конфиг билдера (--config). Launcher читает их с диска и отдаёт SPA по /__reformer-builder/
12
- * runtime.json; без флагов пытается авто-подхватить одноимённые файлы из cwd. Отсутствие файлов —
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] [--catalog <path>] [--config <path>]
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 забирает клиентский bundle (совпадает с RUNTIME_BUNDLE_PATH в src/config/load). */
31
+ /** URL, по которому SPA забирает конфиг (совпадает с RUNTIME_BUNDLE_PATH в shell/boot/runtime-config). */
26
32
  export const RUNTIME_BUNDLE_URL = '/__reformer-builder/runtime.json';
27
33
 
28
- /** Имена файлов для авто-детекта в cwd, если флаги `--catalog`/`--config` не заданы. */
29
- const DEFAULT_CATALOG_FILE = 'component-catalog.json';
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
- * Прочитать и распарсить клиентский JSON-файл. Явно переданный (`--catalog`/`--config`) файл
68
- * обязателен — при ошибке чтения/парсинга завершаемся с сообщением. Авто-детект: отсутствие файла
69
- * (ENOENT) — тихий пропуск (fallback на вшитые дефолты); присутствует, но битый JSON — ошибка
70
- * (файл явно предназначен к использованию).
72
+ * Прочитать и распарсить конфиг. Явно переданный (`--config`) файл обязателен — при ошибке
73
+ * чтения/парсинга завершаемся с сообщением. Авто-детект: отсутствие файла — тихий пропуск
74
+ * (вшитые дефолты); присутствует, но битый JSON — ошибка: файл явно предназначен
75
+ * к использованию, и молча проигнорировать его значило бы обмануть положившего.
71
76
  */
72
- async function readRuntimeFile(path, { explicit, label }) {
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: не удалось прочитать ${label} "${path}": ${err.message}`);
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 в ${label} "${path}": ${err.message}`);
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
- * одноимённых файлов в cwd. Структурную валидацию делает SPA (реюз validateCatalog + AJV конфига);
94
- * здесь ловим только отсутствие/JSON-синтаксис.
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 catalog = await readRuntimeFile(catalogPath, {
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: { catalog: catalog ?? null, config: config ?? null },
109
- sources: { catalog: catalog ? catalogPath : null, config: config ? configPath : null },
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
- // Явно переданные клиентом пути (null — не задан, будет авто-детект в cwd).
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
- --catalog <path> Каталог компонентов (JSON) для палитры/инспектора
161
- --config <path> Конфиг билдера (JSON): палитра, доступные компоненты, дефолты UI, брендинг
155
+ --config <path> Конфиг билдера (JSON): брендинг, дефолты UI, состав плагинов
162
156
  -h, --help Показать эту справку
163
157
  -v, --version Показать версию
164
158
 
165
- Без --catalog/--config билдер пытается подхватить component-catalog.json и
166
- reformer-builder.config.json из текущей папки; если их нет — работает на вшитых дефолтах.
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
- // Клиентский runtime-bundle (каталог/конфиг из файлов) — отдаём ДО резолва static/dist.
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((resolve, reject) => {
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
- resolve(port);
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
- `Похоже, пакет установлен без бандла — переустановите @reformer/builder.`
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);