tempest-express-sdk 0.28.0 → 0.29.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.md +1 -1
- package/dist/{chunk-3NS5KVHT.js → chunk-7T4MZJZT.js} +3 -3
- package/dist/{chunk-3NS5KVHT.js.map → chunk-7T4MZJZT.js.map} +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +559 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +355 -2
- package/dist/index.d.ts +355 -2
- package/dist/index.js +550 -60
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { z, looseBoolean, toDict, PasswordUtils } from './chunk-
|
|
2
|
-
export { PasswordUtils, VERSION, baseAppSettingsSchema, baseAppSettingsShape, baseResponseSchema, centsField, corsSettingsShape, databaseSettingsShape, looseBoolean as envBoolean, hexColorField, latitudeField, loadSettings, longitudeField, looseBoolean, nonEmptyStrField, nonNegativeFloatField, nonNegativeIntField, percentField, portField, positiveFloatField, positiveIntField, priceField, ratingField, ratioField, serverSettingsShape, slugField, toDict, z } from './chunk-
|
|
1
|
+
import { z, looseBoolean, toDict, PasswordUtils } from './chunk-7T4MZJZT.js';
|
|
2
|
+
export { PasswordUtils, VERSION, baseAppSettingsSchema, baseAppSettingsShape, baseResponseSchema, centsField, corsSettingsShape, databaseSettingsShape, looseBoolean as envBoolean, hexColorField, latitudeField, loadSettings, longitudeField, looseBoolean, nonEmptyStrField, nonNegativeFloatField, nonNegativeIntField, percentField, portField, positiveFloatField, positiveIntField, priceField, ratingField, ratioField, serverSettingsShape, slugField, toDict, z } from './chunk-7T4MZJZT.js';
|
|
3
3
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
4
4
|
import { Model, column, sql, BaseRepository, RecordNotFound, detectDialect, columnsOf, NodeSqliteDriver, AsyncEngine, or, and } from 'tempest-db-js';
|
|
5
5
|
export { AsyncEngine, AsyncResult, AsyncSession, BaseRepository, Column, DeleteBuilder, InsertBuilder, Model, NoResultError, NodeSqliteDriver, PostgresDialect, RecordNotFound, SelectBuilder, SqliteDialect, SyncEngine, SyncSession, UpdateBuilder, and, belongsTo, column, columnsOf, createEngine, createSyncEngine, del, detectDialect, getDialect, hasMany, insert, join, loadRelations, not, or, parseDatabaseUrl, select, sql, update } from 'tempest-db-js';
|
|
@@ -9334,6 +9334,199 @@ function partitionTotal(partition) {
|
|
|
9334
9334
|
return partition.segments.reduce((total, segment) => total + segment.value, 0);
|
|
9335
9335
|
}
|
|
9336
9336
|
|
|
9337
|
+
// src/admin/logs.ts
|
|
9338
|
+
var LIFTED = /* @__PURE__ */ new Set(["level", "logger", "message", "timestamp", "stack"]);
|
|
9339
|
+
function toLogEntry(raw) {
|
|
9340
|
+
const context = {};
|
|
9341
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
9342
|
+
if (LIFTED.has(key) || value === null || value === void 0) continue;
|
|
9343
|
+
context[key] = value;
|
|
9344
|
+
}
|
|
9345
|
+
return {
|
|
9346
|
+
level: typeof raw.level === "string" ? raw.level : "info",
|
|
9347
|
+
logger: typeof raw.logger === "string" ? raw.logger : "",
|
|
9348
|
+
message: typeof raw.message === "string" ? raw.message : "",
|
|
9349
|
+
timestamp: typeof raw.timestamp === "string" ? raw.timestamp : "",
|
|
9350
|
+
stack: typeof raw.stack === "string" ? raw.stack : null,
|
|
9351
|
+
context,
|
|
9352
|
+
raw
|
|
9353
|
+
};
|
|
9354
|
+
}
|
|
9355
|
+
function filterLogEntries(entries, term) {
|
|
9356
|
+
const needle = term.trim().toLowerCase();
|
|
9357
|
+
if (needle === "") return entries;
|
|
9358
|
+
return entries.filter(
|
|
9359
|
+
(entry) => `${entry.message} ${entry.logger} ${entry.stack ?? ""}`.toLowerCase().includes(needle)
|
|
9360
|
+
);
|
|
9361
|
+
}
|
|
9362
|
+
function renderLogEntriesMarkdown(entries, options) {
|
|
9363
|
+
const lines = [
|
|
9364
|
+
"# Application logs",
|
|
9365
|
+
"",
|
|
9366
|
+
`- **Source:** \`${options.source}\``,
|
|
9367
|
+
`- **Search:** ${options.query === "" ? "_none_" : `\`${options.query}\``}`,
|
|
9368
|
+
`- **Exported:** ${entries.length} of ${options.total} matching record(s)`,
|
|
9369
|
+
""
|
|
9370
|
+
];
|
|
9371
|
+
if (entries.length < options.total) {
|
|
9372
|
+
lines.push(
|
|
9373
|
+
`> Truncated: the export is capped, so ${options.total - entries.length} older matching record(s) are not included.`,
|
|
9374
|
+
""
|
|
9375
|
+
);
|
|
9376
|
+
}
|
|
9377
|
+
for (const entry of entries) {
|
|
9378
|
+
lines.push(
|
|
9379
|
+
`## ${entry.level.toUpperCase()} \u2014 ${entry.message || "(no message)"}`,
|
|
9380
|
+
"",
|
|
9381
|
+
`- **When:** ${entry.timestamp || "unknown"}`,
|
|
9382
|
+
`- **Logger:** ${entry.logger || "unknown"}`
|
|
9383
|
+
);
|
|
9384
|
+
for (const [key, value] of Object.entries(entry.context)) {
|
|
9385
|
+
lines.push(
|
|
9386
|
+
`- **${key}:** ${typeof value === "string" ? value : JSON.stringify(value)}`
|
|
9387
|
+
);
|
|
9388
|
+
}
|
|
9389
|
+
lines.push("");
|
|
9390
|
+
if (entry.stack !== null) {
|
|
9391
|
+
lines.push("```text", entry.stack, "```", "");
|
|
9392
|
+
}
|
|
9393
|
+
}
|
|
9394
|
+
return lines.join("\n");
|
|
9395
|
+
}
|
|
9396
|
+
function renderLogEntriesJson(entries) {
|
|
9397
|
+
return JSON.stringify(
|
|
9398
|
+
entries.map((entry) => entry.raw),
|
|
9399
|
+
null,
|
|
9400
|
+
2
|
|
9401
|
+
);
|
|
9402
|
+
}
|
|
9403
|
+
|
|
9404
|
+
// src/admin/sqlConsole.ts
|
|
9405
|
+
var SqlCapability = {
|
|
9406
|
+
/** `SELECT`, `WITH … SELECT`, `EXPLAIN`, `SHOW`. */
|
|
9407
|
+
READ: "read",
|
|
9408
|
+
/** Adds rows. */
|
|
9409
|
+
INSERT: "insert",
|
|
9410
|
+
/** Changes rows. */
|
|
9411
|
+
UPDATE: "update",
|
|
9412
|
+
/** Removes rows. */
|
|
9413
|
+
DELETE: "delete",
|
|
9414
|
+
/** `CREATE` / `ALTER` / `COMMENT`. */
|
|
9415
|
+
DDL: "ddl",
|
|
9416
|
+
/** `DROP` and `TRUNCATE`: irreversible structure loss. */
|
|
9417
|
+
DROP: "drop",
|
|
9418
|
+
/**
|
|
9419
|
+
* `GRANT` / `REVOKE` / `SET`, and anything the analyser cannot classify.
|
|
9420
|
+
* Unknown statements land here on purpose, so a construct nobody anticipated
|
|
9421
|
+
* needs the most privileged capability rather than the least.
|
|
9422
|
+
*/
|
|
9423
|
+
ADMIN: "admin"
|
|
9424
|
+
};
|
|
9425
|
+
var STATEMENT_CAPABILITIES = {
|
|
9426
|
+
select: SqlCapability.READ,
|
|
9427
|
+
with: SqlCapability.READ,
|
|
9428
|
+
explain: SqlCapability.READ,
|
|
9429
|
+
show: SqlCapability.READ,
|
|
9430
|
+
desc: SqlCapability.READ,
|
|
9431
|
+
describe: SqlCapability.READ,
|
|
9432
|
+
insert: SqlCapability.INSERT,
|
|
9433
|
+
replace: SqlCapability.INSERT,
|
|
9434
|
+
update: SqlCapability.UPDATE,
|
|
9435
|
+
delete: SqlCapability.DELETE,
|
|
9436
|
+
create: SqlCapability.DDL,
|
|
9437
|
+
alter: SqlCapability.DDL,
|
|
9438
|
+
comment: SqlCapability.DDL,
|
|
9439
|
+
rename: SqlCapability.DDL,
|
|
9440
|
+
drop: SqlCapability.DROP,
|
|
9441
|
+
truncate: SqlCapability.DROP
|
|
9442
|
+
};
|
|
9443
|
+
var PARSER_HINT = "The admin SQL console needs the optional peer `node-sql-parser`. Install it with: npm install node-sql-parser";
|
|
9444
|
+
async function loadSqlParser() {
|
|
9445
|
+
try {
|
|
9446
|
+
const module = await import('node-sql-parser');
|
|
9447
|
+
const Parser = module.Parser ?? module.default?.Parser;
|
|
9448
|
+
if (Parser === void 0) throw new Error(PARSER_HINT);
|
|
9449
|
+
return new Parser();
|
|
9450
|
+
} catch {
|
|
9451
|
+
throw new Error(PARSER_HINT);
|
|
9452
|
+
}
|
|
9453
|
+
}
|
|
9454
|
+
function analyzeSql(sql5, dialect, parser) {
|
|
9455
|
+
const capabilities = /* @__PURE__ */ new Set();
|
|
9456
|
+
const tables = /* @__PURE__ */ new Set();
|
|
9457
|
+
let statements = 0;
|
|
9458
|
+
let parsed = true;
|
|
9459
|
+
let unscopedWrite = false;
|
|
9460
|
+
try {
|
|
9461
|
+
const ast = parser.astify(sql5, { database: dialect });
|
|
9462
|
+
const list = Array.isArray(ast) ? ast : [ast];
|
|
9463
|
+
statements = list.length;
|
|
9464
|
+
for (const statement of list) {
|
|
9465
|
+
const type = String(statement.type ?? "").toLowerCase();
|
|
9466
|
+
capabilities.add(STATEMENT_CAPABILITIES[type] ?? SqlCapability.ADMIN);
|
|
9467
|
+
if ((type === "update" || type === "delete") && !statement.where) {
|
|
9468
|
+
unscopedWrite = true;
|
|
9469
|
+
}
|
|
9470
|
+
}
|
|
9471
|
+
} catch {
|
|
9472
|
+
parsed = false;
|
|
9473
|
+
statements = 1;
|
|
9474
|
+
capabilities.add(SqlCapability.ADMIN);
|
|
9475
|
+
}
|
|
9476
|
+
try {
|
|
9477
|
+
for (const entry of parser.tableList(sql5, { database: dialect })) {
|
|
9478
|
+
const name = entry.split("::").pop();
|
|
9479
|
+
if (name !== void 0 && name !== "null") tables.add(name.toLowerCase());
|
|
9480
|
+
}
|
|
9481
|
+
} catch {
|
|
9482
|
+
}
|
|
9483
|
+
return {
|
|
9484
|
+
statements,
|
|
9485
|
+
capabilities: [...capabilities],
|
|
9486
|
+
tables: [...tables],
|
|
9487
|
+
parsed,
|
|
9488
|
+
unscopedWrite
|
|
9489
|
+
};
|
|
9490
|
+
}
|
|
9491
|
+
function checkSqlPolicy(analysis, policy) {
|
|
9492
|
+
const granted = new Set(policy.capabilities ?? [SqlCapability.READ]);
|
|
9493
|
+
for (const capability of analysis.capabilities) {
|
|
9494
|
+
if (!granted.has(capability)) {
|
|
9495
|
+
return {
|
|
9496
|
+
allowed: false,
|
|
9497
|
+
reason: analysis.parsed ? `This console may not run ${capability} statements.` : "The statement could not be parsed, so it needs the admin capability."
|
|
9498
|
+
};
|
|
9499
|
+
}
|
|
9500
|
+
}
|
|
9501
|
+
if ((policy.requireWhereOnWrites ?? true) && analysis.unscopedWrite) {
|
|
9502
|
+
return {
|
|
9503
|
+
allowed: false,
|
|
9504
|
+
reason: "An UPDATE or DELETE without a WHERE clause is refused."
|
|
9505
|
+
};
|
|
9506
|
+
}
|
|
9507
|
+
const denied = new Set((policy.denyTables ?? []).map((name) => name.toLowerCase()));
|
|
9508
|
+
for (const table of analysis.tables) {
|
|
9509
|
+
if (denied.has(table)) {
|
|
9510
|
+
return { allowed: false, reason: `Table "${table}" is not available here.` };
|
|
9511
|
+
}
|
|
9512
|
+
}
|
|
9513
|
+
if (policy.allowTables !== void 0) {
|
|
9514
|
+
const allowed = new Set(policy.allowTables.map((name) => name.toLowerCase()));
|
|
9515
|
+
if (analysis.tables.length === 0) {
|
|
9516
|
+
return {
|
|
9517
|
+
allowed: false,
|
|
9518
|
+
reason: "This console only runs statements naming an allowed table."
|
|
9519
|
+
};
|
|
9520
|
+
}
|
|
9521
|
+
for (const table of analysis.tables) {
|
|
9522
|
+
if (!allowed.has(table)) {
|
|
9523
|
+
return { allowed: false, reason: `Table "${table}" is not on the allow list.` };
|
|
9524
|
+
}
|
|
9525
|
+
}
|
|
9526
|
+
}
|
|
9527
|
+
return { allowed: true, reason: null };
|
|
9528
|
+
}
|
|
9529
|
+
|
|
9337
9530
|
// src/admin/inlines.ts
|
|
9338
9531
|
function adminInline(options) {
|
|
9339
9532
|
const slug = options.model.tablename;
|
|
@@ -11985,7 +12178,7 @@ function escapeHtml(value) {
|
|
|
11985
12178
|
return String(value ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
11986
12179
|
}
|
|
11987
12180
|
function renderLayout(context, title, body) {
|
|
11988
|
-
const { site, theme, prefix, session, currentPath, navModels, messages } = context;
|
|
12181
|
+
const { site, theme, prefix, session, currentPath, navModels, navSystem, messages } = context;
|
|
11989
12182
|
const authed = session !== null;
|
|
11990
12183
|
const indexUrl = `${prefix}/`;
|
|
11991
12184
|
const navLink = (url, label, active) => `<a href="${escapeHtml(url)}" class="tempest-admin-sidebar__link${active ? " tempest-admin-sidebar__link--active" : ""}">${escapeHtml(label)}</a>`;
|
|
@@ -11995,6 +12188,9 @@ function renderLayout(context, title, body) {
|
|
|
11995
12188
|
${navLink(indexUrl, "Dashboard", currentPath === indexUrl)}
|
|
11996
12189
|
${navModels.length > 0 ? `<span class="tempest-admin-sidebar__heading">Models</span>${navModels.map(
|
|
11997
12190
|
(entry) => navLink(entry.url, entry.label, currentPath.startsWith(entry.url))
|
|
12191
|
+
).join("")}` : ""}
|
|
12192
|
+
${navSystem.length > 0 ? `<span class="tempest-admin-sidebar__heading">System</span>${navSystem.map(
|
|
12193
|
+
(entry) => navLink(entry.url, entry.label, currentPath.startsWith(entry.url))
|
|
11998
12194
|
).join("")}` : ""}
|
|
11999
12195
|
</nav>
|
|
12000
12196
|
</aside>` : "";
|
|
@@ -12345,11 +12541,11 @@ function renderInline(inline, csrfToken, error) {
|
|
|
12345
12541
|
${more}
|
|
12346
12542
|
</section>`;
|
|
12347
12543
|
}
|
|
12348
|
-
function renderAuditPanel(
|
|
12349
|
-
const rows =
|
|
12544
|
+
function renderAuditPanel(audit2) {
|
|
12545
|
+
const rows = audit2.fields.map(
|
|
12350
12546
|
(field) => `<dt>${escapeHtml(field.label)}</dt><dd>${field.value === "" ? "<em>\u2014</em>" : escapeHtml(field.value)}</dd>`
|
|
12351
12547
|
).join("");
|
|
12352
|
-
const history =
|
|
12548
|
+
const history = audit2.history.length > 0 ? `<ol class="tempest-admin-history">${audit2.history.map((entry) => {
|
|
12353
12549
|
const changes = entry.changes.length > 0 ? `<table class="tempest-admin-history__changes"><thead><tr><th>Field</th><th>Before</th><th>After</th></tr></thead><tbody>${entry.changes.map(
|
|
12354
12550
|
(change) => `<tr><td>${escapeHtml(change.field)}</td><td>${escapeHtml(change.before)}</td><td>${escapeHtml(change.after)}</td></tr>`
|
|
12355
12551
|
).join("")}</tbody></table>` : "<p><em>No field changes recorded.</em></p>";
|
|
@@ -12447,6 +12643,86 @@ function renderFormPage(context, view) {
|
|
|
12447
12643
|
</section>`;
|
|
12448
12644
|
return renderLayout(context, `${heading} \xB7 ${context.site.title}`, body);
|
|
12449
12645
|
}
|
|
12646
|
+
function renderLogsPage(context, view) {
|
|
12647
|
+
const options = view.sources.map(
|
|
12648
|
+
(source) => `<option value="${escapeHtml(source.value)}"${source.selected ? " selected" : ""}>${escapeHtml(source.label)}</option>`
|
|
12649
|
+
).join("");
|
|
12650
|
+
const rows = view.rows.length > 0 ? view.rows.map((row) => {
|
|
12651
|
+
const context_ = row.context.map(
|
|
12652
|
+
(entry) => `<span class="tempest-admin-logs__meta"><b>${escapeHtml(entry.key)}</b>: ${escapeHtml(entry.value)}</span>`
|
|
12653
|
+
).join(" ");
|
|
12654
|
+
const message = row.stack === null ? `${escapeHtml(row.message)}${context_ === "" ? "" : `<br>${context_}`}` : `<details><summary>${escapeHtml(row.message)}</summary>${context_ === "" ? "" : `<p>${context_}</p>`}<pre>${escapeHtml(row.stack)}</pre></details>`;
|
|
12655
|
+
return `<tr>
|
|
12656
|
+
<td data-label="Level"><span class="tempest-log-badge tempest-log-badge--${escapeHtml(row.level)}">${escapeHtml(row.level)}</span></td>
|
|
12657
|
+
<td data-label="When">${escapeHtml(row.timestamp)}</td>
|
|
12658
|
+
<td data-label="Logger">${escapeHtml(row.logger)}</td>
|
|
12659
|
+
<td data-label="Message">${message}</td>
|
|
12660
|
+
</tr>`;
|
|
12661
|
+
}).join("") : `<tr><td colspan="4">No log records yet. Point <code>configureFileLogging</code> at the same directory to populate this page.</td></tr>`;
|
|
12662
|
+
const body = `<section class="tempest-admin-logs">
|
|
12663
|
+
<header class="tempest-admin-list__header">
|
|
12664
|
+
<h1>Logs</h1>
|
|
12665
|
+
<p>${escapeHtml(view.total)} record${view.total === 1 ? "" : "s"}.</p>
|
|
12666
|
+
</header>
|
|
12667
|
+
<div class="tempest-admin-list__toolbar">
|
|
12668
|
+
<form method="get" class="tempest-admin-list__filters">
|
|
12669
|
+
<label><span>Source</span><select name="source">${options}</select></label>
|
|
12670
|
+
<input type="search" name="q" value="${escapeHtml(view.query)}" placeholder="Search\u2026" aria-label="Search">
|
|
12671
|
+
<button type="submit">Apply</button>
|
|
12672
|
+
</form>
|
|
12673
|
+
<div class="tempest-admin-list__actions">
|
|
12674
|
+
<a href="${escapeHtml(view.exportMarkdownUrl)}">Export Markdown</a>
|
|
12675
|
+
<a href="${escapeHtml(view.exportJsonUrl)}">Export JSON</a>
|
|
12676
|
+
</div>
|
|
12677
|
+
</div>
|
|
12678
|
+
<div class="tempest-admin-table-wrap">
|
|
12679
|
+
<table class="tempest-admin-list__table">
|
|
12680
|
+
<thead><tr><th>Level</th><th>When</th><th>Logger</th><th>Message</th></tr></thead>
|
|
12681
|
+
<tbody>${rows}</tbody>
|
|
12682
|
+
</table>
|
|
12683
|
+
</div>
|
|
12684
|
+
${view.pages > 1 ? `<nav class="tempest-admin-list__pagination" aria-label="Pagination">
|
|
12685
|
+
${view.prevUrl !== null ? `<a href="${escapeHtml(view.prevUrl)}">\u2190 Prev</a>` : ""}
|
|
12686
|
+
<span>Page ${escapeHtml(view.page)} of ${escapeHtml(view.pages)}</span>
|
|
12687
|
+
${view.nextUrl !== null ? `<a href="${escapeHtml(view.nextUrl)}">Next \u2192</a>` : ""}
|
|
12688
|
+
</nav>` : ""}
|
|
12689
|
+
<p class="tempest-admin-form__hint">Exports carry at most ${escapeHtml(view.exportMax)} records, newest first, honouring the filters above.</p>
|
|
12690
|
+
</section>`;
|
|
12691
|
+
return renderLayout(context, `Logs \xB7 ${context.site.title}`, body);
|
|
12692
|
+
}
|
|
12693
|
+
function renderSqlPage(context, view) {
|
|
12694
|
+
if (context.session === null) throw new Error("The SQL console requires a session");
|
|
12695
|
+
const result = view.rowCount === null ? "" : `<p class="tempest-admin-form__hint">${escapeHtml(view.rowCount)} row${view.rowCount === 1 ? "" : "s"}${view.durationMs === null ? "" : ` in ${escapeHtml(view.durationMs)} ms`}${view.truncated ? " (truncated by the row cap)" : ""}.</p>
|
|
12696
|
+
<div class="tempest-admin-table-wrap">
|
|
12697
|
+
<table class="tempest-admin-list__table">
|
|
12698
|
+
<thead><tr>${view.columns.map((column6) => `<th>${escapeHtml(column6)}</th>`).join("")}</tr></thead>
|
|
12699
|
+
<tbody>${view.rows.map(
|
|
12700
|
+
(row) => `<tr>${row.map((cell) => `<td>${escapeHtml(cell)}</td>`).join("")}</tr>`
|
|
12701
|
+
).join("")}</tbody>
|
|
12702
|
+
</table>
|
|
12703
|
+
</div>`;
|
|
12704
|
+
const body = `<section class="tempest-admin-sql">
|
|
12705
|
+
<header class="tempest-admin-list__header">
|
|
12706
|
+
<h1>SQL console</h1>
|
|
12707
|
+
<p>Capabilities: <code>${escapeHtml(view.capabilities.join(", "))}</code></p>
|
|
12708
|
+
</header>
|
|
12709
|
+
${view.error !== null ? `<p class="tempest-admin-form__error">${escapeHtml(view.error)}</p>` : ""}
|
|
12710
|
+
<form method="post" action="${escapeHtml(`${context.prefix}/sql`)}" class="tempest-admin-form__form">
|
|
12711
|
+
<input type="hidden" name="csrf_token" value="${escapeHtml(context.session.csrfToken)}">
|
|
12712
|
+
<div class="tempest-admin-form__field">
|
|
12713
|
+
<label>
|
|
12714
|
+
<span>Statement</span>
|
|
12715
|
+
<textarea name="sql" rows="6" spellcheck="false" required>${escapeHtml(view.sql)}</textarea>
|
|
12716
|
+
</label>
|
|
12717
|
+
</div>
|
|
12718
|
+
<div class="tempest-admin-form__actions">
|
|
12719
|
+
<button type="submit">Run</button>
|
|
12720
|
+
</div>
|
|
12721
|
+
</form>
|
|
12722
|
+
${result}
|
|
12723
|
+
</section>`;
|
|
12724
|
+
return renderLayout(context, `SQL console \xB7 ${context.site.title}`, body);
|
|
12725
|
+
}
|
|
12450
12726
|
function renderImportPage(context, view) {
|
|
12451
12727
|
if (context.session === null) throw new Error("The import page requires a session");
|
|
12452
12728
|
const summary = view.created === null ? "" : `<p class="tempest-admin-import__summary">Created ${escapeHtml(view.created)} record${view.created === 1 ? "" : "s"}.</p>`;
|
|
@@ -12532,7 +12808,66 @@ var AUTOCOMPLETE_SCRIPT = `<script>
|
|
|
12532
12808
|
});
|
|
12533
12809
|
})();
|
|
12534
12810
|
</script>`;
|
|
12811
|
+
function filesFor(dir, source) {
|
|
12812
|
+
if (source === "500") return [join(dir, HTTP_500_LOG_FILE)];
|
|
12813
|
+
if (source === "all") return Object.values(LEVEL_LOG_FILES).map((f) => join(dir, f));
|
|
12814
|
+
return [join(dir, LEVEL_LOG_FILES[source])];
|
|
12815
|
+
}
|
|
12816
|
+
async function readLogEntries(dir, source) {
|
|
12817
|
+
return await readEntries(filesFor(dir, source));
|
|
12818
|
+
}
|
|
12819
|
+
async function readEntries(files) {
|
|
12820
|
+
const entries = [];
|
|
12821
|
+
for (const file of files) {
|
|
12822
|
+
let content;
|
|
12823
|
+
try {
|
|
12824
|
+
content = await readFile(file, "utf8");
|
|
12825
|
+
} catch {
|
|
12826
|
+
continue;
|
|
12827
|
+
}
|
|
12828
|
+
for (const line of content.split("\n")) {
|
|
12829
|
+
if (!line.trim()) continue;
|
|
12830
|
+
try {
|
|
12831
|
+
entries.push(JSON.parse(line));
|
|
12832
|
+
} catch {
|
|
12833
|
+
}
|
|
12834
|
+
}
|
|
12835
|
+
}
|
|
12836
|
+
return entries;
|
|
12837
|
+
}
|
|
12838
|
+
function makeLogsRouter(options) {
|
|
12839
|
+
const router = Router();
|
|
12840
|
+
const path = options.path ?? "/logs";
|
|
12841
|
+
const guards = options.guards ?? [];
|
|
12842
|
+
const handler = (req, res, next) => {
|
|
12843
|
+
const source = req.query.source ?? "all";
|
|
12844
|
+
const validSources = ["all", "debug", "info", "warning", "error", "500"];
|
|
12845
|
+
if (!validSources.includes(source)) {
|
|
12846
|
+
res.status(422).json({ detail: "Invalid log source", code: "VALIDATION_ERROR", details: {} });
|
|
12847
|
+
return;
|
|
12848
|
+
}
|
|
12849
|
+
const page2 = Math.max(1, Number(req.query.page) || 1);
|
|
12850
|
+
const pageSize = Math.min(500, Math.max(1, Number(req.query.pageSize) || 50));
|
|
12851
|
+
readEntries(filesFor(options.dir, source)).then((entries) => {
|
|
12852
|
+
entries.reverse();
|
|
12853
|
+
const total = entries.length;
|
|
12854
|
+
const start = (page2 - 1) * pageSize;
|
|
12855
|
+
res.json({
|
|
12856
|
+
items: entries.slice(start, start + pageSize),
|
|
12857
|
+
total,
|
|
12858
|
+
page: page2,
|
|
12859
|
+
pageSize,
|
|
12860
|
+
pages: Math.ceil(total / pageSize)
|
|
12861
|
+
});
|
|
12862
|
+
}).catch(next);
|
|
12863
|
+
};
|
|
12864
|
+
router.get(path, ...guards, handler);
|
|
12865
|
+
return router;
|
|
12866
|
+
}
|
|
12535
12867
|
var logger2 = new JSONLogger("tempest_express_sdk.admin.router");
|
|
12868
|
+
var LOG_SOURCES = ["all", "debug", "info", "warning", "error", "500"];
|
|
12869
|
+
var LOG_PAGE_SIZE = 50;
|
|
12870
|
+
var LOG_EXPORT_MAX = 500;
|
|
12536
12871
|
var INLINE_ROW_LIMIT = 50;
|
|
12537
12872
|
var AUTOCOMPLETE_LIMIT = 20;
|
|
12538
12873
|
var AUDIT_HISTORY_LIMIT = 50;
|
|
@@ -12564,6 +12899,13 @@ function makeAdminRouter(site, options) {
|
|
|
12564
12899
|
const theme = resolveAdminTheme(site.theme);
|
|
12565
12900
|
const showMetrics = options.showMetrics ?? true;
|
|
12566
12901
|
const exportMaxRows = options.exportMaxRows ?? 5e3;
|
|
12902
|
+
const systemNav = [];
|
|
12903
|
+
if (options.logDir !== void 0) {
|
|
12904
|
+
systemNav.push({ label: "Logs", url: `${prefix}/logs` });
|
|
12905
|
+
}
|
|
12906
|
+
if (options.sqlConsole !== void 0) {
|
|
12907
|
+
systemNav.push({ label: "SQL console", url: `${prefix}/sql` });
|
|
12908
|
+
}
|
|
12567
12909
|
const maxUploadBytes = options.maxUploadBytes ?? 10 * 1024 * 1024;
|
|
12568
12910
|
const sessions = new AdminSessionStore({
|
|
12569
12911
|
secret: options.secretKey,
|
|
@@ -12585,6 +12927,7 @@ function makeAdminRouter(site, options) {
|
|
|
12585
12927
|
label: admin.verboseNamePlural(),
|
|
12586
12928
|
url: `${prefix}/m/${admin.slug()}`
|
|
12587
12929
|
})),
|
|
12930
|
+
navSystem: systemNav,
|
|
12588
12931
|
messages: flashFor(req)
|
|
12589
12932
|
});
|
|
12590
12933
|
const allows = async (principal, admin, action) => {
|
|
@@ -12795,6 +13138,187 @@ function makeAdminRouter(site, options) {
|
|
|
12795
13138
|
);
|
|
12796
13139
|
})
|
|
12797
13140
|
);
|
|
13141
|
+
if (options.logDir !== void 0) {
|
|
13142
|
+
const logDir = options.logDir;
|
|
13143
|
+
router.get(
|
|
13144
|
+
`${prefix}/logs`,
|
|
13145
|
+
guarded(async (req, res) => {
|
|
13146
|
+
const state = await authenticate(req, res);
|
|
13147
|
+
if (state === null) return;
|
|
13148
|
+
const { entries, source, search } = await readLogs(req, logDir);
|
|
13149
|
+
const page2 = Math.max(1, Number.parseInt(queryString(req.query.page), 10) || 1);
|
|
13150
|
+
const start = (page2 - 1) * LOG_PAGE_SIZE;
|
|
13151
|
+
const pages = Math.max(1, Math.ceil(entries.length / LOG_PAGE_SIZE));
|
|
13152
|
+
const exportUrl = (format) => `${prefix}/logs/export?${buildQuery({ source, q: search, format })}`;
|
|
13153
|
+
const pageUrl = (target) => `?${buildQuery({ source, q: search, page: target })}`;
|
|
13154
|
+
html(
|
|
13155
|
+
res,
|
|
13156
|
+
renderLogsPage(context(req, state.session, state.visible), {
|
|
13157
|
+
sources: LOG_SOURCES.map((value) => ({
|
|
13158
|
+
value,
|
|
13159
|
+
label: value === "500" ? "HTTP 500" : humanizeField(value),
|
|
13160
|
+
selected: value === source
|
|
13161
|
+
})),
|
|
13162
|
+
query: search,
|
|
13163
|
+
rows: entries.slice(start, start + LOG_PAGE_SIZE).map((entry) => ({
|
|
13164
|
+
level: entry.level,
|
|
13165
|
+
timestamp: entry.timestamp,
|
|
13166
|
+
logger: entry.logger,
|
|
13167
|
+
message: entry.message,
|
|
13168
|
+
stack: entry.stack,
|
|
13169
|
+
context: Object.entries(entry.context).map(([key, value]) => ({
|
|
13170
|
+
key,
|
|
13171
|
+
value: typeof value === "string" ? value : JSON.stringify(value)
|
|
13172
|
+
}))
|
|
13173
|
+
})),
|
|
13174
|
+
total: entries.length,
|
|
13175
|
+
page: page2,
|
|
13176
|
+
pages,
|
|
13177
|
+
prevUrl: page2 > 1 ? pageUrl(page2 - 1) : null,
|
|
13178
|
+
nextUrl: page2 < pages ? pageUrl(page2 + 1) : null,
|
|
13179
|
+
exportMarkdownUrl: exportUrl("md"),
|
|
13180
|
+
exportJsonUrl: exportUrl("json"),
|
|
13181
|
+
exportMax: LOG_EXPORT_MAX
|
|
13182
|
+
})
|
|
13183
|
+
);
|
|
13184
|
+
})
|
|
13185
|
+
);
|
|
13186
|
+
router.get(
|
|
13187
|
+
`${prefix}/logs/export`,
|
|
13188
|
+
guarded(async (req, res) => {
|
|
13189
|
+
const state = await authenticate(req, res);
|
|
13190
|
+
if (state === null) return;
|
|
13191
|
+
const format = queryString(req.query.format) === "json" ? "json" : "md";
|
|
13192
|
+
const { entries, source, search } = await readLogs(req, logDir);
|
|
13193
|
+
const window = entries.slice(0, LOG_EXPORT_MAX);
|
|
13194
|
+
const payload = format === "json" ? renderLogEntriesJson(window) : renderLogEntriesMarkdown(window, {
|
|
13195
|
+
source,
|
|
13196
|
+
query: search,
|
|
13197
|
+
total: entries.length
|
|
13198
|
+
});
|
|
13199
|
+
res.status(200).type(format === "json" ? "application/json" : "text/markdown; charset=utf-8").set("content-disposition", `attachment; filename="logs.${format}"`).send(payload);
|
|
13200
|
+
})
|
|
13201
|
+
);
|
|
13202
|
+
}
|
|
13203
|
+
if (options.sqlConsole !== void 0) {
|
|
13204
|
+
const console_ = options.sqlConsole;
|
|
13205
|
+
const policy = console_.policy ?? {};
|
|
13206
|
+
const dialect = console_.dialect ?? "postgresql";
|
|
13207
|
+
const capabilities = policy.capabilities ?? [SqlCapability.READ];
|
|
13208
|
+
const maxRows = policy.maxRows ?? 200;
|
|
13209
|
+
router.get(
|
|
13210
|
+
`${prefix}/sql`,
|
|
13211
|
+
guarded(async (req, res) => {
|
|
13212
|
+
const state = await authenticate(req, res);
|
|
13213
|
+
if (state === null) return;
|
|
13214
|
+
html(
|
|
13215
|
+
res,
|
|
13216
|
+
renderSqlPage(context(req, state.session, state.visible), {
|
|
13217
|
+
sql: "",
|
|
13218
|
+
capabilities: [...capabilities],
|
|
13219
|
+
error: null,
|
|
13220
|
+
columns: [],
|
|
13221
|
+
rows: [],
|
|
13222
|
+
rowCount: null,
|
|
13223
|
+
truncated: false,
|
|
13224
|
+
durationMs: null
|
|
13225
|
+
})
|
|
13226
|
+
);
|
|
13227
|
+
})
|
|
13228
|
+
);
|
|
13229
|
+
router.post(
|
|
13230
|
+
`${prefix}/sql`,
|
|
13231
|
+
guarded(async (req, res) => {
|
|
13232
|
+
const state = await authenticate(req, res);
|
|
13233
|
+
if (state === null) return;
|
|
13234
|
+
if (!checkCsrf(req, res, state)) return;
|
|
13235
|
+
const body = req.body;
|
|
13236
|
+
const sql5 = typeof body.sql === "string" ? body.sql : "";
|
|
13237
|
+
const principal = backend.displayName(state.principal);
|
|
13238
|
+
const render = (view) => {
|
|
13239
|
+
html(
|
|
13240
|
+
res,
|
|
13241
|
+
renderSqlPage(context(req, state.session, state.visible), {
|
|
13242
|
+
sql: sql5,
|
|
13243
|
+
capabilities: [...capabilities],
|
|
13244
|
+
...view
|
|
13245
|
+
}),
|
|
13246
|
+
view.error === null ? 200 : 400
|
|
13247
|
+
);
|
|
13248
|
+
};
|
|
13249
|
+
const parser = await loadSqlParser();
|
|
13250
|
+
const analysis = analyzeSql(sql5, dialect, parser);
|
|
13251
|
+
const verdict = checkSqlPolicy(analysis, policy);
|
|
13252
|
+
if (!verdict.allowed) {
|
|
13253
|
+
await audit(console_.onAudit, {
|
|
13254
|
+
sql: sql5,
|
|
13255
|
+
principal,
|
|
13256
|
+
allowed: false,
|
|
13257
|
+
reason: verdict.reason,
|
|
13258
|
+
analysis,
|
|
13259
|
+
durationMs: null,
|
|
13260
|
+
rowCount: null
|
|
13261
|
+
});
|
|
13262
|
+
render({
|
|
13263
|
+
error: verdict.reason,
|
|
13264
|
+
columns: [],
|
|
13265
|
+
rows: [],
|
|
13266
|
+
rowCount: null,
|
|
13267
|
+
truncated: false,
|
|
13268
|
+
durationMs: null
|
|
13269
|
+
});
|
|
13270
|
+
return;
|
|
13271
|
+
}
|
|
13272
|
+
const started = Date.now();
|
|
13273
|
+
let rows;
|
|
13274
|
+
try {
|
|
13275
|
+
rows = console_.run === void 0 ? await state.dbSession.raw(sql5).all() : await console_.run(sql5, state.dbSession);
|
|
13276
|
+
} catch (error) {
|
|
13277
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
13278
|
+
await audit(console_.onAudit, {
|
|
13279
|
+
sql: sql5,
|
|
13280
|
+
principal,
|
|
13281
|
+
allowed: true,
|
|
13282
|
+
reason: message,
|
|
13283
|
+
analysis,
|
|
13284
|
+
durationMs: Date.now() - started,
|
|
13285
|
+
rowCount: null
|
|
13286
|
+
});
|
|
13287
|
+
render({
|
|
13288
|
+
error: message,
|
|
13289
|
+
columns: [],
|
|
13290
|
+
rows: [],
|
|
13291
|
+
rowCount: null,
|
|
13292
|
+
truncated: false,
|
|
13293
|
+
durationMs: null
|
|
13294
|
+
});
|
|
13295
|
+
return;
|
|
13296
|
+
}
|
|
13297
|
+
const durationMs = Date.now() - started;
|
|
13298
|
+
await audit(console_.onAudit, {
|
|
13299
|
+
sql: sql5,
|
|
13300
|
+
principal,
|
|
13301
|
+
allowed: true,
|
|
13302
|
+
reason: null,
|
|
13303
|
+
analysis,
|
|
13304
|
+
durationMs,
|
|
13305
|
+
rowCount: rows.length
|
|
13306
|
+
});
|
|
13307
|
+
const window = rows.slice(0, maxRows);
|
|
13308
|
+
const columns = window.length === 0 ? [] : Object.keys(window[0] ?? {});
|
|
13309
|
+
render({
|
|
13310
|
+
error: null,
|
|
13311
|
+
columns,
|
|
13312
|
+
rows: window.map(
|
|
13313
|
+
(row) => columns.map((column6) => formatCellValue(row[column6]))
|
|
13314
|
+
),
|
|
13315
|
+
rowCount: rows.length,
|
|
13316
|
+
truncated: rows.length > window.length,
|
|
13317
|
+
durationMs
|
|
13318
|
+
});
|
|
13319
|
+
})
|
|
13320
|
+
);
|
|
13321
|
+
}
|
|
12798
13322
|
router.get(
|
|
12799
13323
|
`${prefix}/m/:slug`,
|
|
12800
13324
|
guarded(async (req, res) => {
|
|
@@ -13512,6 +14036,15 @@ function makeAdminRouter(site, options) {
|
|
|
13512
14036
|
const row = await admin.repository(dbSession).first({ [admin.identityField]: identity });
|
|
13513
14037
|
return row ?? null;
|
|
13514
14038
|
}
|
|
14039
|
+
async function readLogs(req, dir) {
|
|
14040
|
+
const requested = queryString(req.query.source);
|
|
14041
|
+
const source = LOG_SOURCES.includes(requested) ? requested : "all";
|
|
14042
|
+
const search = queryString(req.query.q);
|
|
14043
|
+
const raw = await readLogEntries(dir, source);
|
|
14044
|
+
const entries = filterLogEntries(raw.map(toLogEntry), search);
|
|
14045
|
+
entries.reverse();
|
|
14046
|
+
return { entries, source, search };
|
|
14047
|
+
}
|
|
13515
14048
|
function renderImport(req, state, admin, error, created, rowErrors) {
|
|
13516
14049
|
return renderImportPage(context(req, state.session, state.visible), {
|
|
13517
14050
|
title: admin.verboseNamePlural(),
|
|
@@ -13800,6 +14333,16 @@ function inlineFieldNames(childAdmin, inline) {
|
|
|
13800
14333
|
function inlineFields(childAdmin, names, key, values, errors) {
|
|
13801
14334
|
return buildFormFields(childAdmin, { values, errors }).filter((field) => names.includes(field.name)).map((field) => ({ ...field, name: `row.${key}.${field.name}` }));
|
|
13802
14335
|
}
|
|
14336
|
+
async function audit(hook, entry) {
|
|
14337
|
+
if (hook === void 0) return;
|
|
14338
|
+
try {
|
|
14339
|
+
await hook(entry);
|
|
14340
|
+
} catch (error) {
|
|
14341
|
+
logger2.error("Admin SQL audit hook failed", {
|
|
14342
|
+
error: error instanceof Error ? error.message : String(error)
|
|
14343
|
+
});
|
|
14344
|
+
}
|
|
14345
|
+
}
|
|
13803
14346
|
function flagAllows(admin, action) {
|
|
13804
14347
|
if (action === AdminPermission.CREATE) return admin.canCreate;
|
|
13805
14348
|
if (action === AdminPermission.EDIT) return admin.canEdit;
|
|
@@ -15886,59 +16429,6 @@ function makeToolSpecRouter(spec, options = {}) {
|
|
|
15886
16429
|
});
|
|
15887
16430
|
return router;
|
|
15888
16431
|
}
|
|
15889
|
-
function filesFor(dir, source) {
|
|
15890
|
-
if (source === "500") return [join(dir, HTTP_500_LOG_FILE)];
|
|
15891
|
-
if (source === "all") return Object.values(LEVEL_LOG_FILES).map((f) => join(dir, f));
|
|
15892
|
-
return [join(dir, LEVEL_LOG_FILES[source])];
|
|
15893
|
-
}
|
|
15894
|
-
async function readEntries(files) {
|
|
15895
|
-
const entries = [];
|
|
15896
|
-
for (const file of files) {
|
|
15897
|
-
let content;
|
|
15898
|
-
try {
|
|
15899
|
-
content = await readFile(file, "utf8");
|
|
15900
|
-
} catch {
|
|
15901
|
-
continue;
|
|
15902
|
-
}
|
|
15903
|
-
for (const line of content.split("\n")) {
|
|
15904
|
-
if (!line.trim()) continue;
|
|
15905
|
-
try {
|
|
15906
|
-
entries.push(JSON.parse(line));
|
|
15907
|
-
} catch {
|
|
15908
|
-
}
|
|
15909
|
-
}
|
|
15910
|
-
}
|
|
15911
|
-
return entries;
|
|
15912
|
-
}
|
|
15913
|
-
function makeLogsRouter(options) {
|
|
15914
|
-
const router = Router();
|
|
15915
|
-
const path = options.path ?? "/logs";
|
|
15916
|
-
const guards = options.guards ?? [];
|
|
15917
|
-
const handler = (req, res, next) => {
|
|
15918
|
-
const source = req.query.source ?? "all";
|
|
15919
|
-
const validSources = ["all", "debug", "info", "warning", "error", "500"];
|
|
15920
|
-
if (!validSources.includes(source)) {
|
|
15921
|
-
res.status(422).json({ detail: "Invalid log source", code: "VALIDATION_ERROR", details: {} });
|
|
15922
|
-
return;
|
|
15923
|
-
}
|
|
15924
|
-
const page2 = Math.max(1, Number(req.query.page) || 1);
|
|
15925
|
-
const pageSize = Math.min(500, Math.max(1, Number(req.query.pageSize) || 50));
|
|
15926
|
-
readEntries(filesFor(options.dir, source)).then((entries) => {
|
|
15927
|
-
entries.reverse();
|
|
15928
|
-
const total = entries.length;
|
|
15929
|
-
const start = (page2 - 1) * pageSize;
|
|
15930
|
-
res.json({
|
|
15931
|
-
items: entries.slice(start, start + pageSize),
|
|
15932
|
-
total,
|
|
15933
|
-
page: page2,
|
|
15934
|
-
pageSize,
|
|
15935
|
-
pages: Math.ceil(total / pageSize)
|
|
15936
|
-
});
|
|
15937
|
-
}).catch(next);
|
|
15938
|
-
};
|
|
15939
|
-
router.get(path, ...guards, handler);
|
|
15940
|
-
return router;
|
|
15941
|
-
}
|
|
15942
16432
|
function createTestDatabase(models) {
|
|
15943
16433
|
const driver = NodeSqliteDriver.open(":memory:");
|
|
15944
16434
|
for (const model of models) {
|
|
@@ -15970,6 +16460,6 @@ async function withTestDatabase(models, fn) {
|
|
|
15970
16460
|
}
|
|
15971
16461
|
}
|
|
15972
16462
|
|
|
15973
|
-
export { ADMIN_CSS, ActivationService, AdminJsonSite, AdminModel, AdminPermission, AdminSessionStore, AdminSite, AppException, AttemptThrottle, AuditAction, BaseAuditLogModel, BaseController, BaseModel, BaseOAuthClient, BaseOutboxModel, BaseService, BaseUserModel, BaseUserRefreshTokenModel, BaseUserTokenModel, CEP_PATTERN, CNPJ_PATTERN, CPF_PATTERN, CSRF_COOKIE_NAME, CSRF_HEADER_NAME, CircuitOpenError, CompositeFeatureFlagBackend, ConflictException, DEFAULT_DOCS_FAVICON, DEFAULT_LOCALE, EmailProvider, EmailUtils, EnvFeatureFlagBackend, EventStream, ExpiredTokenException, FeatureFlags, ForbiddenException, GitHubOAuthClient, GoogleOAuthClient, GracefulShutdown, HTTPClient, HTTP_500_LOG_FILE, HTTP_500_MARKER, HttpMetrics, IDEMPOTENCY_HEADER, InvalidTokenException, JSONLogger, JWTUtils, LEVEL_LOG_FILES, LocalUploadStorage, MemoryBroker, MemoryCacheManager, MemoryFeatureFlagBackend, MemoryIdempotencyStore, MemoryRateLimitStore, MemorySessionStore, MemoryThrottleBackend, MessageCatalog, MessagingHub, MetricsUtils, MfaService, MultipartLimitError, NotFoundException, OAuthError, OIDCProvider, OutboxRelay, OutboxStatus, PHONE_BR_PATTERN, PasswordResetService, REDOC_CDN_URL, REQUEST_ID_HEADER, RabbitBroker, RedisCacheManager, RedisIdempotencyStore, RedisRateLimitStore, RedisSSEBroker, RedisSessionStore, Region, RetryPolicy, S3UploadStorage, SSEBroker, ServerSentEvent, SessionService, TOTPHelper, TaskManager, TelegramProvider, TenantScopedRepository, TooManyRequestsException, TwilioSmsProvider, UF, UnauthorizedException, UserAuthService, UserModelAuthBackend, UserTokenPurpose, ValidationException, WebPushDispatcher, WebPushError, WebPushGoneError, WebSocketHub, WebhookSignatureVerifier, WhatsAppProvider, activationSchema, addLogSink, adminAction, adminColumns, adminInline, adminLens, adminThemeCss, attachWebSocketHub, authResponseSchema, authSettingsShape, backupDatabase, bearerToken, bodySizeLimitMiddleware, broadcastText, buildContentDisposition, buildFormFields, buildPaginationLinkHeader, cached2 as cached, cepField, citiesByUf, cnpjField, coerceFlag, configureFileLogging, configureLogging, cpfField, cpfOrCnpjField, createApp, createOpenApiRegistry, createTestDatabase, createdByColumn, csrfMiddleware, csrfTokenMatches, cursorPaginationFilterSchema, cursorPaginationSchema, decodeCursor, defaultMessageCatalog, defineEnum, deletedAtColumn, diffSnapshots, emailSettingsShape, encodeCursor, envList, escapeHtml, filterForColumn, foreignKeyFields, foreignKeyLabel, foreignKeyTable, formatCellValue, formatFieldValue, generateCsrfToken, generateOAuthState, generateOpaqueToken, generateOpenApiDocument, getAuth, getClientIp, getConditions, getPaginationConditions, getRequestId, getState, groupInlineSubmission, hashOpaqueToken, humanizeField, idempotencyMiddleware, inboundMessageSchema, isColumnOptional, isMultipart, isSearchableColumn, isValidCep, isValidCity, isValidCnpj, isValidCpf, isValidCpfCnpj, isValidPhoneBr, isValidUf, jwtSettingsShape, keyByHeader, keyByIp, keyByJwtClaim, keyByJwtSubject, listStates, logEntrySchema, logSettingsShape, loginSchema, makeAdminJsonRouter, makeAdminRouter, makeAppExceptionHandler, makeAuthRouter, makeFlagGuard, makeHealthRouter, makeJwtAuthMiddleware, makeLogsRouter, makeMetricsRouter, makeSessionMiddleware, makeToolSpecRouter, makeTwilioWebhookRouter, makeUnhandledExceptionHandler, makeWhatsAppWebhookRouter, metricCard, mfaChallengeSchema, mfaCodeSchema, mfaEnrollResponseSchema, minioSettingsShape, modifyDict, mountOpenApiJson, mountRedoc, mountSwaggerUi, normalizeCep, normalizeCnpj, normalizeCpf, normalizeCpfCnpj, normalizePhoneBr, normalizeUf, notFoundHandler, onlyDigits, paginationFilterSchema, paginationSchema, parseAcceptLanguage, parseCookies, parseCsv, parseFormBody, parseMultipart, partitionTotal, passwordResetConfirmSchema, passwordResetRequestSchema, phoneBrField, prometheusMiddleware, rabbitmqSettingsShape, rateLimitMiddleware, redisSettingsShape, refreshSchema, registerExceptionHandlers, renderAuthResultPage, renderDashboardPage, renderDetailPage, renderFormPage, renderImportPage, renderLayout, renderListPage, renderLoginPage, renderMfaPage, renderPasswordResetFormPage, requestIdMiddleware, requestTracingMiddleware, requireRoles, resolveAdminTheme, resolveDownloadPath, resolveRedocBundle, runServer, runWithRequestContext, sendBytesDownload, sendFileDownload, sessionCookie, sessionSettingsShape, setRequestId, signupSchema, snapshot, sseResponse, statesByRegion, syncFilterSchema, syncPaginationSchema, tableNameFor, toUtc, tokenFromUrl, tokenPairSchema, tokenSettingsShape, trendDirection, trendPercent, ufField, updatedByColumn, uploadSettingsShape, userPublicSchema, utcnow, validateTwilioSignature, verifyOpaqueToken, webPushKeysSchema, webPushPayloadSchema, webPushSettingsShape, webPushSubscriptionSchema, webSocketSettingsShape, widgetForColumn, withTestDatabase, wrapWithSlowQueryLog, wsEnvelopeSchema };
|
|
16463
|
+
export { ADMIN_CSS, ActivationService, AdminJsonSite, AdminModel, AdminPermission, AdminSessionStore, AdminSite, AppException, AttemptThrottle, AuditAction, BaseAuditLogModel, BaseController, BaseModel, BaseOAuthClient, BaseOutboxModel, BaseService, BaseUserModel, BaseUserRefreshTokenModel, BaseUserTokenModel, CEP_PATTERN, CNPJ_PATTERN, CPF_PATTERN, CSRF_COOKIE_NAME, CSRF_HEADER_NAME, CircuitOpenError, CompositeFeatureFlagBackend, ConflictException, DEFAULT_DOCS_FAVICON, DEFAULT_LOCALE, EmailProvider, EmailUtils, EnvFeatureFlagBackend, EventStream, ExpiredTokenException, FeatureFlags, ForbiddenException, GitHubOAuthClient, GoogleOAuthClient, GracefulShutdown, HTTPClient, HTTP_500_LOG_FILE, HTTP_500_MARKER, HttpMetrics, IDEMPOTENCY_HEADER, InvalidTokenException, JSONLogger, JWTUtils, LEVEL_LOG_FILES, LocalUploadStorage, MemoryBroker, MemoryCacheManager, MemoryFeatureFlagBackend, MemoryIdempotencyStore, MemoryRateLimitStore, MemorySessionStore, MemoryThrottleBackend, MessageCatalog, MessagingHub, MetricsUtils, MfaService, MultipartLimitError, NotFoundException, OAuthError, OIDCProvider, OutboxRelay, OutboxStatus, PHONE_BR_PATTERN, PasswordResetService, REDOC_CDN_URL, REQUEST_ID_HEADER, RabbitBroker, RedisCacheManager, RedisIdempotencyStore, RedisRateLimitStore, RedisSSEBroker, RedisSessionStore, Region, RetryPolicy, S3UploadStorage, SSEBroker, ServerSentEvent, SessionService, SqlCapability, TOTPHelper, TaskManager, TelegramProvider, TenantScopedRepository, TooManyRequestsException, TwilioSmsProvider, UF, UnauthorizedException, UserAuthService, UserModelAuthBackend, UserTokenPurpose, ValidationException, WebPushDispatcher, WebPushError, WebPushGoneError, WebSocketHub, WebhookSignatureVerifier, WhatsAppProvider, activationSchema, addLogSink, adminAction, adminColumns, adminInline, adminLens, adminThemeCss, analyzeSql, attachWebSocketHub, authResponseSchema, authSettingsShape, backupDatabase, bearerToken, bodySizeLimitMiddleware, broadcastText, buildContentDisposition, buildFormFields, buildPaginationLinkHeader, cached2 as cached, cepField, checkSqlPolicy, citiesByUf, cnpjField, coerceFlag, configureFileLogging, configureLogging, cpfField, cpfOrCnpjField, createApp, createOpenApiRegistry, createTestDatabase, createdByColumn, csrfMiddleware, csrfTokenMatches, cursorPaginationFilterSchema, cursorPaginationSchema, decodeCursor, defaultMessageCatalog, defineEnum, deletedAtColumn, diffSnapshots, emailSettingsShape, encodeCursor, envList, escapeHtml, filterForColumn, filterLogEntries, foreignKeyFields, foreignKeyLabel, foreignKeyTable, formatCellValue, formatFieldValue, generateCsrfToken, generateOAuthState, generateOpaqueToken, generateOpenApiDocument, getAuth, getClientIp, getConditions, getPaginationConditions, getRequestId, getState, groupInlineSubmission, hashOpaqueToken, humanizeField, idempotencyMiddleware, inboundMessageSchema, isColumnOptional, isMultipart, isSearchableColumn, isValidCep, isValidCity, isValidCnpj, isValidCpf, isValidCpfCnpj, isValidPhoneBr, isValidUf, jwtSettingsShape, keyByHeader, keyByIp, keyByJwtClaim, keyByJwtSubject, listStates, loadSqlParser, logEntrySchema, logSettingsShape, loginSchema, makeAdminJsonRouter, makeAdminRouter, makeAppExceptionHandler, makeAuthRouter, makeFlagGuard, makeHealthRouter, makeJwtAuthMiddleware, makeLogsRouter, makeMetricsRouter, makeSessionMiddleware, makeToolSpecRouter, makeTwilioWebhookRouter, makeUnhandledExceptionHandler, makeWhatsAppWebhookRouter, metricCard, mfaChallengeSchema, mfaCodeSchema, mfaEnrollResponseSchema, minioSettingsShape, modifyDict, mountOpenApiJson, mountRedoc, mountSwaggerUi, normalizeCep, normalizeCnpj, normalizeCpf, normalizeCpfCnpj, normalizePhoneBr, normalizeUf, notFoundHandler, onlyDigits, paginationFilterSchema, paginationSchema, parseAcceptLanguage, parseCookies, parseCsv, parseFormBody, parseMultipart, partitionTotal, passwordResetConfirmSchema, passwordResetRequestSchema, phoneBrField, prometheusMiddleware, rabbitmqSettingsShape, rateLimitMiddleware, readLogEntries, redisSettingsShape, refreshSchema, registerExceptionHandlers, renderAuthResultPage, renderDashboardPage, renderDetailPage, renderFormPage, renderImportPage, renderLayout, renderListPage, renderLogEntriesJson, renderLogEntriesMarkdown, renderLoginPage, renderLogsPage, renderMfaPage, renderPasswordResetFormPage, renderSqlPage, requestIdMiddleware, requestTracingMiddleware, requireRoles, resolveAdminTheme, resolveDownloadPath, resolveRedocBundle, runServer, runWithRequestContext, sendBytesDownload, sendFileDownload, sessionCookie, sessionSettingsShape, setRequestId, signupSchema, snapshot, sseResponse, statesByRegion, syncFilterSchema, syncPaginationSchema, tableNameFor, toLogEntry, toUtc, tokenFromUrl, tokenPairSchema, tokenSettingsShape, trendDirection, trendPercent, ufField, updatedByColumn, uploadSettingsShape, userPublicSchema, utcnow, validateTwilioSignature, verifyOpaqueToken, webPushKeysSchema, webPushPayloadSchema, webPushSettingsShape, webPushSubscriptionSchema, webSocketSettingsShape, widgetForColumn, withTestDatabase, wrapWithSlowQueryLog, wsEnvelopeSchema };
|
|
15974
16464
|
//# sourceMappingURL=index.js.map
|
|
15975
16465
|
//# sourceMappingURL=index.js.map
|