chatroom-cli 1.98.2 → 1.98.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/dist/index.js +836 -115
- package/dist/index.js.map +22 -9
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -110218,7 +110218,8 @@ var init_file_content_fulfillment = __esm(() => {
|
|
|
110218
110218
|
return exports_Effect.succeed(Buffer.from("[Error reading file]"));
|
|
110219
110219
|
});
|
|
110220
110220
|
if (fileNotFound) {
|
|
110221
|
-
|
|
110221
|
+
yield* fulfillGzippedContentEffect(session2, workingDir, filePath, "[File not found]", false);
|
|
110222
|
+
console.log(`[${formatTimestamp()}] \uD83D\uDCC4 File not found, fulfilled content request: ${filePath}`);
|
|
110222
110223
|
continue;
|
|
110223
110224
|
}
|
|
110224
110225
|
const classification2 = classifyFileContent(filePath, new Uint8Array(buffer));
|
|
@@ -110470,6 +110471,214 @@ var init_sharded_snapshot_publish = __esm(() => {
|
|
|
110470
110471
|
init_file_tree_partition();
|
|
110471
110472
|
});
|
|
110472
110473
|
|
|
110474
|
+
// src/infrastructure/services/workspace/file-tree-sync-ranker.ts
|
|
110475
|
+
function fileExtension(p) {
|
|
110476
|
+
const b = (p.split("/").pop() ?? p).toLowerCase();
|
|
110477
|
+
if (b.endsWith(".min.js"))
|
|
110478
|
+
return ".min.js";
|
|
110479
|
+
if (b.endsWith(".min.css"))
|
|
110480
|
+
return ".min.css";
|
|
110481
|
+
const i2 = b.lastIndexOf(".");
|
|
110482
|
+
return i2 <= 0 ? "" : b.slice(i2);
|
|
110483
|
+
}
|
|
110484
|
+
function pathSegments(p) {
|
|
110485
|
+
return p.split("/").filter(Boolean);
|
|
110486
|
+
}
|
|
110487
|
+
function parentDir(p) {
|
|
110488
|
+
const i2 = p.lastIndexOf("/");
|
|
110489
|
+
return i2 < 0 ? "" : p.slice(0, i2);
|
|
110490
|
+
}
|
|
110491
|
+
function isSourceDirPath(p) {
|
|
110492
|
+
return pathSegments(p).slice(0, -1).some((s) => SOURCE_DIR_NAMES.has(s));
|
|
110493
|
+
}
|
|
110494
|
+
function isBuildDirPath(p) {
|
|
110495
|
+
return pathSegments(p).some((s) => BUILD_DIR_NAMES.has(s));
|
|
110496
|
+
}
|
|
110497
|
+
function isMarkdownFile(p) {
|
|
110498
|
+
return MARKDOWN_EXTENSIONS.has(fileExtension(p));
|
|
110499
|
+
}
|
|
110500
|
+
function isConfigFile(p) {
|
|
110501
|
+
return CONFIG_BASENAMES.has((p.split("/").pop() ?? "").toLowerCase()) || CONFIG_EXTENSIONS.has(fileExtension(p));
|
|
110502
|
+
}
|
|
110503
|
+
function isSourceFile(p) {
|
|
110504
|
+
return SOURCE_EXTENSIONS.has(fileExtension(p));
|
|
110505
|
+
}
|
|
110506
|
+
function isBuildOutputFile(p) {
|
|
110507
|
+
return BUILD_OUTPUT_EXTENSIONS.has(fileExtension(p));
|
|
110508
|
+
}
|
|
110509
|
+
function isDataFile(p) {
|
|
110510
|
+
return !isConfigFile(p) && DATA_EXTENSIONS.has(fileExtension(p));
|
|
110511
|
+
}
|
|
110512
|
+
function countDataFilesByParent(ps) {
|
|
110513
|
+
const m = new Map;
|
|
110514
|
+
for (const p of ps)
|
|
110515
|
+
if (isDataFile(p)) {
|
|
110516
|
+
const d = parentDir(p);
|
|
110517
|
+
m.set(d, (m.get(d) ?? 0) + 1);
|
|
110518
|
+
}
|
|
110519
|
+
return m;
|
|
110520
|
+
}
|
|
110521
|
+
function scoreFile(p, m) {
|
|
110522
|
+
let s = 0;
|
|
110523
|
+
if (isSourceFile(p))
|
|
110524
|
+
s += isSourceDirPath(p) ? SCORE_SOURCE_IN_SOURCE_DIR : SCORE_SOURCE_ELSEWHERE;
|
|
110525
|
+
if (isMarkdownFile(p))
|
|
110526
|
+
s += SCORE_MARKDOWN;
|
|
110527
|
+
if (isConfigFile(p))
|
|
110528
|
+
s += SCORE_CONFIG;
|
|
110529
|
+
if (isBuildDirPath(p))
|
|
110530
|
+
s -= PENALTY_BUILD_DIR;
|
|
110531
|
+
if (isBuildOutputFile(p))
|
|
110532
|
+
s -= PENALTY_BUILD_EXT;
|
|
110533
|
+
const n = m.get(parentDir(p)) ?? 0;
|
|
110534
|
+
return s - n * n;
|
|
110535
|
+
}
|
|
110536
|
+
function compareRankedFiles(a, as7, b, bs) {
|
|
110537
|
+
if (as7 !== bs)
|
|
110538
|
+
return bs - as7;
|
|
110539
|
+
const d = pathSegments(a).length - pathSegments(b).length;
|
|
110540
|
+
return d || a.localeCompare(b);
|
|
110541
|
+
}
|
|
110542
|
+
var SOURCE_DIR_NAMES, BUILD_DIR_NAMES, SOURCE_EXTENSIONS, MARKDOWN_EXTENSIONS, CONFIG_EXTENSIONS, CONFIG_BASENAMES, BUILD_OUTPUT_EXTENSIONS, DATA_EXTENSIONS, SCORE_SOURCE_IN_SOURCE_DIR = 1000, SCORE_MARKDOWN = 800, SCORE_CONFIG = 700, SCORE_SOURCE_ELSEWHERE = 200, PENALTY_BUILD_DIR = 5000, PENALTY_BUILD_EXT = 2000;
|
|
110543
|
+
var init_file_tree_sync_ranker = __esm(() => {
|
|
110544
|
+
SOURCE_DIR_NAMES = new Set([
|
|
110545
|
+
"src",
|
|
110546
|
+
"lib",
|
|
110547
|
+
"app",
|
|
110548
|
+
"apps",
|
|
110549
|
+
"packages",
|
|
110550
|
+
"services",
|
|
110551
|
+
"server",
|
|
110552
|
+
"client",
|
|
110553
|
+
"backend",
|
|
110554
|
+
"frontend",
|
|
110555
|
+
"api",
|
|
110556
|
+
"cmd",
|
|
110557
|
+
"internal",
|
|
110558
|
+
"pkg",
|
|
110559
|
+
"components",
|
|
110560
|
+
"modules",
|
|
110561
|
+
"pages",
|
|
110562
|
+
"routes",
|
|
110563
|
+
"hooks",
|
|
110564
|
+
"domain",
|
|
110565
|
+
"infrastructure",
|
|
110566
|
+
"entry"
|
|
110567
|
+
]);
|
|
110568
|
+
BUILD_DIR_NAMES = new Set([
|
|
110569
|
+
"dist",
|
|
110570
|
+
"build",
|
|
110571
|
+
"out",
|
|
110572
|
+
"output",
|
|
110573
|
+
"coverage",
|
|
110574
|
+
".next",
|
|
110575
|
+
".turbo",
|
|
110576
|
+
".nx",
|
|
110577
|
+
"_generated",
|
|
110578
|
+
"generated",
|
|
110579
|
+
"__pycache__"
|
|
110580
|
+
]);
|
|
110581
|
+
SOURCE_EXTENSIONS = new Set([
|
|
110582
|
+
".ts",
|
|
110583
|
+
".tsx",
|
|
110584
|
+
".js",
|
|
110585
|
+
".jsx",
|
|
110586
|
+
".mjs",
|
|
110587
|
+
".cjs",
|
|
110588
|
+
".py",
|
|
110589
|
+
".go",
|
|
110590
|
+
".rs",
|
|
110591
|
+
".java",
|
|
110592
|
+
".kt",
|
|
110593
|
+
".swift",
|
|
110594
|
+
".rb",
|
|
110595
|
+
".php",
|
|
110596
|
+
".cs",
|
|
110597
|
+
".c",
|
|
110598
|
+
".cc",
|
|
110599
|
+
".cpp",
|
|
110600
|
+
".h",
|
|
110601
|
+
".hpp",
|
|
110602
|
+
".vue",
|
|
110603
|
+
".svelte",
|
|
110604
|
+
".css",
|
|
110605
|
+
".scss",
|
|
110606
|
+
".less"
|
|
110607
|
+
]);
|
|
110608
|
+
MARKDOWN_EXTENSIONS = new Set([".md", ".mdx", ".markdown"]);
|
|
110609
|
+
CONFIG_EXTENSIONS = new Set([".yml", ".yaml", ".toml", ".jsonc", ".ini", ".cfg"]);
|
|
110610
|
+
CONFIG_BASENAMES = new Set([
|
|
110611
|
+
"package.json",
|
|
110612
|
+
"package-lock.json",
|
|
110613
|
+
"pnpm-lock.yaml",
|
|
110614
|
+
"pnpm-workspace.yaml",
|
|
110615
|
+
"yarn.lock",
|
|
110616
|
+
"bun.lock",
|
|
110617
|
+
"tsconfig.json",
|
|
110618
|
+
"jsconfig.json",
|
|
110619
|
+
"turbo.json",
|
|
110620
|
+
"nx.json",
|
|
110621
|
+
"cargo.toml",
|
|
110622
|
+
"go.mod",
|
|
110623
|
+
"go.sum",
|
|
110624
|
+
"pyproject.toml",
|
|
110625
|
+
"requirements.txt",
|
|
110626
|
+
"dockerfile",
|
|
110627
|
+
"docker-compose.yml",
|
|
110628
|
+
"docker-compose.yaml",
|
|
110629
|
+
"makefile",
|
|
110630
|
+
".gitignore",
|
|
110631
|
+
".cursorignore",
|
|
110632
|
+
".editorconfig",
|
|
110633
|
+
".prettierrc",
|
|
110634
|
+
".nvmrc",
|
|
110635
|
+
"eslint.config.mjs",
|
|
110636
|
+
"eslint.config.js",
|
|
110637
|
+
"biome.json",
|
|
110638
|
+
".fallowrc.jsonc"
|
|
110639
|
+
]);
|
|
110640
|
+
BUILD_OUTPUT_EXTENSIONS = new Set([
|
|
110641
|
+
".map",
|
|
110642
|
+
".min.js",
|
|
110643
|
+
".min.css",
|
|
110644
|
+
".pyc",
|
|
110645
|
+
".pyo",
|
|
110646
|
+
".o",
|
|
110647
|
+
".obj",
|
|
110648
|
+
".wasm",
|
|
110649
|
+
".class",
|
|
110650
|
+
".jar",
|
|
110651
|
+
".exe",
|
|
110652
|
+
".dll",
|
|
110653
|
+
".so"
|
|
110654
|
+
]);
|
|
110655
|
+
DATA_EXTENSIONS = new Set([
|
|
110656
|
+
".json",
|
|
110657
|
+
".csv",
|
|
110658
|
+
".tsv",
|
|
110659
|
+
".ndjson",
|
|
110660
|
+
".parquet",
|
|
110661
|
+
".avro",
|
|
110662
|
+
".bin",
|
|
110663
|
+
".dat",
|
|
110664
|
+
".pb",
|
|
110665
|
+
".sqlite",
|
|
110666
|
+
".db",
|
|
110667
|
+
".log",
|
|
110668
|
+
".gz",
|
|
110669
|
+
".zip",
|
|
110670
|
+
".tar",
|
|
110671
|
+
".png",
|
|
110672
|
+
".jpg",
|
|
110673
|
+
".jpeg",
|
|
110674
|
+
".webp",
|
|
110675
|
+
".gif",
|
|
110676
|
+
".mp4",
|
|
110677
|
+
".woff",
|
|
110678
|
+
".woff2"
|
|
110679
|
+
]);
|
|
110680
|
+
});
|
|
110681
|
+
|
|
110473
110682
|
// ../../node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js
|
|
110474
110683
|
var require_ignore = __commonJS((exports, module) => {
|
|
110475
110684
|
function makeArray(subject) {
|
|
@@ -110800,10 +111009,68 @@ var require_ignore = __commonJS((exports, module) => {
|
|
|
110800
111009
|
// src/infrastructure/services/workspace/workspace-ignore.ts
|
|
110801
111010
|
import { promises as fsPromises } from "node:fs";
|
|
110802
111011
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
111012
|
+
import { homedir as homedir7 } from "node:os";
|
|
110803
111013
|
import path3 from "node:path";
|
|
110804
111014
|
function normalizeRelativePath(relativePath) {
|
|
110805
111015
|
return relativePath.replace(/\\/g, "/").replace(/^\.?\//, "").replace(/\/+$/, "");
|
|
110806
111016
|
}
|
|
111017
|
+
function expandUserPath(filePath) {
|
|
111018
|
+
if (filePath === "~")
|
|
111019
|
+
return homedir7();
|
|
111020
|
+
if (filePath.startsWith("~/"))
|
|
111021
|
+
return path3.join(homedir7(), filePath.slice(2));
|
|
111022
|
+
return filePath;
|
|
111023
|
+
}
|
|
111024
|
+
function readExcludesFileFromGitconfig(content) {
|
|
111025
|
+
let inCore = false;
|
|
111026
|
+
for (const line of content.split(/\r?\n/)) {
|
|
111027
|
+
const section = line.match(/^\s*\[([^\]]+)\]/);
|
|
111028
|
+
if (section) {
|
|
111029
|
+
inCore = section[1].trim().toLowerCase() === "core";
|
|
111030
|
+
continue;
|
|
111031
|
+
}
|
|
111032
|
+
if (!inCore)
|
|
111033
|
+
continue;
|
|
111034
|
+
const match17 = line.match(/^\s*excludesfile\s*=\s*(.*?)\s*(?:[#;].*)?$/i);
|
|
111035
|
+
if (!match17)
|
|
111036
|
+
continue;
|
|
111037
|
+
const value = match17[1].trim().replace(/^(["'])(.*)\1$/, "$2");
|
|
111038
|
+
return value ? expandUserPath(value) : null;
|
|
111039
|
+
}
|
|
111040
|
+
return null;
|
|
111041
|
+
}
|
|
111042
|
+
async function readGitconfigExcludesFilePath(configPath) {
|
|
111043
|
+
const content = await readIgnoreFile(configPath);
|
|
111044
|
+
if (content === null)
|
|
111045
|
+
return null;
|
|
111046
|
+
const raw = readExcludesFileFromGitconfig(content);
|
|
111047
|
+
if (!raw)
|
|
111048
|
+
return null;
|
|
111049
|
+
return path3.isAbsolute(raw) ? expandUserPath(raw) : path3.resolve(path3.dirname(configPath), raw);
|
|
111050
|
+
}
|
|
111051
|
+
async function resolveGitExtraExcludeFilePaths(rootDir) {
|
|
111052
|
+
const globalConfig2 = process.env.GIT_CONFIG_GLOBAL?.length ? process.env.GIT_CONFIG_GLOBAL : path3.join(homedir7(), ".gitconfig");
|
|
111053
|
+
const localConfig = path3.join(rootDir, ".git", "config");
|
|
111054
|
+
let excludesFile = await readGitconfigExcludesFilePath(localConfig) ?? await readGitconfigExcludesFilePath(globalConfig2);
|
|
111055
|
+
if (!excludesFile) {
|
|
111056
|
+
excludesFile = path3.join(process.env.XDG_CONFIG_HOME?.length ? process.env.XDG_CONFIG_HOME : path3.join(homedir7(), ".config"), "git", "ignore");
|
|
111057
|
+
}
|
|
111058
|
+
const candidates = [excludesFile, path3.join(rootDir, ".git", "info", "exclude")];
|
|
111059
|
+
const existing = [];
|
|
111060
|
+
for (const candidate of candidates)
|
|
111061
|
+
if (await readIgnoreFile(candidate) !== null)
|
|
111062
|
+
existing.push(candidate);
|
|
111063
|
+
return existing;
|
|
111064
|
+
}
|
|
111065
|
+
async function loadGitExtraExcludeRuleSets(rootDir) {
|
|
111066
|
+
const result = [];
|
|
111067
|
+
for (const filePath of await resolveGitExtraExcludeFilePaths(rootDir)) {
|
|
111068
|
+
const content = await readIgnoreFile(filePath);
|
|
111069
|
+
if (content !== null)
|
|
111070
|
+
result.push({ baseDir: "", matcher: import_ignore.default().add(content) });
|
|
111071
|
+
}
|
|
111072
|
+
return result;
|
|
111073
|
+
}
|
|
110807
111074
|
async function readIgnoreFile(filePath) {
|
|
110808
111075
|
try {
|
|
110809
111076
|
return await readFile10(filePath, "utf-8");
|
|
@@ -110815,7 +111082,7 @@ async function loadDirectoryIgnoreRuleSets(rootDir, relativeDir) {
|
|
|
110815
111082
|
const normalizedDir = normalizeRelativePath(relativeDir);
|
|
110816
111083
|
const absoluteDir = normalizedDir ? path3.join(rootDir, normalizedDir) : rootDir;
|
|
110817
111084
|
const names = normalizedDir ? [".gitignore"] : IGNORE_FILES;
|
|
110818
|
-
const result = [];
|
|
111085
|
+
const result = normalizedDir ? [] : await loadGitExtraExcludeRuleSets(rootDir);
|
|
110819
111086
|
for (const name of names) {
|
|
110820
111087
|
const content = await readIgnoreFile(path3.join(absoluteDir, name));
|
|
110821
111088
|
if (content === null)
|
|
@@ -110912,48 +111179,57 @@ async function walkWorkspaceFiles(rootDir, options) {
|
|
|
110912
111179
|
const filePaths = [];
|
|
110913
111180
|
const directoryStubs = [];
|
|
110914
111181
|
let truncated = false;
|
|
110915
|
-
|
|
110916
|
-
|
|
111182
|
+
let currentLevel = [{ relDir: "", inheritedRuleSets: [], siblingCount: 0 }];
|
|
111183
|
+
while (currentLevel.length > 0) {
|
|
111184
|
+
if (filePaths.length >= maxFilePaths) {
|
|
110917
111185
|
truncated = true;
|
|
110918
|
-
|
|
111186
|
+
break;
|
|
110919
111187
|
}
|
|
110920
|
-
const
|
|
110921
|
-
const
|
|
110922
|
-
|
|
110923
|
-
if (!dirents)
|
|
110924
|
-
return;
|
|
110925
|
-
for (const ent of dirents) {
|
|
110926
|
-
if (truncated || filePaths.length >= maxFilePaths) {
|
|
111188
|
+
const nextLevel = [];
|
|
111189
|
+
for (const frame of currentLevel) {
|
|
111190
|
+
if (filePaths.length >= maxFilePaths) {
|
|
110927
111191
|
truncated = true;
|
|
110928
|
-
|
|
111192
|
+
break;
|
|
110929
111193
|
}
|
|
110930
|
-
const
|
|
110931
|
-
|
|
111194
|
+
const localRuleSets = await loadDirectoryIgnoreRuleSets(rootDir, frame.relDir);
|
|
111195
|
+
const ruleSets = mergeWorkspaceIgnoreRuleSets(frame.inheritedRuleSets, localRuleSets);
|
|
111196
|
+
const dirents = await readWorkspaceDirectoryDirents(rootDir, frame.relDir);
|
|
111197
|
+
if (!dirents)
|
|
110932
111198
|
continue;
|
|
110933
|
-
|
|
110934
|
-
|
|
111199
|
+
for (const ent of dirents) {
|
|
111200
|
+
const relativePath = frame.relDir ? `${frame.relDir}/${ent.name}` : ent.name;
|
|
111201
|
+
if (!isPathVisible(relativePath))
|
|
110935
111202
|
continue;
|
|
110936
|
-
|
|
110937
|
-
relativePath
|
|
110938
|
-
|
|
110939
|
-
|
|
110940
|
-
|
|
110941
|
-
|
|
110942
|
-
|
|
110943
|
-
|
|
110944
|
-
|
|
110945
|
-
|
|
110946
|
-
|
|
110947
|
-
|
|
110948
|
-
|
|
110949
|
-
|
|
110950
|
-
|
|
110951
|
-
|
|
110952
|
-
|
|
111203
|
+
if (ent.isDirectory()) {
|
|
111204
|
+
if (isPathIgnoredByRuleSets(ruleSets, relativePath))
|
|
111205
|
+
continue;
|
|
111206
|
+
const syncMode = classifyDirectorySyncMode(ent.name, {
|
|
111207
|
+
relativePath,
|
|
111208
|
+
immediateSiblingCount: frame.siblingCount,
|
|
111209
|
+
immediateChildCount: dirents.length
|
|
111210
|
+
});
|
|
111211
|
+
if (syncMode === "hidden")
|
|
111212
|
+
continue;
|
|
111213
|
+
directoryStubs.push(relativePath);
|
|
111214
|
+
if (syncMode === "full")
|
|
111215
|
+
nextLevel.push({
|
|
111216
|
+
relDir: relativePath,
|
|
111217
|
+
inheritedRuleSets: ruleSets,
|
|
111218
|
+
siblingCount: dirents.length
|
|
111219
|
+
});
|
|
111220
|
+
} else if (ent.isFile() && !isPathIgnoredByRuleSets(ruleSets, relativePath)) {
|
|
111221
|
+
if (filePaths.length >= maxFilePaths) {
|
|
111222
|
+
truncated = true;
|
|
111223
|
+
continue;
|
|
111224
|
+
}
|
|
111225
|
+
filePaths.push(relativePath);
|
|
111226
|
+
if (filePaths.length >= maxFilePaths)
|
|
111227
|
+
truncated = true;
|
|
111228
|
+
}
|
|
110953
111229
|
}
|
|
110954
111230
|
}
|
|
111231
|
+
currentLevel = truncated ? [] : nextLevel;
|
|
110955
111232
|
}
|
|
110956
|
-
await visitDir("", [], 0);
|
|
110957
111233
|
return { filePaths, directoryStubs, truncated };
|
|
110958
111234
|
}
|
|
110959
111235
|
var init_workspace_file_walk = __esm(() => {
|
|
@@ -110965,7 +111241,7 @@ var init_workspace_file_walk = __esm(() => {
|
|
|
110965
111241
|
async function scanFileTree(rootDir, options) {
|
|
110966
111242
|
const maxEntries = options?.maxEntries ?? DEFAULT_MAX_ENTRIES;
|
|
110967
111243
|
const scannedAt = Date.now();
|
|
110968
|
-
const walk = await walkWorkspaceFiles(rootDir, { maxFilePaths:
|
|
111244
|
+
const walk = await walkWorkspaceFiles(rootDir, { maxFilePaths: DEFAULT_CANDIDATE_FILE_PATHS });
|
|
110969
111245
|
const filteredPaths = walk.filePaths.filter((p) => !isExcluded(p));
|
|
110970
111246
|
const filteredStubs = walk.directoryStubs.filter((p) => !isExcluded(p));
|
|
110971
111247
|
const entries2 = buildEntries(filteredPaths, filteredStubs, maxEntries);
|
|
@@ -110982,30 +111258,35 @@ function entryDepth(entryPath) {
|
|
|
110982
111258
|
return entryPath.split("/").length;
|
|
110983
111259
|
}
|
|
110984
111260
|
function buildEntries(filePaths, directoryStubs, maxEntries) {
|
|
110985
|
-
const
|
|
110986
|
-
|
|
110987
|
-
|
|
110988
|
-
|
|
110989
|
-
|
|
110990
|
-
|
|
111261
|
+
const selected = new Map;
|
|
111262
|
+
const data = countDataFilesByParent(filePaths);
|
|
111263
|
+
const ranked = [...filePaths].sort((a, b) => compareRankedFiles(a, scoreFile(a, data), b, scoreFile(b, data)));
|
|
111264
|
+
for (const file2 of ranked) {
|
|
111265
|
+
const parts2 = file2.split("/");
|
|
111266
|
+
const needed = [file2, ...parts2.slice(0, -1).map((_, i2) => parts2.slice(0, i2 + 1).join("/"))];
|
|
111267
|
+
const missing = needed.filter((p) => !selected.has(p));
|
|
111268
|
+
if (selected.size + missing.length > maxEntries)
|
|
111269
|
+
continue;
|
|
111270
|
+
for (const p of needed)
|
|
111271
|
+
selected.set(p, { path: p, type: p === file2 ? "file" : "directory" });
|
|
110991
111272
|
}
|
|
110992
|
-
const
|
|
110993
|
-
|
|
110994
|
-
|
|
110995
|
-
|
|
110996
|
-
|
|
110997
|
-
|
|
110998
|
-
uniqueByPath.set(entry.path, entry);
|
|
111273
|
+
for (const dir of [...directoryStubs].sort((a, b) => entryDepth(a) - entryDepth(b) || a.localeCompare(b))) {
|
|
111274
|
+
if (selected.has(dir))
|
|
111275
|
+
continue;
|
|
111276
|
+
if (selected.size >= maxEntries)
|
|
111277
|
+
break;
|
|
111278
|
+
selected.set(dir, { path: dir, type: "directory" });
|
|
110999
111279
|
}
|
|
111000
|
-
return Array.from(
|
|
111280
|
+
return Array.from(selected.values()).sort((left3, right3) => {
|
|
111001
111281
|
const depthDelta = entryDepth(left3.path) - entryDepth(right3.path);
|
|
111002
111282
|
if (depthDelta !== 0)
|
|
111003
111283
|
return depthDelta;
|
|
111004
111284
|
return left3.path.localeCompare(right3.path);
|
|
111005
|
-
})
|
|
111285
|
+
});
|
|
111006
111286
|
}
|
|
111007
|
-
var DEFAULT_MAX_ENTRIES = 1e4;
|
|
111287
|
+
var DEFAULT_MAX_ENTRIES = 1e4, DEFAULT_CANDIDATE_FILE_PATHS = 50000;
|
|
111008
111288
|
var init_file_tree_scanner = __esm(() => {
|
|
111289
|
+
init_file_tree_sync_ranker();
|
|
111009
111290
|
init_workspace_file_walk();
|
|
111010
111291
|
init_workspace_visibility_policy();
|
|
111011
111292
|
});
|
|
@@ -112041,12 +112322,12 @@ class NodeFsHandler {
|
|
|
112041
112322
|
});
|
|
112042
112323
|
}
|
|
112043
112324
|
async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath3) {
|
|
112044
|
-
const
|
|
112045
|
-
const tracked =
|
|
112325
|
+
const parentDir2 = this.fsw._getWatchedDir(sp.dirname(dir));
|
|
112326
|
+
const tracked = parentDir2.has(sp.basename(dir));
|
|
112046
112327
|
if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
|
|
112047
112328
|
this.fsw._emit(EV.ADD_DIR, dir, stats);
|
|
112048
112329
|
}
|
|
112049
|
-
|
|
112330
|
+
parentDir2.add(sp.basename(dir));
|
|
112050
112331
|
this.fsw._getWatchedDir(dir);
|
|
112051
112332
|
let throttler;
|
|
112052
112333
|
let closer;
|
|
@@ -113319,7 +113600,7 @@ function diffPathIndexes(previous, next4) {
|
|
|
113319
113600
|
// src/infrastructure/services/workspace/workspace-sync-state.ts
|
|
113320
113601
|
import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
|
|
113321
113602
|
import * as fs11 from "node:fs/promises";
|
|
113322
|
-
import { homedir as
|
|
113603
|
+
import { homedir as homedir8 } from "node:os";
|
|
113323
113604
|
import { join as join24 } from "node:path";
|
|
113324
113605
|
function workspaceKeyFor(workingDir) {
|
|
113325
113606
|
const normalized = normalizeWorkingDirForLookup(workingDir);
|
|
@@ -113397,7 +113678,7 @@ function entriesFromPathIndex(paths) {
|
|
|
113397
113678
|
}
|
|
113398
113679
|
var SYNC_STATE_VERSION = "2", SYNC_STATE_DIR;
|
|
113399
113680
|
var init_workspace_sync_state = __esm(() => {
|
|
113400
|
-
SYNC_STATE_DIR = join24(
|
|
113681
|
+
SYNC_STATE_DIR = join24(homedir8(), ".chatroom", "sync-state");
|
|
113401
113682
|
});
|
|
113402
113683
|
|
|
113403
113684
|
// src/infrastructure/services/workspace/workspace-file-tree-coordinator.ts
|
|
@@ -113547,11 +113828,6 @@ async function startWorkspaceFileTreeCoordinator(options) {
|
|
|
113547
113828
|
if (!delta)
|
|
113548
113829
|
break;
|
|
113549
113830
|
const result = await options.onDelta(delta, manifest.backendRevision);
|
|
113550
|
-
if (result.status === "conflict") {
|
|
113551
|
-
manifest.backendRevision = result.revision;
|
|
113552
|
-
await saveWorkspaceSyncManifest(manifest);
|
|
113553
|
-
continue;
|
|
113554
|
-
}
|
|
113555
113831
|
manifest.backendRevision = result.revision;
|
|
113556
113832
|
manifest.pendingDeltas.shift();
|
|
113557
113833
|
await saveWorkspaceSyncManifest(manifest);
|
|
@@ -113769,12 +114045,450 @@ var init_workspace_sync_queue = __esm(() => {
|
|
|
113769
114045
|
lastCompletedAtByKey = new Map;
|
|
113770
114046
|
});
|
|
113771
114047
|
|
|
114048
|
+
// src/daemon/infrastructure/outbox/lib/coalescing-state-outbox.ts
|
|
114049
|
+
function createCoalescingStateOutbox(options) {
|
|
114050
|
+
const durable = [options.store, options.deliveryKey, options.serialize, options.deserialize];
|
|
114051
|
+
if (durable.some(Boolean) && durable.some((value) => !value))
|
|
114052
|
+
throw new Error("Durable outbox requires store, deliveryKey, serialize, and deserialize");
|
|
114053
|
+
const minIntervalMs = options.minIntervalMs ?? DEFAULT_MIN_INTERVAL_MS;
|
|
114054
|
+
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
114055
|
+
const maxRetryDelayMs = options.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
|
|
114056
|
+
let pending3 = null;
|
|
114057
|
+
let inFlight2 = null;
|
|
114058
|
+
let timer = null;
|
|
114059
|
+
let lastSentAt = 0;
|
|
114060
|
+
let retryAttempt = 0;
|
|
114061
|
+
let stopped = false;
|
|
114062
|
+
if (options.store && options.deliveryKey && options.deserialize) {
|
|
114063
|
+
const recovered = options.store.getPending(options.deliveryKey);
|
|
114064
|
+
if (recovered)
|
|
114065
|
+
pending3 = { state: options.deserialize(recovered.payloadJson), waiters: [] };
|
|
114066
|
+
}
|
|
114067
|
+
const rejectWaiters = (waiters, error51) => {
|
|
114068
|
+
for (const waiter of waiters)
|
|
114069
|
+
waiter.reject(error51);
|
|
114070
|
+
};
|
|
114071
|
+
const mergePending = (older, newer) => ({
|
|
114072
|
+
state: newer?.state ?? older.state,
|
|
114073
|
+
waiters: [...older.waiters, ...newer?.waiters ?? []]
|
|
114074
|
+
});
|
|
114075
|
+
const clearTimer = () => {
|
|
114076
|
+
if (timer)
|
|
114077
|
+
clearTimeout(timer);
|
|
114078
|
+
timer = null;
|
|
114079
|
+
};
|
|
114080
|
+
const schedule2 = (delayMs) => {
|
|
114081
|
+
if (stopped || !pending3 || inFlight2 || timer)
|
|
114082
|
+
return;
|
|
114083
|
+
timer = setTimeout(() => {
|
|
114084
|
+
timer = null;
|
|
114085
|
+
drain2().catch(() => {
|
|
114086
|
+
return;
|
|
114087
|
+
});
|
|
114088
|
+
}, Math.max(0, delayMs));
|
|
114089
|
+
timer.unref?.();
|
|
114090
|
+
};
|
|
114091
|
+
if (pending3)
|
|
114092
|
+
schedule2(0);
|
|
114093
|
+
async function drain2() {
|
|
114094
|
+
if (stopped || !pending3 || inFlight2)
|
|
114095
|
+
return;
|
|
114096
|
+
const batch = pending3;
|
|
114097
|
+
pending3 = null;
|
|
114098
|
+
const sendPromise = Promise.resolve().then(() => options.send(batch.state));
|
|
114099
|
+
inFlight2 = { ...batch, promise: sendPromise };
|
|
114100
|
+
let retryDelay = null;
|
|
114101
|
+
try {
|
|
114102
|
+
const result = await sendPromise;
|
|
114103
|
+
lastSentAt = Date.now();
|
|
114104
|
+
retryAttempt = 0;
|
|
114105
|
+
options.store?.markDone(options.deliveryKey);
|
|
114106
|
+
for (const waiter of batch.waiters)
|
|
114107
|
+
waiter.resolve(result);
|
|
114108
|
+
} catch (error51) {
|
|
114109
|
+
options.onError?.(error51);
|
|
114110
|
+
options.store?.markPendingRetry(options.deliveryKey, error51);
|
|
114111
|
+
pending3 = mergePending(batch, pending3);
|
|
114112
|
+
retryDelay = Math.min(retryDelayMs * 2 ** retryAttempt, maxRetryDelayMs);
|
|
114113
|
+
retryAttempt++;
|
|
114114
|
+
throw error51;
|
|
114115
|
+
} finally {
|
|
114116
|
+
inFlight2 = null;
|
|
114117
|
+
if (pending3) {
|
|
114118
|
+
const intervalDelay = Math.max(0, minIntervalMs - (Date.now() - lastSentAt));
|
|
114119
|
+
schedule2(retryDelay ?? intervalDelay);
|
|
114120
|
+
}
|
|
114121
|
+
}
|
|
114122
|
+
}
|
|
114123
|
+
const enqueue = (state) => {
|
|
114124
|
+
if (stopped)
|
|
114125
|
+
return Promise.reject(new Error("Outbox is stopped"));
|
|
114126
|
+
const promise4 = new Promise((resolve8, reject) => {
|
|
114127
|
+
const waiter = { resolve: resolve8, reject };
|
|
114128
|
+
if (pending3) {
|
|
114129
|
+
pending3 = { state, waiters: [...pending3.waiters, waiter] };
|
|
114130
|
+
} else {
|
|
114131
|
+
pending3 = { state, waiters: [waiter] };
|
|
114132
|
+
}
|
|
114133
|
+
options.store?.upsertPending(options.deliveryKey, options.serialize(state));
|
|
114134
|
+
});
|
|
114135
|
+
if (!inFlight2 && !timer) {
|
|
114136
|
+
const delay3 = lastSentAt === 0 ? 0 : Math.max(0, minIntervalMs - (Date.now() - lastSentAt));
|
|
114137
|
+
schedule2(delay3);
|
|
114138
|
+
}
|
|
114139
|
+
return promise4;
|
|
114140
|
+
};
|
|
114141
|
+
const flushNow = async () => {
|
|
114142
|
+
if (stopped)
|
|
114143
|
+
return;
|
|
114144
|
+
clearTimer();
|
|
114145
|
+
if (inFlight2) {
|
|
114146
|
+
await inFlight2.promise.catch(() => {
|
|
114147
|
+
return;
|
|
114148
|
+
});
|
|
114149
|
+
}
|
|
114150
|
+
if (pending3)
|
|
114151
|
+
await drain2();
|
|
114152
|
+
};
|
|
114153
|
+
const stop4 = async () => {
|
|
114154
|
+
if (stopped)
|
|
114155
|
+
return;
|
|
114156
|
+
await flushNow();
|
|
114157
|
+
stopped = true;
|
|
114158
|
+
clearTimer();
|
|
114159
|
+
if (inFlight2)
|
|
114160
|
+
await inFlight2.promise.catch(() => {
|
|
114161
|
+
return;
|
|
114162
|
+
});
|
|
114163
|
+
const unsent = pending3;
|
|
114164
|
+
pending3 = null;
|
|
114165
|
+
if (unsent)
|
|
114166
|
+
rejectWaiters(unsent.waiters, new Error("Outbox stopped before send completed"));
|
|
114167
|
+
};
|
|
114168
|
+
return { enqueue, flushNow, stop: stop4 };
|
|
114169
|
+
}
|
|
114170
|
+
var DEFAULT_MIN_INTERVAL_MS = 5000, DEFAULT_RETRY_DELAY_MS = 500, DEFAULT_MAX_RETRY_DELAY_MS = 5000;
|
|
114171
|
+
|
|
114172
|
+
// src/daemon/infrastructure/outbox/lib/keyed-coalescing-state-outbox-registry.ts
|
|
114173
|
+
function createKeyedCoalescingStateOutboxRegistry(options) {
|
|
114174
|
+
const outboxes = new Map;
|
|
114175
|
+
const getOrCreate = (key) => {
|
|
114176
|
+
let outbox = outboxes.get(key);
|
|
114177
|
+
if (!outbox) {
|
|
114178
|
+
outbox = createCoalescingStateOutbox({
|
|
114179
|
+
send: (state) => options.createSend(key)(state),
|
|
114180
|
+
minIntervalMs: options.minIntervalMs,
|
|
114181
|
+
retryDelayMs: options.retryDelayMs,
|
|
114182
|
+
maxRetryDelayMs: options.maxRetryDelayMs,
|
|
114183
|
+
onError: (error51) => options.onError?.(key, error51),
|
|
114184
|
+
...options.store ? { store: options.store, deliveryKey: key, serialize: options.serialize, deserialize: options.deserialize } : {}
|
|
114185
|
+
});
|
|
114186
|
+
outboxes.set(key, outbox);
|
|
114187
|
+
}
|
|
114188
|
+
return outbox;
|
|
114189
|
+
};
|
|
114190
|
+
const stop4 = async (key) => {
|
|
114191
|
+
const outbox = outboxes.get(key);
|
|
114192
|
+
outboxes.delete(key);
|
|
114193
|
+
await outbox?.flushNow().catch(() => {
|
|
114194
|
+
return;
|
|
114195
|
+
});
|
|
114196
|
+
await outbox?.stop().catch(() => {
|
|
114197
|
+
return;
|
|
114198
|
+
});
|
|
114199
|
+
};
|
|
114200
|
+
return {
|
|
114201
|
+
enqueue: (key, state) => getOrCreate(key).enqueue(state),
|
|
114202
|
+
stop: stop4,
|
|
114203
|
+
stopAll: async () => {
|
|
114204
|
+
for (const key of [...outboxes.keys()])
|
|
114205
|
+
await stop4(key);
|
|
114206
|
+
options.store?.close();
|
|
114207
|
+
}
|
|
114208
|
+
};
|
|
114209
|
+
}
|
|
114210
|
+
var init_keyed_coalescing_state_outbox_registry = () => {};
|
|
114211
|
+
|
|
114212
|
+
// src/daemon/infrastructure/outbox/outbox-db-path.ts
|
|
114213
|
+
import { homedir as homedir9 } from "node:os";
|
|
114214
|
+
import { join as join25 } from "node:path";
|
|
114215
|
+
function resolveOutboxDbPath(machineId, kind) {
|
|
114216
|
+
return join25(homedir9(), ".chatroom", "daemon", machineId, `outbox-${kind}.sqlite`);
|
|
114217
|
+
}
|
|
114218
|
+
var init_outbox_db_path = () => {};
|
|
114219
|
+
|
|
114220
|
+
// src/daemon/infrastructure/outbox/lib/durable-coalescing-state-schema.ts
|
|
114221
|
+
var DURABLE_COALESCING_STATE_MIGRATIONS;
|
|
114222
|
+
var init_durable_coalescing_state_schema = __esm(() => {
|
|
114223
|
+
DURABLE_COALESCING_STATE_MIGRATIONS = [
|
|
114224
|
+
`CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`,
|
|
114225
|
+
`CREATE TABLE IF NOT EXISTS coalescing_outbox_entries (delivery_key TEXT PRIMARY KEY, payload_json TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', attempts INTEGER NOT NULL DEFAULT 0, last_error TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`
|
|
114226
|
+
];
|
|
114227
|
+
});
|
|
114228
|
+
|
|
114229
|
+
// src/daemon/infrastructure/outbox/lib/durable-coalescing-state-store.ts
|
|
114230
|
+
import { mkdirSync as mkdirSync6 } from "node:fs";
|
|
114231
|
+
import { dirname as dirname12 } from "node:path";
|
|
114232
|
+
import { DatabaseSync } from "node:sqlite";
|
|
114233
|
+
function openDurableCoalescingStateStore(path8) {
|
|
114234
|
+
mkdirSync6(dirname12(path8), { recursive: true });
|
|
114235
|
+
const db = new DatabaseSync(path8);
|
|
114236
|
+
for (const sql of DURABLE_COALESCING_STATE_MIGRATIONS)
|
|
114237
|
+
db.exec(sql);
|
|
114238
|
+
db.prepare("UPDATE coalescing_outbox_entries SET status='pending' WHERE status='in_flight'").run();
|
|
114239
|
+
return { upsertPending: (key, payload) => {
|
|
114240
|
+
const now = Date.now();
|
|
114241
|
+
db.prepare("INSERT INTO coalescing_outbox_entries(delivery_key,payload_json,status,created_at,updated_at) VALUES(?,?,'pending',?,?) ON CONFLICT(delivery_key) DO UPDATE SET payload_json=excluded.payload_json,status='pending',updated_at=excluded.updated_at").run(key, payload, now, now);
|
|
114242
|
+
}, getPending: (key) => db.prepare("SELECT payload_json as payloadJson, attempts FROM coalescing_outbox_entries WHERE delivery_key=? AND status IN ('pending','in_flight')").get(key) ?? null, markDone: (key) => {
|
|
114243
|
+
db.prepare("DELETE FROM coalescing_outbox_entries WHERE delivery_key=?").run(key);
|
|
114244
|
+
}, markPendingRetry: (key, error51) => {
|
|
114245
|
+
db.prepare("UPDATE coalescing_outbox_entries SET status='pending',last_error=?,attempts=attempts+1,updated_at=? WHERE delivery_key=?").run(String(error51), Date.now(), key);
|
|
114246
|
+
}, listPendingKeys: () => db.prepare("SELECT delivery_key as key FROM coalescing_outbox_entries WHERE status IN ('pending','in_flight')").all().map((r) => String(r.key)), close: () => db.close() };
|
|
114247
|
+
}
|
|
114248
|
+
var init_durable_coalescing_state_store = __esm(() => {
|
|
114249
|
+
init_durable_coalescing_state_schema();
|
|
114250
|
+
});
|
|
114251
|
+
|
|
114252
|
+
// src/daemon/infrastructure/outbox/workspace-file-tree-checkpoint-outbox.ts
|
|
114253
|
+
function createWorkspaceFileTreeCheckpointOutboxRegistry(machineId, createSend, options) {
|
|
114254
|
+
return createKeyedCoalescingStateOutboxRegistry({
|
|
114255
|
+
store: openDurableCoalescingStateStore(resolveOutboxDbPath(machineId, "file-tree-checkpoint")),
|
|
114256
|
+
serialize: JSON.stringify,
|
|
114257
|
+
deserialize: JSON.parse,
|
|
114258
|
+
createSend,
|
|
114259
|
+
minIntervalMs: WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MIN_INTERVAL_MS,
|
|
114260
|
+
onError: options?.onError
|
|
114261
|
+
});
|
|
114262
|
+
}
|
|
114263
|
+
var WORKSPACE_FILE_TREE_CHECKPOINT_OUTBOX_MIN_INTERVAL_MS = 5000;
|
|
114264
|
+
var init_workspace_file_tree_checkpoint_outbox = __esm(() => {
|
|
114265
|
+
init_keyed_coalescing_state_outbox_registry();
|
|
114266
|
+
init_outbox_db_path();
|
|
114267
|
+
init_durable_coalescing_state_store();
|
|
114268
|
+
});
|
|
114269
|
+
|
|
114270
|
+
// src/daemon/infrastructure/outbox/lib/durable-fifo-queue-schema.ts
|
|
114271
|
+
var DURABLE_FIFO_QUEUE_MIGRATIONS;
|
|
114272
|
+
var init_durable_fifo_queue_schema = __esm(() => {
|
|
114273
|
+
DURABLE_FIFO_QUEUE_MIGRATIONS = [
|
|
114274
|
+
`CREATE TABLE IF NOT EXISTS schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`,
|
|
114275
|
+
`CREATE TABLE IF NOT EXISTS fifo_outbox_entries (id INTEGER PRIMARY KEY AUTOINCREMENT, delivery_key TEXT NOT NULL, payload_json TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'pending', attempts INTEGER NOT NULL DEFAULT 0, last_error TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`,
|
|
114276
|
+
`CREATE INDEX IF NOT EXISTS idx_fifo_outbox_pending ON fifo_outbox_entries(delivery_key, status, id)`
|
|
114277
|
+
];
|
|
114278
|
+
});
|
|
114279
|
+
|
|
114280
|
+
// src/daemon/infrastructure/outbox/lib/durable-fifo-queue-store.ts
|
|
114281
|
+
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
114282
|
+
import { mkdirSync as mkdirSync7 } from "node:fs";
|
|
114283
|
+
import { dirname as dirname13 } from "node:path";
|
|
114284
|
+
function openDurableFifoQueueStore(dbPath) {
|
|
114285
|
+
mkdirSync7(dirname13(dbPath), { recursive: true });
|
|
114286
|
+
const db = new DatabaseSync2(dbPath);
|
|
114287
|
+
for (const sql of DURABLE_FIFO_QUEUE_MIGRATIONS)
|
|
114288
|
+
db.exec(sql);
|
|
114289
|
+
db.prepare("UPDATE fifo_outbox_entries SET status='pending', updated_at=? WHERE status='in_flight'").run(Date.now());
|
|
114290
|
+
return {
|
|
114291
|
+
enqueue: (key, payloadJson) => {
|
|
114292
|
+
const now = Date.now();
|
|
114293
|
+
return Number(db.prepare("INSERT INTO fifo_outbox_entries(delivery_key,payload_json,created_at,updated_at) VALUES(?,?,?,?) RETURNING id").get(key, payloadJson, now, now).id);
|
|
114294
|
+
},
|
|
114295
|
+
claimNextBatch: (key, limit) => db.prepare("UPDATE fifo_outbox_entries SET status='in_flight', attempts=attempts+1, updated_at=? WHERE id IN (SELECT id FROM fifo_outbox_entries WHERE delivery_key=? AND status='pending' ORDER BY id LIMIT ?) RETURNING id, delivery_key as deliveryKey, payload_json as payloadJson, attempts").all(Date.now(), key, limit),
|
|
114296
|
+
markDone: (id3) => {
|
|
114297
|
+
db.prepare("DELETE FROM fifo_outbox_entries WHERE id=?").run(id3);
|
|
114298
|
+
},
|
|
114299
|
+
markPending: (id3) => {
|
|
114300
|
+
db.prepare("UPDATE fifo_outbox_entries SET status='pending', last_error=NULL, updated_at=? WHERE id=?").run(Date.now(), id3);
|
|
114301
|
+
},
|
|
114302
|
+
updatePayload: (id3, payloadJson) => {
|
|
114303
|
+
db.prepare("UPDATE fifo_outbox_entries SET payload_json=?, updated_at=? WHERE id=?").run(payloadJson, Date.now(), id3);
|
|
114304
|
+
},
|
|
114305
|
+
markPendingRetry: (id3, error51) => {
|
|
114306
|
+
db.prepare("UPDATE fifo_outbox_entries SET status='pending', last_error=?, updated_at=? WHERE id=?").run(String(error51), Date.now(), id3);
|
|
114307
|
+
},
|
|
114308
|
+
listPendingForRecovery: (key) => db.prepare("SELECT id, delivery_key as deliveryKey, payload_json as payloadJson, attempts FROM fifo_outbox_entries WHERE delivery_key=? AND status IN ('pending','in_flight') ORDER BY id").all(key),
|
|
114309
|
+
close: () => db.close()
|
|
114310
|
+
};
|
|
114311
|
+
}
|
|
114312
|
+
var init_durable_fifo_queue_store = __esm(() => {
|
|
114313
|
+
init_durable_fifo_queue_schema();
|
|
114314
|
+
});
|
|
114315
|
+
|
|
114316
|
+
// src/daemon/infrastructure/outbox/lib/fifo-batched-outbox.ts
|
|
114317
|
+
function createFifoBatchedOutbox(o) {
|
|
114318
|
+
const waiters = new Map;
|
|
114319
|
+
let running3;
|
|
114320
|
+
let stopped = false;
|
|
114321
|
+
let retryTimer;
|
|
114322
|
+
let retryAttempt = 0;
|
|
114323
|
+
const retryDelay = () => Math.min((o.retryDelayMs ?? 500) * 2 ** retryAttempt++, o.maxRetryDelayMs ?? 5000);
|
|
114324
|
+
const scheduleRetry = () => {
|
|
114325
|
+
if (!stopped && !retryTimer) {
|
|
114326
|
+
retryTimer = setTimeout(() => {
|
|
114327
|
+
retryTimer = undefined;
|
|
114328
|
+
drain2().catch(() => {
|
|
114329
|
+
return;
|
|
114330
|
+
});
|
|
114331
|
+
}, retryDelay());
|
|
114332
|
+
retryTimer.unref?.();
|
|
114333
|
+
}
|
|
114334
|
+
};
|
|
114335
|
+
const drain2 = async () => {
|
|
114336
|
+
if (running3)
|
|
114337
|
+
return running3;
|
|
114338
|
+
running3 = (async () => {
|
|
114339
|
+
while (true) {
|
|
114340
|
+
const rows2 = o.store.claimNextBatch(o.deliveryKey, o.batchSize);
|
|
114341
|
+
if (!rows2.length)
|
|
114342
|
+
break;
|
|
114343
|
+
try {
|
|
114344
|
+
const results = await o.send(rows2.map((r) => o.deserialize(r.payloadJson)));
|
|
114345
|
+
let hasRetry = false;
|
|
114346
|
+
for (let i2 = 0;i2 < results.length; i2++) {
|
|
114347
|
+
const item = o.deserialize(rows2[i2].payloadJson);
|
|
114348
|
+
const outcome = o.classifyOutcome?.(results[i2], item) ?? { kind: "success" };
|
|
114349
|
+
if (outcome.kind === "retry") {
|
|
114350
|
+
o.store.updatePayload(rows2[i2].id, o.serialize(outcome.item));
|
|
114351
|
+
o.store.markPending(rows2[i2].id);
|
|
114352
|
+
hasRetry = true;
|
|
114353
|
+
continue;
|
|
114354
|
+
}
|
|
114355
|
+
o.store.markDone(rows2[i2].id);
|
|
114356
|
+
waiters.get(rows2[i2].id)?.resolve(results[i2]);
|
|
114357
|
+
waiters.delete(rows2[i2].id);
|
|
114358
|
+
}
|
|
114359
|
+
for (let i2 = results.length;i2 < rows2.length; i2++)
|
|
114360
|
+
o.store.markPending(rows2[i2].id);
|
|
114361
|
+
if (hasRetry) {
|
|
114362
|
+
scheduleRetry();
|
|
114363
|
+
break;
|
|
114364
|
+
}
|
|
114365
|
+
} catch (e) {
|
|
114366
|
+
o.onError?.(e);
|
|
114367
|
+
for (const r of rows2)
|
|
114368
|
+
o.store.markPendingRetry(r.id, e);
|
|
114369
|
+
scheduleRetry();
|
|
114370
|
+
break;
|
|
114371
|
+
}
|
|
114372
|
+
}
|
|
114373
|
+
})().finally(() => {
|
|
114374
|
+
running3 = undefined;
|
|
114375
|
+
});
|
|
114376
|
+
return running3;
|
|
114377
|
+
};
|
|
114378
|
+
const enqueue = (item) => {
|
|
114379
|
+
if (stopped)
|
|
114380
|
+
return Promise.reject(new Error("Outbox is stopped"));
|
|
114381
|
+
const id3 = o.store.enqueue(o.deliveryKey, o.serialize(item));
|
|
114382
|
+
const p = new Promise((resolve8, reject) => waiters.set(id3, { resolve: resolve8, reject }));
|
|
114383
|
+
drain2().catch(() => {
|
|
114384
|
+
return;
|
|
114385
|
+
});
|
|
114386
|
+
return p;
|
|
114387
|
+
};
|
|
114388
|
+
const flushNow = async () => {
|
|
114389
|
+
while (o.store.listPendingForRecovery(o.deliveryKey).length) {
|
|
114390
|
+
await drain2();
|
|
114391
|
+
}
|
|
114392
|
+
};
|
|
114393
|
+
const stop4 = async () => {
|
|
114394
|
+
if (stopped)
|
|
114395
|
+
return;
|
|
114396
|
+
if (retryTimer)
|
|
114397
|
+
clearTimeout(retryTimer);
|
|
114398
|
+
retryTimer = undefined;
|
|
114399
|
+
await flushNow();
|
|
114400
|
+
stopped = true;
|
|
114401
|
+
};
|
|
114402
|
+
return { enqueue, flushNow, stop: stop4 };
|
|
114403
|
+
}
|
|
114404
|
+
|
|
114405
|
+
// src/daemon/infrastructure/outbox/lib/keyed-fifo-batched-outbox-registry.ts
|
|
114406
|
+
function createKeyedFifoBatchedOutboxRegistry(o) {
|
|
114407
|
+
const boxes = new Map;
|
|
114408
|
+
const get13 = (key) => {
|
|
114409
|
+
let b = boxes.get(key);
|
|
114410
|
+
if (!b) {
|
|
114411
|
+
b = createFifoBatchedOutbox({
|
|
114412
|
+
batchSize: o.batchSize,
|
|
114413
|
+
send: o.createSend(key),
|
|
114414
|
+
store: o.store,
|
|
114415
|
+
deliveryKey: key,
|
|
114416
|
+
serialize: o.serialize,
|
|
114417
|
+
deserialize: o.deserialize,
|
|
114418
|
+
onError: (e) => o.onError?.(key, e),
|
|
114419
|
+
classifyOutcome: o.classifyOutcome
|
|
114420
|
+
});
|
|
114421
|
+
boxes.set(key, b);
|
|
114422
|
+
}
|
|
114423
|
+
return b;
|
|
114424
|
+
};
|
|
114425
|
+
const stop4 = async (k) => {
|
|
114426
|
+
const b = boxes.get(k);
|
|
114427
|
+
if (b) {
|
|
114428
|
+
await b.stop();
|
|
114429
|
+
boxes.delete(k);
|
|
114430
|
+
}
|
|
114431
|
+
};
|
|
114432
|
+
return {
|
|
114433
|
+
enqueue: (k, i2) => get13(k).enqueue(i2),
|
|
114434
|
+
flushNow: async (k) => {
|
|
114435
|
+
if (k)
|
|
114436
|
+
await get13(k).flushNow();
|
|
114437
|
+
else
|
|
114438
|
+
for (const b of boxes.values())
|
|
114439
|
+
await b.flushNow();
|
|
114440
|
+
},
|
|
114441
|
+
stop: stop4,
|
|
114442
|
+
stopAll: async () => {
|
|
114443
|
+
for (const k of [...boxes.keys()])
|
|
114444
|
+
await stop4(k);
|
|
114445
|
+
o.store.close();
|
|
114446
|
+
}
|
|
114447
|
+
};
|
|
114448
|
+
}
|
|
114449
|
+
var init_keyed_fifo_batched_outbox_registry = __esm(() => {
|
|
114450
|
+
init_durable_fifo_queue_store();
|
|
114451
|
+
});
|
|
114452
|
+
|
|
114453
|
+
// src/daemon/infrastructure/outbox/workspace-file-tree-delta-outbox.ts
|
|
114454
|
+
function createWorkspaceFileTreeDeltaOutboxRegistry(machineId, createSend, options) {
|
|
114455
|
+
const store = openDurableFifoQueueStore(resolveOutboxDbPath(machineId, "file-tree-delta"));
|
|
114456
|
+
return createKeyedFifoBatchedOutboxRegistry({
|
|
114457
|
+
store,
|
|
114458
|
+
batchSize: options?.batchSize ?? WORKSPACE_FILE_TREE_DELTA_OUTBOX_BATCH_SIZE,
|
|
114459
|
+
createSend: (key) => async (units) => {
|
|
114460
|
+
const out = [];
|
|
114461
|
+
for (const u of units) {
|
|
114462
|
+
const r = await createSend(key)(u);
|
|
114463
|
+
out.push(r);
|
|
114464
|
+
}
|
|
114465
|
+
return out;
|
|
114466
|
+
},
|
|
114467
|
+
serialize: JSON.stringify,
|
|
114468
|
+
deserialize: JSON.parse,
|
|
114469
|
+
onError: options?.onError,
|
|
114470
|
+
classifyOutcome: (result, unit) => result.status === "conflict" ? { kind: "retry", item: { ...unit, baseRevision: result.revision } } : { kind: "success" }
|
|
114471
|
+
});
|
|
114472
|
+
}
|
|
114473
|
+
var WORKSPACE_FILE_TREE_DELTA_OUTBOX_BATCH_SIZE = 5;
|
|
114474
|
+
var init_workspace_file_tree_delta_outbox = __esm(() => {
|
|
114475
|
+
init_outbox_db_path();
|
|
114476
|
+
init_durable_fifo_queue_store();
|
|
114477
|
+
init_keyed_fifo_batched_outbox_registry();
|
|
114478
|
+
});
|
|
114479
|
+
|
|
114480
|
+
// src/daemon/infrastructure/outbox/index.ts
|
|
114481
|
+
var init_outbox = __esm(() => {
|
|
114482
|
+
init_workspace_file_tree_checkpoint_outbox();
|
|
114483
|
+
init_workspace_file_tree_delta_outbox();
|
|
114484
|
+
});
|
|
114485
|
+
|
|
113772
114486
|
// src/daemon/entry/files/file-tree-subscription.ts
|
|
113773
114487
|
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
113774
114488
|
function logSubscriptionWarn(label, err) {
|
|
113775
114489
|
console.warn(`[${formatTimestamp()}] ⚠️ ${label}: ${getErrorMessage(err)}`);
|
|
113776
114490
|
}
|
|
113777
|
-
async function stopCoordinatorForWorkingDir(coordinators, normalized) {
|
|
114491
|
+
async function stopCoordinatorForWorkingDir(coordinators, checkpointOutboxRegistry, deltaOutboxRegistry, normalized) {
|
|
113778
114492
|
const coordinatorPromise = coordinators.get(normalized);
|
|
113779
114493
|
if (!coordinatorPromise)
|
|
113780
114494
|
return;
|
|
@@ -113782,8 +114496,10 @@ async function stopCoordinatorForWorkingDir(coordinators, normalized) {
|
|
|
113782
114496
|
await coordinatorPromise.then((coordinator2) => coordinator2.stop()).catch(() => {
|
|
113783
114497
|
return;
|
|
113784
114498
|
});
|
|
114499
|
+
await checkpointOutboxRegistry.stop(normalized);
|
|
114500
|
+
await deltaOutboxRegistry.stop(normalized);
|
|
113785
114501
|
}
|
|
113786
|
-
async function drainPendingFileTreeReleaseRequests(session2, coordinators) {
|
|
114502
|
+
async function drainPendingFileTreeReleaseRequests(session2, coordinators, checkpointOutboxRegistry, deltaOutboxRegistry) {
|
|
113787
114503
|
const releases = await session2.backend.query(api.workspaceFiles.getPendingFileTreeReleaseRequests, {
|
|
113788
114504
|
sessionId: session2.sessionId,
|
|
113789
114505
|
machineId: session2.machineId
|
|
@@ -113795,7 +114511,7 @@ async function drainPendingFileTreeReleaseRequests(session2, coordinators) {
|
|
|
113795
114511
|
releasesByDir.add(normalizeWorkingDirForLookup(release.workingDir));
|
|
113796
114512
|
}
|
|
113797
114513
|
for (const normalized of releasesByDir) {
|
|
113798
|
-
await stopCoordinatorForWorkingDir(coordinators, normalized).then(() => session2.backend.mutation(api.workspaceFiles.fulfillFileTreeReleaseRequest, {
|
|
114514
|
+
await stopCoordinatorForWorkingDir(coordinators, checkpointOutboxRegistry, deltaOutboxRegistry, normalized).then(() => session2.backend.mutation(api.workspaceFiles.fulfillFileTreeReleaseRequest, {
|
|
113799
114515
|
sessionId: session2.sessionId,
|
|
113800
114516
|
machineId: session2.machineId,
|
|
113801
114517
|
workingDir: normalized
|
|
@@ -113893,6 +114609,22 @@ async function publishCheckpoint(session2, normalizedWorkingDir, tree, revision)
|
|
|
113893
114609
|
var startFileTreeSubscriptionEffect = () => exports_Effect.gen(function* () {
|
|
113894
114610
|
const session2 = yield* DaemonSessionService;
|
|
113895
114611
|
const coordinators = new Map;
|
|
114612
|
+
const checkpointOutboxRegistry = createWorkspaceFileTreeCheckpointOutboxRegistry(session2.machineId, (normalized) => (state) => publishCheckpoint(session2, normalized, state.tree, state.revision), {
|
|
114613
|
+
onError: (normalized, error51) => logSubscriptionWarn(`File tree checkpoint outbox failed for ${normalized}`, error51)
|
|
114614
|
+
});
|
|
114615
|
+
const deltaOutboxRegistry = createWorkspaceFileTreeDeltaOutboxRegistry(session2.machineId, (normalized) => async (unit) => {
|
|
114616
|
+
const result = await session2.backend.mutation(api.workspaceFiles.applyFileTreeDeltaBatch, {
|
|
114617
|
+
sessionId: session2.sessionId,
|
|
114618
|
+
machineId: session2.machineId,
|
|
114619
|
+
workingDir: normalized,
|
|
114620
|
+
operationId: unit.delta.operationId,
|
|
114621
|
+
baseRevision: unit.baseRevision,
|
|
114622
|
+
operations: toDeltaOperations(unit.delta)
|
|
114623
|
+
});
|
|
114624
|
+
if (result.status === "resync-required")
|
|
114625
|
+
return { status: "conflict", revision: result.expectedRevision };
|
|
114626
|
+
return result;
|
|
114627
|
+
});
|
|
113896
114628
|
const ensureCoordinator = (workingDir, forceReconcile) => {
|
|
113897
114629
|
const normalized = normalizeWorkingDirForLookup(workingDir);
|
|
113898
114630
|
let coordinatorPromise = coordinators.get(normalized);
|
|
@@ -113900,23 +114632,8 @@ var startFileTreeSubscriptionEffect = () => exports_Effect.gen(function* () {
|
|
|
113900
114632
|
coordinatorPromise = startWorkspaceFileTreeCoordinator({
|
|
113901
114633
|
machineId: session2.machineId,
|
|
113902
114634
|
workingDir: normalized,
|
|
113903
|
-
onDelta:
|
|
113904
|
-
|
|
113905
|
-
const result = await session2.backend.mutation(api.workspaceFiles.applyFileTreeDeltaBatch, {
|
|
113906
|
-
sessionId: session2.sessionId,
|
|
113907
|
-
machineId: session2.machineId,
|
|
113908
|
-
workingDir: normalized,
|
|
113909
|
-
operationId: delta.operationId,
|
|
113910
|
-
baseRevision,
|
|
113911
|
-
operations
|
|
113912
|
-
});
|
|
113913
|
-
if (result.status === "resync-required") {
|
|
113914
|
-
return { status: "conflict", revision: result.expectedRevision };
|
|
113915
|
-
}
|
|
113916
|
-
console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree delta: ${normalized} (${operations.length} operations, ${Buffer.byteLength(JSON.stringify(operations))} bytes, revision ${result.revision})`);
|
|
113917
|
-
return result;
|
|
113918
|
-
},
|
|
113919
|
-
onCheckpoint: (tree, revision) => publishCheckpoint(session2, normalized, tree, revision),
|
|
114635
|
+
onDelta: (delta, baseRevision) => deltaOutboxRegistry.enqueue(normalized, { delta, baseRevision }),
|
|
114636
|
+
onCheckpoint: (tree, revision) => checkpointOutboxRegistry.enqueue(normalized, { tree, revision }),
|
|
113920
114637
|
onError: (error51) => logSubscriptionWarn(`File tree coordinator failed for ${normalized}`, error51),
|
|
113921
114638
|
onReconciled: (correctedPathCount) => {
|
|
113922
114639
|
console.log(`[${formatTimestamp()}] \uD83C\uDF33 File tree reconciled: ${normalized} (${correctedPathCount} corrected paths)`);
|
|
@@ -113942,12 +114659,15 @@ var startFileTreeSubscriptionEffect = () => exports_Effect.gen(function* () {
|
|
|
113942
114659
|
};
|
|
113943
114660
|
return {
|
|
113944
114661
|
drainPendingFileTreeRequests: () => drainPendingFileTreeRequests(session2, coordinators, ensureCoordinator),
|
|
113945
|
-
drainPendingFileTreeReleaseRequests: () => drainPendingFileTreeReleaseRequests(session2, coordinators),
|
|
114662
|
+
drainPendingFileTreeReleaseRequests: () => drainPendingFileTreeReleaseRequests(session2, coordinators, checkpointOutboxRegistry, deltaOutboxRegistry),
|
|
113946
114663
|
stop: () => {
|
|
113947
|
-
|
|
113948
|
-
|
|
113949
|
-
|
|
113950
|
-
|
|
114664
|
+
(async () => {
|
|
114665
|
+
const keys3 = [...coordinators.keys()];
|
|
114666
|
+
await Promise.all(keys3.map((normalized) => stopCoordinatorForWorkingDir(coordinators, checkpointOutboxRegistry, deltaOutboxRegistry, normalized)));
|
|
114667
|
+
await deltaOutboxRegistry.stopAll();
|
|
114668
|
+
await checkpointOutboxRegistry.stopAll();
|
|
114669
|
+
coordinators.clear();
|
|
114670
|
+
})();
|
|
113951
114671
|
}
|
|
113952
114672
|
};
|
|
113953
114673
|
});
|
|
@@ -113961,6 +114681,7 @@ var init_file_tree_subscription = __esm(() => {
|
|
|
113961
114681
|
init_workspace_file_tree_coordinator();
|
|
113962
114682
|
init_workspace_sync_queue();
|
|
113963
114683
|
init_convex_error();
|
|
114684
|
+
init_outbox();
|
|
113964
114685
|
init_daemon_services();
|
|
113965
114686
|
});
|
|
113966
114687
|
|
|
@@ -114074,7 +114795,7 @@ var init_file_write_request_priority = __esm(() => {
|
|
|
114074
114795
|
|
|
114075
114796
|
// src/daemon/entry/files/file-write-fulfillment.ts
|
|
114076
114797
|
import { access as access4, mkdir as mkdir10, rename as rename4, rm as rm4, writeFile as writeFile9 } from "node:fs/promises";
|
|
114077
|
-
import { dirname as
|
|
114798
|
+
import { dirname as dirname14 } from "node:path";
|
|
114078
114799
|
function isTerminalFileWriteError(errorMessage) {
|
|
114079
114800
|
const terminalMessages = new Set([
|
|
114080
114801
|
"Invalid file path",
|
|
@@ -114173,7 +114894,7 @@ async function validateWriteOperation(operation, absolutePath) {
|
|
|
114173
114894
|
}
|
|
114174
114895
|
async function writePayloadToDisk(absolutePath, operation, content) {
|
|
114175
114896
|
if (operation === "create") {
|
|
114176
|
-
await mkdir10(
|
|
114897
|
+
await mkdir10(dirname14(absolutePath), { recursive: true });
|
|
114177
114898
|
await writeFile9(absolutePath, content, { flag: "wx" });
|
|
114178
114899
|
return;
|
|
114179
114900
|
}
|
|
@@ -114251,7 +114972,7 @@ async function fulfillOneFileWriteRequest(session2, request2) {
|
|
|
114251
114972
|
});
|
|
114252
114973
|
return;
|
|
114253
114974
|
}
|
|
114254
|
-
await mkdir10(
|
|
114975
|
+
await mkdir10(dirname14(targetResolved.absolutePath), { recursive: true });
|
|
114255
114976
|
await rename4(resolved.absolutePath, targetResolved.absolutePath);
|
|
114256
114977
|
await completeWriteRequest(session2, claimed._id, claimed.revision, { status: "done" });
|
|
114257
114978
|
const elapsed4 = Date.now() - startTime;
|
|
@@ -116551,10 +117272,10 @@ var init_deps = __esm(() => {
|
|
|
116551
117272
|
});
|
|
116552
117273
|
|
|
116553
117274
|
// src/daemon/entry/persistence-path.ts
|
|
116554
|
-
import { homedir as
|
|
116555
|
-
import { join as
|
|
117275
|
+
import { homedir as homedir10 } from "node:os";
|
|
117276
|
+
import { join as join26 } from "node:path";
|
|
116556
117277
|
function resolvePersistenceDbPath(machineId) {
|
|
116557
|
-
return
|
|
117278
|
+
return join26(homedir10(), ".chatroom", "daemon", machineId, "events.sqlite");
|
|
116558
117279
|
}
|
|
116559
117280
|
var init_persistence_path = () => {};
|
|
116560
117281
|
|
|
@@ -117590,10 +118311,10 @@ function resolveEnvSlug(convexUrl) {
|
|
|
117590
118311
|
}
|
|
117591
118312
|
|
|
117592
118313
|
// src/infrastructure/log-server/resolve-logs-db-path.ts
|
|
117593
|
-
import { homedir as
|
|
117594
|
-
import { join as
|
|
118314
|
+
import { homedir as homedir11 } from "node:os";
|
|
118315
|
+
import { join as join27 } from "node:path";
|
|
117595
118316
|
function resolveLogsDbPath(convexUrl) {
|
|
117596
|
-
return
|
|
118317
|
+
return join27(homedir11(), ".chatroom", resolveEnvSlug(convexUrl ?? getConvexUrl()), "logs.sqlite");
|
|
117597
118318
|
}
|
|
117598
118319
|
var init_resolve_logs_db_path = __esm(() => {
|
|
117599
118320
|
init_client2();
|
|
@@ -117626,12 +118347,12 @@ var init_log_schema = __esm(() => {
|
|
|
117626
118347
|
});
|
|
117627
118348
|
|
|
117628
118349
|
// src/infrastructure/log-server/open-log-database.ts
|
|
117629
|
-
import { mkdirSync as
|
|
117630
|
-
import { dirname as
|
|
117631
|
-
import { DatabaseSync } from "node:sqlite";
|
|
118350
|
+
import { mkdirSync as mkdirSync8 } from "node:fs";
|
|
118351
|
+
import { dirname as dirname15 } from "node:path";
|
|
118352
|
+
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
117632
118353
|
function openLogDatabase(dbPath) {
|
|
117633
|
-
|
|
117634
|
-
const db = new
|
|
118354
|
+
mkdirSync8(dirname15(dbPath), { recursive: true });
|
|
118355
|
+
const db = new DatabaseSync3(dbPath);
|
|
117635
118356
|
db.exec("PRAGMA journal_mode = WAL");
|
|
117636
118357
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
117637
118358
|
db.exec("PRAGMA synchronous = NORMAL");
|
|
@@ -117857,12 +118578,12 @@ var init_schema = __esm(() => {
|
|
|
117857
118578
|
});
|
|
117858
118579
|
|
|
117859
118580
|
// src/daemon/infrastructure/persistence/open-database.ts
|
|
117860
|
-
import { mkdirSync as
|
|
117861
|
-
import { dirname as
|
|
117862
|
-
import { DatabaseSync as
|
|
118581
|
+
import { mkdirSync as mkdirSync9 } from "node:fs";
|
|
118582
|
+
import { dirname as dirname16 } from "node:path";
|
|
118583
|
+
import { DatabaseSync as DatabaseSync4 } from "node:sqlite";
|
|
117863
118584
|
function openDatabase(dbPath) {
|
|
117864
|
-
|
|
117865
|
-
const db = new
|
|
118585
|
+
mkdirSync9(dirname16(dbPath), { recursive: true });
|
|
118586
|
+
const db = new DatabaseSync4(dbPath);
|
|
117866
118587
|
for (const sql of MIGRATIONS2) {
|
|
117867
118588
|
db.exec(sql);
|
|
117868
118589
|
}
|
|
@@ -131572,19 +132293,19 @@ function routeRequest(req, res, deps) {
|
|
|
131572
132293
|
|
|
131573
132294
|
// src/daemon/local-web/server/serve-static.ts
|
|
131574
132295
|
import { existsSync as existsSync10, readFileSync as readFileSync11 } from "node:fs";
|
|
131575
|
-
import { dirname as
|
|
132296
|
+
import { dirname as dirname17, join as join28 } from "node:path";
|
|
131576
132297
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
131577
132298
|
function clientDistCandidates(here) {
|
|
131578
132299
|
return [
|
|
131579
|
-
|
|
131580
|
-
|
|
131581
|
-
|
|
132300
|
+
join28(here, "client/build"),
|
|
132301
|
+
join28(here, "../client/build"),
|
|
132302
|
+
join28(here, "../src/daemon/local-web/client/build")
|
|
131582
132303
|
];
|
|
131583
132304
|
}
|
|
131584
|
-
function resolveClientDistDir(here =
|
|
132305
|
+
function resolveClientDistDir(here = dirname17(fileURLToPath7(import.meta.url))) {
|
|
131585
132306
|
const candidates = clientDistCandidates(here);
|
|
131586
132307
|
for (const dir of candidates) {
|
|
131587
|
-
if (existsSync10(
|
|
132308
|
+
if (existsSync10(join28(dir, "index.html")))
|
|
131588
132309
|
return dir;
|
|
131589
132310
|
}
|
|
131590
132311
|
return candidates[0];
|
|
@@ -131597,7 +132318,7 @@ function tryServeStatic(req, res, distDir) {
|
|
|
131597
132318
|
return false;
|
|
131598
132319
|
}
|
|
131599
132320
|
const safePath = pathname === "/" ? "/index.html" : pathname;
|
|
131600
|
-
const filePath =
|
|
132321
|
+
const filePath = join28(distDir, safePath);
|
|
131601
132322
|
if (!filePath.startsWith(distDir)) {
|
|
131602
132323
|
res.writeHead(403);
|
|
131603
132324
|
res.end();
|
|
@@ -131614,7 +132335,7 @@ function tryServeStatic(req, res, distDir) {
|
|
|
131614
132335
|
}
|
|
131615
132336
|
return true;
|
|
131616
132337
|
}
|
|
131617
|
-
const indexPath =
|
|
132338
|
+
const indexPath = join28(distDir, "index.html");
|
|
131618
132339
|
if (existsSync10(indexPath)) {
|
|
131619
132340
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
131620
132341
|
if (req.method === "HEAD") {
|
|
@@ -133345,4 +134066,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
133345
134066
|
});
|
|
133346
134067
|
program2.parse();
|
|
133347
134068
|
|
|
133348
|
-
//# debugId=
|
|
134069
|
+
//# debugId=DE791FABFBB4390C64756E2164756E21
|