@foxford/den 3.7.0 → 4.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 +58 -7
- package/adapter.d.cts +1 -1
- package/adapter.d.ts +1 -1
- package/bin/den.cjs +3 -3
- package/bin/den.js +1 -1
- package/builder/index.cjs +2 -2
- package/builder/index.d.cts +4 -2
- package/builder/index.d.ts +4 -2
- package/builder/index.js +1 -1
- package/{chunk-2GTQK2PZ.js → chunk-7FOG2MJV.js} +9 -6
- package/chunk-A2CYL5LY.js +240 -0
- package/chunk-HJFBEJT6.cjs +240 -0
- package/{chunk-P4J4M2WZ.cjs → chunk-IATA5QZ7.cjs} +9 -6
- package/{define-repository-AO7JI6Cb.d.ts → define-repository-Ck45La_2.d.ts} +1 -1
- package/{define-repository-C0MI-J32.d.cts → define-repository-DAyeXF48.d.cts} +1 -1
- package/{define-slot-CdWdFM16.d.ts → define-slot-BTlLQ__T.d.ts} +1 -1
- package/{define-slot-BEeHNEph.d.cts → define-slot-C6hrdJS3.d.cts} +1 -1
- package/define.d.cts +3 -3
- package/define.d.ts +3 -3
- package/{descriptor-BSaHM5B4.d.ts → descriptor-CNJFrEbS.d.ts} +2 -2
- package/{descriptor-C2j6Zz6c.d.cts → descriptor-DmfJP4jQ.d.cts} +2 -2
- package/index.d.cts +6 -6
- package/index.d.ts +6 -6
- package/island/index.d.cts +9 -6
- package/island/index.d.ts +9 -6
- package/ops/index.cjs +17 -0
- package/ops/index.d.cts +39 -0
- package/ops/index.d.ts +39 -0
- package/ops/index.js +17 -0
- package/package.json +25 -16
- package/{routes-BvV405k4.d.cts → routes-DQ4ud4bu.d.cts} +1 -1
- package/{routes-Di3K_0uQ.d.ts → routes-TkIxQ0Uc.d.ts} +1 -1
- package/serve/index.cjs +270 -17
- package/serve/index.d.cts +21 -6
- package/serve/index.d.ts +21 -6
- package/serve/index.js +273 -20
- package/{types-BxMQ-VOd.d.cts → types-Ccd5bmt1.d.cts} +23 -4
- package/{types-BxMQ-VOd.d.ts → types-Ccd5bmt1.d.ts} +23 -4
- package/{view-adapter-DMLlp3Iu.d.cts → view-adapter-CrHh7CjB.d.cts} +2 -2
- package/{view-adapter-DNLRSFka.d.ts → view-adapter-DPDvv09J.d.ts} +2 -2
package/serve/index.js
CHANGED
|
@@ -13,12 +13,21 @@ import {
|
|
|
13
13
|
logger
|
|
14
14
|
} from "../chunk-TPBI6TOU.js";
|
|
15
15
|
import {
|
|
16
|
-
|
|
16
|
+
closeHttpServer,
|
|
17
|
+
clusterMetrics,
|
|
18
|
+
getProcessMetrics,
|
|
19
|
+
isOpsPath,
|
|
20
|
+
startOpsServer
|
|
21
|
+
} from "../chunk-A2CYL5LY.js";
|
|
22
|
+
import {
|
|
23
|
+
__async,
|
|
24
|
+
__spreadProps,
|
|
25
|
+
__spreadValues
|
|
17
26
|
} from "../chunk-6FNC3XMI.js";
|
|
18
27
|
|
|
19
28
|
// src/serve/index.ts
|
|
20
29
|
import Fastify from "fastify";
|
|
21
|
-
import { log as
|
|
30
|
+
import { log as log4 } from "@foxford/logger";
|
|
22
31
|
|
|
23
32
|
// src/serve/assets.ts
|
|
24
33
|
import { createReadStream, existsSync, statSync } from "fs";
|
|
@@ -79,7 +88,7 @@ function matchClaim(app, pathname) {
|
|
|
79
88
|
}
|
|
80
89
|
return (_b = (_a = matchRoute(app.routes, pathname)) == null ? void 0 : _a.params) != null ? _b : null;
|
|
81
90
|
}
|
|
82
|
-
function
|
|
91
|
+
function requestContextOf(req, fromBody) {
|
|
83
92
|
const headers = {};
|
|
84
93
|
const forwarded = {
|
|
85
94
|
"accept-language": req.headers["x-forwarded-accept-language"],
|
|
@@ -91,22 +100,32 @@ function browserContext(req) {
|
|
|
91
100
|
}
|
|
92
101
|
}
|
|
93
102
|
const cookie = req.headers.cookie;
|
|
94
|
-
|
|
95
|
-
|
|
103
|
+
const backendHeaders = __spreadValues(__spreadValues({}, typeof cookie === "string" && cookie !== "" ? { cookie } : {}), fromBody);
|
|
104
|
+
return { backendHeaders, cookies: parseCookieHeader(cookie), headers };
|
|
105
|
+
}
|
|
106
|
+
function backendHeadersOf(value) {
|
|
107
|
+
if (value === void 0) {
|
|
108
|
+
return void 0;
|
|
96
109
|
}
|
|
97
|
-
|
|
110
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
111
|
+
return "invalid";
|
|
112
|
+
}
|
|
113
|
+
const entries = Object.entries(value);
|
|
114
|
+
if (entries.some(([, single]) => typeof single !== "string")) {
|
|
115
|
+
return "invalid";
|
|
116
|
+
}
|
|
117
|
+
return Object.fromEntries(entries.map(([name, single]) => [name.toLowerCase(), single]));
|
|
98
118
|
}
|
|
99
119
|
var appPlugin = (instance, options) => {
|
|
100
120
|
var _a, _b;
|
|
101
121
|
const { app, slowRenderMs = DEFAULT_SLOW_RENDER_MS } = options;
|
|
102
122
|
const appLog = (_a = log.getLogger(app.name)) != null ? _a : logger;
|
|
103
123
|
const serveLog = (_b = appLog.getLogger("serve")) != null ? _b : appLog;
|
|
104
|
-
instance.get("/_health", () => "ok");
|
|
105
124
|
instance.get("/_routes", (_req, reply) => {
|
|
106
125
|
void reply.header("cache-control", "no-store");
|
|
107
126
|
return claim(app);
|
|
108
127
|
});
|
|
109
|
-
function handleRender(req, reply, target, inputs) {
|
|
128
|
+
function handleRender(req, reply, target, inputs, rawBackendHeaders) {
|
|
110
129
|
return __async(this, null, function* () {
|
|
111
130
|
if (typeof target !== "string" || !target.startsWith("/")) {
|
|
112
131
|
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" });
|
|
@@ -114,6 +133,10 @@ var appPlugin = (instance, options) => {
|
|
|
114
133
|
if (inputs !== void 0 && (typeof inputs !== "object" || inputs === null || Array.isArray(inputs))) {
|
|
115
134
|
return reply.code(400).send({ error: "inputs \u0434\u043E\u043B\u0436\u043D\u044B \u0431\u044B\u0442\u044C \u043E\u0431\u044A\u0435\u043A\u0442\u043E\u043C \u043F\u043E \u043A\u043B\u044E\u0447\u0443 token.description" });
|
|
116
135
|
}
|
|
136
|
+
const backendHeaders = backendHeadersOf(rawBackendHeaders);
|
|
137
|
+
if (backendHeaders === "invalid") {
|
|
138
|
+
return reply.code(400).send({ error: "backendHeaders \u0434\u043E\u043B\u0436\u043D\u044B \u0431\u044B\u0442\u044C \u043E\u0431\u044A\u0435\u043A\u0442\u043E\u043C \xAB\u0438\u043C\u044F \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430 \u2192 \u0441\u0442\u0440\u043E\u043A\u0430\xBB" });
|
|
139
|
+
}
|
|
117
140
|
const { pathname, search } = new URL(target, "http://localhost");
|
|
118
141
|
const params = matchClaim(app, pathname);
|
|
119
142
|
if (params === null) {
|
|
@@ -123,7 +146,7 @@ var appPlugin = (instance, options) => {
|
|
|
123
146
|
const startedAt = Date.now();
|
|
124
147
|
try {
|
|
125
148
|
const result = yield renderApp(app, {
|
|
126
|
-
context:
|
|
149
|
+
context: requestContextOf(req, backendHeaders),
|
|
127
150
|
inputs,
|
|
128
151
|
params,
|
|
129
152
|
pathname,
|
|
@@ -140,12 +163,15 @@ var appPlugin = (instance, options) => {
|
|
|
140
163
|
}
|
|
141
164
|
});
|
|
142
165
|
}
|
|
143
|
-
instance.get(
|
|
166
|
+
instance.get(
|
|
167
|
+
"/_render",
|
|
168
|
+
(req, reply) => handleRender(req, reply, req.query.url, void 0, void 0)
|
|
169
|
+
);
|
|
144
170
|
instance.route({
|
|
145
171
|
handler: (req, reply) => {
|
|
146
172
|
var _a2;
|
|
147
173
|
const body = (_a2 = req.body) != null ? _a2 : {};
|
|
148
|
-
return handleRender(req, reply, body.url, body.inputs);
|
|
174
|
+
return handleRender(req, reply, body.url, body.inputs, body.backendHeaders);
|
|
149
175
|
},
|
|
150
176
|
method: "QUERY",
|
|
151
177
|
url: "/_render"
|
|
@@ -153,14 +179,235 @@ var appPlugin = (instance, options) => {
|
|
|
153
179
|
return Promise.resolve();
|
|
154
180
|
};
|
|
155
181
|
|
|
182
|
+
// src/serve/process.ts
|
|
183
|
+
import cluster from "cluster";
|
|
184
|
+
import { log as log3 } from "@foxford/logger";
|
|
185
|
+
|
|
186
|
+
// src/serve/worker.ts
|
|
187
|
+
import { log as log2 } from "@foxford/logger";
|
|
188
|
+
var ALIVE = "den:app-worker-alive";
|
|
189
|
+
var SIGNALS = ["SIGTERM", "SIGINT"];
|
|
190
|
+
var SHUTDOWN_MS = 1e4;
|
|
191
|
+
function startWorker(appName, start) {
|
|
192
|
+
return __async(this, null, function* () {
|
|
193
|
+
const aggregation = clusterMetrics();
|
|
194
|
+
const logger2 = log2.getLogger(appName).getLogger("cluster");
|
|
195
|
+
let timer;
|
|
196
|
+
let closing;
|
|
197
|
+
const starting = start();
|
|
198
|
+
const close = () => {
|
|
199
|
+
closing != null ? closing : closing = (() => __async(null, null, function* () {
|
|
200
|
+
clearInterval(timer);
|
|
201
|
+
try {
|
|
202
|
+
const instance = yield starting;
|
|
203
|
+
yield instance.close();
|
|
204
|
+
} finally {
|
|
205
|
+
try {
|
|
206
|
+
if (process.connected) yield aggregation.shutdown();
|
|
207
|
+
} finally {
|
|
208
|
+
for (const signal of SIGNALS) process.removeListener(signal, shutdown);
|
|
209
|
+
process.removeListener("disconnect", shutdown);
|
|
210
|
+
if (process.connected) process.disconnect();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}))();
|
|
214
|
+
return closing;
|
|
215
|
+
};
|
|
216
|
+
const shutdown = () => {
|
|
217
|
+
const deadline = setTimeout(() => process.exit(1), SHUTDOWN_MS);
|
|
218
|
+
deadline.unref();
|
|
219
|
+
void close().then(() => process.exit(0)).catch((error) => {
|
|
220
|
+
logger2.error("\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u0432\u043E\u0440\u043A\u0435\u0440\u0430 \u043D\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0430\u0441\u044C:", error);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
for (const signal of SIGNALS) process.on(signal, shutdown);
|
|
225
|
+
process.once("disconnect", shutdown);
|
|
226
|
+
try {
|
|
227
|
+
yield starting;
|
|
228
|
+
if (!closing) {
|
|
229
|
+
const notify = () => {
|
|
230
|
+
var _a;
|
|
231
|
+
if (process.connected) (_a = process.send) == null ? void 0 : _a.call(process, { type: ALIVE });
|
|
232
|
+
};
|
|
233
|
+
timer = setInterval(notify, 2e3);
|
|
234
|
+
timer.unref();
|
|
235
|
+
notify();
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
yield close().catch(() => void 0);
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
return { close };
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/serve/process.ts
|
|
246
|
+
var STARTUP_MS = 6e4;
|
|
247
|
+
function startAppProcess(appName, options, start) {
|
|
248
|
+
return __async(this, null, function* () {
|
|
249
|
+
var _a;
|
|
250
|
+
const workers = (_a = options.workers) != null ? _a : 1;
|
|
251
|
+
if (!Number.isSafeInteger(workers) || workers < 1) {
|
|
252
|
+
throw new Error("WORKERS must be a positive integer");
|
|
253
|
+
}
|
|
254
|
+
if (workers === 1) {
|
|
255
|
+
const instance = yield start(options);
|
|
256
|
+
return { close: () => instance.close() };
|
|
257
|
+
}
|
|
258
|
+
const metrics = getProcessMetrics();
|
|
259
|
+
metrics.startRuntime(appName);
|
|
260
|
+
if (cluster.isWorker) {
|
|
261
|
+
return startWorker(appName, () => start(__spreadProps(__spreadValues({}, options), { gracefulShutdown: false, ops: false })));
|
|
262
|
+
}
|
|
263
|
+
return startPrimary(appName, options, workers);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
function startPrimary(appName, options, workers) {
|
|
267
|
+
return __async(this, null, function* () {
|
|
268
|
+
const aggregation = clusterMetrics();
|
|
269
|
+
const logger2 = log3.getLogger(appName).getLogger("cluster");
|
|
270
|
+
const children = /* @__PURE__ */ new Set();
|
|
271
|
+
const alive = /* @__PURE__ */ new Map();
|
|
272
|
+
let ops;
|
|
273
|
+
let closing;
|
|
274
|
+
let started = false;
|
|
275
|
+
let resolveReady = () => void 0;
|
|
276
|
+
let rejectReady = () => void 0;
|
|
277
|
+
const ready = new Promise((resolve, reject) => {
|
|
278
|
+
resolveReady = resolve;
|
|
279
|
+
rejectReady = reject;
|
|
280
|
+
});
|
|
281
|
+
void ready.catch(() => void 0);
|
|
282
|
+
const timeout = setTimeout(() => rejectReady(new Error("Den workers startup timeout")), STARTUP_MS);
|
|
283
|
+
const onMessage = (worker, message) => {
|
|
284
|
+
if (children.has(worker) && typeof message === "object" && message !== null && "type" in message && message.type === ALIVE) {
|
|
285
|
+
alive.set(worker.id, Date.now());
|
|
286
|
+
if (alive.size === workers) resolveReady();
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
const close = () => {
|
|
290
|
+
closing != null ? closing : closing = (() => __async(null, null, function* () {
|
|
291
|
+
clearTimeout(timeout);
|
|
292
|
+
resolveReady();
|
|
293
|
+
cluster.removeListener("message", onMessage);
|
|
294
|
+
yield Promise.all([...children].map(stopWorker));
|
|
295
|
+
if (ops) yield closeHttpServer(ops);
|
|
296
|
+
yield aggregation.shutdown();
|
|
297
|
+
for (const signal of SIGNALS) process.removeListener(signal, shutdown);
|
|
298
|
+
}))();
|
|
299
|
+
return closing;
|
|
300
|
+
};
|
|
301
|
+
const shutdown = () => {
|
|
302
|
+
void close().then(() => process.exit()).catch((error) => {
|
|
303
|
+
logger2.error("\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u043A\u043B\u0430\u0441\u0442\u0435\u0440\u0430 \u043D\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043B\u0430\u0441\u044C:", error);
|
|
304
|
+
process.exit(1);
|
|
305
|
+
});
|
|
306
|
+
};
|
|
307
|
+
const failed = (error) => {
|
|
308
|
+
if (closing) return;
|
|
309
|
+
if (!started) {
|
|
310
|
+
rejectReady(error);
|
|
311
|
+
} else {
|
|
312
|
+
logger2.error(error);
|
|
313
|
+
process.exitCode = 1;
|
|
314
|
+
shutdown();
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
cluster.on("message", onMessage);
|
|
318
|
+
if (options.gracefulShutdown !== false) {
|
|
319
|
+
for (const signal of SIGNALS) process.on(signal, shutdown);
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
if (options.ops !== false) {
|
|
323
|
+
const supplied = options.ops;
|
|
324
|
+
ops = yield startOpsServer(__spreadProps(__spreadValues({}, supplied), {
|
|
325
|
+
collect: aggregation.collect,
|
|
326
|
+
contentType: aggregation.contentType,
|
|
327
|
+
isLive: () => {
|
|
328
|
+
var _a;
|
|
329
|
+
return [...children].some((worker) => {
|
|
330
|
+
var _a2;
|
|
331
|
+
return worker.isConnected() && Date.now() - ((_a2 = alive.get(worker.id)) != null ? _a2 : 0) < 1e4;
|
|
332
|
+
}) && ((_a = supplied == null ? void 0 : supplied.isLive) == null ? void 0 : _a.call(supplied)) !== false;
|
|
333
|
+
}
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
336
|
+
if (closing) {
|
|
337
|
+
if (ops) yield closeHttpServer(ops);
|
|
338
|
+
yield closing;
|
|
339
|
+
return { close };
|
|
340
|
+
}
|
|
341
|
+
for (let i = 0; i < workers; i++) {
|
|
342
|
+
const worker = cluster.fork();
|
|
343
|
+
children.add(worker);
|
|
344
|
+
worker.once("error", failed);
|
|
345
|
+
worker.once("exit", (code, signal) => {
|
|
346
|
+
alive.delete(worker.id);
|
|
347
|
+
failed(new Error(`Den worker ${String(worker.process.pid)} exited (${String(code != null ? code : signal)})`));
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
yield ready;
|
|
351
|
+
started = true;
|
|
352
|
+
clearTimeout(timeout);
|
|
353
|
+
if (!closing) logger2.info(`\u0437\u0430\u043F\u0443\u0449\u0435\u043D\u043E \u0432\u043E\u0440\u043A\u0435\u0440\u043E\u0432: ${String(workers)}`);
|
|
354
|
+
return { close };
|
|
355
|
+
} catch (error) {
|
|
356
|
+
yield close();
|
|
357
|
+
throw error;
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function stopWorker(worker) {
|
|
362
|
+
return __async(this, null, function* () {
|
|
363
|
+
if (worker.isDead()) return;
|
|
364
|
+
yield new Promise((resolve) => {
|
|
365
|
+
const timeout = setTimeout(() => worker.kill("SIGKILL"), SHUTDOWN_MS);
|
|
366
|
+
worker.once("exit", () => {
|
|
367
|
+
clearTimeout(timeout);
|
|
368
|
+
resolve();
|
|
369
|
+
});
|
|
370
|
+
worker.kill("SIGTERM");
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
156
375
|
// src/serve/index.ts
|
|
376
|
+
function serveAppProcess(app, options = {}) {
|
|
377
|
+
return startAppProcess(app.name, options, (serveOptions) => serveApp(app, serveOptions));
|
|
378
|
+
}
|
|
157
379
|
var SHUTDOWN_SIGNALS = ["SIGTERM", "SIGINT"];
|
|
158
380
|
function serveApp(_0) {
|
|
159
381
|
return __async(this, arguments, function* (app, options = {}) {
|
|
160
|
-
var _a, _b, _c, _d;
|
|
161
|
-
const appLog = (_a =
|
|
382
|
+
var _a, _b, _c, _d, _e;
|
|
383
|
+
const appLog = (_a = log4.getLogger(app.name)) != null ? _a : logger;
|
|
162
384
|
const serveLog = (_b = appLog.getLogger("serve")) != null ? _b : appLog;
|
|
163
385
|
const instance = Fastify({ logger: false });
|
|
386
|
+
const metrics = getProcessMetrics();
|
|
387
|
+
metrics.startRuntime(app.name);
|
|
388
|
+
let ops;
|
|
389
|
+
const shutdown = () => {
|
|
390
|
+
void instance.close();
|
|
391
|
+
};
|
|
392
|
+
instance.addHook("onRequest", (req, reply, done) => {
|
|
393
|
+
if (isOpsPath(req.url)) {
|
|
394
|
+
void reply.code(404).send();
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
metrics.trackHttp(req.raw, reply.raw, () => {
|
|
398
|
+
var _a2;
|
|
399
|
+
return (_a2 = req.routeOptions.url) != null ? _a2 : "unmatched";
|
|
400
|
+
});
|
|
401
|
+
done();
|
|
402
|
+
});
|
|
403
|
+
instance.addHook("onClose", () => __async(null, null, function* () {
|
|
404
|
+
for (const signal of SHUTDOWN_SIGNALS) {
|
|
405
|
+
process.removeListener(signal, shutdown);
|
|
406
|
+
}
|
|
407
|
+
if (ops) {
|
|
408
|
+
yield closeHttpServer(ops);
|
|
409
|
+
}
|
|
410
|
+
}));
|
|
164
411
|
yield instance.register(appPlugin, { app, slowRenderMs: options.slowRenderMs });
|
|
165
412
|
if (options.assets) {
|
|
166
413
|
registerAssets(instance, options.assets);
|
|
@@ -174,14 +421,19 @@ function serveApp(_0) {
|
|
|
174
421
|
serveLog.info(`\u2190 ${String(reply.statusCode)} ${req.method} ${req.url} ${elapsed}\u043C\u0441`);
|
|
175
422
|
done();
|
|
176
423
|
});
|
|
177
|
-
|
|
178
|
-
|
|
424
|
+
try {
|
|
425
|
+
yield (_c = options.configure) == null ? void 0 : _c.call(options, instance);
|
|
426
|
+
if (options.ops !== false) {
|
|
427
|
+
ops = yield startOpsServer(options.ops);
|
|
428
|
+
}
|
|
429
|
+
yield instance.listen({ host: (_d = options.host) != null ? _d : "0.0.0.0", port: (_e = options.port) != null ? _e : 8080 });
|
|
430
|
+
} catch (error) {
|
|
431
|
+
yield instance.close();
|
|
432
|
+
throw error;
|
|
433
|
+
}
|
|
179
434
|
if (options.gracefulShutdown !== false) {
|
|
180
435
|
for (const signal of SHUTDOWN_SIGNALS) {
|
|
181
|
-
process.once(signal,
|
|
182
|
-
serveLog.info(`${signal}: \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u044E \u0438\u043D\u0441\u0442\u0430\u043D\u0441`);
|
|
183
|
-
void instance.close();
|
|
184
|
-
});
|
|
436
|
+
process.once(signal, shutdown);
|
|
185
437
|
}
|
|
186
438
|
}
|
|
187
439
|
serveLog.info(
|
|
@@ -194,5 +446,6 @@ export {
|
|
|
194
446
|
appPlugin,
|
|
195
447
|
loadAppEnv,
|
|
196
448
|
registerAssets,
|
|
197
|
-
serveApp
|
|
449
|
+
serveApp,
|
|
450
|
+
serveAppProcess
|
|
198
451
|
};
|
|
@@ -477,14 +477,33 @@ declare class StateRegistry {
|
|
|
477
477
|
}
|
|
478
478
|
|
|
479
479
|
/**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
480
|
+
* Реквизиты HTTP-запроса. Три поля отвечают на ТРИ РАЗНЫХ вопроса, и путать их нельзя:
|
|
481
|
+
* что прислал браузер, чему равна отдельная кука и что предъявлять бэкенду.
|
|
482
|
+
*
|
|
483
|
+
* На клиенте заголовков нет, куки берутся из документа, а реквизиты бэкенда подставляет
|
|
484
|
+
* сам браузер.
|
|
482
485
|
*/
|
|
483
486
|
interface RequestContext {
|
|
484
|
-
/**
|
|
487
|
+
/**
|
|
488
|
+
* Что прислал БРАУЗЕР: `host`, `accept-language` (в нижнем регистре).
|
|
489
|
+
*
|
|
490
|
+
* Читается для решений о рендере — собрать абсолютную ссылку, выбрать язык. Заголовка
|
|
491
|
+
* `cookie` здесь НЕТ намеренно: собери кто-нибудь по нему запрос — он отправил бы браузерную
|
|
492
|
+
* куку вместо реквизитов этого запроса, и на первом визите это был бы другой посетитель.
|
|
493
|
+
* Нужно значение куки — есть `cookies`; нужно сходить в бэкенд — есть `backendHeaders`.
|
|
494
|
+
*/
|
|
485
495
|
headers: Record<string, string>;
|
|
486
|
-
/**
|
|
496
|
+
/** Разобранные куки — чтобы прочитать значение конкретной куки. */
|
|
487
497
|
cookies: Record<string, string>;
|
|
498
|
+
/**
|
|
499
|
+
* Что предъявлять БЭКЕНДУ в каждом запросе: `cookie` и то, что бэкенд выдал хосту на
|
|
500
|
+
* бутстрапе своими заголовками (идентичность посетителя и прочее).
|
|
501
|
+
*
|
|
502
|
+
* Один набор на все походы приложения, и собирает его хост — до рендера и один раз.
|
|
503
|
+
* Навешивает на клиент расширение рантайма `@foxford/den-sdk`, поэтому прикладной код
|
|
504
|
+
* заголовков не касается вовсе.
|
|
505
|
+
*/
|
|
506
|
+
backendHeaders?: Record<string, string>;
|
|
488
507
|
}
|
|
489
508
|
/**
|
|
490
509
|
* Результат проверки guard.
|
|
@@ -477,14 +477,33 @@ declare class StateRegistry {
|
|
|
477
477
|
}
|
|
478
478
|
|
|
479
479
|
/**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
480
|
+
* Реквизиты HTTP-запроса. Три поля отвечают на ТРИ РАЗНЫХ вопроса, и путать их нельзя:
|
|
481
|
+
* что прислал браузер, чему равна отдельная кука и что предъявлять бэкенду.
|
|
482
|
+
*
|
|
483
|
+
* На клиенте заголовков нет, куки берутся из документа, а реквизиты бэкенда подставляет
|
|
484
|
+
* сам браузер.
|
|
482
485
|
*/
|
|
483
486
|
interface RequestContext {
|
|
484
|
-
/**
|
|
487
|
+
/**
|
|
488
|
+
* Что прислал БРАУЗЕР: `host`, `accept-language` (в нижнем регистре).
|
|
489
|
+
*
|
|
490
|
+
* Читается для решений о рендере — собрать абсолютную ссылку, выбрать язык. Заголовка
|
|
491
|
+
* `cookie` здесь НЕТ намеренно: собери кто-нибудь по нему запрос — он отправил бы браузерную
|
|
492
|
+
* куку вместо реквизитов этого запроса, и на первом визите это был бы другой посетитель.
|
|
493
|
+
* Нужно значение куки — есть `cookies`; нужно сходить в бэкенд — есть `backendHeaders`.
|
|
494
|
+
*/
|
|
485
495
|
headers: Record<string, string>;
|
|
486
|
-
/**
|
|
496
|
+
/** Разобранные куки — чтобы прочитать значение конкретной куки. */
|
|
487
497
|
cookies: Record<string, string>;
|
|
498
|
+
/**
|
|
499
|
+
* Что предъявлять БЭКЕНДУ в каждом запросе: `cookie` и то, что бэкенд выдал хосту на
|
|
500
|
+
* бутстрапе своими заголовками (идентичность посетителя и прочее).
|
|
501
|
+
*
|
|
502
|
+
* Один набор на все походы приложения, и собирает его хост — до рендера и один раз.
|
|
503
|
+
* Навешивает на клиент расширение рантайма `@foxford/den-sdk`, поэтому прикладной код
|
|
504
|
+
* заголовков не касается вовсе.
|
|
505
|
+
*/
|
|
506
|
+
backendHeaders?: Record<string, string>;
|
|
488
507
|
}
|
|
489
508
|
/**
|
|
490
509
|
* Результат проверки guard.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { I as IslandDescriptor } from './descriptor-
|
|
1
|
+
import { I as IslandDescriptor } from './descriptor-DmfJP4jQ.cjs';
|
|
2
2
|
import { S as ServerRenderResult } from './server-render-CocWXQKC.cjs';
|
|
3
|
-
import { L as LayerDefinition, h as LayerConfig } from './types-
|
|
3
|
+
import { L as LayerDefinition, h as LayerConfig } from './types-Ccd5bmt1.cjs';
|
|
4
4
|
import { Container, Token } from '@foxford/ioc';
|
|
5
5
|
|
|
6
6
|
/** Что нужно адаптеру, чтобы отрисовать остров на сервере. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { I as IslandDescriptor } from './descriptor-
|
|
1
|
+
import { I as IslandDescriptor } from './descriptor-CNJFrEbS.js';
|
|
2
2
|
import { S as ServerRenderResult } from './server-render-CocWXQKC.js';
|
|
3
|
-
import { L as LayerDefinition, h as LayerConfig } from './types-
|
|
3
|
+
import { L as LayerDefinition, h as LayerConfig } from './types-Ccd5bmt1.js';
|
|
4
4
|
import { Container, Token } from '@foxford/ioc';
|
|
5
5
|
|
|
6
6
|
/** Что нужно адаптеру, чтобы отрисовать остров на сервере. */
|