@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.
- package/README.mdx +266 -2
- package/adapter.cjs +1 -1
- package/adapter.d.cts +1 -1
- package/adapter.d.ts +1 -1
- package/adapter.js +1 -1
- package/bin/den.cjs +88 -0
- package/bin/den.d.cts +2 -0
- package/bin/den.d.ts +2 -0
- package/bin/den.js +88 -0
- package/builder/index.cjs +12 -0
- package/builder/index.d.cts +120 -0
- package/builder/index.d.ts +120 -0
- package/builder/index.js +12 -0
- package/chunk-3RX2OSUL.js +21 -0
- package/{chunk-HJO26HIQ.js → chunk-6FNC3XMI.js} +4 -0
- package/chunk-6QV4L6R2.cjs +21 -0
- package/{chunk-WRQC6BVJ.js → chunk-MCN4GFEQ.js} +4 -19
- package/chunk-OKRO4G4L.cjs +354 -0
- package/chunk-REFU7UMG.js +354 -0
- package/{chunk-XHYR3SGG.cjs → chunk-T5QVCXVB.cjs} +5 -1
- package/chunk-TPHJUDHG.js +230 -0
- package/{chunk-5DJZZML5.cjs → chunk-Z5BL4DJA.cjs} +10 -25
- package/chunk-ZOU6W6ZQ.cjs +230 -0
- package/{define-repository-MDEWHqM7.d.cts → define-repository-CwAXed2X.d.cts} +1 -1
- package/{define-repository-Ca62_YCy.d.ts → define-repository-q_T4hqeP.d.ts} +1 -1
- package/{define-slot-Dil8Kr1A.d.ts → define-slot-Cngzae6i.d.ts} +1 -1
- package/{define-slot-BKvArA02.d.cts → define-slot-DYNCLDJY.d.cts} +1 -1
- package/define.cjs +6 -4
- package/define.d.cts +3 -3
- package/define.d.ts +3 -3
- package/define.js +5 -3
- package/den.js +60 -0
- package/descriptor-DQ6Gi7A_.d.ts +98 -0
- package/descriptor-Dujg_1on.d.cts +98 -0
- package/index.cjs +25 -23
- package/index.d.cts +7 -5
- package/index.d.ts +7 -5
- package/index.js +12 -10
- package/island/index.cjs +12 -157
- package/island/index.d.cts +40 -30
- package/island/index.d.ts +40 -30
- package/island/index.js +19 -164
- package/package.json +59 -16
- package/routes-0uXJ0fux.d.ts +64 -0
- package/routes-B0hDrkiF.d.cts +64 -0
- package/serve/index.cjs +137 -0
- package/serve/index.d.cts +60 -0
- package/serve/index.d.ts +60 -0
- package/serve/index.js +137 -0
- package/server-render-CocWXQKC.d.cts +48 -0
- package/server-render-CocWXQKC.d.ts +48 -0
- package/{types-COwVwgzE.d.cts → types-Dx5qGiwk.d.cts} +1 -1
- package/{types-COwVwgzE.d.ts → types-Dx5qGiwk.d.ts} +1 -1
- package/view-adapter-B4gEb-ms.d.ts +77 -0
- package/view-adapter-DJ7yB6Ml.d.cts +77 -0
- package/view-adapter-BvDC5O4y.d.cts +0 -188
- package/view-adapter-DtNgyjIf.d.ts +0 -188
package/serve/index.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { I as IslandDescriptor } from '../descriptor-DQ6Gi7A_.js';
|
|
2
|
+
import { A as AppRoute } from '../routes-0uXJ0fux.js';
|
|
3
|
+
import { FastifyPluginAsync, FastifyInstance } from 'fastify';
|
|
4
|
+
import '../define-slot-Cngzae6i.js';
|
|
5
|
+
import '../types-Dx5qGiwk.js';
|
|
6
|
+
import '@foxford/ioc';
|
|
7
|
+
|
|
8
|
+
/** Приложение, которое можно поднять сервисом: остров плюс его заявка на адреса. */
|
|
9
|
+
type ServableApp = IslandDescriptor & {
|
|
10
|
+
routes?: ReadonlyArray<AppRoute>;
|
|
11
|
+
};
|
|
12
|
+
/** Настройки плагина. */
|
|
13
|
+
interface AppPluginOptions {
|
|
14
|
+
app: ServableApp;
|
|
15
|
+
/** Порог, выше которого рендер считается медленным и уходит в `warn`, мс. */
|
|
16
|
+
slowRenderMs?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Регистрирует ручки приложения на инстансе fastify: `/_render`, `/_routes`, `/_health`.
|
|
20
|
+
*
|
|
21
|
+
* Плагином, поэтому монтируется и в свой сервер, и в чужой — под префиксом, рядом с ручками
|
|
22
|
+
* потребителя, вместе с его плагинами.
|
|
23
|
+
*
|
|
24
|
+
* @param instance - Инстанс fastify
|
|
25
|
+
* @param options - Приложение и порог медленного рендера
|
|
26
|
+
*/
|
|
27
|
+
declare const appPlugin: FastifyPluginAsync<AppPluginOptions>;
|
|
28
|
+
|
|
29
|
+
/** Настройки инстанса. */
|
|
30
|
+
interface ServeAppOptions {
|
|
31
|
+
/** Порт; `0` — свободный, фактический смотри в `server.addresses()`. */
|
|
32
|
+
port?: number;
|
|
33
|
+
/** Интерфейс прослушивания. */
|
|
34
|
+
host?: string;
|
|
35
|
+
/** Порог, выше которого рендер считается медленным и уходит в `warn`, мс. */
|
|
36
|
+
slowRenderMs?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Расширение инстанса ДО прослушивания: сюда потребитель регистрирует свои плагины.
|
|
39
|
+
* Вызывается после ручек приложения, поэтому хуки видят и их.
|
|
40
|
+
*/
|
|
41
|
+
configure?: (instance: FastifyInstance) => void | Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Закрывать инстанс по `SIGTERM`/`SIGINT`. По умолчанию да: сервис живёт в оркестраторе,
|
|
44
|
+
* который именно так и просит его уйти, а незакрытый инстанс рвёт запросы на середине.
|
|
45
|
+
*/
|
|
46
|
+
gracefulShutdown?: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Поднимает приложение отдельным сервисом.
|
|
50
|
+
*
|
|
51
|
+
* Сахар над {@link appPlugin}: если сервер нужен свой (общий порт с чужими ручками, свой
|
|
52
|
+
* порядок плагинов), бери плагин и регистрируй сам.
|
|
53
|
+
*
|
|
54
|
+
* @param app - Дескриптор приложения вместе с его заявкой на адреса
|
|
55
|
+
* @param options - Порт, расширение инстанса, поведение при остановке
|
|
56
|
+
* @returns Слушающий инстанс fastify
|
|
57
|
+
*/
|
|
58
|
+
declare function serveApp(app: ServableApp, options?: ServeAppOptions): Promise<FastifyInstance>;
|
|
59
|
+
|
|
60
|
+
export { type AppPluginOptions, type ServableApp, type ServeAppOptions, appPlugin, serveApp };
|
package/serve/index.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import {
|
|
2
|
+
matchRoute,
|
|
3
|
+
normalizeRoutes,
|
|
4
|
+
renderApp
|
|
5
|
+
} from "../chunk-TPHJUDHG.js";
|
|
6
|
+
import "../chunk-E23E2VUC.js";
|
|
7
|
+
import "../chunk-3RX2OSUL.js";
|
|
8
|
+
import {
|
|
9
|
+
logger
|
|
10
|
+
} from "../chunk-TPBI6TOU.js";
|
|
11
|
+
import {
|
|
12
|
+
__async
|
|
13
|
+
} from "../chunk-6FNC3XMI.js";
|
|
14
|
+
|
|
15
|
+
// src/serve/index.ts
|
|
16
|
+
import Fastify from "fastify";
|
|
17
|
+
import { log as log2 } from "@foxford/logger";
|
|
18
|
+
|
|
19
|
+
// src/serve/plugin.ts
|
|
20
|
+
import { log } from "@foxford/logger";
|
|
21
|
+
var DEFAULT_SLOW_RENDER_MS = 1e3;
|
|
22
|
+
function claim(app) {
|
|
23
|
+
return normalizeRoutes(app.routes).map((route) => route.source);
|
|
24
|
+
}
|
|
25
|
+
function matchClaim(app, pathname) {
|
|
26
|
+
var _a, _b;
|
|
27
|
+
if (claim(app).length === 0) {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
return (_b = (_a = matchRoute(app.routes, pathname)) == null ? void 0 : _a.params) != null ? _b : null;
|
|
31
|
+
}
|
|
32
|
+
function parseCookies(header) {
|
|
33
|
+
const cookies = {};
|
|
34
|
+
for (const part of (header != null ? header : "").split(";")) {
|
|
35
|
+
const eq = part.indexOf("=");
|
|
36
|
+
if (eq < 1) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const name = part.slice(0, eq).trim();
|
|
40
|
+
if (name && !(name in cookies)) {
|
|
41
|
+
cookies[name] = part.slice(eq + 1).trim();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return cookies;
|
|
45
|
+
}
|
|
46
|
+
function browserContext(req) {
|
|
47
|
+
const headers = {};
|
|
48
|
+
const forwarded = {
|
|
49
|
+
"accept-language": req.headers["x-forwarded-accept-language"],
|
|
50
|
+
host: req.headers["x-forwarded-host"]
|
|
51
|
+
};
|
|
52
|
+
for (const [name, value] of Object.entries(forwarded)) {
|
|
53
|
+
if (typeof value === "string" && value !== "") {
|
|
54
|
+
headers[name] = value;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const cookie = req.headers.cookie;
|
|
58
|
+
if (typeof cookie === "string" && cookie !== "") {
|
|
59
|
+
headers.cookie = cookie;
|
|
60
|
+
}
|
|
61
|
+
return { cookies: parseCookies(cookie), headers };
|
|
62
|
+
}
|
|
63
|
+
var appPlugin = (instance, options) => {
|
|
64
|
+
var _a, _b;
|
|
65
|
+
const { app, slowRenderMs = DEFAULT_SLOW_RENDER_MS } = options;
|
|
66
|
+
const appLog = (_a = log.getLogger(app.name)) != null ? _a : logger;
|
|
67
|
+
const serveLog = (_b = appLog.getLogger("serve")) != null ? _b : appLog;
|
|
68
|
+
instance.get("/_health", () => "ok");
|
|
69
|
+
instance.get("/_routes", (_req, reply) => {
|
|
70
|
+
void reply.header("cache-control", "no-store");
|
|
71
|
+
return claim(app);
|
|
72
|
+
});
|
|
73
|
+
instance.get("/_render", (req, reply) => __async(null, null, function* () {
|
|
74
|
+
const target = req.query.url;
|
|
75
|
+
if (typeof target !== "string" || !target.startsWith("/")) {
|
|
76
|
+
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" });
|
|
77
|
+
}
|
|
78
|
+
const { pathname, search } = new URL(target, "http://localhost");
|
|
79
|
+
const params = matchClaim(app, pathname);
|
|
80
|
+
if (params === null) {
|
|
81
|
+
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`);
|
|
82
|
+
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` });
|
|
83
|
+
}
|
|
84
|
+
const startedAt = Date.now();
|
|
85
|
+
try {
|
|
86
|
+
const result = yield renderApp(app, { context: browserContext(req), params, pathname, search });
|
|
87
|
+
const elapsed = Date.now() - startedAt;
|
|
88
|
+
if (elapsed >= slowRenderMs) {
|
|
89
|
+
serveLog.warn(`\u043C\u0435\u0434\u043B\u0435\u043D\u043D\u044B\u0439 \u0440\u0435\u043D\u0434\u0435\u0440 \xAB${pathname}\xBB: ${String(elapsed)}\u043C\u0441`);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
serveLog.error(`\u0440\u0435\u043D\u0434\u0435\u0440 \xAB${pathname}\xBB \u0443\u043F\u0430\u043B \u0437\u0430 ${String(Date.now() - startedAt)}\u043C\u0441`, error);
|
|
94
|
+
return reply.code(500).send({ error: error instanceof Error ? error.message : String(error) });
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// src/serve/index.ts
|
|
101
|
+
var SHUTDOWN_SIGNALS = ["SIGTERM", "SIGINT"];
|
|
102
|
+
function serveApp(_0) {
|
|
103
|
+
return __async(this, arguments, function* (app, options = {}) {
|
|
104
|
+
var _a, _b, _c, _d;
|
|
105
|
+
const appLog = (_a = log2.getLogger(app.name)) != null ? _a : logger;
|
|
106
|
+
const serveLog = (_b = appLog.getLogger("serve")) != null ? _b : appLog;
|
|
107
|
+
const instance = Fastify({ logger: false });
|
|
108
|
+
yield instance.register(appPlugin, { app, slowRenderMs: options.slowRenderMs });
|
|
109
|
+
instance.addHook("onRequest", (req, _reply, done) => {
|
|
110
|
+
serveLog.debug(`\u2192 ${req.method} ${req.url}`);
|
|
111
|
+
done();
|
|
112
|
+
});
|
|
113
|
+
instance.addHook("onResponse", (req, reply, done) => {
|
|
114
|
+
const elapsed = reply.elapsedTime.toFixed(1);
|
|
115
|
+
serveLog.info(`\u2190 ${String(reply.statusCode)} ${req.method} ${req.url} ${elapsed}\u043C\u0441`);
|
|
116
|
+
done();
|
|
117
|
+
});
|
|
118
|
+
yield (_c = options.configure) == null ? void 0 : _c.call(options, instance);
|
|
119
|
+
yield instance.listen({ host: options.host, port: (_d = options.port) != null ? _d : 0 });
|
|
120
|
+
if (options.gracefulShutdown !== false) {
|
|
121
|
+
for (const signal of SHUTDOWN_SIGNALS) {
|
|
122
|
+
process.once(signal, () => {
|
|
123
|
+
serveLog.info(`${signal}: \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u044E \u0438\u043D\u0441\u0442\u0430\u043D\u0441`);
|
|
124
|
+
void instance.close();
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
serveLog.info(
|
|
129
|
+
`\u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u0435 \xAB${app.name}\xBB \u0441\u043B\u0443\u0448\u0430\u0435\u0442 ${instance.addresses().map((a) => String(a.port)).join(", ")}`
|
|
130
|
+
);
|
|
131
|
+
return instance;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
export {
|
|
135
|
+
appPlugin,
|
|
136
|
+
serveApp
|
|
137
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Что приложение отдало серверным рендером. */
|
|
2
|
+
interface ServerRenderResult {
|
|
3
|
+
/** Разметка дерева — результат переданного рендера. */
|
|
4
|
+
html: string;
|
|
5
|
+
/**
|
|
6
|
+
* Вклад в `<head>` ГОТОВОЙ разметкой: то, что рождается только во время рендера и
|
|
7
|
+
* данными не описывается.
|
|
8
|
+
*
|
|
9
|
+
* Таковы стили CSS-in-JS: стороннее представление у них одно — тег со служебными
|
|
10
|
+
* атрибутами, по которым клиентский рантайм узнаёт свои правила. Разобрав его на поля,
|
|
11
|
+
* потеряешь регидратацию, и стили впрыснутся вторым экземпляром. Поэтому вклад в документ
|
|
12
|
+
* ДАННЫМИ (`DocumentHead` у хостов) остаётся отдельным каналом, а это — разметка.
|
|
13
|
+
*
|
|
14
|
+
* Разметка приезжает в документ хоста ДОСЛОВНО, без экранирования — иначе служебные
|
|
15
|
+
* атрибуты не пережили бы вставку. Отвечает за содержимое приложение: у сетевого
|
|
16
|
+
* транспорта строка приходит из чужого процесса, и хост её не разбирает.
|
|
17
|
+
*/
|
|
18
|
+
head?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Рендер дерева в разметку. Его даёт тот, кто серверный рендер исполняет. */
|
|
21
|
+
type RenderTree<Tree = unknown> = (tree: Tree) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Серверный рендер приложения: приложению дают его дерево и рендер, оно возвращает
|
|
24
|
+
* разметку и свой вклад в документ.
|
|
25
|
+
*
|
|
26
|
+
* Рендер приходит АРГУМЕНТОМ, потому что приложение им не владеет: страницу собирает тот,
|
|
27
|
+
* кто держит документ, и приложений на ней может быть несколько. Отдав рендер аргументом,
|
|
28
|
+
* приложение получает обычную функцию — состояние прохода живёт локальной переменной и
|
|
29
|
+
* между запросами не утекает.
|
|
30
|
+
*
|
|
31
|
+
* Подпись одна на оба транспорта, и в этом смысл: у приложения в процессе хоста рендер
|
|
32
|
+
* передаёт хост, у сетевого — его собственный сервер, а `html` и `head` едут ответом.
|
|
33
|
+
* Перевод приложения между транспортами эту часть не задевает.
|
|
34
|
+
*
|
|
35
|
+
* `Tree` — дерево view-фреймворка, для ядра непрозрачное. View-адаптер сужает параметр
|
|
36
|
+
* до своего типа (`ReactServerRender` в `@foxford/den-react`), и приложение пишет проход
|
|
37
|
+
* в терминах СВОЕГО фреймворка.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* serverRender: (tree, render) => {
|
|
41
|
+
* const sheet = new ServerStyleSheet()
|
|
42
|
+
*
|
|
43
|
+
* return { head: sheet.getStyleTags(), html: render(sheet.collectStyles(tree)) }
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
type ServerRender<Tree = unknown> = (tree: Tree, render: RenderTree<Tree>) => ServerRenderResult;
|
|
47
|
+
|
|
48
|
+
export type { RenderTree as R, ServerRenderResult as S, ServerRender as a };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** Что приложение отдало серверным рендером. */
|
|
2
|
+
interface ServerRenderResult {
|
|
3
|
+
/** Разметка дерева — результат переданного рендера. */
|
|
4
|
+
html: string;
|
|
5
|
+
/**
|
|
6
|
+
* Вклад в `<head>` ГОТОВОЙ разметкой: то, что рождается только во время рендера и
|
|
7
|
+
* данными не описывается.
|
|
8
|
+
*
|
|
9
|
+
* Таковы стили CSS-in-JS: стороннее представление у них одно — тег со служебными
|
|
10
|
+
* атрибутами, по которым клиентский рантайм узнаёт свои правила. Разобрав его на поля,
|
|
11
|
+
* потеряешь регидратацию, и стили впрыснутся вторым экземпляром. Поэтому вклад в документ
|
|
12
|
+
* ДАННЫМИ (`DocumentHead` у хостов) остаётся отдельным каналом, а это — разметка.
|
|
13
|
+
*
|
|
14
|
+
* Разметка приезжает в документ хоста ДОСЛОВНО, без экранирования — иначе служебные
|
|
15
|
+
* атрибуты не пережили бы вставку. Отвечает за содержимое приложение: у сетевого
|
|
16
|
+
* транспорта строка приходит из чужого процесса, и хост её не разбирает.
|
|
17
|
+
*/
|
|
18
|
+
head?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Рендер дерева в разметку. Его даёт тот, кто серверный рендер исполняет. */
|
|
21
|
+
type RenderTree<Tree = unknown> = (tree: Tree) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Серверный рендер приложения: приложению дают его дерево и рендер, оно возвращает
|
|
24
|
+
* разметку и свой вклад в документ.
|
|
25
|
+
*
|
|
26
|
+
* Рендер приходит АРГУМЕНТОМ, потому что приложение им не владеет: страницу собирает тот,
|
|
27
|
+
* кто держит документ, и приложений на ней может быть несколько. Отдав рендер аргументом,
|
|
28
|
+
* приложение получает обычную функцию — состояние прохода живёт локальной переменной и
|
|
29
|
+
* между запросами не утекает.
|
|
30
|
+
*
|
|
31
|
+
* Подпись одна на оба транспорта, и в этом смысл: у приложения в процессе хоста рендер
|
|
32
|
+
* передаёт хост, у сетевого — его собственный сервер, а `html` и `head` едут ответом.
|
|
33
|
+
* Перевод приложения между транспортами эту часть не задевает.
|
|
34
|
+
*
|
|
35
|
+
* `Tree` — дерево view-фреймворка, для ядра непрозрачное. View-адаптер сужает параметр
|
|
36
|
+
* до своего типа (`ReactServerRender` в `@foxford/den-react`), и приложение пишет проход
|
|
37
|
+
* в терминах СВОЕГО фреймворка.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* serverRender: (tree, render) => {
|
|
41
|
+
* const sheet = new ServerStyleSheet()
|
|
42
|
+
*
|
|
43
|
+
* return { head: sheet.getStyleTags(), html: render(sheet.collectStyles(tree)) }
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
type ServerRender<Tree = unknown> = (tree: Tree, render: RenderTree<Tree>) => ServerRenderResult;
|
|
47
|
+
|
|
48
|
+
export type { RenderTree as R, ServerRenderResult as S, ServerRender as a };
|
|
@@ -774,4 +774,4 @@ declare const ActivatableToken: Token<Activatable>;
|
|
|
774
774
|
*/
|
|
775
775
|
declare const RequestContextToken: Token<RequestContext>;
|
|
776
776
|
|
|
777
|
-
export { type ActionGuard as A, type
|
|
777
|
+
export { type ActionGuard as A, type Activatable as B, type Core as C, type DefineRepositoryOptions as D, type ExtensionConfig as E, ActivatableToken as F, type GuardDefinition as G, ContainerManagerToken as H, GuardRunnerToken as I, NavigationManagerToken as J, RequestContextToken as K, type LayerDefinition as L, StateCache as M, type NavigationManager as N, type StateParticipant as O, StateRegistry as P, StateRegistryToken as Q, type RequestContext as R, type ServiceDefinition as S, StateSerializerToken as T, type ViewModelDefinition as V, type DefineServiceOptions as a, type DefineViewModelOptions as b, type Definition as c, type RepositoryDefinition as d, type SlotEntry as e, SlotRegistry as f, SlotRegistryToken as g, type LayerConfig as h, type ContainerManager as i, type GuardRunner as j, type Guard as k, type GuardResult as l, type NavigationEntry as m, type NavigationInterceptor as n, type Disposable as o, type LeaveGuardResult as p, type StateSerializer as q, type DefineGuardOptions as r, type DefineExtensionOptions as s, type ExtensionDefinition as t, type DefineActionGuardOptions as u, type ActionGuardDefinition as v, type LayoutConfig as w, type DefineLayoutOptions as x, type LayoutDefinition as y, type DefineLayerOptions as z };
|
|
@@ -774,4 +774,4 @@ declare const ActivatableToken: Token<Activatable>;
|
|
|
774
774
|
*/
|
|
775
775
|
declare const RequestContextToken: Token<RequestContext>;
|
|
776
776
|
|
|
777
|
-
export { type ActionGuard as A, type
|
|
777
|
+
export { type ActionGuard as A, type Activatable as B, type Core as C, type DefineRepositoryOptions as D, type ExtensionConfig as E, ActivatableToken as F, type GuardDefinition as G, ContainerManagerToken as H, GuardRunnerToken as I, NavigationManagerToken as J, RequestContextToken as K, type LayerDefinition as L, StateCache as M, type NavigationManager as N, type StateParticipant as O, StateRegistry as P, StateRegistryToken as Q, type RequestContext as R, type ServiceDefinition as S, StateSerializerToken as T, type ViewModelDefinition as V, type DefineServiceOptions as a, type DefineViewModelOptions as b, type Definition as c, type RepositoryDefinition as d, type SlotEntry as e, SlotRegistry as f, SlotRegistryToken as g, type LayerConfig as h, type ContainerManager as i, type GuardRunner as j, type Guard as k, type GuardResult as l, type NavigationEntry as m, type NavigationInterceptor as n, type Disposable as o, type LeaveGuardResult as p, type StateSerializer as q, type DefineGuardOptions as r, type DefineExtensionOptions as s, type ExtensionDefinition as t, type DefineActionGuardOptions as u, type ActionGuardDefinition as v, type LayoutConfig as w, type DefineLayoutOptions as x, type LayoutDefinition as y, type DefineLayerOptions as z };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { I as IslandDescriptor } from './descriptor-DQ6Gi7A_.js';
|
|
2
|
+
import { S as ServerRenderResult } from './server-render-CocWXQKC.js';
|
|
3
|
+
import { L as LayerDefinition, h as LayerConfig } from './types-Dx5qGiwk.js';
|
|
4
|
+
import { Container, Token } from '@foxford/ioc';
|
|
5
|
+
|
|
6
|
+
/** Что нужно адаптеру, чтобы отрисовать остров на сервере. */
|
|
7
|
+
interface RenderIslandOptions {
|
|
8
|
+
/** Контейнер острова — уже собранный, с активированными VM. */
|
|
9
|
+
container: Container;
|
|
10
|
+
/** Внешние заполнители слотов; для ядра непрозрачны, как и само дерево. */
|
|
11
|
+
slots?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Порт view-адаптера. Реализуется пакетом фреймворка (`@foxford/den-react` и его аналоги),
|
|
15
|
+
* объявляется приложением через `defineLayer(ViewLayerToken, { adapter })`.
|
|
16
|
+
*/
|
|
17
|
+
interface ViewAdapter {
|
|
18
|
+
/** Имя фреймворка (`react`, `vue`) — для диагностики и сообщений об ошибках. */
|
|
19
|
+
readonly type: string;
|
|
20
|
+
/**
|
|
21
|
+
* Компонент острова для этого фреймворка: драйвит жизненный цикл ядра своими средствами
|
|
22
|
+
* (у React — хуки, у Vue — `setup`) и рисует `descriptor.view`.
|
|
23
|
+
*
|
|
24
|
+
* @param descriptor - Дескриптор острова
|
|
25
|
+
* @returns Компонент фреймворка — для ядра непрозрачен
|
|
26
|
+
*/
|
|
27
|
+
createIsland(descriptor: IslandDescriptor): unknown;
|
|
28
|
+
/**
|
|
29
|
+
* Отрисовывает остров в разметку на сервере.
|
|
30
|
+
*
|
|
31
|
+
* Единственная операция острова, которую ядро не может сделать само: `renderToString` —
|
|
32
|
+
* функция конкретного фреймворка, а ядро view-агностично. Здесь же адаптер исполняет
|
|
33
|
+
* `serverRender` приложения, если тот объявлен, — тип дерева известен только адаптеру.
|
|
34
|
+
*
|
|
35
|
+
* @param descriptor - Дескриптор острова
|
|
36
|
+
* @param options - Контейнер острова и заполнители слотов
|
|
37
|
+
* @returns Разметка и вклад в `<head>` готовой разметкой
|
|
38
|
+
*/
|
|
39
|
+
renderIsland(descriptor: IslandDescriptor, options: RenderIslandOptions): ServerRenderResult;
|
|
40
|
+
/**
|
|
41
|
+
* Ставит стратегию резолва `define*` во view (`installResolver` из `@foxford/den/adapter`).
|
|
42
|
+
* У каждого фреймворка она своя: у React — хук поверх контекста контейнера, у Vue —
|
|
43
|
+
* `inject`. Зовёт хост при инициализации трека.
|
|
44
|
+
*/
|
|
45
|
+
installResolver(): void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Канонический токен view-слоя.
|
|
49
|
+
*
|
|
50
|
+
* Живёт в ядре именно потому, что «мы знаем, что зарегистрировано» работает лишь тогда,
|
|
51
|
+
* когда токен один на всех: заведи его каждое приложение у себя — и движок не найдёт
|
|
52
|
+
* чужую регистрацию.
|
|
53
|
+
*/
|
|
54
|
+
declare const ViewLayerToken: Token<LayerConfig>;
|
|
55
|
+
/** View-слой приложения — результат `defineLayer(ViewLayerToken, { adapter })`. */
|
|
56
|
+
type ViewLayerDefinition = LayerDefinition;
|
|
57
|
+
/**
|
|
58
|
+
* Достаёт адаптер из объявленного приложением view-слоя.
|
|
59
|
+
*
|
|
60
|
+
* @param layer - View-слой (`defineLayer(ViewLayerToken, { adapter })`)
|
|
61
|
+
* @returns Адаптер view-фреймворка
|
|
62
|
+
* @throws Если слой объявлен без адаптера или адаптер не закрывает порт
|
|
63
|
+
*/
|
|
64
|
+
declare function viewAdapterOf(layer: ViewLayerDefinition): ViewAdapter;
|
|
65
|
+
/**
|
|
66
|
+
* Достаёт адаптер из контейнера — с подъёмом по parent-chain, как это делает резолв во view.
|
|
67
|
+
*
|
|
68
|
+
* Нужен там, где на руках только контейнер (например, отрисовка слота внутри острова).
|
|
69
|
+
* Дефолта нет намеренно: фреймворк за приложение ядро не выбирает.
|
|
70
|
+
*
|
|
71
|
+
* @param container - Контейнер острова/страницы
|
|
72
|
+
* @returns Адаптер view-фреймворка
|
|
73
|
+
* @throws Если приложение не объявило view-слой
|
|
74
|
+
*/
|
|
75
|
+
declare function resolveViewAdapter(container: Container): ViewAdapter;
|
|
76
|
+
|
|
77
|
+
export { type RenderIslandOptions as R, type ViewAdapter as V, type ViewLayerDefinition as a, ViewLayerToken as b, resolveViewAdapter as r, viewAdapterOf as v };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { I as IslandDescriptor } from './descriptor-Dujg_1on.cjs';
|
|
2
|
+
import { S as ServerRenderResult } from './server-render-CocWXQKC.cjs';
|
|
3
|
+
import { L as LayerDefinition, h as LayerConfig } from './types-Dx5qGiwk.cjs';
|
|
4
|
+
import { Container, Token } from '@foxford/ioc';
|
|
5
|
+
|
|
6
|
+
/** Что нужно адаптеру, чтобы отрисовать остров на сервере. */
|
|
7
|
+
interface RenderIslandOptions {
|
|
8
|
+
/** Контейнер острова — уже собранный, с активированными VM. */
|
|
9
|
+
container: Container;
|
|
10
|
+
/** Внешние заполнители слотов; для ядра непрозрачны, как и само дерево. */
|
|
11
|
+
slots?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Порт view-адаптера. Реализуется пакетом фреймворка (`@foxford/den-react` и его аналоги),
|
|
15
|
+
* объявляется приложением через `defineLayer(ViewLayerToken, { adapter })`.
|
|
16
|
+
*/
|
|
17
|
+
interface ViewAdapter {
|
|
18
|
+
/** Имя фреймворка (`react`, `vue`) — для диагностики и сообщений об ошибках. */
|
|
19
|
+
readonly type: string;
|
|
20
|
+
/**
|
|
21
|
+
* Компонент острова для этого фреймворка: драйвит жизненный цикл ядра своими средствами
|
|
22
|
+
* (у React — хуки, у Vue — `setup`) и рисует `descriptor.view`.
|
|
23
|
+
*
|
|
24
|
+
* @param descriptor - Дескриптор острова
|
|
25
|
+
* @returns Компонент фреймворка — для ядра непрозрачен
|
|
26
|
+
*/
|
|
27
|
+
createIsland(descriptor: IslandDescriptor): unknown;
|
|
28
|
+
/**
|
|
29
|
+
* Отрисовывает остров в разметку на сервере.
|
|
30
|
+
*
|
|
31
|
+
* Единственная операция острова, которую ядро не может сделать само: `renderToString` —
|
|
32
|
+
* функция конкретного фреймворка, а ядро view-агностично. Здесь же адаптер исполняет
|
|
33
|
+
* `serverRender` приложения, если тот объявлен, — тип дерева известен только адаптеру.
|
|
34
|
+
*
|
|
35
|
+
* @param descriptor - Дескриптор острова
|
|
36
|
+
* @param options - Контейнер острова и заполнители слотов
|
|
37
|
+
* @returns Разметка и вклад в `<head>` готовой разметкой
|
|
38
|
+
*/
|
|
39
|
+
renderIsland(descriptor: IslandDescriptor, options: RenderIslandOptions): ServerRenderResult;
|
|
40
|
+
/**
|
|
41
|
+
* Ставит стратегию резолва `define*` во view (`installResolver` из `@foxford/den/adapter`).
|
|
42
|
+
* У каждого фреймворка она своя: у React — хук поверх контекста контейнера, у Vue —
|
|
43
|
+
* `inject`. Зовёт хост при инициализации трека.
|
|
44
|
+
*/
|
|
45
|
+
installResolver(): void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Канонический токен view-слоя.
|
|
49
|
+
*
|
|
50
|
+
* Живёт в ядре именно потому, что «мы знаем, что зарегистрировано» работает лишь тогда,
|
|
51
|
+
* когда токен один на всех: заведи его каждое приложение у себя — и движок не найдёт
|
|
52
|
+
* чужую регистрацию.
|
|
53
|
+
*/
|
|
54
|
+
declare const ViewLayerToken: Token<LayerConfig>;
|
|
55
|
+
/** View-слой приложения — результат `defineLayer(ViewLayerToken, { adapter })`. */
|
|
56
|
+
type ViewLayerDefinition = LayerDefinition;
|
|
57
|
+
/**
|
|
58
|
+
* Достаёт адаптер из объявленного приложением view-слоя.
|
|
59
|
+
*
|
|
60
|
+
* @param layer - View-слой (`defineLayer(ViewLayerToken, { adapter })`)
|
|
61
|
+
* @returns Адаптер view-фреймворка
|
|
62
|
+
* @throws Если слой объявлен без адаптера или адаптер не закрывает порт
|
|
63
|
+
*/
|
|
64
|
+
declare function viewAdapterOf(layer: ViewLayerDefinition): ViewAdapter;
|
|
65
|
+
/**
|
|
66
|
+
* Достаёт адаптер из контейнера — с подъёмом по parent-chain, как это делает резолв во view.
|
|
67
|
+
*
|
|
68
|
+
* Нужен там, где на руках только контейнер (например, отрисовка слота внутри острова).
|
|
69
|
+
* Дефолта нет намеренно: фреймворк за приложение ядро не выбирает.
|
|
70
|
+
*
|
|
71
|
+
* @param container - Контейнер острова/страницы
|
|
72
|
+
* @returns Адаптер view-фреймворка
|
|
73
|
+
* @throws Если приложение не объявило view-слой
|
|
74
|
+
*/
|
|
75
|
+
declare function resolveViewAdapter(container: Container): ViewAdapter;
|
|
76
|
+
|
|
77
|
+
export { type RenderIslandOptions as R, type ViewAdapter as V, type ViewLayerDefinition as a, ViewLayerToken as b, resolveViewAdapter as r, viewAdapterOf as v };
|