jskelet 0.6.2 → 0.6.3
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/AGENTS.md +136 -136
- package/CHANGELOG.md +620 -596
- package/LICENSE +21 -21
- package/bin/jskelet.mjs +130 -130
- package/docs/01-baslangic.md +291 -291
- package/docs/02-mimari.md +310 -309
- package/docs/03-routing.md +515 -515
- package/docs/04-render-ve-sablonlar.md +661 -661
- package/docs/05-islands.md +486 -486
- package/docs/06-cache.md +1443 -1423
- package/docs/07-yapilandirma.md +12 -6
- package/docs/08-build.md +429 -428
- package/docs/09-dev-araclari.md +364 -364
- package/docs/10-dagitim.md +338 -338
- package/docs/12-panel-ve-oturum.md +478 -478
- package/docs/README.md +83 -83
- package/docs/en/01-getting-started.md +298 -298
- package/docs/en/02-architecture.md +329 -328
- package/docs/en/03-routing.md +531 -531
- package/docs/en/04-rendering.md +669 -669
- package/docs/en/05-islands.md +497 -497
- package/docs/en/06-caching.md +1453 -1431
- package/docs/en/07-configuration.md +1219 -1214
- package/docs/en/08-build.md +447 -446
- package/docs/en/09-dev-tools.md +373 -373
- package/docs/en/10-deployment.md +340 -340
- package/docs/en/11-migration.md +398 -398
- package/docs/en/12-dashboards-and-sessions.md +488 -488
- package/docs/en/README.md +87 -87
- package/package.json +137 -137
- package/src/build/ensure-build.mjs +19 -19
- package/src/build/paths.mjs +153 -153
- package/src/build/resolve-peer.mjs +36 -36
- package/src/build/tasks/client.mjs +349 -349
- package/src/build/tasks/css.mjs +235 -235
- package/src/build/tasks/fonts.mjs +146 -146
- package/src/build/tasks/icons.mjs +357 -357
- package/src/build/tasks/images.mjs +244 -244
- package/src/build/tasks/precompress.mjs +78 -78
- package/src/build/tasks/templates.mjs +20 -20
- package/src/client/admin/i18n.js +764 -764
- package/src/client/admin/login.html +74 -74
- package/src/client/admin/panel.css +809 -809
- package/src/client/admin/panel.html +495 -495
- package/src/client/admin/panel.js +1251 -1251
- package/src/client/devtools/report.html +185 -185
- package/src/client/devtools/report.js +745 -745
- package/src/client/devtools/seo.js +628 -628
- package/src/client/dom.js +95 -95
- package/src/client/form.js +192 -192
- package/src/client/index.js +45 -45
- package/src/client/registry.js +305 -305
- package/src/client/safe-image.js +91 -91
- package/src/client/shared-cookie.js +225 -225
- package/src/client/store.js +36 -36
- package/src/client/swap.js +188 -188
- package/src/compile/codegen.js +336 -336
- package/src/compile/compile-all.js +149 -149
- package/src/compile/errors.js +66 -66
- package/src/compile/expr.js +409 -409
- package/src/compile/index.js +17 -17
- package/src/compile/parse.js +541 -541
- package/src/compile/resolve.js +211 -211
- package/src/compile/scan-exports.js +51 -51
- package/src/config/defaults.js +17 -1
- package/src/config/index.js +13 -0
- package/src/config/pattern.js +107 -107
- package/src/generate.mjs +163 -163
- package/src/http/control-flow.js +71 -71
- package/src/http/cookies-entry.js +21 -21
- package/src/http/cookies.js +277 -277
- package/src/http/request-cache.js +46 -46
- package/src/http/request-context.js +165 -165
- package/src/http/shared-cookie.js +178 -178
- package/src/index.js +101 -101
- package/src/init.mjs +230 -230
- package/src/migrate/apply.mjs +262 -262
- package/src/migrate/babel.mjs +79 -79
- package/src/migrate/classify.mjs +155 -155
- package/src/migrate/config.mjs +126 -126
- package/src/migrate/fs-walk.mjs +191 -191
- package/src/migrate/parse.mjs +26 -26
- package/src/migrate/scan.mjs +177 -177
- package/src/migrate/transform/expr-source.mjs +168 -168
- package/src/migrate/transform/island.mjs +67 -67
- package/src/migrate/transform/jsx-to-component.mjs +302 -302
- package/src/migrate/transform/jsx-to-jsk.mjs +330 -330
- package/src/migrate/transform/page-split.mjs +435 -435
- package/src/migrate/write.mjs +81 -81
- package/src/migrate.mjs +171 -171
- package/src/runtime/alias-hooks.mjs +119 -119
- package/src/runtime/register.mjs +4 -4
- package/src/server/admin/actions.js +229 -229
- package/src/server/admin/auth.js +125 -125
- package/src/server/admin/event-log.js +151 -151
- package/src/server/admin/gate.js +209 -209
- package/src/server/admin/inventory.js +188 -188
- package/src/server/admin/mount.js +56 -56
- package/src/server/admin/router.js +216 -216
- package/src/server/admin/snapshot.js +241 -241
- package/src/server/assets.js +147 -147
- package/src/server/auth/handoff.js +309 -309
- package/src/server/cache-blob.js +70 -0
- package/src/server/cache-deps.js +42 -42
- package/src/server/cache-vary.js +113 -113
- package/src/server/cloudflare.js +607 -607
- package/src/server/create-app.js +366 -366
- package/src/server/data-cache.js +553 -462
- package/src/server/dev/report.js +485 -485
- package/src/server/dev/socket.js +170 -170
- package/src/server/dev/version-check.mjs +139 -139
- package/src/server/disk-cache.js +233 -0
- package/src/server/ejs-adapter.js +59 -59
- package/src/server/html-cache.js +1196 -1122
- package/src/server/image-optimizer.js +500 -407
- package/src/server/logs/access-middleware.js +66 -66
- package/src/server/logs/file-sink.js +193 -66
- package/src/server/logs/pipeline.js +165 -158
- package/src/server/logs/s3-put.js +214 -214
- package/src/server/logs/s3-sink.js +112 -112
- package/src/server/metadata.js +102 -102
- package/src/server/middleware/compression.js +205 -205
- package/src/server/middleware/csrf.js +134 -134
- package/src/server/middleware/dev-gate.js +75 -75
- package/src/server/middleware/headers.js +37 -37
- package/src/server/middleware/redirects.js +32 -32
- package/src/server/middleware/robots-txt.js +341 -341
- package/src/server/middleware/static-precompressed.js +121 -100
- package/src/server/middleware/trailing-slash.js +53 -53
- package/src/server/middleware/upstream-proxy.js +141 -141
- package/src/server/og-image.js +356 -356
- package/src/server/port-guard.js +255 -255
- package/src/server/prewarm.js +1082 -1058
- package/src/server/redis.js +588 -569
- package/src/server/render.js +4 -4
- package/src/server/router.js +157 -157
- package/src/server/status-page.js +265 -265
- package/src/server/upstream-limiter.js +376 -376
- package/src/server/upstream-tracking.js +166 -166
- package/src/shared/cookie-domain.js +66 -66
- package/src/start.mjs +22 -22
- package/src/templates/layout.ejs +30 -30
- package/src/templates/layout.jsk +30 -30
- package/src/version.mjs +31 -31
- package/src/views/components/loader.js +101 -101
- package/src/views/helpers/html.js +102 -102
- package/src/views/helpers/tags.js +375 -375
- package/types/config/defaults.d.ts +15 -1
- package/types/config/index.d.ts +8 -0
- package/types/server/cache-blob.d.ts +13 -0
- package/types/server/data-cache.d.ts +9 -0
- package/types/server/disk-cache.d.ts +36 -0
- package/types/server/html-cache.d.ts +26 -3
- package/types/server/logs/file-sink.d.ts +16 -5
- package/types/server/redis.d.ts +2 -1
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP access log middleware.
|
|
3
|
-
*
|
|
4
|
-
* Admin ve prewarm yolları atlanır. Kayıt `log.http` ile stdout'a (console
|
|
5
|
-
* açıksa) ve `acceptLogEntry` ile sink'lere gider. `emitHttp` kapalı olduğu
|
|
6
|
-
* için `log.http` abonelere ikinci kez yazmaz.
|
|
7
|
-
*/
|
|
8
|
-
import * as log from "../../log.mjs";
|
|
9
|
-
import { getConfig } from "../../config/index.js";
|
|
10
|
-
import { acceptLogEntry } from "./pipeline.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param {{ basePath?: string }} [options]
|
|
14
|
-
* @returns {import('express').RequestHandler}
|
|
15
|
-
*/
|
|
16
|
-
export function accessLogMiddleware(options = {}) {
|
|
17
|
-
const config = getConfig();
|
|
18
|
-
const brand = config.brand;
|
|
19
|
-
const basePath =
|
|
20
|
-
options.basePath ??
|
|
21
|
-
(config.admin.enabled ? config.admin.basePath : null);
|
|
22
|
-
|
|
23
|
-
/** @type {import('express').RequestHandler} */
|
|
24
|
-
return (req, res, next) => {
|
|
25
|
-
const pathname = req.path || "";
|
|
26
|
-
if (basePath && (pathname === basePath || pathname.startsWith(`${basePath}/`))) {
|
|
27
|
-
return next();
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (req.headers["user-agent"] === brand.prewarmUserAgent) {
|
|
31
|
-
return next();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const started = process.hrtime.bigint();
|
|
35
|
-
|
|
36
|
-
res.on("finish", () => {
|
|
37
|
-
const ms = Number(process.hrtime.bigint() - started) / 1e6;
|
|
38
|
-
const cache = /** @type {string | null} */ (
|
|
39
|
-
res.getHeader(brand.cacheHeader) ?? null
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
const info = {
|
|
43
|
-
method: req.method,
|
|
44
|
-
url: req.originalUrl,
|
|
45
|
-
status: res.statusCode,
|
|
46
|
-
ms,
|
|
47
|
-
cache,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// Stdout (console açıksa). emitHttp kapalı → subscribe çiftlemez.
|
|
51
|
-
log.http(info);
|
|
52
|
-
|
|
53
|
-
acceptLogEntry({
|
|
54
|
-
kind: "http",
|
|
55
|
-
method: info.method,
|
|
56
|
-
url: info.url,
|
|
57
|
-
path: req.path,
|
|
58
|
-
status: info.status,
|
|
59
|
-
ms: info.ms,
|
|
60
|
-
cache: info.cache,
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
next();
|
|
65
|
-
};
|
|
66
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* HTTP access log middleware.
|
|
3
|
+
*
|
|
4
|
+
* Admin ve prewarm yolları atlanır. Kayıt `log.http` ile stdout'a (console
|
|
5
|
+
* açıksa) ve `acceptLogEntry` ile sink'lere gider. `emitHttp` kapalı olduğu
|
|
6
|
+
* için `log.http` abonelere ikinci kez yazmaz.
|
|
7
|
+
*/
|
|
8
|
+
import * as log from "../../log.mjs";
|
|
9
|
+
import { getConfig } from "../../config/index.js";
|
|
10
|
+
import { acceptLogEntry } from "./pipeline.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {{ basePath?: string }} [options]
|
|
14
|
+
* @returns {import('express').RequestHandler}
|
|
15
|
+
*/
|
|
16
|
+
export function accessLogMiddleware(options = {}) {
|
|
17
|
+
const config = getConfig();
|
|
18
|
+
const brand = config.brand;
|
|
19
|
+
const basePath =
|
|
20
|
+
options.basePath ??
|
|
21
|
+
(config.admin.enabled ? config.admin.basePath : null);
|
|
22
|
+
|
|
23
|
+
/** @type {import('express').RequestHandler} */
|
|
24
|
+
return (req, res, next) => {
|
|
25
|
+
const pathname = req.path || "";
|
|
26
|
+
if (basePath && (pathname === basePath || pathname.startsWith(`${basePath}/`))) {
|
|
27
|
+
return next();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (req.headers["user-agent"] === brand.prewarmUserAgent) {
|
|
31
|
+
return next();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const started = process.hrtime.bigint();
|
|
35
|
+
|
|
36
|
+
res.on("finish", () => {
|
|
37
|
+
const ms = Number(process.hrtime.bigint() - started) / 1e6;
|
|
38
|
+
const cache = /** @type {string | null} */ (
|
|
39
|
+
res.getHeader(brand.cacheHeader) ?? null
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const info = {
|
|
43
|
+
method: req.method,
|
|
44
|
+
url: req.originalUrl,
|
|
45
|
+
status: res.statusCode,
|
|
46
|
+
ms,
|
|
47
|
+
cache,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Stdout (console açıksa). emitHttp kapalı → subscribe çiftlemez.
|
|
51
|
+
log.http(info);
|
|
52
|
+
|
|
53
|
+
acceptLogEntry({
|
|
54
|
+
kind: "http",
|
|
55
|
+
method: info.method,
|
|
56
|
+
url: info.url,
|
|
57
|
+
path: req.path,
|
|
58
|
+
status: info.status,
|
|
59
|
+
ms: info.ms,
|
|
60
|
+
cache: info.cache,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
next();
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -1,66 +1,193 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* @
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Kısa ömürlü dosya logu.
|
|
3
|
+
*
|
|
4
|
+
* Satırlar ~1 sn veya 32 satırda bir zstd NDJSON parçası olur. Diskte en
|
|
5
|
+
* fazla 5 dakika kalır; süresi dolan en eski parça silinir. `drainLog`
|
|
6
|
+
* her mühürlenen parçayı alır — hook hata verse de site düşmez, dosya
|
|
7
|
+
* süresi dolana kadar durur.
|
|
8
|
+
*
|
|
9
|
+
* Yol `path.resolve(root, dir)` ile bulunur. `getConfig().dirs` şişirilmez;
|
|
10
|
+
* log dizini opsiyoneldir ve çoğu kurulumda hiç açılmaz.
|
|
11
|
+
*/
|
|
12
|
+
import fs from "node:fs/promises";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import zlib from "node:zlib";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {{ body: Buffer, encoding: "zstd", bytes: number, lines: number,
|
|
18
|
+
* at: number }} LogChunk
|
|
19
|
+
* @typedef {{ write: (entry: Record<string, unknown>) => Promise<void>,
|
|
20
|
+
* flush: () => Promise<void>, close: () => Promise<void> }} LogSink
|
|
21
|
+
* @typedef {(chunk: LogChunk) => void | Promise<void>} DrainLog
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Satır satır yazmak yerine kısa tampon. */
|
|
25
|
+
const FLUSH_INTERVAL_MS = 1000;
|
|
26
|
+
const FLUSH_MAX_LINES = 32;
|
|
27
|
+
|
|
28
|
+
/** Diskteki parçaların ömrü. Config yükseltemez. */
|
|
29
|
+
export const FILE_LOG_RETENTION_MS = 5 * 60 * 1000;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {{ root: string, dir: string, persist?: boolean,
|
|
33
|
+
* retentionMs?: number, drainLog?: DrainLog | null }} options
|
|
34
|
+
* `persist: false` diske yazmaz; yalnız `drainLog` çağrılır.
|
|
35
|
+
* @returns {LogSink}
|
|
36
|
+
*/
|
|
37
|
+
export function createFileSink(options) {
|
|
38
|
+
const persist = options.persist !== false;
|
|
39
|
+
const retentionMs = options.retentionMs ?? FILE_LOG_RETENTION_MS;
|
|
40
|
+
const drainLog = typeof options.drainLog === "function" ? options.drainLog : null;
|
|
41
|
+
const baseDir = path.resolve(options.root, options.dir);
|
|
42
|
+
/** @type {string[]} */
|
|
43
|
+
let pending = [];
|
|
44
|
+
/** @type {ReturnType<typeof setTimeout> | null} */
|
|
45
|
+
let timer = null;
|
|
46
|
+
/** @type {Promise<void>} */
|
|
47
|
+
let chain = Promise.resolve();
|
|
48
|
+
let seq = 0;
|
|
49
|
+
let ready = false;
|
|
50
|
+
let drainWarned = false;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {string} message
|
|
54
|
+
* @param {unknown} [error]
|
|
55
|
+
*/
|
|
56
|
+
function warnDrain(message, error) {
|
|
57
|
+
if (drainWarned) return;
|
|
58
|
+
drainWarned = true;
|
|
59
|
+
console.warn(`[logs] ${message}`, error ?? "");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @returns {Promise<void>}
|
|
64
|
+
*/
|
|
65
|
+
async function ensureDir() {
|
|
66
|
+
if (ready) return;
|
|
67
|
+
await fs.mkdir(baseDir, { recursive: true });
|
|
68
|
+
ready = true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Süresi dolmuş `jskelet-*` parçalarını eskiden yeniye siler. Başka
|
|
73
|
+
* dosyalara dokunulmaz. Eski günlük `.log` dosyaları da bu ada uyar.
|
|
74
|
+
*
|
|
75
|
+
* @returns {Promise<void>}
|
|
76
|
+
*/
|
|
77
|
+
async function prune() {
|
|
78
|
+
if (!persist) return;
|
|
79
|
+
let names;
|
|
80
|
+
try {
|
|
81
|
+
names = await fs.readdir(baseDir);
|
|
82
|
+
} catch {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
/** @type {{ file: string, mtimeMs: number }[]} */
|
|
88
|
+
const doomed = [];
|
|
89
|
+
|
|
90
|
+
for (const name of names) {
|
|
91
|
+
if (!name.startsWith("jskelet-")) continue;
|
|
92
|
+
const file = path.join(baseDir, name);
|
|
93
|
+
try {
|
|
94
|
+
const stat = await fs.stat(file);
|
|
95
|
+
if (!stat.isFile()) continue;
|
|
96
|
+
if (now - stat.mtimeMs < retentionMs) continue;
|
|
97
|
+
doomed.push({ file, mtimeMs: stat.mtimeMs });
|
|
98
|
+
} catch {
|
|
99
|
+
// Silinmiş veya okunamayan girdi turu bozmasın.
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
doomed.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
104
|
+
for (const item of doomed) {
|
|
105
|
+
await fs.rm(item.file, { force: true });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {string} text
|
|
111
|
+
* @param {number} lines
|
|
112
|
+
* @returns {Promise<void>}
|
|
113
|
+
*/
|
|
114
|
+
async function seal(text, lines) {
|
|
115
|
+
const body = zlib.zstdCompressSync(Buffer.from(text, "utf8"));
|
|
116
|
+
const at = Date.now();
|
|
117
|
+
|
|
118
|
+
if (persist) {
|
|
119
|
+
await ensureDir();
|
|
120
|
+
seq += 1;
|
|
121
|
+
const file = path.join(baseDir, `jskelet-${at}-${seq}.ndjson.zst`);
|
|
122
|
+
await fs.writeFile(file, body);
|
|
123
|
+
await prune();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (!drainLog) return;
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
await drainLog({
|
|
130
|
+
body,
|
|
131
|
+
encoding: "zstd",
|
|
132
|
+
bytes: body.length,
|
|
133
|
+
lines,
|
|
134
|
+
at,
|
|
135
|
+
});
|
|
136
|
+
} catch (error) {
|
|
137
|
+
warnDrain(
|
|
138
|
+
persist
|
|
139
|
+
? "drainLog failed; the chunk stays on disk until it expires"
|
|
140
|
+
: "drainLog failed; the chunk was not stored",
|
|
141
|
+
error,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @returns {Promise<void>}
|
|
148
|
+
*/
|
|
149
|
+
async function flushPending() {
|
|
150
|
+
if (timer) {
|
|
151
|
+
clearTimeout(timer);
|
|
152
|
+
timer = null;
|
|
153
|
+
}
|
|
154
|
+
if (!pending.length) return;
|
|
155
|
+
|
|
156
|
+
const lines = pending;
|
|
157
|
+
pending = [];
|
|
158
|
+
await seal(lines.join(""), lines.length);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** @returns {void} */
|
|
162
|
+
function schedule() {
|
|
163
|
+
if (timer || !pending.length) return;
|
|
164
|
+
timer = setTimeout(() => {
|
|
165
|
+
timer = null;
|
|
166
|
+
chain = chain.then(() => flushPending());
|
|
167
|
+
}, FLUSH_INTERVAL_MS);
|
|
168
|
+
timer.unref?.();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
async write(entry) {
|
|
173
|
+
pending.push(`${JSON.stringify(entry)}\n`);
|
|
174
|
+
|
|
175
|
+
if (pending.length >= FLUSH_MAX_LINES) {
|
|
176
|
+
chain = chain.then(() => flushPending());
|
|
177
|
+
await chain;
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
schedule();
|
|
182
|
+
},
|
|
183
|
+
async flush() {
|
|
184
|
+
chain = chain.then(() => flushPending());
|
|
185
|
+
await chain;
|
|
186
|
+
},
|
|
187
|
+
async close() {
|
|
188
|
+
chain = chain.then(() => flushPending());
|
|
189
|
+
await chain;
|
|
190
|
+
if (persist) await prune();
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|