@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
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { a as ServerRender } from '../server-render-CocWXQKC.js';
|
|
2
|
+
import { Container } from '@foxford/ioc';
|
|
3
|
+
import { FastifyInstance } from 'fastify';
|
|
4
|
+
import { PluginOption } from 'vite';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Пресет фреймворка: чем собирать его исходники и чем оживлять фрагмент в браузере.
|
|
8
|
+
*
|
|
9
|
+
* Отдаёт его пакет адаптера — он единственный, кто знает и то, и другое. Команды сборки
|
|
10
|
+
* пресет не разбирают, а укладывают: `plugins` — в конфиг сборщика, `clientEntry` — в
|
|
11
|
+
* сгенерированный клиентский вход.
|
|
12
|
+
*/
|
|
13
|
+
interface AppBuildPreset {
|
|
14
|
+
/** Имя фреймворка — им пресет представляется в логах и сообщениях об ошибках. */
|
|
15
|
+
view: string;
|
|
16
|
+
/** Плагины сборщика, которыми рисуется этот фреймворк. */
|
|
17
|
+
plugins: PluginOption[];
|
|
18
|
+
/**
|
|
19
|
+
* Модуль с `hydrateApp(descriptor)` — по нему сборка генерирует клиентский вход.
|
|
20
|
+
*
|
|
21
|
+
* Специфицируется именем, а не функцией: вход собирается в браузерный бандл, и функция из
|
|
22
|
+
* процесса сборки в него не переедет.
|
|
23
|
+
*/
|
|
24
|
+
clientEntry: string;
|
|
25
|
+
/**
|
|
26
|
+
* Проверка, что пресету хватает объявленного: получает зависимости приложения, возвращает
|
|
27
|
+
* причину отказа либо `null`.
|
|
28
|
+
*
|
|
29
|
+
* Здесь, а не в командах: какая зависимость требует сборочной поддержки, знает пресет —
|
|
30
|
+
* командам об этом знать нечем, и захардкоженный список сделал бы их привязанными к стеку.
|
|
31
|
+
* Нужна проверка потому, что цена ошибки — молчание: имена классов разъезжаются между
|
|
32
|
+
* выходами, и это видно только сломанной гидрацией в браузере.
|
|
33
|
+
*/
|
|
34
|
+
validate?: (dependencies: string[]) => string | null;
|
|
35
|
+
}
|
|
36
|
+
/** Серверная часть конфига — всё, что вплавляется в серверный выход. */
|
|
37
|
+
interface AppServerConfig {
|
|
38
|
+
/**
|
|
39
|
+
* Настройка процесса перед первым рендером: разбор разметки, полифиллы, прогрев.
|
|
40
|
+
*
|
|
41
|
+
* Дожидается её движок, один раз на процесс, — приложению ждать не нужно.
|
|
42
|
+
*/
|
|
43
|
+
setup?: () => void | Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Обёртка серверного рендера: через неё собираются стили, которые фреймворк заводит по
|
|
46
|
+
* ходу рендера, и уезжают в `<head>` разметкой.
|
|
47
|
+
*/
|
|
48
|
+
render?: ServerRender;
|
|
49
|
+
/**
|
|
50
|
+
* Биндинги app-контейнера: адрес ручек, ключи, всё, что приложение читает через `requires`.
|
|
51
|
+
*
|
|
52
|
+
* Контейнер приложения — родитель контейнеров островов, поэтому положенное здесь резолвится
|
|
53
|
+
* по parent-chain на любом рендере.
|
|
54
|
+
*/
|
|
55
|
+
container?: (container: Container) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Расширение сетевого инстанса до начала прослушивания: Sentry, метрики, cors.
|
|
58
|
+
*
|
|
59
|
+
* Зовётся только сетевым транспортом — в процессе хоста инстанса нет.
|
|
60
|
+
*/
|
|
61
|
+
configure?: (instance: FastifyInstance) => void | Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Зависимости, которые серверный выход обязан собрать ИСХОДНИКАМИ, а не оставить внешним
|
|
64
|
+
* модулем.
|
|
65
|
+
*
|
|
66
|
+
* Нужно тем пакетам, чей выход не переживает загрузку через node-ESM: интероп
|
|
67
|
+
* default-экспорта разъезжается, и вместо фабрики приходит пространство имён модуля.
|
|
68
|
+
*/
|
|
69
|
+
noExternal?: Array<string | RegExp>;
|
|
70
|
+
}
|
|
71
|
+
/** Конфиг приложения. */
|
|
72
|
+
interface AppConfig {
|
|
73
|
+
/** Модуль дескриптора; по умолчанию `src/index.ts`. */
|
|
74
|
+
entry?: string;
|
|
75
|
+
/** Пресет фреймворка — из пакета адаптера. */
|
|
76
|
+
preset: AppBuildPreset;
|
|
77
|
+
server?: AppServerConfig;
|
|
78
|
+
/**
|
|
79
|
+
* Последнее слово за приложением: правит собранный конфиг сборщика перед запуском.
|
|
80
|
+
*
|
|
81
|
+
* Щель на случай, когда коробки не хватило. Зовётся отдельно для каждого выхода, поэтому
|
|
82
|
+
* правка адресуется тому, кому предназначена.
|
|
83
|
+
*/
|
|
84
|
+
vite?: (config: Record<string, unknown>, target: 'server' | 'client') => Record<string, unknown>;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Объявляет конфиг приложения.
|
|
88
|
+
*
|
|
89
|
+
* Функция, а не голый объект, ради типизации на месте: интерфейс проверяется там, где конфиг
|
|
90
|
+
* написан, а не там, где его прочитали команды.
|
|
91
|
+
*
|
|
92
|
+
* @param config - Конфиг приложения
|
|
93
|
+
*/
|
|
94
|
+
declare function defineAppConfig(config: AppConfig): AppConfig;
|
|
95
|
+
|
|
96
|
+
/** Что нужно собрать. */
|
|
97
|
+
interface BuildAppOptions {
|
|
98
|
+
/** Корень приложения. */
|
|
99
|
+
root: string;
|
|
100
|
+
/** Префикс адресов артефактов: в проде CDN, в разработке развязка у хоста. */
|
|
101
|
+
base?: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Собирает приложение целиком.
|
|
105
|
+
*
|
|
106
|
+
* @param options - Корень приложения и префикс адресов артефактов
|
|
107
|
+
* @throws Если конфига нет либо пресет сообщил, что ему не хватает объявленного
|
|
108
|
+
*/
|
|
109
|
+
declare function buildApp(options: BuildAppOptions): Promise<void>;
|
|
110
|
+
|
|
111
|
+
/** Наблюдение берёт те же опции, что сборка: путь у них один. */
|
|
112
|
+
type DevAppOptions = BuildAppOptions;
|
|
113
|
+
/**
|
|
114
|
+
* Собирает приложение и держит его поднятым, пересобирая на изменение исходников.
|
|
115
|
+
*
|
|
116
|
+
* @param options - Корень приложения и префикс адресов артефактов
|
|
117
|
+
*/
|
|
118
|
+
declare function devApp(options: DevAppOptions): Promise<void>;
|
|
119
|
+
|
|
120
|
+
export { type AppBuildPreset, type AppConfig, type AppServerConfig, type BuildAppOptions, type DevAppOptions, buildApp, defineAppConfig, devApp };
|
package/builder/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
export {
|
|
13
|
+
ContainerManagerToken,
|
|
14
|
+
GuardRunnerToken,
|
|
15
|
+
NavigationManagerToken,
|
|
16
|
+
StateSerializerToken,
|
|
17
|
+
StateRegistryToken,
|
|
18
|
+
SlotRegistryToken,
|
|
19
|
+
ActivatableToken,
|
|
20
|
+
RequestContextToken
|
|
21
|
+
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -14,6 +16,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
16
|
}
|
|
15
17
|
return a;
|
|
16
18
|
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
17
20
|
var __async = (__this, __arguments, generator) => {
|
|
18
21
|
return new Promise((resolve, reject) => {
|
|
19
22
|
var fulfilled = (value) => {
|
|
@@ -37,5 +40,6 @@ var __async = (__this, __arguments, generator) => {
|
|
|
37
40
|
|
|
38
41
|
export {
|
|
39
42
|
__spreadValues,
|
|
43
|
+
__spreadProps,
|
|
40
44
|
__async
|
|
41
45
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
exports.ContainerManagerToken = ContainerManagerToken; exports.GuardRunnerToken = GuardRunnerToken; exports.NavigationManagerToken = NavigationManagerToken; exports.StateSerializerToken = StateSerializerToken; exports.StateRegistryToken = StateRegistryToken; exports.SlotRegistryToken = SlotRegistryToken; exports.ActivatableToken = ActivatableToken; exports.RequestContextToken = RequestContextToken;
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveDefinition
|
|
3
3
|
} from "./chunk-WBHHHICS.js";
|
|
4
|
+
import {
|
|
5
|
+
SlotRegistryToken,
|
|
6
|
+
StateRegistryToken
|
|
7
|
+
} from "./chunk-3RX2OSUL.js";
|
|
4
8
|
import {
|
|
5
9
|
unitLogger
|
|
6
10
|
} from "./chunk-TPBI6TOU.js";
|
|
7
11
|
|
|
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");
|
|
18
|
-
|
|
19
12
|
// src/core/slot-registry.ts
|
|
20
13
|
var SlotRegistry = class {
|
|
21
14
|
constructor() {
|
|
@@ -208,14 +201,6 @@ function defineSlot({ view, units = [], viewLayer } = {}) {
|
|
|
208
201
|
}
|
|
209
202
|
|
|
210
203
|
export {
|
|
211
|
-
ContainerManagerToken,
|
|
212
|
-
GuardRunnerToken,
|
|
213
|
-
NavigationManagerToken,
|
|
214
|
-
StateSerializerToken,
|
|
215
|
-
StateRegistryToken,
|
|
216
|
-
SlotRegistryToken,
|
|
217
|
-
ActivatableToken,
|
|
218
|
-
RequestContextToken,
|
|
219
204
|
SlotRegistry,
|
|
220
205
|
defineService,
|
|
221
206
|
defineViewModel,
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
2
|
+
|
|
3
|
+
var _chunkA6ZPAM6Zcjs = require('./chunk-A6ZPAM6Z.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
var _chunkT5QVCXVBcjs = require('./chunk-T5QVCXVB.cjs');
|
|
9
|
+
|
|
10
|
+
// src/builder/config.ts
|
|
11
|
+
function defineAppConfig(config) {
|
|
12
|
+
return config;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/builder/build.ts
|
|
16
|
+
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
|
|
17
|
+
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
18
|
+
|
|
19
|
+
// src/builder/assets.ts
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
var MANIFEST_PATH = ".vite/manifest.json";
|
|
23
|
+
function readManifest(outDir) {
|
|
24
|
+
const manifestPath = _path2.default.join(outDir, MANIFEST_PATH);
|
|
25
|
+
if (!_fs2.default.existsSync(manifestPath)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return JSON.parse(_fs2.default.readFileSync(manifestPath, "utf-8"));
|
|
29
|
+
}
|
|
30
|
+
function collectAssets(outDir, base) {
|
|
31
|
+
const manifest = readManifest(outDir);
|
|
32
|
+
if (manifest === null) {
|
|
33
|
+
return { css: [], js: [] };
|
|
34
|
+
}
|
|
35
|
+
const css = [];
|
|
36
|
+
const js = [];
|
|
37
|
+
const seen = /* @__PURE__ */ new Set();
|
|
38
|
+
const prefix = base.endsWith("/") ? base : `${base}/`;
|
|
39
|
+
function walk(key) {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
if (seen.has(key)) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
seen.add(key);
|
|
45
|
+
const chunk = manifest == null ? void 0 : manifest[key];
|
|
46
|
+
if (!chunk) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
for (const imported of (_a = chunk.imports) != null ? _a : []) {
|
|
50
|
+
walk(imported);
|
|
51
|
+
}
|
|
52
|
+
for (const href of (_b = chunk.css) != null ? _b : []) {
|
|
53
|
+
css.push(`${prefix}${href}`);
|
|
54
|
+
}
|
|
55
|
+
js.push(`${prefix}${chunk.file}`);
|
|
56
|
+
}
|
|
57
|
+
for (const [key, chunk] of Object.entries(manifest)) {
|
|
58
|
+
if (chunk.isEntry === true) {
|
|
59
|
+
walk(key);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { css, js };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/builder/entries.ts
|
|
66
|
+
var VIRTUAL_CLIENT = "virtual:den/client";
|
|
67
|
+
var VIRTUAL_SERVER_APP = "virtual:den/server-app";
|
|
68
|
+
var VIRTUAL_SERVER_PROCESS = "virtual:den/server-process";
|
|
69
|
+
var DEFAULT_PORT = 3e3;
|
|
70
|
+
function toResolvedId(id) {
|
|
71
|
+
return `\0${id}`;
|
|
72
|
+
}
|
|
73
|
+
function generateClientEntry(entry, clientEntry) {
|
|
74
|
+
return `import app from ${JSON.stringify(entry)}
|
|
75
|
+
import { hydrateApp } from ${JSON.stringify(clientEntry)}
|
|
76
|
+
|
|
77
|
+
hydrateApp(app)
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
function generateServerApp(entry, configPath, assets) {
|
|
81
|
+
return `import { getAppContainer, viewAdapterOf } from '@foxford/den/island'
|
|
82
|
+
|
|
83
|
+
import app from ${JSON.stringify(entry)}
|
|
84
|
+
import config from ${JSON.stringify(configPath)}
|
|
85
|
+
|
|
86
|
+
const server = config.server ?? {}
|
|
87
|
+
|
|
88
|
+
async function setup() {
|
|
89
|
+
viewAdapterOf(app.viewLayer).installResolver()
|
|
90
|
+
server.container?.(getAppContainer())
|
|
91
|
+
await server.setup?.()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const descriptor = { ...app, assets: ${JSON.stringify(assets)}, setup }
|
|
95
|
+
|
|
96
|
+
if (server.render) {
|
|
97
|
+
descriptor.serverRender = server.render
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default descriptor
|
|
101
|
+
`;
|
|
102
|
+
}
|
|
103
|
+
function generateServerProcess(configPath) {
|
|
104
|
+
return `import { serveApp } from '@foxford/den/serve'
|
|
105
|
+
|
|
106
|
+
import app from ${JSON.stringify(VIRTUAL_SERVER_APP)}
|
|
107
|
+
import config from ${JSON.stringify(configPath)}
|
|
108
|
+
|
|
109
|
+
await serveApp(app, {
|
|
110
|
+
configure: config.server?.configure,
|
|
111
|
+
host: process.env.HOST,
|
|
112
|
+
port: Number(process.env.PORT ?? ${String(DEFAULT_PORT)}),
|
|
113
|
+
})
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/builder/plugin.ts
|
|
118
|
+
function denAppModules(options) {
|
|
119
|
+
const { assets, config, configPath, entry } = options;
|
|
120
|
+
const sources = {
|
|
121
|
+
[VIRTUAL_CLIENT]: () => generateClientEntry(entry, config.preset.clientEntry),
|
|
122
|
+
[VIRTUAL_SERVER_APP]: () => generateServerApp(entry, configPath, assets),
|
|
123
|
+
[VIRTUAL_SERVER_PROCESS]: () => generateServerProcess(configPath)
|
|
124
|
+
};
|
|
125
|
+
return {
|
|
126
|
+
load: (id) => {
|
|
127
|
+
for (const [virtual, source] of Object.entries(sources)) {
|
|
128
|
+
if (id === toResolvedId(virtual)) {
|
|
129
|
+
return source();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
},
|
|
134
|
+
name: "den:app-modules",
|
|
135
|
+
resolveId: (id) => id in sources ? toResolvedId(id) : null
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/builder/build.ts
|
|
140
|
+
var CONFIG_FILE = "den.config.ts";
|
|
141
|
+
var OUT_ROOT = "build";
|
|
142
|
+
var OUT_CLIENT = "build/client";
|
|
143
|
+
var OUT_SERVER = "build/server";
|
|
144
|
+
var ENGINE = /^@foxford\/den(\/|$)/;
|
|
145
|
+
function loadAppConfig(root) {
|
|
146
|
+
return _chunkT5QVCXVBcjs.__async.call(void 0, this, null, function* () {
|
|
147
|
+
const configPath = _path2.default.join(root, CONFIG_FILE);
|
|
148
|
+
if (!_fs2.default.existsSync(configPath)) {
|
|
149
|
+
throw new Error(`den: ${CONFIG_FILE} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D \u0432 \xAB${root}\xBB`);
|
|
150
|
+
}
|
|
151
|
+
const { createServer } = yield Promise.resolve().then(() => _interopRequireWildcard(require("vite")));
|
|
152
|
+
const server = yield createServer({
|
|
153
|
+
appType: "custom",
|
|
154
|
+
configFile: false,
|
|
155
|
+
logLevel: "silent",
|
|
156
|
+
root,
|
|
157
|
+
server: { middlewareMode: true }
|
|
158
|
+
});
|
|
159
|
+
try {
|
|
160
|
+
const loaded = yield server.ssrLoadModule(configPath);
|
|
161
|
+
const config = loaded.default;
|
|
162
|
+
if (!(config == null ? void 0 : config.preset)) {
|
|
163
|
+
throw new Error(`den: ${CONFIG_FILE} \u043D\u0435 \u043E\u0431\u044A\u044F\u0432\u043B\u044F\u0435\u0442 \u043F\u0440\u0435\u0441\u0435\u0442 \u0444\u0440\u0435\u0439\u043C\u0432\u043E\u0440\u043A\u0430 \u2014 \u0441\u043E\u0431\u0438\u0440\u0430\u0442\u044C \u043D\u0435\u0447\u0435\u043C`);
|
|
164
|
+
}
|
|
165
|
+
return { config, configPath };
|
|
166
|
+
} finally {
|
|
167
|
+
yield server.close();
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function dependenciesOf(root) {
|
|
172
|
+
var _a, _b;
|
|
173
|
+
const manifestPath = _path2.default.join(root, "package.json");
|
|
174
|
+
if (!_fs2.default.existsSync(manifestPath)) {
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
const manifest = JSON.parse(_fs2.default.readFileSync(manifestPath, "utf-8"));
|
|
178
|
+
return [...Object.keys((_a = manifest.dependencies) != null ? _a : {}), ...Object.keys((_b = manifest.devDependencies) != null ? _b : {})];
|
|
179
|
+
}
|
|
180
|
+
function viteConfigFor(options) {
|
|
181
|
+
var _a, _b, _c;
|
|
182
|
+
const { assets, base, config, configPath, entryFileNames, input, outDir, root, target } = options;
|
|
183
|
+
const entry = (_a = config.entry) != null ? _a : "src/index.ts";
|
|
184
|
+
const composed = {
|
|
185
|
+
base,
|
|
186
|
+
build: {
|
|
187
|
+
// Клиентский выход чистит свой каталог сам, серверные — нет: они пишут рядом с уже
|
|
188
|
+
// собранным клиентским, и очистка снесла бы его вместе с манифестом
|
|
189
|
+
emptyOutDir: target === "client",
|
|
190
|
+
manifest: target === "client",
|
|
191
|
+
outDir: _path2.default.join(root, outDir),
|
|
192
|
+
// Вход задаётся `input`, а не `build.ssr`: строку в `build.ssr` сборщик понимает как путь
|
|
193
|
+
// к файлу, а входы у нас виртуальные — их резолвит плагин
|
|
194
|
+
rollupOptions: _chunkT5QVCXVBcjs.__spreadValues.call(void 0, _chunkT5QVCXVBcjs.__spreadValues.call(void 0, {
|
|
195
|
+
input
|
|
196
|
+
}, target === "server" ? { external: [ENGINE] } : {}), entryFileNames === void 0 ? {} : { output: { entryFileNames } }),
|
|
197
|
+
ssr: target === "server"
|
|
198
|
+
},
|
|
199
|
+
configFile: false,
|
|
200
|
+
plugins: [...config.preset.plugins, denAppModules({ assets, config, configPath, entry: _path2.default.join(root, entry) })],
|
|
201
|
+
root,
|
|
202
|
+
ssr: { noExternal: (_c = (_b = config.server) == null ? void 0 : _b.noExternal) != null ? _c : [] }
|
|
203
|
+
};
|
|
204
|
+
return config.vite ? config.vite(composed, target) : composed;
|
|
205
|
+
}
|
|
206
|
+
function buildApp(options) {
|
|
207
|
+
return _chunkT5QVCXVBcjs.__async.call(void 0, this, null, function* () {
|
|
208
|
+
var _a, _b;
|
|
209
|
+
const { base = "/" } = options;
|
|
210
|
+
const root = _path2.default.resolve(options.root);
|
|
211
|
+
const { config, configPath } = yield loadAppConfig(root);
|
|
212
|
+
const refusal = (_b = (_a = config.preset).validate) == null ? void 0 : _b.call(_a, dependenciesOf(root));
|
|
213
|
+
if (refusal !== void 0 && refusal !== null) {
|
|
214
|
+
throw new Error(`den: ${refusal}`);
|
|
215
|
+
}
|
|
216
|
+
const { build } = yield Promise.resolve().then(() => _interopRequireWildcard(require("vite")));
|
|
217
|
+
const shared = { base, config, configPath, root };
|
|
218
|
+
const empty = { css: [], js: [] };
|
|
219
|
+
_chunkA6ZPAM6Zcjs.logger.info(`\u0441\u0431\u043E\u0440\u043A\u0430 \u043A\u043B\u0438\u0435\u043D\u0442\u0441\u043A\u043E\u0433\u043E \u0432\u044B\u0445\u043E\u0434\u0430 (${config.preset.view})`);
|
|
220
|
+
yield build(viteConfigFor(_chunkT5QVCXVBcjs.__spreadProps.call(void 0, _chunkT5QVCXVBcjs.__spreadValues.call(void 0, {}, shared), { assets: empty, input: VIRTUAL_CLIENT, outDir: OUT_CLIENT, target: "client" })));
|
|
221
|
+
const assets = collectAssets(_path2.default.join(root, OUT_CLIENT), base);
|
|
222
|
+
_chunkA6ZPAM6Zcjs.logger.info(`\u0430\u0440\u0442\u0435\u0444\u0430\u043A\u0442\u044B: ${String(assets.js.length)} js, ${String(assets.css.length)} css`);
|
|
223
|
+
_chunkA6ZPAM6Zcjs.logger.info("\u0441\u0431\u043E\u0440\u043A\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043D\u043E\u0433\u043E \u0434\u0435\u0441\u043A\u0440\u0438\u043F\u0442\u043E\u0440\u0430");
|
|
224
|
+
yield build(
|
|
225
|
+
viteConfigFor(_chunkT5QVCXVBcjs.__spreadProps.call(void 0, _chunkT5QVCXVBcjs.__spreadValues.call(void 0, {}, shared), {
|
|
226
|
+
assets,
|
|
227
|
+
entryFileNames: "index.mjs",
|
|
228
|
+
input: VIRTUAL_SERVER_APP,
|
|
229
|
+
outDir: OUT_SERVER,
|
|
230
|
+
target: "server"
|
|
231
|
+
}))
|
|
232
|
+
);
|
|
233
|
+
_chunkA6ZPAM6Zcjs.logger.info("\u0441\u0431\u043E\u0440\u043A\u0430 \u0442\u043E\u0447\u043A\u0438 \u0432\u0445\u043E\u0434\u0430 \u043F\u0440\u043E\u0446\u0435\u0441\u0441\u0430");
|
|
234
|
+
yield build(
|
|
235
|
+
viteConfigFor(_chunkT5QVCXVBcjs.__spreadProps.call(void 0, _chunkT5QVCXVBcjs.__spreadValues.call(void 0, {}, shared), {
|
|
236
|
+
assets,
|
|
237
|
+
entryFileNames: "server.mjs",
|
|
238
|
+
input: VIRTUAL_SERVER_PROCESS,
|
|
239
|
+
outDir: OUT_ROOT,
|
|
240
|
+
target: "server"
|
|
241
|
+
}))
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/builder/dev.ts
|
|
247
|
+
var _child_process = require('child_process');
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
var SERVER_ENTRY = "build/server.mjs";
|
|
251
|
+
var WATCHED = ["src", "den.config.ts"];
|
|
252
|
+
var DEBOUNCE_MS = 150;
|
|
253
|
+
var SHUTDOWN_TIMEOUT_MS = 5e3;
|
|
254
|
+
function devApp(options) {
|
|
255
|
+
return _chunkT5QVCXVBcjs.__async.call(void 0, this, null, function* () {
|
|
256
|
+
const root = _path2.default.resolve(options.root);
|
|
257
|
+
const entry = _path2.default.join(root, SERVER_ENTRY);
|
|
258
|
+
let child = null;
|
|
259
|
+
let pending = null;
|
|
260
|
+
let building = false;
|
|
261
|
+
let dirty = false;
|
|
262
|
+
function signalGroup(pid, signal) {
|
|
263
|
+
try {
|
|
264
|
+
process.kill(-pid, signal);
|
|
265
|
+
} catch (e) {
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function stop() {
|
|
269
|
+
return _chunkT5QVCXVBcjs.__async.call(void 0, this, null, function* () {
|
|
270
|
+
const running = child;
|
|
271
|
+
child = null;
|
|
272
|
+
if (!running || running.exitCode !== null || running.pid === void 0) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const { pid } = running;
|
|
276
|
+
yield new Promise((resolve) => {
|
|
277
|
+
const forced = setTimeout(() => signalGroup(pid, "SIGKILL"), SHUTDOWN_TIMEOUT_MS);
|
|
278
|
+
running.once("exit", () => {
|
|
279
|
+
clearTimeout(forced);
|
|
280
|
+
resolve();
|
|
281
|
+
});
|
|
282
|
+
signalGroup(pid, "SIGTERM");
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function start() {
|
|
287
|
+
const started = _child_process.spawn.call(void 0, process.execPath, [...process.execArgv, entry], {
|
|
288
|
+
detached: true,
|
|
289
|
+
stdio: "inherit"
|
|
290
|
+
});
|
|
291
|
+
child = started;
|
|
292
|
+
started.on("exit", (code, signal) => {
|
|
293
|
+
if (child !== started) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
child = null;
|
|
297
|
+
_chunkA6ZPAM6Zcjs.logger.error(`\u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u043F\u0440\u0438\u043B\u043E\u0436\u0435\u043D\u0438\u044F \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0441\u044F \u0441\u0430\u043C (\u043A\u043E\u0434 ${String(code)}, \u0441\u0438\u0433\u043D\u0430\u043B ${String(signal)})`);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
function rebuild() {
|
|
301
|
+
return _chunkT5QVCXVBcjs.__async.call(void 0, this, null, function* () {
|
|
302
|
+
if (building) {
|
|
303
|
+
dirty = true;
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
building = true;
|
|
307
|
+
try {
|
|
308
|
+
do {
|
|
309
|
+
dirty = false;
|
|
310
|
+
yield stop();
|
|
311
|
+
try {
|
|
312
|
+
yield buildApp(options);
|
|
313
|
+
start();
|
|
314
|
+
} catch (error) {
|
|
315
|
+
_chunkA6ZPAM6Zcjs.logger.error("\u0441\u0431\u043E\u0440\u043A\u0430 \u043D\u0435 \u043F\u0440\u043E\u0448\u043B\u0430, \u0436\u0434\u0443 \u043F\u0440\u0430\u0432\u043A\u0438:", error);
|
|
316
|
+
}
|
|
317
|
+
} while (dirty);
|
|
318
|
+
} finally {
|
|
319
|
+
building = false;
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
yield rebuild();
|
|
324
|
+
for (const target of WATCHED) {
|
|
325
|
+
const watched = _path2.default.join(root, target);
|
|
326
|
+
if (!_fs2.default.existsSync(watched)) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
_fs2.default.watch(watched, { recursive: true }, () => {
|
|
330
|
+
if (pending) {
|
|
331
|
+
clearTimeout(pending);
|
|
332
|
+
}
|
|
333
|
+
pending = setTimeout(() => void rebuild(), DEBOUNCE_MS);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
_chunkA6ZPAM6Zcjs.logger.info(`\u0436\u0434\u0443 \u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439 \u0432 ${WATCHED.join(", ")}`);
|
|
337
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
338
|
+
process.once(signal, () => {
|
|
339
|
+
void stop().then(() => process.exit(0));
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
process.on("exit", () => {
|
|
343
|
+
if ((child == null ? void 0 : child.pid) !== void 0) {
|
|
344
|
+
signalGroup(child.pid, "SIGTERM");
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
exports.defineAppConfig = defineAppConfig; exports.buildApp = buildApp; exports.devApp = devApp;
|