@foxford/den 3.0.0 → 3.1.1

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 (57) hide show
  1. package/README.mdx +266 -2
  2. package/adapter.cjs +1 -1
  3. package/adapter.d.cts +1 -1
  4. package/adapter.d.ts +1 -1
  5. package/adapter.js +1 -1
  6. package/bin/den.cjs +88 -0
  7. package/bin/den.d.cts +2 -0
  8. package/bin/den.d.ts +2 -0
  9. package/bin/den.js +88 -0
  10. package/builder/index.cjs +12 -0
  11. package/builder/index.d.cts +120 -0
  12. package/builder/index.d.ts +120 -0
  13. package/builder/index.js +12 -0
  14. package/chunk-3RX2OSUL.js +21 -0
  15. package/{chunk-HJO26HIQ.js → chunk-6FNC3XMI.js} +4 -0
  16. package/chunk-6QV4L6R2.cjs +21 -0
  17. package/{chunk-WRQC6BVJ.js → chunk-MCN4GFEQ.js} +4 -19
  18. package/chunk-OKRO4G4L.cjs +354 -0
  19. package/chunk-REFU7UMG.js +354 -0
  20. package/{chunk-XHYR3SGG.cjs → chunk-T5QVCXVB.cjs} +5 -1
  21. package/chunk-TPHJUDHG.js +230 -0
  22. package/{chunk-5DJZZML5.cjs → chunk-Z5BL4DJA.cjs} +10 -25
  23. package/chunk-ZOU6W6ZQ.cjs +230 -0
  24. package/{define-repository-MDEWHqM7.d.cts → define-repository-CwAXed2X.d.cts} +1 -1
  25. package/{define-repository-Ca62_YCy.d.ts → define-repository-q_T4hqeP.d.ts} +1 -1
  26. package/{define-slot-Dil8Kr1A.d.ts → define-slot-Cngzae6i.d.ts} +1 -1
  27. package/{define-slot-BKvArA02.d.cts → define-slot-DYNCLDJY.d.cts} +1 -1
  28. package/define.cjs +6 -4
  29. package/define.d.cts +3 -3
  30. package/define.d.ts +3 -3
  31. package/define.js +5 -3
  32. package/den.js +60 -0
  33. package/descriptor-DQ6Gi7A_.d.ts +98 -0
  34. package/descriptor-Dujg_1on.d.cts +98 -0
  35. package/index.cjs +25 -23
  36. package/index.d.cts +7 -5
  37. package/index.d.ts +7 -5
  38. package/index.js +12 -10
  39. package/island/index.cjs +12 -157
  40. package/island/index.d.cts +40 -30
  41. package/island/index.d.ts +40 -30
  42. package/island/index.js +19 -164
  43. package/package.json +59 -16
  44. package/routes-0uXJ0fux.d.ts +64 -0
  45. package/routes-B0hDrkiF.d.cts +64 -0
  46. package/serve/index.cjs +137 -0
  47. package/serve/index.d.cts +60 -0
  48. package/serve/index.d.ts +60 -0
  49. package/serve/index.js +137 -0
  50. package/server-render-CocWXQKC.d.cts +48 -0
  51. package/server-render-CocWXQKC.d.ts +48 -0
  52. package/{types-COwVwgzE.d.cts → types-Dx5qGiwk.d.cts} +1 -1
  53. package/{types-COwVwgzE.d.ts → types-Dx5qGiwk.d.ts} +1 -1
  54. package/view-adapter-B4gEb-ms.d.ts +77 -0
  55. package/view-adapter-DJ7yB6Ml.d.cts +77 -0
  56. package/view-adapter-BvDC5O4y.d.cts +0 -188
  57. package/view-adapter-DtNgyjIf.d.ts +0 -188
@@ -1,188 +0,0 @@
1
- import { S as SlotDefinition } from './define-slot-BKvArA02.cjs';
2
- import { q as LayerDefinition, x as Definition, o as LayerConfig } from './types-COwVwgzE.cjs';
3
- import { Token, Container } from '@foxford/ioc';
4
-
5
- /**
6
- * Дескриптор острова — что ядру нужно, чтобы остров прожил свой цикл.
7
- *
8
- * `view` типизирован как `unknown` по той же причине, что и в `defineSlot`: остров не
9
- * прибит к React. Ядро собирает контейнер, гидрирует VM и ведёт учёт, ни разу не заглянув
10
- * во view; красит его view-адаптер (`ViewAdapter.createIsland`), и он же знает, дерево
11
- * какого фреймворка перед ним.
12
- *
13
- * Дескрипторы страниц у хостов (`PageDescriptor` в `@foxford/den-vike` и `@foxford/den-next`)
14
- * шире: у каждого своя часть про оркестрацию — `load`, `routes`, `provides`/`requires`,
15
- * вклад в документ. Сводить их в один тип нечем, оркестраторы у хостов разные. Общее
16
- * ровно это, и структурная типизация делает остальное: дескриптор хоста подходит сюда как есть.
17
- */
18
- interface IslandDescriptor {
19
- /**
20
- * Имя мини-приложения (`market-app`).
21
- *
22
- * Работает дважды: корень именованного иерархического логгера (ядро биндит по нему
23
- * scope-логгер в контейнер острова, поэтому регистрация единиц логируется под именем
24
- * приложения) и пространство имён для адресов его слотов (см. `slotAddress`). Из-за
25
- * второго оно обязательное: без него у мест приложения не было бы адреса.
26
- */
27
- name: string;
28
- /** Непрозрачная ссылка на view острова (компонент view-фреймворка). */
29
- view: unknown;
30
- /**
31
- * View-слой — чем остров рисовать: `defineLayer(ViewLayerToken, { adapter: reactAdapter() })`.
32
- *
33
- * Обязателен, и дефолта нет ни у ядра, ни у хоста: фреймворк за приложение не выбирают.
34
- * Слой регистрируется в контейнере острова, поэтому слоты внутри по умолчанию рисуются
35
- * им же; слот перекрывает выбор своим `viewLayer`.
36
- */
37
- viewLayer: LayerDefinition;
38
- /**
39
- * Data/Business единицы (repository/service). Регистрируются в контейнере острова.
40
- * Не должны импортировать VM.
41
- */
42
- units: ReadonlyArray<Definition<unknown>>;
43
- /**
44
- * VM-единицы: регистрируются только в острове — оркестратор их не читает, состояние
45
- * ездит через denState.
46
- */
47
- viewModels?: ReadonlyArray<Definition<unknown>>;
48
- /**
49
- * Единицы, которые обязаны жить с загрузки, а не с первого резолва.
50
- *
51
- * Регистрация ленива по природе: не спросили — не создали. Обычно это то, что нужно, но
52
- * сервису, который сам на что-то подписывается или греет кэш, ждать первого потребителя
53
- * незачем. Токены — из тех же `units`.
54
- *
55
- * Поднимаются при МОНТИРОВАНИИ острова, а не при сборке контейнера: контейнер строится и на
56
- * сервере, а сервер живёт один рендер — открытая там WS-подписка это не «eager», а утечка.
57
- * Серверное состояние приложения считает активация VM.
58
- */
59
- eager?: ReadonlyArray<Token<unknown>>;
60
- /**
61
- * Места расширения приложения: ключ — локальное имя слота, значение — `defineSlot`.
62
- *
63
- * Карта, а не массив, потому что имя даёт хозяин места: адрес получается `app:key`
64
- * (см. `slotAddress`), занять чужое пространство имён нечем, а руками писать префикс
65
- * не нужно. Единицы слотов регистрируются в контейнере острова вместе с его собственными.
66
- */
67
- slots?: Readonly<Record<string, SlotDefinition>>;
68
- }
69
-
70
- /** Что приложение отдало серверным рендером. */
71
- interface ServerRenderResult {
72
- /** Разметка дерева — результат переданного рендера. */
73
- html: string;
74
- /**
75
- * Вклад в `<head>` ГОТОВОЙ разметкой: то, что рождается только во время рендера и
76
- * данными не описывается.
77
- *
78
- * Таковы стили CSS-in-JS: стороннее представление у них одно — тег со служебными
79
- * атрибутами, по которым клиентский рантайм узнаёт свои правила. Разобрав его на поля,
80
- * потеряешь регидратацию, и стили впрыснутся вторым экземпляром. Поэтому вклад в документ
81
- * ДАННЫМИ (`DocumentHead` у хостов) остаётся отдельным каналом, а это — разметка.
82
- *
83
- * Разметка приезжает в документ хоста ДОСЛОВНО, без экранирования — иначе служебные
84
- * атрибуты не пережили бы вставку. Отвечает за содержимое приложение: у сетевого
85
- * транспорта строка приходит из чужого процесса, и хост её не разбирает.
86
- */
87
- head?: string;
88
- }
89
- /** Рендер дерева в разметку. Его даёт тот, кто серверный рендер исполняет. */
90
- type RenderTree<Tree = unknown> = (tree: Tree) => string;
91
- /**
92
- * Серверный рендер приложения: приложению дают его дерево и рендер, оно возвращает
93
- * разметку и свой вклад в документ.
94
- *
95
- * Рендер приходит АРГУМЕНТОМ, потому что приложение им не владеет: страницу собирает тот,
96
- * кто держит документ, и приложений на ней может быть несколько. Отдав рендер аргументом,
97
- * приложение получает обычную функцию — состояние прохода живёт локальной переменной и
98
- * между запросами не утекает.
99
- *
100
- * Подпись одна на оба транспорта, и в этом смысл: у приложения в процессе хоста рендер
101
- * передаёт хост, у сетевого — его собственный сервер, а `html` и `head` едут ответом.
102
- * Перевод приложения между транспортами эту часть не задевает.
103
- *
104
- * `Tree` — дерево view-фреймворка, для ядра непрозрачное. View-адаптер сужает параметр
105
- * до своего типа (`ReactServerRender` в `@foxford/den-react`), и приложение пишет проход
106
- * в терминах СВОЕГО фреймворка.
107
- *
108
- * @example
109
- * serverRender: (tree, render) => {
110
- * const sheet = new ServerStyleSheet()
111
- *
112
- * return { head: sheet.getStyleTags(), html: render(sheet.collectStyles(tree)) }
113
- * }
114
- */
115
- type ServerRender<Tree = unknown> = (tree: Tree, render: RenderTree<Tree>) => ServerRenderResult;
116
-
117
- /** Что нужно адаптеру, чтобы отрисовать остров на сервере. */
118
- interface RenderIslandOptions {
119
- /** Контейнер острова — уже собранный, с активированными VM. */
120
- container: Container;
121
- /** Внешние заполнители слотов; для ядра непрозрачны, как и само дерево. */
122
- slots?: Record<string, unknown>;
123
- }
124
- /**
125
- * Порт view-адаптера. Реализуется пакетом фреймворка (`@foxford/den-react` и его аналоги),
126
- * объявляется приложением через `defineLayer(ViewLayerToken, { adapter })`.
127
- */
128
- interface ViewAdapter {
129
- /** Имя фреймворка (`react`, `vue`) — для диагностики и сообщений об ошибках. */
130
- readonly type: string;
131
- /**
132
- * Компонент острова для этого фреймворка: драйвит жизненный цикл ядра своими средствами
133
- * (у React — хуки, у Vue — `setup`) и рисует `descriptor.view`.
134
- *
135
- * @param descriptor - Дескриптор острова
136
- * @returns Компонент фреймворка — для ядра непрозрачен
137
- */
138
- createIsland(descriptor: IslandDescriptor): unknown;
139
- /**
140
- * Отрисовывает остров в разметку на сервере.
141
- *
142
- * Единственная операция острова, которую ядро не может сделать само: `renderToString` —
143
- * функция конкретного фреймворка, а ядро view-агностично. Здесь же адаптер исполняет
144
- * `serverRender` приложения, если тот объявлен, — тип дерева известен только адаптеру.
145
- *
146
- * @param descriptor - Дескриптор острова
147
- * @param options - Контейнер острова и заполнители слотов
148
- * @returns Разметка и вклад в `<head>` готовой разметкой
149
- */
150
- renderIsland(descriptor: IslandDescriptor, options: RenderIslandOptions): ServerRenderResult;
151
- /**
152
- * Ставит стратегию резолва `define*` во view (`installResolver` из `@foxford/den/adapter`).
153
- * У каждого фреймворка она своя: у React — хук поверх контекста контейнера, у Vue —
154
- * `inject`. Зовёт хост при инициализации трека.
155
- */
156
- installResolver(): void;
157
- }
158
- /**
159
- * Канонический токен view-слоя.
160
- *
161
- * Живёт в ядре именно потому, что «мы знаем, что зарегистрировано» работает лишь тогда,
162
- * когда токен один на всех: заведи его каждое приложение у себя — и движок не найдёт
163
- * чужую регистрацию.
164
- */
165
- declare const ViewLayerToken: Token<LayerConfig>;
166
- /** View-слой приложения — результат `defineLayer(ViewLayerToken, { adapter })`. */
167
- type ViewLayerDefinition = LayerDefinition;
168
- /**
169
- * Достаёт адаптер из объявленного приложением view-слоя.
170
- *
171
- * @param layer - View-слой (`defineLayer(ViewLayerToken, { adapter })`)
172
- * @returns Адаптер view-фреймворка
173
- * @throws Если слой объявлен без адаптера или адаптер не закрывает порт
174
- */
175
- declare function viewAdapterOf(layer: ViewLayerDefinition): ViewAdapter;
176
- /**
177
- * Достаёт адаптер из контейнера — с подъёмом по parent-chain, как это делает резолв во view.
178
- *
179
- * Нужен там, где на руках только контейнер (например, отрисовка слота внутри острова).
180
- * Дефолта нет намеренно: фреймворк за приложение ядро не выбирает.
181
- *
182
- * @param container - Контейнер острова/страницы
183
- * @returns Адаптер view-фреймворка
184
- * @throws Если приложение не объявило view-слой
185
- */
186
- declare function resolveViewAdapter(container: Container): ViewAdapter;
187
-
188
- export { type IslandDescriptor as I, type RenderIslandOptions as R, type ServerRender as S, type ViewAdapter as V, type ViewLayerDefinition as a, ViewLayerToken as b, type RenderTree as c, type ServerRenderResult as d, resolveViewAdapter as r, viewAdapterOf as v };
@@ -1,188 +0,0 @@
1
- import { S as SlotDefinition } from './define-slot-Dil8Kr1A.js';
2
- import { q as LayerDefinition, x as Definition, o as LayerConfig } from './types-COwVwgzE.js';
3
- import { Token, Container } from '@foxford/ioc';
4
-
5
- /**
6
- * Дескриптор острова — что ядру нужно, чтобы остров прожил свой цикл.
7
- *
8
- * `view` типизирован как `unknown` по той же причине, что и в `defineSlot`: остров не
9
- * прибит к React. Ядро собирает контейнер, гидрирует VM и ведёт учёт, ни разу не заглянув
10
- * во view; красит его view-адаптер (`ViewAdapter.createIsland`), и он же знает, дерево
11
- * какого фреймворка перед ним.
12
- *
13
- * Дескрипторы страниц у хостов (`PageDescriptor` в `@foxford/den-vike` и `@foxford/den-next`)
14
- * шире: у каждого своя часть про оркестрацию — `load`, `routes`, `provides`/`requires`,
15
- * вклад в документ. Сводить их в один тип нечем, оркестраторы у хостов разные. Общее
16
- * ровно это, и структурная типизация делает остальное: дескриптор хоста подходит сюда как есть.
17
- */
18
- interface IslandDescriptor {
19
- /**
20
- * Имя мини-приложения (`market-app`).
21
- *
22
- * Работает дважды: корень именованного иерархического логгера (ядро биндит по нему
23
- * scope-логгер в контейнер острова, поэтому регистрация единиц логируется под именем
24
- * приложения) и пространство имён для адресов его слотов (см. `slotAddress`). Из-за
25
- * второго оно обязательное: без него у мест приложения не было бы адреса.
26
- */
27
- name: string;
28
- /** Непрозрачная ссылка на view острова (компонент view-фреймворка). */
29
- view: unknown;
30
- /**
31
- * View-слой — чем остров рисовать: `defineLayer(ViewLayerToken, { adapter: reactAdapter() })`.
32
- *
33
- * Обязателен, и дефолта нет ни у ядра, ни у хоста: фреймворк за приложение не выбирают.
34
- * Слой регистрируется в контейнере острова, поэтому слоты внутри по умолчанию рисуются
35
- * им же; слот перекрывает выбор своим `viewLayer`.
36
- */
37
- viewLayer: LayerDefinition;
38
- /**
39
- * Data/Business единицы (repository/service). Регистрируются в контейнере острова.
40
- * Не должны импортировать VM.
41
- */
42
- units: ReadonlyArray<Definition<unknown>>;
43
- /**
44
- * VM-единицы: регистрируются только в острове — оркестратор их не читает, состояние
45
- * ездит через denState.
46
- */
47
- viewModels?: ReadonlyArray<Definition<unknown>>;
48
- /**
49
- * Единицы, которые обязаны жить с загрузки, а не с первого резолва.
50
- *
51
- * Регистрация ленива по природе: не спросили — не создали. Обычно это то, что нужно, но
52
- * сервису, который сам на что-то подписывается или греет кэш, ждать первого потребителя
53
- * незачем. Токены — из тех же `units`.
54
- *
55
- * Поднимаются при МОНТИРОВАНИИ острова, а не при сборке контейнера: контейнер строится и на
56
- * сервере, а сервер живёт один рендер — открытая там WS-подписка это не «eager», а утечка.
57
- * Серверное состояние приложения считает активация VM.
58
- */
59
- eager?: ReadonlyArray<Token<unknown>>;
60
- /**
61
- * Места расширения приложения: ключ — локальное имя слота, значение — `defineSlot`.
62
- *
63
- * Карта, а не массив, потому что имя даёт хозяин места: адрес получается `app:key`
64
- * (см. `slotAddress`), занять чужое пространство имён нечем, а руками писать префикс
65
- * не нужно. Единицы слотов регистрируются в контейнере острова вместе с его собственными.
66
- */
67
- slots?: Readonly<Record<string, SlotDefinition>>;
68
- }
69
-
70
- /** Что приложение отдало серверным рендером. */
71
- interface ServerRenderResult {
72
- /** Разметка дерева — результат переданного рендера. */
73
- html: string;
74
- /**
75
- * Вклад в `<head>` ГОТОВОЙ разметкой: то, что рождается только во время рендера и
76
- * данными не описывается.
77
- *
78
- * Таковы стили CSS-in-JS: стороннее представление у них одно — тег со служебными
79
- * атрибутами, по которым клиентский рантайм узнаёт свои правила. Разобрав его на поля,
80
- * потеряешь регидратацию, и стили впрыснутся вторым экземпляром. Поэтому вклад в документ
81
- * ДАННЫМИ (`DocumentHead` у хостов) остаётся отдельным каналом, а это — разметка.
82
- *
83
- * Разметка приезжает в документ хоста ДОСЛОВНО, без экранирования — иначе служебные
84
- * атрибуты не пережили бы вставку. Отвечает за содержимое приложение: у сетевого
85
- * транспорта строка приходит из чужого процесса, и хост её не разбирает.
86
- */
87
- head?: string;
88
- }
89
- /** Рендер дерева в разметку. Его даёт тот, кто серверный рендер исполняет. */
90
- type RenderTree<Tree = unknown> = (tree: Tree) => string;
91
- /**
92
- * Серверный рендер приложения: приложению дают его дерево и рендер, оно возвращает
93
- * разметку и свой вклад в документ.
94
- *
95
- * Рендер приходит АРГУМЕНТОМ, потому что приложение им не владеет: страницу собирает тот,
96
- * кто держит документ, и приложений на ней может быть несколько. Отдав рендер аргументом,
97
- * приложение получает обычную функцию — состояние прохода живёт локальной переменной и
98
- * между запросами не утекает.
99
- *
100
- * Подпись одна на оба транспорта, и в этом смысл: у приложения в процессе хоста рендер
101
- * передаёт хост, у сетевого — его собственный сервер, а `html` и `head` едут ответом.
102
- * Перевод приложения между транспортами эту часть не задевает.
103
- *
104
- * `Tree` — дерево view-фреймворка, для ядра непрозрачное. View-адаптер сужает параметр
105
- * до своего типа (`ReactServerRender` в `@foxford/den-react`), и приложение пишет проход
106
- * в терминах СВОЕГО фреймворка.
107
- *
108
- * @example
109
- * serverRender: (tree, render) => {
110
- * const sheet = new ServerStyleSheet()
111
- *
112
- * return { head: sheet.getStyleTags(), html: render(sheet.collectStyles(tree)) }
113
- * }
114
- */
115
- type ServerRender<Tree = unknown> = (tree: Tree, render: RenderTree<Tree>) => ServerRenderResult;
116
-
117
- /** Что нужно адаптеру, чтобы отрисовать остров на сервере. */
118
- interface RenderIslandOptions {
119
- /** Контейнер острова — уже собранный, с активированными VM. */
120
- container: Container;
121
- /** Внешние заполнители слотов; для ядра непрозрачны, как и само дерево. */
122
- slots?: Record<string, unknown>;
123
- }
124
- /**
125
- * Порт view-адаптера. Реализуется пакетом фреймворка (`@foxford/den-react` и его аналоги),
126
- * объявляется приложением через `defineLayer(ViewLayerToken, { adapter })`.
127
- */
128
- interface ViewAdapter {
129
- /** Имя фреймворка (`react`, `vue`) — для диагностики и сообщений об ошибках. */
130
- readonly type: string;
131
- /**
132
- * Компонент острова для этого фреймворка: драйвит жизненный цикл ядра своими средствами
133
- * (у React — хуки, у Vue — `setup`) и рисует `descriptor.view`.
134
- *
135
- * @param descriptor - Дескриптор острова
136
- * @returns Компонент фреймворка — для ядра непрозрачен
137
- */
138
- createIsland(descriptor: IslandDescriptor): unknown;
139
- /**
140
- * Отрисовывает остров в разметку на сервере.
141
- *
142
- * Единственная операция острова, которую ядро не может сделать само: `renderToString` —
143
- * функция конкретного фреймворка, а ядро view-агностично. Здесь же адаптер исполняет
144
- * `serverRender` приложения, если тот объявлен, — тип дерева известен только адаптеру.
145
- *
146
- * @param descriptor - Дескриптор острова
147
- * @param options - Контейнер острова и заполнители слотов
148
- * @returns Разметка и вклад в `<head>` готовой разметкой
149
- */
150
- renderIsland(descriptor: IslandDescriptor, options: RenderIslandOptions): ServerRenderResult;
151
- /**
152
- * Ставит стратегию резолва `define*` во view (`installResolver` из `@foxford/den/adapter`).
153
- * У каждого фреймворка она своя: у React — хук поверх контекста контейнера, у Vue —
154
- * `inject`. Зовёт хост при инициализации трека.
155
- */
156
- installResolver(): void;
157
- }
158
- /**
159
- * Канонический токен view-слоя.
160
- *
161
- * Живёт в ядре именно потому, что «мы знаем, что зарегистрировано» работает лишь тогда,
162
- * когда токен один на всех: заведи его каждое приложение у себя — и движок не найдёт
163
- * чужую регистрацию.
164
- */
165
- declare const ViewLayerToken: Token<LayerConfig>;
166
- /** View-слой приложения — результат `defineLayer(ViewLayerToken, { adapter })`. */
167
- type ViewLayerDefinition = LayerDefinition;
168
- /**
169
- * Достаёт адаптер из объявленного приложением view-слоя.
170
- *
171
- * @param layer - View-слой (`defineLayer(ViewLayerToken, { adapter })`)
172
- * @returns Адаптер view-фреймворка
173
- * @throws Если слой объявлен без адаптера или адаптер не закрывает порт
174
- */
175
- declare function viewAdapterOf(layer: ViewLayerDefinition): ViewAdapter;
176
- /**
177
- * Достаёт адаптер из контейнера — с подъёмом по parent-chain, как это делает резолв во view.
178
- *
179
- * Нужен там, где на руках только контейнер (например, отрисовка слота внутри острова).
180
- * Дефолта нет намеренно: фреймворк за приложение ядро не выбирает.
181
- *
182
- * @param container - Контейнер острова/страницы
183
- * @returns Адаптер view-фреймворка
184
- * @throws Если приложение не объявило view-слой
185
- */
186
- declare function resolveViewAdapter(container: Container): ViewAdapter;
187
-
188
- export { type IslandDescriptor as I, type RenderIslandOptions as R, type ServerRender as S, type ViewAdapter as V, type ViewLayerDefinition as a, ViewLayerToken as b, type RenderTree as c, type ServerRenderResult as d, resolveViewAdapter as r, viewAdapterOf as v };