@foxford/den 3.2.5 → 3.4.0

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.
@@ -1,10 +1,11 @@
1
- import { A as AppAssets, I as IslandDescriptor } from '../descriptor-w8oxeIAe.cjs';
1
+ import { A as AppAssets, I as IslandDescriptor } from '../descriptor-Ced0k1__.cjs';
2
+ import { R as RequestContext } from '../types-BxMQ-VOd.cjs';
3
+ export { i as RequestContextToken } from '../types-BxMQ-VOd.cjs';
2
4
  import { Container } from '@foxford/ioc';
3
- import { R as RequestContext } from '../types-Dx5qGiwk.cjs';
4
- export { A as AppRoute, R as RouteDeclaration, a as RouteMatch, m as matchRoute, n as normalizeRoutes, p as pathPattern } from '../routes-B0hDrkiF.cjs';
5
+ export { A as AppRoute, R as RouteDeclaration, a as RouteMatch, m as matchRoute, n as normalizeRoutes, p as pathPattern } from '../routes-BvV405k4.cjs';
5
6
  export { R as RenderTree, a as ServerRender, S as ServerRenderResult } from '../server-render-CocWXQKC.cjs';
6
- export { R as RenderIslandOptions, V as ViewAdapter, a as ViewLayerDefinition, b as ViewLayerToken, r as resolveViewAdapter, v as viewAdapterOf } from '../view-adapter-DF1me25J.cjs';
7
- import '../define-slot-DouHW8RK.cjs';
7
+ export { R as RenderIslandOptions, V as ViewAdapter, a as ViewLayerDefinition, b as ViewLayerToken, r as resolveViewAdapter, v as viewAdapterOf } from '../view-adapter-D8I06K7s.cjs';
8
+ import '../define-slot-BEeHNEph.cjs';
8
9
 
9
10
  /** Вклад приложения в `<head>` документа. */
10
11
  interface DocumentHead {
@@ -69,6 +70,38 @@ interface DocumentSource {
69
70
  */
70
71
  declare function isDocumentSource(value: unknown): value is DocumentSource;
71
72
 
73
+ /**
74
+ * Клиентские падения острова между бандлами.
75
+ *
76
+ * Сетевое приложение оживает своим бандлом, хост — своим. У каждого своя копия модулей,
77
+ * module-level очередь в одной не видна в другой. Шина — массив на `window`.
78
+ *
79
+ * Остров кладёт исходное исключение через {@link reportIslandError}. Хост после Sentry.init
80
+ * сам сливает backlog и при необходимости перехватывает `.push` того же массива. Обёртки
81
+ * нет: стек и тип остаются приложению.
82
+ */
83
+ /** Фаза, на которой остров упал. */
84
+ type IslandErrorPhase = 'render' | 'hydrate' | 'navigate';
85
+ /** Контекст падения острова. */
86
+ interface IslandErrorContext {
87
+ /** Имя приложения из дескриптора. */
88
+ appName: string;
89
+ phase: IslandErrorPhase;
90
+ }
91
+ /** Одна запись очереди: исходное исключение и контекст. */
92
+ interface IslandErrorReport {
93
+ error: unknown;
94
+ context: IslandErrorContext;
95
+ }
96
+ /** Ключ массива на `window` — обязан совпадать у хоста и remote. */
97
+ declare const ISLAND_ERRORS_KEY = "__DEN_ISLAND_ERRORS__";
98
+ /**
99
+ * Кладёт исходное исключение в очередь на `window`.
100
+ *
101
+ * Хост разгребает массив сам (после инициализации наблюдаемости).
102
+ */
103
+ declare function reportIslandError(error: unknown, context: IslandErrorContext): void;
104
+
72
105
  /**
73
106
  * Адрес, по которому рендерится остров.
74
107
  *
@@ -92,6 +125,18 @@ interface CreateIslandContainerOptions {
92
125
  * сервисы. Хост биндит их один раз в app-контейнер, а резолв поднимается по parent-chain.
93
126
  */
94
127
  parent?: Container;
128
+ /**
129
+ * Реквизиты запроса — заголовки и куки. На сервере их даёт исполнитель (хост либо сетевой
130
+ * рантайм из `X-Forwarded-*`), в браузере адаптер берёт их из документа. Биндятся под
131
+ * `RequestContextToken` до регистрации единиц, поэтому единица вправе их требовать на
132
+ * обеих сторонах.
133
+ */
134
+ context?: RequestContext;
135
+ /**
136
+ * Входные данные хоста по ключу `token.description` — биндятся те, что дескриптор объявил
137
+ * в `inputs`. На сервере — из запроса, в браузере — из состояния документа.
138
+ */
139
+ inputs?: Record<string, unknown>;
95
140
  }
96
141
  /**
97
142
  * Собирает контейнер острова: scope-логгер, биндинги хоста, регистрация units + VM + слотов.
@@ -208,6 +253,43 @@ declare function publishIslandDocument(node: EventTarget, contribution: Document
208
253
  */
209
254
  declare function onIslandDocument(node: EventTarget, onDocument: (contribution: DocumentContribution) => void): () => void;
210
255
 
256
+ /**
257
+ * Входные данные, объявленные дескриптором, из переданного набора.
258
+ *
259
+ * @param descriptor - Дескриптор острова
260
+ * @param source - Набор по ключу `token.description`: тело запроса либо состояние документа
261
+ * @returns Только объявленные и присутствующие ключи
262
+ */
263
+ declare function islandInputsOf(descriptor: IslandDescriptor, source: Record<string, unknown> | undefined): Record<string, unknown>;
264
+ /**
265
+ * Биндит входные данные в контейнер острова под объявленными токенами.
266
+ *
267
+ * Не присланное не биндится: единица, которая требует такой токен, упадёт на резолве, и это
268
+ * честный отказ — хост не отдал то, без чего приложение работать не обязано.
269
+ *
270
+ * @param container - Контейнер острова
271
+ * @param descriptor - Дескриптор острова
272
+ * @param inputs - Входные данные по ключу `token.description`
273
+ */
274
+ declare function bindIslandInputs(container: Container, descriptor: IslandDescriptor, inputs: Record<string, unknown> | undefined): void;
275
+ /** Разбирает `Cookie` в карту. Дубли: побеждает первый, как и в браузере. */
276
+ declare function parseCookieHeader(header: string | undefined): Record<string, string>;
277
+ /**
278
+ * Реквизиты запроса в браузере: куки документа, заголовков нет.
279
+ *
280
+ * Биндится в контейнер острова при сборке, чтобы единица, требующая `RequestContextToken`,
281
+ * резолвилась на обеих сторонах одинаково; иначе приложению пришлось бы держать две
282
+ * реализации и переключать их по среде.
283
+ */
284
+ declare function browserRequestContext(): RequestContext;
285
+ /**
286
+ * Биндит реквизиты запроса в контейнер острова.
287
+ *
288
+ * @param container - Контейнер острова
289
+ * @param context - Реквизиты: серверные из `X-Forwarded-*`, браузерные из документа
290
+ */
291
+ declare function bindRequestContext(container: Container, context: RequestContext | undefined): void;
292
+
211
293
  /** Запрос на рендер приложения. */
212
294
  interface RenderAppRequest {
213
295
  /** Путь без search, с ведущим слэшем: `/legal/general`. */
@@ -222,6 +304,12 @@ interface RenderAppRequest {
222
304
  * транспортов: в процессе хоста их даёт хост, за сетью — сетевой рантайм из `X-Forwarded-*`.
223
305
  */
224
306
  context?: RequestContext;
307
+ /**
308
+ * Входные данные хоста по ключу `token.description`: посетитель, настройки, эксперименты.
309
+ * В контейнер попадают только те, что дескриптор объявил в `inputs`; они же уезжают в
310
+ * состояние ответа, чтобы остров в браузере получил их вместе с состоянием VM.
311
+ */
312
+ inputs?: Record<string, unknown>;
225
313
  /**
226
314
  * Родитель контейнера приложения: через него приезжает всё, что настроил исполнитель, —
227
315
  * логгер, конфиг HTTP, выданные возможности. По умолчанию — app-scope контейнер.
@@ -324,4 +412,4 @@ declare function getAppContainer(): Container;
324
412
  */
325
413
  declare function slotAddress(app: string, slot: string): string;
326
414
 
327
- export { AppAssets, type CreateIslandContainerOptions, DOCUMENT_EVENT, type DocumentContribution, type DocumentHead, type DocumentSource, IslandDescriptor, type IslandRecord, type IslandRoute, NAVIGATE_EVENT, type RenderAppRequest, type RenderAppResult, activateIslandViewModels, collectDocumentContribution, collectIslandState, createIslandContainer, describeIsland, getAppContainer, getIslandsSnapshot, hydrateIslandState, isDocumentSource, navigateIsland, onIslandDocument, onIslandNavigate, publishIslandDocument, registerIsland, renderApp, resolveEagerUnits, slotAddress, subscribeIslands };
415
+ export { AppAssets, type CreateIslandContainerOptions, DOCUMENT_EVENT, type DocumentContribution, type DocumentHead, type DocumentSource, ISLAND_ERRORS_KEY, IslandDescriptor, type IslandErrorContext, type IslandErrorPhase, type IslandErrorReport, type IslandRecord, type IslandRoute, NAVIGATE_EVENT, type RenderAppRequest, type RenderAppResult, RequestContext, activateIslandViewModels, bindIslandInputs, bindRequestContext, browserRequestContext, collectDocumentContribution, collectIslandState, createIslandContainer, describeIsland, getAppContainer, getIslandsSnapshot, hydrateIslandState, isDocumentSource, islandInputsOf, navigateIsland, onIslandDocument, onIslandNavigate, parseCookieHeader, publishIslandDocument, registerIsland, renderApp, reportIslandError, resolveEagerUnits, slotAddress, subscribeIslands };
package/island/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import { A as AppAssets, I as IslandDescriptor } from '../descriptor-tWPa9j-x.js';
1
+ import { A as AppAssets, I as IslandDescriptor } from '../descriptor-CLIZRmY4.js';
2
+ import { R as RequestContext } from '../types-BxMQ-VOd.js';
3
+ export { i as RequestContextToken } from '../types-BxMQ-VOd.js';
2
4
  import { Container } from '@foxford/ioc';
3
- import { R as RequestContext } from '../types-Dx5qGiwk.js';
4
- export { A as AppRoute, R as RouteDeclaration, a as RouteMatch, m as matchRoute, n as normalizeRoutes, p as pathPattern } from '../routes-0uXJ0fux.js';
5
+ export { A as AppRoute, R as RouteDeclaration, a as RouteMatch, m as matchRoute, n as normalizeRoutes, p as pathPattern } from '../routes-Di3K_0uQ.js';
5
6
  export { R as RenderTree, a as ServerRender, S as ServerRenderResult } from '../server-render-CocWXQKC.js';
6
- export { R as RenderIslandOptions, V as ViewAdapter, a as ViewLayerDefinition, b as ViewLayerToken, r as resolveViewAdapter, v as viewAdapterOf } from '../view-adapter-BV62bdhM.js';
7
- import '../define-slot-TkqbLySB.js';
7
+ export { R as RenderIslandOptions, V as ViewAdapter, a as ViewLayerDefinition, b as ViewLayerToken, r as resolveViewAdapter, v as viewAdapterOf } from '../view-adapter-BTaoZgTQ.js';
8
+ import '../define-slot-CdWdFM16.js';
8
9
 
9
10
  /** Вклад приложения в `<head>` документа. */
10
11
  interface DocumentHead {
@@ -69,6 +70,38 @@ interface DocumentSource {
69
70
  */
70
71
  declare function isDocumentSource(value: unknown): value is DocumentSource;
71
72
 
73
+ /**
74
+ * Клиентские падения острова между бандлами.
75
+ *
76
+ * Сетевое приложение оживает своим бандлом, хост — своим. У каждого своя копия модулей,
77
+ * module-level очередь в одной не видна в другой. Шина — массив на `window`.
78
+ *
79
+ * Остров кладёт исходное исключение через {@link reportIslandError}. Хост после Sentry.init
80
+ * сам сливает backlog и при необходимости перехватывает `.push` того же массива. Обёртки
81
+ * нет: стек и тип остаются приложению.
82
+ */
83
+ /** Фаза, на которой остров упал. */
84
+ type IslandErrorPhase = 'render' | 'hydrate' | 'navigate';
85
+ /** Контекст падения острова. */
86
+ interface IslandErrorContext {
87
+ /** Имя приложения из дескриптора. */
88
+ appName: string;
89
+ phase: IslandErrorPhase;
90
+ }
91
+ /** Одна запись очереди: исходное исключение и контекст. */
92
+ interface IslandErrorReport {
93
+ error: unknown;
94
+ context: IslandErrorContext;
95
+ }
96
+ /** Ключ массива на `window` — обязан совпадать у хоста и remote. */
97
+ declare const ISLAND_ERRORS_KEY = "__DEN_ISLAND_ERRORS__";
98
+ /**
99
+ * Кладёт исходное исключение в очередь на `window`.
100
+ *
101
+ * Хост разгребает массив сам (после инициализации наблюдаемости).
102
+ */
103
+ declare function reportIslandError(error: unknown, context: IslandErrorContext): void;
104
+
72
105
  /**
73
106
  * Адрес, по которому рендерится остров.
74
107
  *
@@ -92,6 +125,18 @@ interface CreateIslandContainerOptions {
92
125
  * сервисы. Хост биндит их один раз в app-контейнер, а резолв поднимается по parent-chain.
93
126
  */
94
127
  parent?: Container;
128
+ /**
129
+ * Реквизиты запроса — заголовки и куки. На сервере их даёт исполнитель (хост либо сетевой
130
+ * рантайм из `X-Forwarded-*`), в браузере адаптер берёт их из документа. Биндятся под
131
+ * `RequestContextToken` до регистрации единиц, поэтому единица вправе их требовать на
132
+ * обеих сторонах.
133
+ */
134
+ context?: RequestContext;
135
+ /**
136
+ * Входные данные хоста по ключу `token.description` — биндятся те, что дескриптор объявил
137
+ * в `inputs`. На сервере — из запроса, в браузере — из состояния документа.
138
+ */
139
+ inputs?: Record<string, unknown>;
95
140
  }
96
141
  /**
97
142
  * Собирает контейнер острова: scope-логгер, биндинги хоста, регистрация units + VM + слотов.
@@ -208,6 +253,43 @@ declare function publishIslandDocument(node: EventTarget, contribution: Document
208
253
  */
209
254
  declare function onIslandDocument(node: EventTarget, onDocument: (contribution: DocumentContribution) => void): () => void;
210
255
 
256
+ /**
257
+ * Входные данные, объявленные дескриптором, из переданного набора.
258
+ *
259
+ * @param descriptor - Дескриптор острова
260
+ * @param source - Набор по ключу `token.description`: тело запроса либо состояние документа
261
+ * @returns Только объявленные и присутствующие ключи
262
+ */
263
+ declare function islandInputsOf(descriptor: IslandDescriptor, source: Record<string, unknown> | undefined): Record<string, unknown>;
264
+ /**
265
+ * Биндит входные данные в контейнер острова под объявленными токенами.
266
+ *
267
+ * Не присланное не биндится: единица, которая требует такой токен, упадёт на резолве, и это
268
+ * честный отказ — хост не отдал то, без чего приложение работать не обязано.
269
+ *
270
+ * @param container - Контейнер острова
271
+ * @param descriptor - Дескриптор острова
272
+ * @param inputs - Входные данные по ключу `token.description`
273
+ */
274
+ declare function bindIslandInputs(container: Container, descriptor: IslandDescriptor, inputs: Record<string, unknown> | undefined): void;
275
+ /** Разбирает `Cookie` в карту. Дубли: побеждает первый, как и в браузере. */
276
+ declare function parseCookieHeader(header: string | undefined): Record<string, string>;
277
+ /**
278
+ * Реквизиты запроса в браузере: куки документа, заголовков нет.
279
+ *
280
+ * Биндится в контейнер острова при сборке, чтобы единица, требующая `RequestContextToken`,
281
+ * резолвилась на обеих сторонах одинаково; иначе приложению пришлось бы держать две
282
+ * реализации и переключать их по среде.
283
+ */
284
+ declare function browserRequestContext(): RequestContext;
285
+ /**
286
+ * Биндит реквизиты запроса в контейнер острова.
287
+ *
288
+ * @param container - Контейнер острова
289
+ * @param context - Реквизиты: серверные из `X-Forwarded-*`, браузерные из документа
290
+ */
291
+ declare function bindRequestContext(container: Container, context: RequestContext | undefined): void;
292
+
211
293
  /** Запрос на рендер приложения. */
212
294
  interface RenderAppRequest {
213
295
  /** Путь без search, с ведущим слэшем: `/legal/general`. */
@@ -222,6 +304,12 @@ interface RenderAppRequest {
222
304
  * транспортов: в процессе хоста их даёт хост, за сетью — сетевой рантайм из `X-Forwarded-*`.
223
305
  */
224
306
  context?: RequestContext;
307
+ /**
308
+ * Входные данные хоста по ключу `token.description`: посетитель, настройки, эксперименты.
309
+ * В контейнер попадают только те, что дескриптор объявил в `inputs`; они же уезжают в
310
+ * состояние ответа, чтобы остров в браузере получил их вместе с состоянием VM.
311
+ */
312
+ inputs?: Record<string, unknown>;
225
313
  /**
226
314
  * Родитель контейнера приложения: через него приезжает всё, что настроил исполнитель, —
227
315
  * логгер, конфиг HTTP, выданные возможности. По умолчанию — app-scope контейнер.
@@ -324,4 +412,4 @@ declare function getAppContainer(): Container;
324
412
  */
325
413
  declare function slotAddress(app: string, slot: string): string;
326
414
 
327
- export { AppAssets, type CreateIslandContainerOptions, DOCUMENT_EVENT, type DocumentContribution, type DocumentHead, type DocumentSource, IslandDescriptor, type IslandRecord, type IslandRoute, NAVIGATE_EVENT, type RenderAppRequest, type RenderAppResult, activateIslandViewModels, collectDocumentContribution, collectIslandState, createIslandContainer, describeIsland, getAppContainer, getIslandsSnapshot, hydrateIslandState, isDocumentSource, navigateIsland, onIslandDocument, onIslandNavigate, publishIslandDocument, registerIsland, renderApp, resolveEagerUnits, slotAddress, subscribeIslands };
415
+ export { AppAssets, type CreateIslandContainerOptions, DOCUMENT_EVENT, type DocumentContribution, type DocumentHead, type DocumentSource, ISLAND_ERRORS_KEY, IslandDescriptor, type IslandErrorContext, type IslandErrorPhase, type IslandErrorReport, type IslandRecord, type IslandRoute, NAVIGATE_EVENT, type RenderAppRequest, type RenderAppResult, RequestContext, activateIslandViewModels, bindIslandInputs, bindRequestContext, browserRequestContext, collectDocumentContribution, collectIslandState, createIslandContainer, describeIsland, getAppContainer, getIslandsSnapshot, hydrateIslandState, isDocumentSource, islandInputsOf, navigateIsland, onIslandDocument, onIslandNavigate, parseCookieHeader, publishIslandDocument, registerIsland, renderApp, reportIslandError, resolveEagerUnits, slotAddress, subscribeIslands };
package/island/index.js CHANGED
@@ -1,28 +1,50 @@
1
1
  import {
2
2
  activateIslandViewModels,
3
+ bindIslandInputs,
4
+ bindRequestContext,
5
+ browserRequestContext,
3
6
  collectDocumentContribution,
4
7
  collectIslandState,
5
8
  createIslandContainer,
6
9
  getAppContainer,
7
10
  hydrateIslandState,
8
11
  isDocumentSource,
12
+ islandInputsOf,
9
13
  matchRoute,
10
14
  normalizeRoutes,
15
+ parseCookieHeader,
11
16
  pathPattern,
12
17
  renderApp,
13
18
  resolveEagerUnits
14
- } from "../chunk-SOH2TL2N.js";
19
+ } from "../chunk-LBXA2QIB.js";
15
20
  import {
16
21
  ViewLayerToken,
17
22
  resolveViewAdapter,
18
23
  viewAdapterOf
19
24
  } from "../chunk-E23E2VUC.js";
20
- import "../chunk-3RX2OSUL.js";
25
+ import {
26
+ RequestContextToken
27
+ } from "../chunk-3RX2OSUL.js";
21
28
  import "../chunk-TPBI6TOU.js";
22
29
  import {
23
30
  __spreadValues
24
31
  } from "../chunk-6FNC3XMI.js";
25
32
 
33
+ // src/island/errors.ts
34
+ var ISLAND_ERRORS_KEY = "__DEN_ISLAND_ERRORS__";
35
+ function reportIslandError(error, context) {
36
+ var _a;
37
+ if (typeof window === "undefined") {
38
+ return;
39
+ }
40
+ const w = window;
41
+ const queue = (_a = w[ISLAND_ERRORS_KEY]) != null ? _a : [];
42
+ if (w[ISLAND_ERRORS_KEY] === void 0) {
43
+ w[ISLAND_ERRORS_KEY] = queue;
44
+ }
45
+ queue.push({ context, error });
46
+ }
47
+
26
48
  // src/island/navigate.ts
27
49
  var NAVIGATE_EVENT = "den:navigate";
28
50
  function navigateIsland(node, route) {
@@ -97,9 +119,14 @@ function describeIsland(descriptor, denState) {
97
119
  }
98
120
  export {
99
121
  DOCUMENT_EVENT,
122
+ ISLAND_ERRORS_KEY,
100
123
  NAVIGATE_EVENT,
124
+ RequestContextToken,
101
125
  ViewLayerToken,
102
126
  activateIslandViewModels,
127
+ bindIslandInputs,
128
+ bindRequestContext,
129
+ browserRequestContext,
103
130
  collectDocumentContribution,
104
131
  collectIslandState,
105
132
  createIslandContainer,
@@ -108,15 +135,18 @@ export {
108
135
  getIslandsSnapshot,
109
136
  hydrateIslandState,
110
137
  isDocumentSource,
138
+ islandInputsOf,
111
139
  matchRoute,
112
140
  navigateIsland,
113
141
  normalizeRoutes,
114
142
  onIslandDocument,
115
143
  onIslandNavigate,
144
+ parseCookieHeader,
116
145
  pathPattern,
117
146
  publishIslandDocument,
118
147
  registerIsland,
119
148
  renderApp,
149
+ reportIslandError,
120
150
  resolveEagerUnits,
121
151
  resolveViewAdapter,
122
152
  slotAddress,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@foxford/den",
3
- "version": "3.2.5",
3
+ "version": "3.4.0",
4
4
  "description": "Den — декларативный метафреймворк Foxford (core runtime)",
5
5
  "keywords": [
6
6
  "foxford",
@@ -100,40 +100,40 @@
100
100
  "chunk-G6RT4EBO.cjs",
101
101
  "chunk-H5DKRHHQ.cjs",
102
102
  "chunk-KQAB6C6Q.cjs",
103
+ "chunk-LBXA2QIB.js",
104
+ "chunk-M5CR4TJC.cjs",
103
105
  "chunk-RG7ZV5BD.js",
104
- "chunk-SOH2TL2N.js",
105
106
  "chunk-T5QVCXVB.cjs",
106
107
  "chunk-TPBI6TOU.js",
107
108
  "chunk-WBHHHICS.js",
108
- "chunk-XDM6J4LJ.cjs",
109
109
  "chunk-XOJ2VWX4.cjs",
110
- "define-repository-CwAXed2X.d.cts",
111
- "define-repository-q_T4hqeP.d.ts",
112
- "define-slot-DouHW8RK.d.cts",
113
- "define-slot-TkqbLySB.d.ts",
110
+ "define-repository-AO7JI6Cb.d.ts",
111
+ "define-repository-C0MI-J32.d.cts",
112
+ "define-slot-BEeHNEph.d.cts",
113
+ "define-slot-CdWdFM16.d.ts",
114
114
  "define.cjs",
115
115
  "define.d.cts",
116
116
  "define.d.ts",
117
117
  "define.js",
118
118
  "den.js",
119
- "descriptor-tWPa9j-x.d.ts",
120
- "descriptor-w8oxeIAe.d.cts",
119
+ "descriptor-CLIZRmY4.d.ts",
120
+ "descriptor-Ced0k1__.d.cts",
121
121
  "index.cjs",
122
122
  "index.d.cts",
123
123
  "index.d.ts",
124
124
  "index.js",
125
125
  "island",
126
126
  "package.json",
127
- "routes-0uXJ0fux.d.ts",
128
- "routes-B0hDrkiF.d.cts",
127
+ "routes-BvV405k4.d.cts",
128
+ "routes-Di3K_0uQ.d.ts",
129
129
  "serve",
130
130
  "server-render-CocWXQKC.d.cts",
131
131
  "server-render-CocWXQKC.d.ts",
132
- "types-Dx5qGiwk.d.cts",
133
- "types-Dx5qGiwk.d.ts",
134
- "view-adapter-BV62bdhM.d.ts",
135
- "view-adapter-DF1me25J.d.cts"
132
+ "types-BxMQ-VOd.d.cts",
133
+ "types-BxMQ-VOd.d.ts",
134
+ "view-adapter-BTaoZgTQ.d.ts",
135
+ "view-adapter-D8I06K7s.d.cts"
136
136
  ],
137
- "sha": "25ef468",
137
+ "sha": "7da7d38",
138
138
  "scripts": {}
139
139
  }
@@ -1,4 +1,4 @@
1
- import { G as GuardDefinition } from './types-Dx5qGiwk.cjs';
1
+ import { G as GuardDefinition } from './types-BxMQ-VOd.cjs';
2
2
 
3
3
  /** Маршрут с политикой доступа. */
4
4
  interface RouteDeclaration {
@@ -1,4 +1,4 @@
1
- import { G as GuardDefinition } from './types-Dx5qGiwk.js';
1
+ import { G as GuardDefinition } from './types-BxMQ-VOd.js';
2
2
 
3
3
  /** Маршрут с политикой доступа. */
4
4
  interface RouteDeclaration {
package/serve/index.cjs CHANGED
@@ -5,7 +5,8 @@ var _chunkKQAB6C6Qcjs = require('../chunk-KQAB6C6Q.cjs');
5
5
 
6
6
 
7
7
 
8
- var _chunkXDM6J4LJcjs = require('../chunk-XDM6J4LJ.cjs');
8
+
9
+ var _chunkM5CR4TJCcjs = require('../chunk-M5CR4TJC.cjs');
9
10
  require('../chunk-XOJ2VWX4.cjs');
10
11
  require('../chunk-6QV4L6R2.cjs');
11
12
 
@@ -69,28 +70,14 @@ function registerAssets(instance, source) {
69
70
 
70
71
  var DEFAULT_SLOW_RENDER_MS = 1e3;
71
72
  function claim(app) {
72
- return _chunkXDM6J4LJcjs.normalizeRoutes.call(void 0, app.routes).map((route) => route.source);
73
+ return _chunkM5CR4TJCcjs.normalizeRoutes.call(void 0, app.routes).map((route) => route.source);
73
74
  }
74
75
  function matchClaim(app, pathname) {
75
76
  var _a, _b;
76
77
  if (claim(app).length === 0) {
77
78
  return {};
78
79
  }
79
- return (_b = (_a = _chunkXDM6J4LJcjs.matchRoute.call(void 0, app.routes, pathname)) == null ? void 0 : _a.params) != null ? _b : null;
80
- }
81
- function parseCookies(header) {
82
- const cookies = {};
83
- for (const part of (header != null ? header : "").split(";")) {
84
- const eq = part.indexOf("=");
85
- if (eq < 1) {
86
- continue;
87
- }
88
- const name = part.slice(0, eq).trim();
89
- if (name && !(name in cookies)) {
90
- cookies[name] = part.slice(eq + 1).trim();
91
- }
92
- }
93
- return cookies;
80
+ return (_b = (_a = _chunkM5CR4TJCcjs.matchRoute.call(void 0, app.routes, pathname)) == null ? void 0 : _a.params) != null ? _b : null;
94
81
  }
95
82
  function browserContext(req) {
96
83
  const headers = {};
@@ -107,7 +94,7 @@ function browserContext(req) {
107
94
  if (typeof cookie === "string" && cookie !== "") {
108
95
  headers.cookie = cookie;
109
96
  }
110
- return { cookies: parseCookies(cookie), headers };
97
+ return { cookies: _chunkM5CR4TJCcjs.parseCookieHeader.call(void 0, cookie), headers };
111
98
  }
112
99
  var appPlugin = (instance, options) => {
113
100
  var _a, _b;
@@ -119,30 +106,50 @@ var appPlugin = (instance, options) => {
119
106
  void reply.header("cache-control", "no-store");
120
107
  return claim(app);
121
108
  });
122
- instance.get("/_render", (req, reply) => _chunkT5QVCXVBcjs.__async.call(void 0, null, null, function* () {
123
- const target = req.query.url;
124
- if (typeof target !== "string" || !target.startsWith("/")) {
125
- return reply.code(400).send({ error: "\u043D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u043D \u0438\u043B\u0438 \u043D\u0435\u0432\u0430\u043B\u0438\u0434\u0435\u043D \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 url" });
126
- }
127
- const { pathname, search } = new URL(target, "http://localhost");
128
- const params = matchClaim(app, pathname);
129
- if (params === null) {
130
- serveLog.error(`\u043F\u0443\u0442\u044C \xAB${pathname}\xBB \u0432\u043D\u0435 \u0437\u0430\u044F\u0432\u043A\u0438 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F`);
131
- return reply.code(404).send({ error: `\u043F\u0443\u0442\u044C \xAB${pathname}\xBB \u0432\u043D\u0435 \u0437\u0430\u044F\u0432\u043A\u0438 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F` });
132
- }
133
- const startedAt = Date.now();
134
- try {
135
- const result = yield _chunkXDM6J4LJcjs.renderApp.call(void 0, app, { context: browserContext(req), params, pathname, search });
136
- const elapsed = Date.now() - startedAt;
137
- if (elapsed >= slowRenderMs) {
138
- serveLog.warn(`\u043C\u0435\u0434\u043B\u0435\u043D\u043D\u044B\u0439 \u0440\u0435\u043D\u0434\u0435\u0440 \xAB${pathname}\xBB: ${String(elapsed)}\u043C\u0441`);
109
+ function handleRender(req, reply, target, inputs) {
110
+ return _chunkT5QVCXVBcjs.__async.call(void 0, this, null, function* () {
111
+ if (typeof target !== "string" || !target.startsWith("/")) {
112
+ return reply.code(400).send({ error: "\u043D\u0435 \u043F\u0435\u0440\u0435\u0434\u0430\u043D \u0438\u043B\u0438 \u043D\u0435\u0432\u0430\u043B\u0438\u0434\u0435\u043D \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 url" });
139
113
  }
140
- return result;
141
- } catch (error) {
142
- serveLog.error(`\u0440\u0435\u043D\u0434\u0435\u0440 \xAB${pathname}\xBB \u0443\u043F\u0430\u043B \u0437\u0430 ${String(Date.now() - startedAt)}\u043C\u0441`, error);
143
- return reply.send(error instanceof Error ? error : new Error(String(error)));
144
- }
145
- }));
114
+ if (inputs !== void 0 && (typeof inputs !== "object" || inputs === null || Array.isArray(inputs))) {
115
+ return reply.code(400).send({ error: "inputs \u0434\u043E\u043B\u0436\u043D\u044B \u0431\u044B\u0442\u044C \u043E\u0431\u044A\u0435\u043A\u0442\u043E\u043C \u043F\u043E \u043A\u043B\u044E\u0447\u0443 token.description" });
116
+ }
117
+ const { pathname, search } = new URL(target, "http://localhost");
118
+ const params = matchClaim(app, pathname);
119
+ if (params === null) {
120
+ serveLog.error(`\u043F\u0443\u0442\u044C \xAB${pathname}\xBB \u0432\u043D\u0435 \u0437\u0430\u044F\u0432\u043A\u0438 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F`);
121
+ return reply.code(404).send({ error: `\u043F\u0443\u0442\u044C \xAB${pathname}\xBB \u0432\u043D\u0435 \u0437\u0430\u044F\u0432\u043A\u0438 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F` });
122
+ }
123
+ const startedAt = Date.now();
124
+ try {
125
+ const result = yield _chunkM5CR4TJCcjs.renderApp.call(void 0, app, {
126
+ context: browserContext(req),
127
+ inputs,
128
+ params,
129
+ pathname,
130
+ search
131
+ });
132
+ const elapsed = Date.now() - startedAt;
133
+ if (elapsed >= slowRenderMs) {
134
+ serveLog.warn(`\u043C\u0435\u0434\u043B\u0435\u043D\u043D\u044B\u0439 \u0440\u0435\u043D\u0434\u0435\u0440 \xAB${pathname}\xBB: ${String(elapsed)}\u043C\u0441`);
135
+ }
136
+ return result;
137
+ } catch (error) {
138
+ serveLog.error(`\u0440\u0435\u043D\u0434\u0435\u0440 \xAB${pathname}\xBB \u0443\u043F\u0430\u043B \u0437\u0430 ${String(Date.now() - startedAt)}\u043C\u0441`, error);
139
+ return reply.send(error instanceof Error ? error : new Error(String(error)));
140
+ }
141
+ });
142
+ }
143
+ instance.get("/_render", (req, reply) => handleRender(req, reply, req.query.url, void 0));
144
+ instance.route({
145
+ handler: (req, reply) => {
146
+ var _a2;
147
+ const body = (_a2 = req.body) != null ? _a2 : {};
148
+ return handleRender(req, reply, body.url, body.inputs);
149
+ },
150
+ method: "QUERY",
151
+ url: "/_render"
152
+ });
146
153
  return Promise.resolve();
147
154
  };
148
155
 
package/serve/index.d.cts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { FastifyInstance, FastifyPluginAsync } from 'fastify';
2
- import { I as IslandDescriptor } from '../descriptor-w8oxeIAe.cjs';
3
- import { A as AppRoute } from '../routes-B0hDrkiF.cjs';
4
- import '../define-slot-DouHW8RK.cjs';
5
- import '../types-Dx5qGiwk.cjs';
2
+ import { I as IslandDescriptor } from '../descriptor-Ced0k1__.cjs';
3
+ import { A as AppRoute } from '../routes-BvV405k4.cjs';
4
+ import '../define-slot-BEeHNEph.cjs';
5
+ import '../types-BxMQ-VOd.cjs';
6
6
  import '@foxford/ioc';
7
7
 
8
8
  /** Что раздаётся и по какому префиксу. */
package/serve/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { FastifyInstance, FastifyPluginAsync } from 'fastify';
2
- import { I as IslandDescriptor } from '../descriptor-tWPa9j-x.js';
3
- import { A as AppRoute } from '../routes-0uXJ0fux.js';
4
- import '../define-slot-TkqbLySB.js';
5
- import '../types-Dx5qGiwk.js';
2
+ import { I as IslandDescriptor } from '../descriptor-CLIZRmY4.js';
3
+ import { A as AppRoute } from '../routes-Di3K_0uQ.js';
4
+ import '../define-slot-CdWdFM16.js';
5
+ import '../types-BxMQ-VOd.js';
6
6
  import '@foxford/ioc';
7
7
 
8
8
  /** Что раздаётся и по какому префиксу. */