@foxford/den 3.0.0 → 3.1.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.
- package/README.mdx +215 -2
- package/chunk-6ZFVV3AV.cjs +214 -0
- package/chunk-7M5OAOQ4.js +214 -0
- package/chunk-CZVYVNLI.cjs +45 -0
- package/chunk-KJ6NDOOL.js +45 -0
- package/{chunk-5DJZZML5.cjs → chunk-P4QJCHMM.cjs} +12 -29
- package/{chunk-WRQC6BVJ.js → chunk-PZVUKTZG.js} +3 -20
- package/define.cjs +4 -4
- package/define.js +3 -3
- package/den-serve.js +146 -0
- package/descriptor-DZDNH7R5.d.ts +70 -0
- package/descriptor-h0JE9jFx.d.cts +70 -0
- package/index.cjs +16 -15
- package/index.d.cts +2 -1
- package/index.d.ts +2 -1
- package/index.js +11 -10
- package/island/index.cjs +10 -156
- package/island/index.d.cts +32 -29
- package/island/index.d.ts +32 -29
- package/island/index.js +17 -163
- package/package.json +27 -10
- package/routes-BqIoqbt1.d.cts +64 -0
- package/routes-CWpIqVAM.d.ts +64 -0
- package/serve/index.cjs +136 -0
- package/serve/index.d.cts +60 -0
- package/serve/index.d.ts +60 -0
- package/serve/index.js +136 -0
- package/{view-adapter-BvDC5O4y.d.cts → view-adapter-CPI8056c.d.ts} +4 -69
- package/{view-adapter-DtNgyjIf.d.ts → view-adapter-D2597RJZ.d.cts} +4 -69
- package/chunk-A6ZPAM6Z.cjs +0 -26
- package/chunk-TPBI6TOU.js +0 -26
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/core/types.ts
|
|
2
|
+
var _ioc = require('@foxford/ioc');
|
|
3
|
+
var ContainerManagerToken = _ioc.createToken.call(void 0, "core:ContainerManager");
|
|
4
|
+
var GuardRunnerToken = _ioc.createToken.call(void 0, "core:GuardRunner");
|
|
5
|
+
var NavigationManagerToken = _ioc.createToken.call(void 0, "core:NavigationManager");
|
|
6
|
+
var StateSerializerToken = _ioc.createToken.call(void 0, "core:StateSerializer");
|
|
7
|
+
var StateRegistryToken = _ioc.createToken.call(void 0, "core:StateRegistry");
|
|
8
|
+
var SlotRegistryToken = _ioc.createToken.call(void 0, "core:SlotRegistry");
|
|
9
|
+
var ActivatableToken = _ioc.createToken.call(void 0, "core:Activatable");
|
|
10
|
+
var RequestContextToken = _ioc.createToken.call(void 0, "core:RequestContext");
|
|
11
|
+
|
|
12
|
+
// src/logger.ts
|
|
13
|
+
|
|
14
|
+
var _logger = require('@foxford/logger');
|
|
15
|
+
var logger = _logger.log.getLogger("@foxford/den");
|
|
16
|
+
var LoggerToken = _ioc.createToken.call(void 0, "den:Logger");
|
|
17
|
+
function scopeLogger(container) {
|
|
18
|
+
if (container.has(LoggerToken)) {
|
|
19
|
+
const resolved = container.resolve(LoggerToken);
|
|
20
|
+
if (!(resolved instanceof Promise)) {
|
|
21
|
+
return resolved;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return logger;
|
|
25
|
+
}
|
|
26
|
+
function unitLogger(container, name) {
|
|
27
|
+
var _a;
|
|
28
|
+
const base = scopeLogger(container);
|
|
29
|
+
return (_a = base.getLogger(name)) != null ? _a : base;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
exports.ContainerManagerToken = ContainerManagerToken; exports.GuardRunnerToken = GuardRunnerToken; exports.NavigationManagerToken = NavigationManagerToken; exports.StateSerializerToken = StateSerializerToken; exports.StateRegistryToken = StateRegistryToken; exports.SlotRegistryToken = SlotRegistryToken; exports.ActivatableToken = ActivatableToken; exports.RequestContextToken = RequestContextToken; exports.logger = logger; exports.LoggerToken = LoggerToken; exports.scopeLogger = scopeLogger; exports.unitLogger = unitLogger;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// src/core/types.ts
|
|
2
|
+
import { createToken } from "@foxford/ioc";
|
|
3
|
+
var ContainerManagerToken = createToken("core:ContainerManager");
|
|
4
|
+
var GuardRunnerToken = createToken("core:GuardRunner");
|
|
5
|
+
var NavigationManagerToken = createToken("core:NavigationManager");
|
|
6
|
+
var StateSerializerToken = createToken("core:StateSerializer");
|
|
7
|
+
var StateRegistryToken = createToken("core:StateRegistry");
|
|
8
|
+
var SlotRegistryToken = createToken("core:SlotRegistry");
|
|
9
|
+
var ActivatableToken = createToken("core:Activatable");
|
|
10
|
+
var RequestContextToken = createToken("core:RequestContext");
|
|
11
|
+
|
|
12
|
+
// src/logger.ts
|
|
13
|
+
import { createToken as createToken2 } from "@foxford/ioc";
|
|
14
|
+
import { log } from "@foxford/logger";
|
|
15
|
+
var logger = log.getLogger("@foxford/den");
|
|
16
|
+
var LoggerToken = createToken2("den:Logger");
|
|
17
|
+
function scopeLogger(container) {
|
|
18
|
+
if (container.has(LoggerToken)) {
|
|
19
|
+
const resolved = container.resolve(LoggerToken);
|
|
20
|
+
if (!(resolved instanceof Promise)) {
|
|
21
|
+
return resolved;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return logger;
|
|
25
|
+
}
|
|
26
|
+
function unitLogger(container, name) {
|
|
27
|
+
var _a;
|
|
28
|
+
const base = scopeLogger(container);
|
|
29
|
+
return (_a = base.getLogger(name)) != null ? _a : base;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
ContainerManagerToken,
|
|
34
|
+
GuardRunnerToken,
|
|
35
|
+
NavigationManagerToken,
|
|
36
|
+
StateSerializerToken,
|
|
37
|
+
StateRegistryToken,
|
|
38
|
+
SlotRegistryToken,
|
|
39
|
+
ActivatableToken,
|
|
40
|
+
RequestContextToken,
|
|
41
|
+
logger,
|
|
42
|
+
LoggerToken,
|
|
43
|
+
scopeLogger,
|
|
44
|
+
unitLogger
|
|
45
|
+
};
|
|
@@ -3,18 +3,9 @@
|
|
|
3
3
|
var _chunkC7BM4DGXcjs = require('./chunk-C7BM4DGX.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
var _chunkA6ZPAM6Zcjs = require('./chunk-A6ZPAM6Z.cjs');
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
var
|
|
10
|
-
var ContainerManagerToken = _ioc.createToken.call(void 0, "core:ContainerManager");
|
|
11
|
-
var GuardRunnerToken = _ioc.createToken.call(void 0, "core:GuardRunner");
|
|
12
|
-
var NavigationManagerToken = _ioc.createToken.call(void 0, "core:NavigationManager");
|
|
13
|
-
var StateSerializerToken = _ioc.createToken.call(void 0, "core:StateSerializer");
|
|
14
|
-
var StateRegistryToken = _ioc.createToken.call(void 0, "core:StateRegistry");
|
|
15
|
-
var SlotRegistryToken = _ioc.createToken.call(void 0, "core:SlotRegistry");
|
|
16
|
-
var ActivatableToken = _ioc.createToken.call(void 0, "core:Activatable");
|
|
17
|
-
var RequestContextToken = _ioc.createToken.call(void 0, "core:RequestContext");
|
|
7
|
+
|
|
8
|
+
var _chunkCZVYVNLIcjs = require('./chunk-CZVYVNLI.cjs');
|
|
18
9
|
|
|
19
10
|
// src/core/slot-registry.ts
|
|
20
11
|
var SlotRegistry = class {
|
|
@@ -45,7 +36,7 @@ var SlotRegistry = class {
|
|
|
45
36
|
};
|
|
46
37
|
|
|
47
38
|
// src/define-service.ts
|
|
48
|
-
|
|
39
|
+
var _ioc = require('@foxford/ioc');
|
|
49
40
|
function defineService(token, options) {
|
|
50
41
|
const { requires, create, activate, deactivate, serialize, deserialize, scope } = options;
|
|
51
42
|
const requireTokens = requires != null ? requires : [];
|
|
@@ -62,7 +53,7 @@ function defineService(token, options) {
|
|
|
62
53
|
* @param container - Контейнер для регистрации
|
|
63
54
|
*/
|
|
64
55
|
register(container) {
|
|
65
|
-
const unitLog =
|
|
56
|
+
const unitLog = _chunkCZVYVNLIcjs.unitLogger.call(void 0, container, token.description);
|
|
66
57
|
const factory = _ioc.inject.call(void 0, requireTokens, (...args) => {
|
|
67
58
|
unitLog.debug(`\u0441\u043E\u0437\u0434\u0430\u043D\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 (${create ? "\u0444\u0430\u0431\u0440\u0438\u043A\u0430" : "lifecycle-\u043E\u0431\u0451\u0440\u0442\u043A\u0430"})`);
|
|
68
59
|
let instance;
|
|
@@ -92,10 +83,10 @@ function defineService(token, options) {
|
|
|
92
83
|
};
|
|
93
84
|
}
|
|
94
85
|
function registerStateParticipant(container, token, instance, deps, serialize, deserialize) {
|
|
95
|
-
if (!container.has(StateRegistryToken)) {
|
|
86
|
+
if (!container.has(_chunkCZVYVNLIcjs.StateRegistryToken)) {
|
|
96
87
|
return;
|
|
97
88
|
}
|
|
98
|
-
const resolved = container.resolve(StateRegistryToken);
|
|
89
|
+
const resolved = container.resolve(_chunkCZVYVNLIcjs.StateRegistryToken);
|
|
99
90
|
if (resolved instanceof Promise) {
|
|
100
91
|
return;
|
|
101
92
|
}
|
|
@@ -124,7 +115,7 @@ function defineViewModel(token, options) {
|
|
|
124
115
|
* @param container - Контейнер для регистрации
|
|
125
116
|
*/
|
|
126
117
|
register(container) {
|
|
127
|
-
const unitLog =
|
|
118
|
+
const unitLog = _chunkCZVYVNLIcjs.unitLogger.call(void 0, container, token.description);
|
|
128
119
|
const factory = _ioc.inject.call(void 0, requireTokens, (...args) => {
|
|
129
120
|
unitLog.debug("\u0441\u043E\u0437\u0434\u0430\u043D\u0438\u0435 view-model");
|
|
130
121
|
return create(args);
|
|
@@ -171,7 +162,7 @@ function defineRepository(token, options) {
|
|
|
171
162
|
* @param container - Контейнер для регистрации
|
|
172
163
|
*/
|
|
173
164
|
register(container) {
|
|
174
|
-
const unitLog =
|
|
165
|
+
const unitLog = _chunkCZVYVNLIcjs.unitLogger.call(void 0, container, token.description);
|
|
175
166
|
const factory = _ioc.inject.call(void 0, requireTokens, (...args) => {
|
|
176
167
|
unitLog.debug("\u0441\u043E\u0437\u0434\u0430\u043D\u0438\u0435 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u044F");
|
|
177
168
|
return create(args);
|
|
@@ -188,13 +179,13 @@ function defineSlot({ view, units = [], viewLayer } = {}) {
|
|
|
188
179
|
return {
|
|
189
180
|
__type: "slot",
|
|
190
181
|
register(container, name) {
|
|
191
|
-
const slotLog =
|
|
182
|
+
const slotLog = _chunkCZVYVNLIcjs.unitLogger.call(void 0, container, `slot:${name}`);
|
|
192
183
|
for (const unit of units) {
|
|
193
184
|
unit.register(container);
|
|
194
185
|
}
|
|
195
|
-
const registry = container.has(SlotRegistryToken) ? container.resolve(SlotRegistryToken) : (() => {
|
|
186
|
+
const registry = container.has(_chunkCZVYVNLIcjs.SlotRegistryToken) ? container.resolve(_chunkCZVYVNLIcjs.SlotRegistryToken) : (() => {
|
|
196
187
|
const created = new SlotRegistry();
|
|
197
|
-
container.bind(SlotRegistryToken).toValue(created);
|
|
188
|
+
container.bind(_chunkCZVYVNLIcjs.SlotRegistryToken).toValue(created);
|
|
198
189
|
slotLog.debug("\u0441\u043E\u0437\u0434\u0430\u043D SlotRegistry \u043A\u043E\u043D\u0442\u0435\u0439\u043D\u0435\u0440\u0430");
|
|
199
190
|
return created;
|
|
200
191
|
})();
|
|
@@ -213,12 +204,4 @@ function defineSlot({ view, units = [], viewLayer } = {}) {
|
|
|
213
204
|
|
|
214
205
|
|
|
215
206
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
exports.ContainerManagerToken = ContainerManagerToken; exports.GuardRunnerToken = GuardRunnerToken; exports.NavigationManagerToken = NavigationManagerToken; exports.StateSerializerToken = StateSerializerToken; exports.StateRegistryToken = StateRegistryToken; exports.SlotRegistryToken = SlotRegistryToken; exports.ActivatableToken = ActivatableToken; exports.RequestContextToken = RequestContextToken; exports.SlotRegistry = SlotRegistry; exports.defineService = defineService; exports.defineViewModel = defineViewModel; exports.defineRepository = defineRepository; exports.defineSlot = defineSlot;
|
|
207
|
+
exports.SlotRegistry = SlotRegistry; exports.defineService = defineService; exports.defineViewModel = defineViewModel; exports.defineRepository = defineRepository; exports.defineSlot = defineSlot;
|
|
@@ -2,19 +2,10 @@ import {
|
|
|
2
2
|
resolveDefinition
|
|
3
3
|
} from "./chunk-WBHHHICS.js";
|
|
4
4
|
import {
|
|
5
|
+
SlotRegistryToken,
|
|
6
|
+
StateRegistryToken,
|
|
5
7
|
unitLogger
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
|
|
8
|
-
// src/core/types.ts
|
|
9
|
-
import { createToken } from "@foxford/ioc";
|
|
10
|
-
var ContainerManagerToken = createToken("core:ContainerManager");
|
|
11
|
-
var GuardRunnerToken = createToken("core:GuardRunner");
|
|
12
|
-
var NavigationManagerToken = createToken("core:NavigationManager");
|
|
13
|
-
var StateSerializerToken = createToken("core:StateSerializer");
|
|
14
|
-
var StateRegistryToken = createToken("core:StateRegistry");
|
|
15
|
-
var SlotRegistryToken = createToken("core:SlotRegistry");
|
|
16
|
-
var ActivatableToken = createToken("core:Activatable");
|
|
17
|
-
var RequestContextToken = createToken("core:RequestContext");
|
|
8
|
+
} from "./chunk-KJ6NDOOL.js";
|
|
18
9
|
|
|
19
10
|
// src/core/slot-registry.ts
|
|
20
11
|
var SlotRegistry = class {
|
|
@@ -208,14 +199,6 @@ function defineSlot({ view, units = [], viewLayer } = {}) {
|
|
|
208
199
|
}
|
|
209
200
|
|
|
210
201
|
export {
|
|
211
|
-
ContainerManagerToken,
|
|
212
|
-
GuardRunnerToken,
|
|
213
|
-
NavigationManagerToken,
|
|
214
|
-
StateSerializerToken,
|
|
215
|
-
StateRegistryToken,
|
|
216
|
-
SlotRegistryToken,
|
|
217
|
-
ActivatableToken,
|
|
218
|
-
RequestContextToken,
|
|
219
202
|
SlotRegistry,
|
|
220
203
|
defineService,
|
|
221
204
|
defineViewModel,
|
package/define.cjs
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
var _chunk5DJZZML5cjs = require('./chunk-5DJZZML5.cjs');
|
|
7
|
+
var _chunkP4QJCHMMcjs = require('./chunk-P4QJCHMM.cjs');
|
|
9
8
|
require('./chunk-C7BM4DGX.cjs');
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
var _chunkCZVYVNLIcjs = require('./chunk-CZVYVNLI.cjs');
|
|
15
15
|
require('./chunk-XHYR3SGG.cjs');
|
|
16
16
|
|
|
17
17
|
|
|
@@ -23,4 +23,4 @@ require('./chunk-XHYR3SGG.cjs');
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
exports.LoggerToken =
|
|
26
|
+
exports.LoggerToken = _chunkCZVYVNLIcjs.LoggerToken; exports.SlotRegistry = _chunkP4QJCHMMcjs.SlotRegistry; exports.SlotRegistryToken = _chunkCZVYVNLIcjs.SlotRegistryToken; exports.defineRepository = _chunkP4QJCHMMcjs.defineRepository; exports.defineService = _chunkP4QJCHMMcjs.defineService; exports.defineSlot = _chunkP4QJCHMMcjs.defineSlot; exports.defineViewModel = _chunkP4QJCHMMcjs.defineViewModel; exports.logger = _chunkCZVYVNLIcjs.logger; exports.scopeLogger = _chunkCZVYVNLIcjs.scopeLogger;
|
package/define.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SlotRegistry,
|
|
3
|
-
SlotRegistryToken,
|
|
4
3
|
defineRepository,
|
|
5
4
|
defineService,
|
|
6
5
|
defineSlot,
|
|
7
6
|
defineViewModel
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-PZVUKTZG.js";
|
|
9
8
|
import "./chunk-WBHHHICS.js";
|
|
10
9
|
import {
|
|
11
10
|
LoggerToken,
|
|
11
|
+
SlotRegistryToken,
|
|
12
12
|
logger,
|
|
13
13
|
scopeLogger
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KJ6NDOOL.js";
|
|
15
15
|
import "./chunk-HJO26HIQ.js";
|
|
16
16
|
export {
|
|
17
17
|
LoggerToken,
|
package/den-serve.js
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { resolve } from 'node:path'
|
|
4
|
+
import { pathToFileURL } from 'node:url'
|
|
5
|
+
|
|
6
|
+
// Команда, поднимающая приложение сервисом. Ради неё потребителю не нужен свой серверный файл:
|
|
7
|
+
// он объявляет дескриптор через `defineApp` и запускает `den-serve` — сервер внутрь дескриптора
|
|
8
|
+
// при этом не заезжает.
|
|
9
|
+
//
|
|
10
|
+
// Внутрь его класть нельзя: `defineApp` импортирует ХОСТ, чтобы поднять приложение у себя в
|
|
11
|
+
// процессе, и вместе с дескриптором к нему приехали бы fastify и `node:http` — в серверный
|
|
12
|
+
// бандл и в браузерный. Дескриптор к тому же перестал бы быть данными, а инвариант
|
|
13
|
+
// «приложение не знает своего класса» сломался бы: дескриптор, поднимающий сервер, знает,
|
|
14
|
+
// что он сетевой.
|
|
15
|
+
//
|
|
16
|
+
// Watch внутри команды нет намеренно: приложение всё равно собирается сборщиком потребителя,
|
|
17
|
+
// и он же умеет перезапускать (`tsup --watch --onSuccess "den-serve build/index.js"`). Второй
|
|
18
|
+
// сторож поверх первого только путал бы.
|
|
19
|
+
//
|
|
20
|
+
// Обычный `.js`, а не собираемый исходник: команда должна работать одинаково из воркспейса и
|
|
21
|
+
// из опубликованного пакета, а `@foxford/den/serve` — self-reference по имени пакета, поэтому
|
|
22
|
+
// в обоих случаях резолвится своим `exports`.
|
|
23
|
+
//
|
|
24
|
+
// Shebang здесь — `tsx`, потому что в воркспейсе `exports` ведут на `src/*.ts`. В артефакт
|
|
25
|
+
// файл кладётся сборкой с заменой на `node`: там те же `exports` ведут уже на собранный js
|
|
26
|
+
// (см. `installCli` в tsup.config.ts).
|
|
27
|
+
|
|
28
|
+
const USAGE = `den-serve <модуль> [опции]
|
|
29
|
+
|
|
30
|
+
<модуль> путь к модулю, чей дефолтный экспорт — дескриптор приложения
|
|
31
|
+
|
|
32
|
+
--port <порт> порт (по умолчанию PORT из окружения либо 3000)
|
|
33
|
+
--host <адрес> интерфейс прослушивания (по умолчанию HOST либо 0.0.0.0)
|
|
34
|
+
--slow <мс> порог медленного рендера для лога (по умолчанию 1000)
|
|
35
|
+
--configure <модуль> модуль, чей дефолтный экспорт получает инстанс fastify до
|
|
36
|
+
прослушивания: Sentry, метрики, cors — сюда
|
|
37
|
+
-h, --help эта справка
|
|
38
|
+
`
|
|
39
|
+
|
|
40
|
+
function parseArgs(argv) {
|
|
41
|
+
const options = {}
|
|
42
|
+
let entry
|
|
43
|
+
|
|
44
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
45
|
+
const arg = argv[i]
|
|
46
|
+
switch (arg) {
|
|
47
|
+
case '-h':
|
|
48
|
+
case '--help':
|
|
49
|
+
return { help: true }
|
|
50
|
+
case '--port':
|
|
51
|
+
case '--host':
|
|
52
|
+
case '--slow':
|
|
53
|
+
case '--configure':
|
|
54
|
+
i += 1
|
|
55
|
+
options[arg.slice(2)] = argv[i]
|
|
56
|
+
break
|
|
57
|
+
default:
|
|
58
|
+
if (arg.startsWith('-')) {
|
|
59
|
+
throw new Error(`неизвестная опция ${arg}`)
|
|
60
|
+
}
|
|
61
|
+
if (entry !== undefined) {
|
|
62
|
+
throw new Error('модуль указывается один')
|
|
63
|
+
}
|
|
64
|
+
entry = arg
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return { entry, options }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function fail(message) {
|
|
72
|
+
process.stderr.write(`den-serve: ${message}\n\n${USAGE}`)
|
|
73
|
+
process.exit(1)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Достаёт дескриптор из указанного модуля.
|
|
78
|
+
*
|
|
79
|
+
* Форма проверяется ДО подъёма сервера: иначе первая же ошибка вылезла бы на запросе, из
|
|
80
|
+
* середины рендера, и выглядела бы как проблема приложения, а не запуска.
|
|
81
|
+
*/
|
|
82
|
+
async function loadApp(entry) {
|
|
83
|
+
const module = await import(pathToFileURL(resolve(process.cwd(), entry)).href)
|
|
84
|
+
const app = module.default
|
|
85
|
+
|
|
86
|
+
if (typeof app !== 'object' || app === null || typeof app.name !== 'string') {
|
|
87
|
+
fail(`дефолтный экспорт «${entry}» не похож на дескриптор приложения`)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return app
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Достаёт расширение инстанса из указанного модуля.
|
|
95
|
+
*
|
|
96
|
+
* Отдельной опцией, а не соглашением об имени файла: команда не должна угадывать, что в
|
|
97
|
+
* проекте считается конфигом. Без неё «серверного файла не нужно» и «расширяется снаружи»
|
|
98
|
+
* не сходились бы — за первым же плагином потребитель писал бы свою точку входа.
|
|
99
|
+
*/
|
|
100
|
+
async function loadConfigure(entry) {
|
|
101
|
+
const module = await import(pathToFileURL(resolve(process.cwd(), entry)).href)
|
|
102
|
+
|
|
103
|
+
if (typeof module.default !== 'function') {
|
|
104
|
+
fail(`дефолтный экспорт «${entry}» не функция — расширять инстанс нечем`)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return module.default
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function main() {
|
|
111
|
+
// Разбор аргументов — единственное место, где ошибка означает «человек опечатался»,
|
|
112
|
+
// поэтому она показывается подсказкой, а не стектрейсом
|
|
113
|
+
let parsed
|
|
114
|
+
try {
|
|
115
|
+
parsed = parseArgs(process.argv.slice(2))
|
|
116
|
+
} catch (error) {
|
|
117
|
+
fail(error.message)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const { entry, help, options = {} } = parsed
|
|
121
|
+
|
|
122
|
+
if (help) {
|
|
123
|
+
process.stdout.write(USAGE)
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (entry === undefined) {
|
|
128
|
+
fail('не указан модуль с дескриптором')
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Рантайм грузится ПОСЛЕ разбора аргументов: `--help` и опечатка в опции не должны тянуть
|
|
132
|
+
// fastify и весь серверный граф
|
|
133
|
+
const { serveApp } = await import('@foxford/den/serve')
|
|
134
|
+
|
|
135
|
+
await serveApp(await loadApp(entry), {
|
|
136
|
+
configure: options.configure === undefined ? undefined : await loadConfigure(options.configure),
|
|
137
|
+
host: options.host ?? process.env.HOST ?? '0.0.0.0',
|
|
138
|
+
port: Number(options.port ?? process.env.PORT ?? 3000),
|
|
139
|
+
slowRenderMs: options.slow === undefined ? undefined : Number(options.slow),
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
main().catch((error) => {
|
|
144
|
+
process.stderr.write(`den-serve: ${error instanceof Error ? error.message : String(error)}\n`)
|
|
145
|
+
process.exit(1)
|
|
146
|
+
})
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { S as SlotDefinition } from './define-slot-Dil8Kr1A.js';
|
|
2
|
+
import { q as LayerDefinition, x as Definition } from './types-COwVwgzE.js';
|
|
3
|
+
import { Token } 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
|
+
export type { IslandDescriptor as I };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { S as SlotDefinition } from './define-slot-BKvArA02.cjs';
|
|
2
|
+
import { q as LayerDefinition, x as Definition } from './types-COwVwgzE.cjs';
|
|
3
|
+
import { Token } 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
|
+
export type { IslandDescriptor as I };
|
package/index.cjs
CHANGED
|
@@ -4,20 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
var _chunkP4QJCHMMcjs = require('./chunk-P4QJCHMM.cjs');
|
|
8
|
+
require('./chunk-C7BM4DGX.cjs');
|
|
7
9
|
|
|
8
10
|
|
|
11
|
+
var _chunkXOJ2VWX4cjs = require('./chunk-XOJ2VWX4.cjs');
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
|
|
15
|
-
var _chunk5DJZZML5cjs = require('./chunk-5DJZZML5.cjs');
|
|
16
|
-
require('./chunk-C7BM4DGX.cjs');
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
require('./chunk-
|
|
20
|
+
|
|
21
|
+
var _chunkCZVYVNLIcjs = require('./chunk-CZVYVNLI.cjs');
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
var _chunkXHYR3SGGcjs = require('./chunk-XHYR3SGG.cjs');
|
|
@@ -83,7 +84,7 @@ var ContainerManagerImpl = class {
|
|
|
83
84
|
return existing;
|
|
84
85
|
}
|
|
85
86
|
const child = this.appContainer.createChild();
|
|
86
|
-
child.bind(
|
|
87
|
+
child.bind(_chunkCZVYVNLIcjs.StateRegistryToken).toValue(new StateRegistry());
|
|
87
88
|
this.pageContainers.set(routeId, child);
|
|
88
89
|
return child;
|
|
89
90
|
}
|
|
@@ -114,8 +115,8 @@ var ContainerManagerImpl = class {
|
|
|
114
115
|
return existing;
|
|
115
116
|
}
|
|
116
117
|
const child = this.appContainer.createChild();
|
|
117
|
-
child.bind(
|
|
118
|
-
child.bind(
|
|
118
|
+
child.bind(_chunkCZVYVNLIcjs.RequestContextToken).toValue(context);
|
|
119
|
+
child.bind(_chunkCZVYVNLIcjs.StateRegistryToken).toValue(new StateRegistry());
|
|
119
120
|
this.requestContainers.set(requestId, child);
|
|
120
121
|
return child;
|
|
121
122
|
}
|
|
@@ -154,7 +155,7 @@ var ContainerManagerImpl = class {
|
|
|
154
155
|
return existing;
|
|
155
156
|
}
|
|
156
157
|
const child = parent.createChild();
|
|
157
|
-
child.bind(
|
|
158
|
+
child.bind(_chunkCZVYVNLIcjs.StateRegistryToken).toValue(new StateRegistry());
|
|
158
159
|
this.ssrPageContainers.set(requestId, child);
|
|
159
160
|
return child;
|
|
160
161
|
}
|
|
@@ -414,10 +415,10 @@ var StateSerializerImpl = class {
|
|
|
414
415
|
*/
|
|
415
416
|
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
416
417
|
getRegistry(container) {
|
|
417
|
-
if (!container.has(
|
|
418
|
+
if (!container.has(_chunkCZVYVNLIcjs.StateRegistryToken)) {
|
|
418
419
|
return void 0;
|
|
419
420
|
}
|
|
420
|
-
const resolved = container.resolve(
|
|
421
|
+
const resolved = container.resolve(_chunkCZVYVNLIcjs.StateRegistryToken);
|
|
421
422
|
return resolved instanceof Promise ? void 0 : resolved;
|
|
422
423
|
}
|
|
423
424
|
/**
|
|
@@ -531,10 +532,10 @@ function createCore(options = {}) {
|
|
|
531
532
|
const navigationManager = new NavigationManagerImpl();
|
|
532
533
|
const stateSerializer = new StateSerializerImpl();
|
|
533
534
|
const stateCache = new StateCache();
|
|
534
|
-
container.bind(
|
|
535
|
-
container.bind(
|
|
536
|
-
container.bind(
|
|
537
|
-
container.bind(
|
|
535
|
+
container.bind(_chunkCZVYVNLIcjs.ContainerManagerToken).toValue(containerManager);
|
|
536
|
+
container.bind(_chunkCZVYVNLIcjs.GuardRunnerToken).toValue(guardRunner);
|
|
537
|
+
container.bind(_chunkCZVYVNLIcjs.NavigationManagerToken).toValue(navigationManager);
|
|
538
|
+
container.bind(_chunkCZVYVNLIcjs.StateSerializerToken).toValue(stateSerializer);
|
|
538
539
|
return {
|
|
539
540
|
container,
|
|
540
541
|
containerManager,
|
|
@@ -717,4 +718,4 @@ function defineLayer(token, options) {
|
|
|
717
718
|
|
|
718
719
|
|
|
719
720
|
|
|
720
|
-
exports.ActivatableToken =
|
|
721
|
+
exports.ActivatableToken = _chunkCZVYVNLIcjs.ActivatableToken; exports.ContainerManagerImpl = ContainerManagerImpl; exports.ContainerManagerToken = _chunkCZVYVNLIcjs.ContainerManagerToken; exports.GuardRunnerImpl = GuardRunnerImpl; exports.GuardRunnerToken = _chunkCZVYVNLIcjs.GuardRunnerToken; exports.NavigationManagerImpl = NavigationManagerImpl; exports.NavigationManagerToken = _chunkCZVYVNLIcjs.NavigationManagerToken; exports.RequestContextToken = _chunkCZVYVNLIcjs.RequestContextToken; exports.SlotRegistry = _chunkP4QJCHMMcjs.SlotRegistry; exports.SlotRegistryToken = _chunkCZVYVNLIcjs.SlotRegistryToken; exports.StateCache = StateCache; exports.StateRegistry = StateRegistry; exports.StateRegistryToken = _chunkCZVYVNLIcjs.StateRegistryToken; exports.StateSerializerImpl = StateSerializerImpl; exports.StateSerializerToken = _chunkCZVYVNLIcjs.StateSerializerToken; exports.ViewLayerToken = _chunkXOJ2VWX4cjs.ViewLayerToken; exports.createCore = createCore; exports.defaultGlobalResolver = defaultGlobalResolver; exports.defineActionGuard = defineActionGuard; exports.defineExtension = defineExtension; exports.defineGuard = defineGuard; exports.defineLayer = defineLayer; exports.defineLayout = defineLayout; exports.defineRepository = _chunkP4QJCHMMcjs.defineRepository; exports.defineService = _chunkP4QJCHMMcjs.defineService; exports.defineSlot = _chunkP4QJCHMMcjs.defineSlot; exports.defineViewModel = _chunkP4QJCHMMcjs.defineViewModel;
|