@musnows/scriverse 0.6.11 → 0.7.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 +2 -0
- package/dist/ai.js +43 -10
- package/dist/ai.js.map +1 -1
- package/dist/app.js +16 -0
- package/dist/app.js.map +1 -1
- package/dist/database.js +48 -3
- package/dist/database.js.map +1 -1
- package/dist/public/app.js +298 -15
- package/dist/public/display-labels.js +1 -1
- package/dist/public/entity-version.js +2 -1
- package/dist/public/index.html +29 -3
- package/dist/public/styles.css +56 -12
- package/dist/server-runtime.js +118 -4
- package/dist/server-runtime.js.map +1 -1
- package/dist/store.js +170 -16
- package/dist/store.js.map +1 -1
- package/dist/user-auth.js +8 -0
- package/dist/user-auth.js.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
package/dist/public/styles.css
CHANGED
|
@@ -944,6 +944,27 @@ body.work-viewer-mode .character-editor-actions { display: none !important; }
|
|
|
944
944
|
font-size: 13px;
|
|
945
945
|
}
|
|
946
946
|
.search-form .primary-button { min-height: 38px; white-space: nowrap; }
|
|
947
|
+
.replace-dialog { display: flex; width: min(620px, calc(100vw - 32px)); height: min(680px, calc(100dvh - 32px)); max-height: calc(100dvh - 32px); overflow: hidden; }
|
|
948
|
+
.replace-dialog:not([open]) { display: none; }
|
|
949
|
+
.replace-dialog > form { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; width: 100%; min-height: 0; }
|
|
950
|
+
.replace-dialog-body { display: grid; min-height: 0; gap: 16px; padding: 20px 24px 6px; overflow-y: auto; }
|
|
951
|
+
.replace-field { display: grid; gap: 6px; color: var(--muted); font-size: 11px; }
|
|
952
|
+
.replace-field input, .replace-field textarea { width: 100%; padding: 9px 10px; border: 1px solid var(--line); border-radius: 4px; background: var(--surface); color: var(--ink); font-size: 13px; line-height: 1.6; }
|
|
953
|
+
.replace-field textarea { min-height: 96px; resize: vertical; }
|
|
954
|
+
.replace-scope-fieldset { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin: 0; padding: 12px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface-soft); }
|
|
955
|
+
.replace-scope-fieldset legend { padding: 0 6px; color: var(--ink); font-size: 12px; font-weight: 650; }
|
|
956
|
+
.replace-scope-fieldset legend, .replace-scope-fieldset > p { grid-column: 1 / -1; }
|
|
957
|
+
.replace-scope-fieldset > p { margin: -1px 0 1px; color: var(--muted); font-size: 10px; line-height: 1.5; }
|
|
958
|
+
.replace-scope-option { display: grid; grid-template-columns: 18px minmax(0, 1fr); align-items: start; gap: 7px; min-width: 0; padding: 8px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface); cursor: pointer; }
|
|
959
|
+
.replace-scope-option > span { display: grid; gap: 3px; min-width: 0; }
|
|
960
|
+
.replace-scope-option strong { color: var(--ink); font-size: 12px; }
|
|
961
|
+
.replace-scope-option small { color: var(--muted); font-size: 10px; line-height: 1.45; }
|
|
962
|
+
.replace-scope-option:has(input:checked) { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--surface)); box-shadow: inset 0 0 0 1px var(--accent); }
|
|
963
|
+
.replace-scope-option.is-disabled, .replace-scope-option:has(input:disabled) { cursor: not-allowed; opacity: .5; }
|
|
964
|
+
.replace-scope-option input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
965
|
+
.replace-permission-note { margin: 0; color: var(--accent-dark); font-size: 10px; line-height: 1.5; }
|
|
966
|
+
.replace-permission-note:empty { display: none; }
|
|
967
|
+
.replace-dialog .primary-button:disabled { cursor: not-allowed; opacity: .42; }
|
|
947
968
|
.search-results { display: grid; gap: 8px; max-height: min(52vh, 480px); overflow: auto; }
|
|
948
969
|
.search-results-summary { margin: 0; padding: 2px 2px 5px; color: var(--muted); font-size: 10px; }
|
|
949
970
|
.search-results-empty, .search-results-status {
|
|
@@ -1479,7 +1500,7 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1479
1500
|
.platform-image-tool-panel .config-save-button { flex: 0 0 auto; min-height: 36px; padding: 8px 14px; }
|
|
1480
1501
|
.task-auto-run-panel {
|
|
1481
1502
|
display: grid;
|
|
1482
|
-
grid-template-columns: minmax(0, 1fr)
|
|
1503
|
+
grid-template-columns: minmax(0, 1fr) 268px;
|
|
1483
1504
|
gap: 12px;
|
|
1484
1505
|
column-gap: 24px;
|
|
1485
1506
|
margin-bottom: 22px;
|
|
@@ -1488,12 +1509,13 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1488
1509
|
border-radius: 5px;
|
|
1489
1510
|
background: var(--surface-soft);
|
|
1490
1511
|
}
|
|
1491
|
-
.task-auto-run-header { display: grid; grid-column: 1; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 12px; }
|
|
1512
|
+
.task-auto-run-header { display: grid; grid-column: 1 / -1; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 12px; }
|
|
1492
1513
|
.task-auto-run-copy { display: grid; gap: 4px; }
|
|
1493
1514
|
.task-auto-run-copy strong { font-size: 13px; }
|
|
1494
1515
|
.task-auto-run-copy small { color: var(--muted); font-size: 10px; line-height: 1.5; }
|
|
1495
1516
|
.task-auto-run-actions { display: flex; align-items: start; justify-content: flex-end; min-height: 32px; }
|
|
1496
1517
|
.task-auto-run-actions:empty { display: none; }
|
|
1518
|
+
.task-auto-run-actions .record-card-edit { position: static; flex: 0 0 32px; width: 32px; height: 32px; }
|
|
1497
1519
|
.task-auto-run-controls {
|
|
1498
1520
|
display: flex;
|
|
1499
1521
|
grid-column: 1;
|
|
@@ -1525,12 +1547,12 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1525
1547
|
.task-auto-run-progress {
|
|
1526
1548
|
display: grid;
|
|
1527
1549
|
grid-column: 2;
|
|
1528
|
-
grid-row:
|
|
1550
|
+
grid-row: 2 / 5;
|
|
1529
1551
|
align-self: center;
|
|
1530
|
-
justify-self:
|
|
1531
|
-
width:
|
|
1552
|
+
justify-self: start;
|
|
1553
|
+
width: 192px;
|
|
1532
1554
|
}
|
|
1533
|
-
.task-auto-run-progress-ring { position: relative; display: grid; width:
|
|
1555
|
+
.task-auto-run-progress-ring { position: relative; display: grid; width: 192px; height: 192px; place-items: center; }
|
|
1534
1556
|
.task-auto-run-progress-ring svg { display: block; width: 100%; height: 100%; overflow: visible; transform: rotate(-90deg); }
|
|
1535
1557
|
.task-auto-run-progress-ring-track, .task-auto-run-progress-ring-value { fill: none; stroke-width: 8; }
|
|
1536
1558
|
.task-auto-run-progress-ring-track { stroke: color-mix(in srgb, var(--line) 72%, transparent); }
|
|
@@ -1538,9 +1560,9 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1538
1560
|
.task-auto-run-progress-ring.is-running svg { animation: task-auto-run-active 1.8s ease-in-out infinite; }
|
|
1539
1561
|
.task-auto-run-progress-ring.is-running .task-auto-run-progress-ring-value { stroke: var(--task-running); }
|
|
1540
1562
|
.task-auto-run-progress-ring.is-paused .task-auto-run-progress-ring-value { stroke: var(--accent); }
|
|
1541
|
-
.task-auto-run-progress-ring-label { position: absolute; inset:
|
|
1542
|
-
.task-auto-run-progress-ring-label strong { color: var(--ink); font-family: var(--font-latin), monospace; font-size:
|
|
1543
|
-
.task-auto-run-progress-ring-label span { color: var(--muted); font-size:
|
|
1563
|
+
.task-auto-run-progress-ring-label { position: absolute; inset: 32px; display: grid; align-content: center; justify-items: center; gap: 4px; text-align: center; }
|
|
1564
|
+
.task-auto-run-progress-ring-label strong { color: var(--ink); font-family: var(--font-latin), monospace; font-size: 28px; font-weight: 600; line-height: 1; }
|
|
1565
|
+
.task-auto-run-progress-ring-label span { color: var(--muted); font-size: 10px; line-height: 1.35; }
|
|
1544
1566
|
.task-auto-run-progress-bar-layout { display: none; }
|
|
1545
1567
|
.task-auto-run-progress-label { display: flex; align-items: center; justify-content: space-between; gap: 12px; color: var(--muted); font-size: 10px; }
|
|
1546
1568
|
.task-auto-run-progress-label strong { color: var(--ink); font-family: var(--font-latin), monospace; font-size: 10px; font-weight: 600; }
|
|
@@ -1626,6 +1648,23 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1626
1648
|
background: color-mix(in srgb, var(--accent) 32%, transparent);
|
|
1627
1649
|
animation: task-progress-waiting 1.9s ease-in-out infinite;
|
|
1628
1650
|
}
|
|
1651
|
+
.task-scope-link, .task-reference-link {
|
|
1652
|
+
display: inline;
|
|
1653
|
+
margin: 0;
|
|
1654
|
+
padding: 0;
|
|
1655
|
+
border: 0;
|
|
1656
|
+
border-bottom: 1px dashed color-mix(in srgb, var(--accent) 58%, var(--line));
|
|
1657
|
+
background: transparent;
|
|
1658
|
+
color: var(--accent-dark);
|
|
1659
|
+
font: inherit;
|
|
1660
|
+
text-align: left;
|
|
1661
|
+
cursor: pointer;
|
|
1662
|
+
}
|
|
1663
|
+
.task-scope-link:hover, .task-scope-link:focus-visible, .task-reference-link:hover, .task-reference-link:focus-visible {
|
|
1664
|
+
border-bottom-style: solid;
|
|
1665
|
+
color: var(--accent);
|
|
1666
|
+
outline: none;
|
|
1667
|
+
}
|
|
1629
1668
|
@keyframes task-auto-run-active { 0%, 100% { filter: drop-shadow(0 0 0 transparent); opacity: .72; } 50% { filter: drop-shadow(0 0 4px color-mix(in srgb, var(--green) 42%, transparent)); opacity: 1; } }
|
|
1630
1669
|
@keyframes task-status-waiting { 0%, 100% { opacity: .45; transform: scale(.74); } 50% { opacity: 1; transform: scale(1); } }
|
|
1631
1670
|
@keyframes task-status-running-breathe { 0%, 100% { background: color-mix(in srgb, var(--green) 5%, transparent); box-shadow: 0 0 0 0 transparent; opacity: .72; } 50% { background: color-mix(in srgb, var(--green) 16%, transparent); box-shadow: 0 0 12px color-mix(in srgb, var(--green) 20%, transparent); opacity: 1; } }
|
|
@@ -1690,8 +1729,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
1690
1729
|
.task-result-item summary, .task-result-technical > summary { width: fit-content; cursor: pointer; color: var(--accent-dark); font-size: 10px; }
|
|
1691
1730
|
.task-result-evidence { display: grid; gap: 7px; margin-top: 8px !important; padding-left: 17px !important; }
|
|
1692
1731
|
.task-result-evidence li { padding-left: 2px; }
|
|
1693
|
-
.task-result-evidence li strong, .task-result-evidence li q, .task-result-evidence li small { display: block; }
|
|
1694
|
-
.task-result-evidence li strong { font-size: 10px; }
|
|
1732
|
+
.task-result-evidence li strong, .task-result-evidence li button, .task-result-evidence li q, .task-result-evidence li small { display: block; }
|
|
1733
|
+
.task-result-evidence li strong, .task-result-evidence li button { font-size: 10px; }
|
|
1695
1734
|
.task-result-evidence li q { margin-top: 2px; color: var(--ink); }
|
|
1696
1735
|
.task-result-evidence li small, .task-result-muted { color: var(--muted); }
|
|
1697
1736
|
.task-result-empty, .task-result-warning { padding: 9px; border-radius: 5px; background: var(--surface-soft); color: var(--muted); }
|
|
@@ -3325,6 +3364,10 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3325
3364
|
.dialog-header h2 { font-size: 20px; }
|
|
3326
3365
|
.settings-dialog-header-actions { gap: 6px; }
|
|
3327
3366
|
.dialog-fields, .appearance-grid, .access-dialog-body, .account-settings-body, .versions-list, .entity-history-list, .chapter-annotations-list { padding-inline: 16px; }
|
|
3367
|
+
.replace-dialog-body { padding-inline: 16px; }
|
|
3368
|
+
.replace-dialog { height: calc(100dvh - 20px); max-height: calc(100dvh - 20px); }
|
|
3369
|
+
.replace-scope-fieldset { grid-template-columns: minmax(0, 1fr); }
|
|
3370
|
+
.replace-scope-fieldset legend, .replace-scope-fieldset > p { grid-column: auto; }
|
|
3328
3371
|
.task-detail-overview { grid-template-columns: minmax(0, 1fr); padding: 12px; }
|
|
3329
3372
|
.task-detail-overview > * { grid-column: 1 !important; }
|
|
3330
3373
|
.task-result-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
@@ -3379,7 +3422,8 @@ select:focus, input:focus, textarea:focus { border-color: #a77768; box-shadow: 0
|
|
|
3379
3422
|
}
|
|
3380
3423
|
|
|
3381
3424
|
@media (max-width: 480px) {
|
|
3382
|
-
.
|
|
3425
|
+
.app-shell:not(.shelf-mode) .topbar .brand-block > div { display: none; }
|
|
3426
|
+
.top-actions .settings-button { display: grid; flex: 0 0 32px; }
|
|
3383
3427
|
.topbar-icon-button, .theme-toggle, .account-button { flex: 0 0 32px; width: 32px; min-width: 32px; height: 32px; }
|
|
3384
3428
|
button.account-button { width: 32px; height: 32px; }
|
|
3385
3429
|
.top-actions { gap: 3px; }
|
package/dist/server-runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { chmodSync, cpSync, existsSync, mkdirSync, renameSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { chmodSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { basename, join } from "node:path";
|
|
4
4
|
import { createRuntime } from "./app.js";
|
|
@@ -8,6 +8,12 @@ import { isDevelopmentAuthBypassEnabled, resolveRuntimeSecurity } from "./securi
|
|
|
8
8
|
import { logger, sanitizeError } from "./logger.js";
|
|
9
9
|
import { resolveReleaseCheckIntervalMs, resolveReleaseCheckRetries, resolveReleaseCheckTimeoutMs } from "./release-update.js";
|
|
10
10
|
const publicPath = fileURLToPath(new URL("./public/", import.meta.url));
|
|
11
|
+
export const PRE_MIGRATION_BACKUP_RETENTION_ENV = "SCRIVERSE_PRE_MIGRATION_BACKUP_RETENTION";
|
|
12
|
+
export const DEFAULT_PRE_MIGRATION_BACKUP_RETENTION = 5;
|
|
13
|
+
export const MIN_PRE_MIGRATION_BACKUP_RETENTION = 2;
|
|
14
|
+
export const STARTUP_RETRY_LIMIT_ENV = "SCRIVERSE_STARTUP_RETRY_LIMIT";
|
|
15
|
+
export const DEFAULT_STARTUP_RETRY_LIMIT = 2;
|
|
16
|
+
export const STARTUP_RETRY_STATE_FILENAME = ".startup-retry.json";
|
|
11
17
|
export function isDevelopmentServer(environment) {
|
|
12
18
|
return environment.NODE_ENV === "development" || environment.npm_lifecycle_event === "dev";
|
|
13
19
|
}
|
|
@@ -15,12 +21,118 @@ export function isLoopbackHost(host) {
|
|
|
15
21
|
const normalized = host.trim().toLocaleLowerCase().replace(/^\[|\]$/gu, "");
|
|
16
22
|
return normalized === "localhost" || normalized === "::1" || /^127(?:\.\d{1,3}){3}$/u.test(normalized);
|
|
17
23
|
}
|
|
18
|
-
export function
|
|
24
|
+
export function resolvePreMigrationBackupRetention(environment) {
|
|
25
|
+
const raw = environment[PRE_MIGRATION_BACKUP_RETENTION_ENV]?.trim() ?? "";
|
|
26
|
+
if (raw === "")
|
|
27
|
+
return DEFAULT_PRE_MIGRATION_BACKUP_RETENTION;
|
|
28
|
+
const configured = Number(raw);
|
|
29
|
+
if (!Number.isFinite(configured))
|
|
30
|
+
return DEFAULT_PRE_MIGRATION_BACKUP_RETENTION;
|
|
31
|
+
return Math.max(MIN_PRE_MIGRATION_BACKUP_RETENTION, Math.floor(configured));
|
|
32
|
+
}
|
|
33
|
+
export function resolveStartupRetryLimit(environment) {
|
|
34
|
+
const raw = environment[STARTUP_RETRY_LIMIT_ENV]?.trim() ?? "";
|
|
35
|
+
if (raw === "")
|
|
36
|
+
return DEFAULT_STARTUP_RETRY_LIMIT;
|
|
37
|
+
const configured = Number(raw);
|
|
38
|
+
if (!Number.isFinite(configured) || configured < 1)
|
|
39
|
+
return DEFAULT_STARTUP_RETRY_LIMIT;
|
|
40
|
+
return Math.floor(configured);
|
|
41
|
+
}
|
|
42
|
+
function startupRetryStatePath(dataDirectory) {
|
|
43
|
+
return join(dataDirectory, STARTUP_RETRY_STATE_FILENAME);
|
|
44
|
+
}
|
|
45
|
+
function readStartupRetryCount(dataDirectory) {
|
|
46
|
+
const statePath = startupRetryStatePath(dataDirectory);
|
|
47
|
+
if (!existsSync(statePath))
|
|
48
|
+
return 0;
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(readFileSync(statePath, "utf8"));
|
|
51
|
+
const attempts = Number(parsed.attempts);
|
|
52
|
+
return Number.isInteger(attempts) && attempts >= 0 ? attempts : 0;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
logger.warn("server.startup_retry_state.invalid", { retryStatePath: statePath, error: sanitizeError(error) });
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function writeStartupRetryCount(dataDirectory, attempts) {
|
|
60
|
+
const statePath = startupRetryStatePath(dataDirectory);
|
|
61
|
+
const temporaryPath = `${statePath}.tmp`;
|
|
62
|
+
writeFileSync(temporaryPath, JSON.stringify({ attempts, updatedAt: new Date().toISOString() }, null, 2), { encoding: "utf8", mode: 0o600 });
|
|
63
|
+
chmodSync(temporaryPath, 0o600);
|
|
64
|
+
renameSync(temporaryPath, statePath);
|
|
65
|
+
chmodSync(statePath, 0o600);
|
|
66
|
+
}
|
|
67
|
+
function recordStartupAttempt(dataDirectory, environment) {
|
|
68
|
+
const retryLimit = resolveStartupRetryLimit(environment);
|
|
69
|
+
const previousAttempts = readStartupRetryCount(dataDirectory);
|
|
70
|
+
const retryStatePath = startupRetryStatePath(dataDirectory);
|
|
71
|
+
if (previousAttempts >= retryLimit) {
|
|
72
|
+
logger.error("server.startup_retry_limit_reached", {
|
|
73
|
+
retryStatePath,
|
|
74
|
+
attempts: previousAttempts,
|
|
75
|
+
retryLimit,
|
|
76
|
+
message: "Startup retry limit reached. Fix the previous initialization error, remove the startup retry state file, and restart Scriverse."
|
|
77
|
+
});
|
|
78
|
+
throw new Error(`Startup retry limit reached (${retryLimit}); fix the previous initialization error and remove ${retryStatePath} before restarting`);
|
|
79
|
+
}
|
|
80
|
+
const attempts = previousAttempts + 1;
|
|
81
|
+
writeStartupRetryCount(dataDirectory, attempts);
|
|
82
|
+
logger.warn("server.startup_attempt.recorded", { retryStatePath, attempts, retryLimit });
|
|
83
|
+
}
|
|
84
|
+
function clearStartupRetryState(dataDirectory) {
|
|
85
|
+
const statePath = startupRetryStatePath(dataDirectory);
|
|
86
|
+
if (!existsSync(statePath))
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
rmSync(statePath, { force: true });
|
|
90
|
+
logger.info("server.startup_retry_state.cleared", { retryStatePath: statePath });
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
logger.error("server.startup_retry_state.clear_failed", { retryStatePath: statePath, error: sanitizeError(error) });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function listPreMigrationBackups(backupsDirectory) {
|
|
97
|
+
if (!existsSync(backupsDirectory))
|
|
98
|
+
return [];
|
|
99
|
+
return readdirSync(backupsDirectory, { withFileTypes: true })
|
|
100
|
+
.filter((entry) => entry.isDirectory() && entry.name.startsWith("pre-migration-v") && !entry.name.endsWith(".incomplete"))
|
|
101
|
+
.map((entry) => {
|
|
102
|
+
const directory = join(backupsDirectory, entry.name);
|
|
103
|
+
return { directory, modifiedAt: statSync(directory).mtimeMs };
|
|
104
|
+
})
|
|
105
|
+
.filter(({ directory }) => existsSync(join(directory, "backup.json")))
|
|
106
|
+
.sort((left, right) => left.modifiedAt - right.modifiedAt || left.directory.localeCompare(right.directory));
|
|
107
|
+
}
|
|
108
|
+
function prunePreMigrationBackups(backupsDirectory, maximumCount) {
|
|
109
|
+
const backups = listPreMigrationBackups(backupsDirectory);
|
|
110
|
+
const excessCount = Math.max(0, backups.length - maximumCount);
|
|
111
|
+
for (const backup of backups.slice(0, excessCount)) {
|
|
112
|
+
try {
|
|
113
|
+
rmSync(backup.directory, { recursive: true, force: true });
|
|
114
|
+
logger.info("database.pre_migration_backup.pruned", {
|
|
115
|
+
backupDirectory: backup.directory,
|
|
116
|
+
retentionCount: maximumCount
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
logger.warn("database.pre_migration_backup.prune_failed", {
|
|
121
|
+
backupDirectory: backup.directory,
|
|
122
|
+
error: sanitizeError(error)
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export function createPreMigrationBackup(options, environment = process.env) {
|
|
128
|
+
const backupsDirectory = join(options.dataDirectory, "backups");
|
|
129
|
+
const retentionCount = resolvePreMigrationBackupRetention(environment);
|
|
130
|
+
prunePreMigrationBackups(backupsDirectory, retentionCount);
|
|
19
131
|
const schemaVersion = readDatabaseSchemaVersion(options.databasePath);
|
|
20
132
|
if (schemaVersion === null || schemaVersion >= DATABASE_SCHEMA_VERSION)
|
|
21
133
|
return null;
|
|
134
|
+
prunePreMigrationBackups(backupsDirectory, retentionCount - 1);
|
|
22
135
|
const timestamp = new Date().toISOString().replace(/[:.]/gu, "-");
|
|
23
|
-
const backupsDirectory = join(options.dataDirectory, "backups");
|
|
24
136
|
const backupName = `pre-migration-v${schemaVersion}-to-v${DATABASE_SCHEMA_VERSION}-${timestamp}`;
|
|
25
137
|
const incompleteDirectory = join(backupsDirectory, `${backupName}.incomplete`);
|
|
26
138
|
const backupDirectory = join(backupsDirectory, backupName);
|
|
@@ -64,8 +176,9 @@ export async function startLocalServer(options) {
|
|
|
64
176
|
try {
|
|
65
177
|
mkdirSync(options.dataDirectory, { recursive: true, mode: 0o700 });
|
|
66
178
|
chmodSync(options.dataDirectory, 0o700);
|
|
179
|
+
recordStartupAttempt(options.dataDirectory, options.env);
|
|
67
180
|
security = resolveRuntimeSecurity(options.env);
|
|
68
|
-
createPreMigrationBackup(options);
|
|
181
|
+
createPreMigrationBackup(options, options.env);
|
|
69
182
|
const devAuthBypass = isDevelopmentAuthBypassEnabled(options.env);
|
|
70
183
|
if (devAuthBypass && !isLoopbackHost(options.host)) {
|
|
71
184
|
throw new Error("APP_DEV_SKIP_AUTH 仅允许绑定本机回环地址");
|
|
@@ -108,6 +221,7 @@ export async function startLocalServer(options) {
|
|
|
108
221
|
}
|
|
109
222
|
const port = address.port;
|
|
110
223
|
const displayHost = options.host.includes(":") ? `[${options.host}]` : options.host;
|
|
224
|
+
clearStartupRetryState(options.dataDirectory);
|
|
111
225
|
let closed = false;
|
|
112
226
|
const close = async () => {
|
|
113
227
|
if (closed)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-runtime.js","sourceRoot":"","sources":["../src/server-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9F,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAgB,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,8BAA8B,EAAE,sBAAsB,EAA+B,MAAM,eAAe,CAAC;AACpH,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAsB9H,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAExE,MAAM,UAAU,mBAAmB,CAAC,WAA8B;IAChE,OAAO,WAAW,CAAC,QAAQ,KAAK,aAAa,IAAI,WAAW,CAAC,mBAAmB,KAAK,KAAK,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,iBAAiB,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC5E,OAAO,UAAU,KAAK,WAAW,IAAI,UAAU,KAAK,KAAK,IAAI,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACzG,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,OAAmE;IAC1G,MAAM,aAAa,GAAG,yBAAyB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACtE,IAAI,aAAa,KAAK,IAAI,IAAI,aAAa,IAAI,uBAAuB;QAAE,OAAO,IAAI,CAAC;IACpF,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAClE,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,kBAAkB,aAAa,QAAQ,uBAAuB,IAAI,SAAS,EAAE,CAAC;IACjG,MAAM,mBAAmB,GAAG,IAAI,CAAC,gBAAgB,EAAE,GAAG,UAAU,aAAa,CAAC,CAAC;IAC/E,MAAM,eAAe,GAAG,IAAI,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IAC3D,SAAS,CAAC,mBAAmB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACjE,SAAS,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;IACtC,KAAK,MAAM,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,GAAG,OAAO,CAAC,YAAY,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,MAAM,CAAC,EAAE,CAAC;QAC1G,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;YAAE,SAAS;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAChE,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QACvD,MAAM,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IACnE,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;IACnH,CAAC;IACD,aAAa,CAAC,IAAI,CAAC,mBAAmB,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;QACrE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACnC,iBAAiB,EAAE,aAAa;QAChC,eAAe,EAAE,uBAAuB;QACxC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC;KAC7C,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChD,UAAU,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE;QACnD,eAAe;QACf,iBAAiB,EAAE,aAAa;QAChC,eAAe,EAAE,uBAAuB;KACzC,CAAC,CAAC;IACH,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAA2B;IAChE,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACrJ,IAAI,QAAgC,CAAC;IACrC,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnE,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QACxC,QAAQ,GAAG,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC/C,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAClC,MAAM,aAAa,GAAG,8BAA8B,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClE,IAAI,aAAa,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,GAAG,aAAa,CAAC;YACtB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,mBAAmB,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC;YAC/D,YAAY,EAAE,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;YAC1G,UAAU;YACV,QAAQ;YACR,eAAe,EAAE,aAAa;YAC9B,aAAa;YACb,iBAAiB,EAAE,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC;YACnD,sBAAsB,EAAE,6BAA6B,CAAC,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC;YACpG,qBAAqB,EAAE,4BAA4B,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC;YACjG,mBAAmB,EAAE,0BAA0B,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;SACtF,CAAC,CAAC;QACH,MAAM,OAAO,CAAC,kBAAkB,EAAE,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACtH,MAAM,KAAK,CAAC;IACd,CAAC;IAED,OAAO,MAAM,IAAI,OAAO,CAAqB,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;QACzE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,kBAAkB,GAAG,CAAC,KAAY,EAAQ,EAAE;YAChD,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC7G,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;YAC5B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;YACxC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YACjC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAC5C,MAAM,CAAC,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChB,WAAW,CAAC,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC,CAAC;gBACrE,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YAC1B,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;YACpF,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;gBACtC,IAAI,MAAM;oBAAE,OAAO;gBACnB,MAAM,GAAG,IAAI,CAAC;gBACd,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC7D,MAAM,CAAC,mBAAmB,EAAE,CAAC;gBAC7B,IAAI,CAAC;oBACH,MAAM,IAAI,OAAO,CAAO,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;wBACpD,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;oBACvE,CAAC,CAAC,CAAC;gBACL,CAAC;wBAAS,CAAC;oBACT,OAAO,CAAC,KAAK,EAAE,CAAC;oBAChB,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC,CAAC;YACF,YAAY,CAAC;gBACX,MAAM;gBACN,OAAO;gBACP,GAAG,EAAE,UAAU,WAAW,IAAI,IAAI,EAAE;gBACpC,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,IAAI;gBACJ,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,QAAQ;gBACR,KAAK;aACN,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,OAA2B;IACvE,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAQ,EAAE;QACxC,IAAI,YAAY;YAAE,OAAO;QACzB,YAAY,GAAG,IAAI,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CACvB,GAAG,EAAE,GAAG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,EAC/B,CAAC,KAAc,EAAE,EAAE;YACjB,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC5E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC,CACF,CAAC;IACJ,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACrD,CAAC"}
|
|
1
|
+
{"version":3,"file":"server-runtime.js","sourceRoot":"","sources":["../src/server-runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/store.js
CHANGED
|
@@ -1488,6 +1488,81 @@ export class Store {
|
|
|
1488
1488
|
});
|
|
1489
1489
|
return this.getChapter(chapterId);
|
|
1490
1490
|
}
|
|
1491
|
+
replaceWorkText(workId, input) {
|
|
1492
|
+
const find = input.find;
|
|
1493
|
+
if (!find)
|
|
1494
|
+
throw new AppError(400, "REPLACE_TEXT_REQUIRED", "查找内容不能为空");
|
|
1495
|
+
if (!["prose", "settings", "prose-and-settings"].includes(input.scope)) {
|
|
1496
|
+
throw new AppError(400, "REPLACE_SCOPE_INVALID", "替换范围无效");
|
|
1497
|
+
}
|
|
1498
|
+
const operationId = id("globalReplace");
|
|
1499
|
+
let chapterCount = 0;
|
|
1500
|
+
let settingCount = 0;
|
|
1501
|
+
let totalMatches = 0;
|
|
1502
|
+
const includeProse = input.scope === "prose" || input.scope === "prose-and-settings";
|
|
1503
|
+
const includeSettings = input.scope === "settings" || input.scope === "prose-and-settings";
|
|
1504
|
+
const replaceLiteral = (value) => {
|
|
1505
|
+
let matches = 0;
|
|
1506
|
+
let offset = 0;
|
|
1507
|
+
while (true) {
|
|
1508
|
+
const index = value.indexOf(find, offset);
|
|
1509
|
+
if (index < 0)
|
|
1510
|
+
break;
|
|
1511
|
+
matches += 1;
|
|
1512
|
+
offset = index + find.length;
|
|
1513
|
+
}
|
|
1514
|
+
return {
|
|
1515
|
+
content: value.replaceAll(find, () => input.replacement),
|
|
1516
|
+
matches
|
|
1517
|
+
};
|
|
1518
|
+
};
|
|
1519
|
+
this.getWork(workId);
|
|
1520
|
+
this.db.transaction(() => {
|
|
1521
|
+
if (includeProse) {
|
|
1522
|
+
const chapters = this.db.all("SELECT id, content FROM chapters WHERE work_id = ? AND deleted_at IS NULL ORDER BY sort_order, created_at", workId);
|
|
1523
|
+
for (const row of chapters) {
|
|
1524
|
+
const chapterId = requiredString(row, "id");
|
|
1525
|
+
const result = replaceLiteral(requiredString(row, "content"));
|
|
1526
|
+
if (!result.matches || result.content === requiredString(row, "content"))
|
|
1527
|
+
continue;
|
|
1528
|
+
this.saveChapter(chapterId, { content: result.content }, "global-replace", operationId, "全局替换正文");
|
|
1529
|
+
chapterCount += 1;
|
|
1530
|
+
totalMatches += result.matches;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
if (includeSettings) {
|
|
1534
|
+
const settings = this.db.all("SELECT id, content FROM settings WHERE work_id = ? ORDER BY id", workId);
|
|
1535
|
+
for (const row of settings) {
|
|
1536
|
+
const settingId = requiredString(row, "id");
|
|
1537
|
+
const currentContent = requiredString(row, "content");
|
|
1538
|
+
const result = replaceLiteral(currentContent);
|
|
1539
|
+
if (!result.matches || result.content === currentContent)
|
|
1540
|
+
continue;
|
|
1541
|
+
this.updateSetting(settingId, { content: result.content }, "global-replace", operationId, "全局替换设定库");
|
|
1542
|
+
settingCount += 1;
|
|
1543
|
+
totalMatches += result.matches;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
if (totalMatches > 0) {
|
|
1547
|
+
this.db.run("UPDATE works SET updated_at = ? WHERE id = ?", now(), workId);
|
|
1548
|
+
this.audit(workId, "work.global-replace", "work", workId, {
|
|
1549
|
+
operationId,
|
|
1550
|
+
scope: input.scope,
|
|
1551
|
+
chapterCount,
|
|
1552
|
+
settingCount,
|
|
1553
|
+
totalMatches
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
});
|
|
1557
|
+
return {
|
|
1558
|
+
operationId,
|
|
1559
|
+
scope: input.scope,
|
|
1560
|
+
chapterCount,
|
|
1561
|
+
settingCount,
|
|
1562
|
+
totalMatches,
|
|
1563
|
+
work: this.getWorkDirectory(workId)
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1491
1566
|
restoreChapter(chapterId, versionNo, expectedVersionNo) {
|
|
1492
1567
|
const version = this.db.get("SELECT * FROM chapter_versions WHERE chapter_id = ? AND version_no = ?", chapterId, versionNo);
|
|
1493
1568
|
if (!version)
|
|
@@ -3451,10 +3526,32 @@ export class Store {
|
|
|
3451
3526
|
const row = this.db.get(`SELECT attachment.*
|
|
3452
3527
|
FROM attachments attachment
|
|
3453
3528
|
JOIN attachment_references reference ON reference.attachment_id = attachment.id
|
|
3454
|
-
WHERE attachment.id = ? AND attachment.work_id = ? AND reference.work_id = ?
|
|
3529
|
+
WHERE attachment.id = ? AND attachment.work_id = ? AND reference.work_id = ?
|
|
3530
|
+
AND (
|
|
3531
|
+
(reference.entity_type = 'setting' AND EXISTS (
|
|
3532
|
+
SELECT 1 FROM settings current_setting
|
|
3533
|
+
WHERE current_setting.id = reference.entity_id AND current_setting.work_id = reference.work_id
|
|
3534
|
+
))
|
|
3535
|
+
OR (reference.entity_type = 'character-section' AND EXISTS (
|
|
3536
|
+
SELECT 1
|
|
3537
|
+
FROM character_profile_sections current_section
|
|
3538
|
+
JOIN characters current_character ON current_character.id = current_section.character_id
|
|
3539
|
+
WHERE current_section.id = reference.entity_id
|
|
3540
|
+
AND current_section.work_id = reference.work_id
|
|
3541
|
+
AND current_character.work_id = reference.work_id
|
|
3542
|
+
))
|
|
3543
|
+
OR (reference.entity_type = 'race' AND EXISTS (
|
|
3544
|
+
SELECT 1 FROM races current_race
|
|
3545
|
+
WHERE current_race.id = reference.entity_id AND current_race.work_id = reference.work_id
|
|
3546
|
+
))
|
|
3547
|
+
OR (reference.entity_type = 'organization' AND EXISTS (
|
|
3548
|
+
SELECT 1 FROM organizations current_organization
|
|
3549
|
+
WHERE current_organization.id = reference.entity_id AND current_organization.work_id = reference.work_id
|
|
3550
|
+
))
|
|
3551
|
+
)
|
|
3455
3552
|
LIMIT 1`, attachmentId, workId, workId);
|
|
3456
3553
|
if (!row)
|
|
3457
|
-
throw new AppError(404, "SETTING_IMAGE_ATTACHMENT_NOT_FOUND", "
|
|
3554
|
+
throw new AppError(404, "SETTING_IMAGE_ATTACHMENT_NOT_FOUND", "图片附件不存在或未被生效设定库当前文档引用");
|
|
3458
3555
|
return this.mapAttachment(row);
|
|
3459
3556
|
}
|
|
3460
3557
|
attachmentModules(attachmentId) {
|
|
@@ -4967,7 +5064,7 @@ export class Store {
|
|
|
4967
5064
|
const volumeTitles = new Map(this.db.all("SELECT id, title FROM volumes WHERE work_id = ?", workId).map((row) => [requiredString(row, "id"), requiredString(row, "title")]));
|
|
4968
5065
|
const characterNames = this.taskCharacterNames(workId, rows.map((row) => json(requiredString(row, "scope_json"), {})));
|
|
4969
5066
|
return {
|
|
4970
|
-
...paginated(rows.map((row) => this.mapTaskSummary(row, chapterSummaries, volumeTitles, characterNames)), pagination, total),
|
|
5067
|
+
...paginated(rows.map((row) => this.mapTaskSummary(workId, row, chapterSummaries, volumeTitles, characterNames)), pagination, total),
|
|
4971
5068
|
stats: {
|
|
4972
5069
|
total,
|
|
4973
5070
|
pendingCount: numberValue(statsRow, "pending_count"),
|
|
@@ -5125,12 +5222,30 @@ export class Store {
|
|
|
5125
5222
|
: [];
|
|
5126
5223
|
}
|
|
5127
5224
|
taskResultEvidence(value) {
|
|
5128
|
-
return this.taskResultObjects(value).map((item) =>
|
|
5129
|
-
chapterId
|
|
5130
|
-
chapterTitle
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5225
|
+
return this.taskResultObjects(value).map((item) => {
|
|
5226
|
+
const chapterId = String(item.chapterId ?? "");
|
|
5227
|
+
const chapterTitle = String(item.chapterTitle ?? "");
|
|
5228
|
+
const settingId = String(item.settingId ?? "");
|
|
5229
|
+
const settingTitle = String(item.settingTitle ?? "");
|
|
5230
|
+
const sourceType = item.contextType === "setting" || settingId || settingTitle
|
|
5231
|
+
? "setting"
|
|
5232
|
+
: chapterId || chapterTitle
|
|
5233
|
+
? "chapter"
|
|
5234
|
+
: "";
|
|
5235
|
+
const sourceId = sourceType === "chapter" ? chapterId : sourceType === "setting" ? settingId : "";
|
|
5236
|
+
const sourceTitle = sourceType === "chapter" ? chapterTitle : sourceType === "setting" ? settingTitle : "";
|
|
5237
|
+
return {
|
|
5238
|
+
...(chapterId ? { chapterId } : {}),
|
|
5239
|
+
...(chapterTitle ? { chapterTitle } : {}),
|
|
5240
|
+
...(settingId ? { settingId } : {}),
|
|
5241
|
+
...(settingTitle ? { settingTitle } : {}),
|
|
5242
|
+
...(sourceType ? { sourceType } : {}),
|
|
5243
|
+
...(sourceId ? { sourceId } : {}),
|
|
5244
|
+
...(sourceTitle ? { sourceTitle } : {}),
|
|
5245
|
+
quote: String(item.quote ?? ""),
|
|
5246
|
+
supports: String(item.supports ?? item.conclusion ?? "")
|
|
5247
|
+
};
|
|
5248
|
+
}).filter((item) => item.sourceId || item.sourceTitle || item.quote || item.supports).slice(0, 5);
|
|
5134
5249
|
}
|
|
5135
5250
|
taskResultItem(value, fallbackTitle) {
|
|
5136
5251
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
@@ -5880,12 +5995,7 @@ export class Store {
|
|
|
5880
5995
|
confidence: numberValue(row, "confidence"),
|
|
5881
5996
|
confirmationStatus: requiredString(row, "confirmation_status"),
|
|
5882
5997
|
evidenceCount: evidence.length,
|
|
5883
|
-
evidence: evidence.slice(0, 3)
|
|
5884
|
-
chapterId: String(item.chapterId ?? ""),
|
|
5885
|
-
chapterTitle: String(item.chapterTitle ?? ""),
|
|
5886
|
-
quote: String(item.quote ?? ""),
|
|
5887
|
-
supports: String(item.supports ?? "")
|
|
5888
|
-
})),
|
|
5998
|
+
evidence: this.taskResultEvidence(evidence).slice(0, 3),
|
|
5889
5999
|
evidenceTruncated: evidence.length > 3
|
|
5890
6000
|
};
|
|
5891
6001
|
});
|
|
@@ -5922,6 +6032,7 @@ export class Store {
|
|
|
5922
6032
|
scope,
|
|
5923
6033
|
scopeSummary: this.taskScopeSummary(workId, scope, characterNames),
|
|
5924
6034
|
scopeSummaryWithoutCharacterNames: this.taskScopeSummary(workId, scope, new Map(), false),
|
|
6035
|
+
scopeTarget: this.taskScopeTarget(workId, scope),
|
|
5925
6036
|
scopeDetails: this.taskScopeDetails(workId, scope),
|
|
5926
6037
|
status: requiredString(row, "status"),
|
|
5927
6038
|
progress: numberValue(row, "progress"),
|
|
@@ -5935,7 +6046,7 @@ export class Store {
|
|
|
5935
6046
|
updatedAt: requiredString(row, "updated_at")
|
|
5936
6047
|
};
|
|
5937
6048
|
}
|
|
5938
|
-
mapTaskSummary(row, chapterSummaries, volumeTitles, characterNames) {
|
|
6049
|
+
mapTaskSummary(workId, row, chapterSummaries, volumeTitles, characterNames) {
|
|
5939
6050
|
const scope = json(requiredString(row, "scope_json"), {});
|
|
5940
6051
|
return {
|
|
5941
6052
|
id: requiredString(row, "id"),
|
|
@@ -5943,6 +6054,7 @@ export class Store {
|
|
|
5943
6054
|
taskType: requiredString(row, "task_type"),
|
|
5944
6055
|
scopeSummary: this.taskScopeSummaryFromMaps(scope, chapterSummaries, volumeTitles, characterNames),
|
|
5945
6056
|
scopeSummaryWithoutCharacterNames: this.taskScopeSummaryFromMaps(scope, chapterSummaries, volumeTitles, new Map(), false),
|
|
6057
|
+
scopeTarget: this.taskScopeTargetFromMaps(workId, scope, chapterSummaries),
|
|
5946
6058
|
status: requiredString(row, "status"),
|
|
5947
6059
|
progress: numberValue(row, "progress"),
|
|
5948
6060
|
attemptCount: numberValue(row, "attempt_count"),
|
|
@@ -6050,6 +6162,48 @@ export class Store {
|
|
|
6050
6162
|
const names = characterIds.map((characterId) => snapshotNames.get(characterId) ?? characterNames.get(characterId) ?? "已删除角色");
|
|
6051
6163
|
return ` · 定向 ${characterIds.length} 人:${names.join("、")}${preFilterSuffix}${sourcePreviewSuffix}${overwriteSuffix}`;
|
|
6052
6164
|
}
|
|
6165
|
+
taskScopeTargetFromMaps(workId, scope, chapterSummaries) {
|
|
6166
|
+
const characterIds = Array.isArray(scope.characterIds)
|
|
6167
|
+
? scope.characterIds.filter((characterId) => typeof characterId === "string")
|
|
6168
|
+
: [];
|
|
6169
|
+
if (characterIds.length === 1 && typeof scope.chapterId !== "string") {
|
|
6170
|
+
const characterId = characterIds[0];
|
|
6171
|
+
if (!characterId)
|
|
6172
|
+
return null;
|
|
6173
|
+
const character = this.db.get("SELECT name FROM characters WHERE id = ? AND work_id = ?", characterId, workId);
|
|
6174
|
+
return character ? { type: "character", id: characterId, label: requiredString(character, "name") } : null;
|
|
6175
|
+
}
|
|
6176
|
+
if (characterIds.length === 0 && typeof scope.chapterId === "string") {
|
|
6177
|
+
const label = chapterSummaries.get(scope.chapterId);
|
|
6178
|
+
return label ? { type: "chapter", id: scope.chapterId, label } : null;
|
|
6179
|
+
}
|
|
6180
|
+
return null;
|
|
6181
|
+
}
|
|
6182
|
+
taskScopeTarget(workId, scope) {
|
|
6183
|
+
const characterIds = Array.isArray(scope.characterIds)
|
|
6184
|
+
? scope.characterIds.filter((characterId) => typeof characterId === "string")
|
|
6185
|
+
: [];
|
|
6186
|
+
if (characterIds.length === 1 && typeof scope.chapterId !== "string") {
|
|
6187
|
+
const characterId = characterIds[0];
|
|
6188
|
+
if (!characterId)
|
|
6189
|
+
return null;
|
|
6190
|
+
const character = this.db.get("SELECT name FROM characters WHERE id = ? AND work_id = ?", characterId, workId);
|
|
6191
|
+
return character ? { type: "character", id: characterId, label: requiredString(character, "name") } : null;
|
|
6192
|
+
}
|
|
6193
|
+
if (characterIds.length !== 0 || typeof scope.chapterId !== "string")
|
|
6194
|
+
return null;
|
|
6195
|
+
const chapter = this.db.get(`SELECT chapter.title AS title, volume.title AS volume_title
|
|
6196
|
+
FROM chapters chapter
|
|
6197
|
+
JOIN volumes volume ON volume.id = chapter.volume_id
|
|
6198
|
+
WHERE chapter.id = ? AND chapter.work_id = ? AND chapter.deleted_at IS NULL`, scope.chapterId, workId);
|
|
6199
|
+
if (!chapter)
|
|
6200
|
+
return null;
|
|
6201
|
+
return {
|
|
6202
|
+
type: "chapter",
|
|
6203
|
+
id: scope.chapterId,
|
|
6204
|
+
label: `${requiredString(chapter, "volume_title")} · ${requiredString(chapter, "title")}`
|
|
6205
|
+
};
|
|
6206
|
+
}
|
|
6053
6207
|
taskCharacterSnapshotNames(scope) {
|
|
6054
6208
|
const snapshotNames = new Map();
|
|
6055
6209
|
if (Array.isArray(scope.targetCharacters)) {
|