@youtyan/code-viewer 0.5.2 → 0.5.4
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/code-viewer.js +52 -20
- package/package.json +1 -1
- package/web/app.js +674 -130
- package/web/style.css +467 -97
package/dist/code-viewer.js
CHANGED
|
@@ -3766,6 +3766,7 @@ function parseComposeContent(content, filepath, composeDir, cwd, composeDirEnv,
|
|
|
3766
3766
|
const image = imageMatch ? imageMatch[1] : null;
|
|
3767
3767
|
const env = parseComposeEnv(svcBlock, composeDirEnv);
|
|
3768
3768
|
const containerPort = parseComposeContainerPort(svcBlock);
|
|
3769
|
+
const profiled = /^\s+profiles:/m.test(svcBlock);
|
|
3769
3770
|
const kind = (image ? detectDbKind(image, env) : null) ?? detectDbKindFromEnv(env) ?? detectDbKindFromContainerPort(containerPort) ?? detectDbKindFromServiceName(svc.name);
|
|
3770
3771
|
if (!kind)
|
|
3771
3772
|
continue;
|
|
@@ -3797,7 +3798,8 @@ function parseComposeContent(content, filepath, composeDir, cwd, composeDirEnv,
|
|
|
3797
3798
|
composeDir,
|
|
3798
3799
|
relDirSlash,
|
|
3799
3800
|
...hostPort ? { hostPort } : {},
|
|
3800
|
-
containerPort: serviceContainerPort
|
|
3801
|
+
containerPort: serviceContainerPort,
|
|
3802
|
+
...profiled ? { profiled: true } : {}
|
|
3801
3803
|
});
|
|
3802
3804
|
}
|
|
3803
3805
|
}
|
|
@@ -4327,10 +4329,13 @@ function summarizeDockerSources(discovery) {
|
|
|
4327
4329
|
const entry = byComposeDir.get(source.composeDir);
|
|
4328
4330
|
if (entry) {
|
|
4329
4331
|
entry.services.push(source.serviceName);
|
|
4332
|
+
if (source.profiled)
|
|
4333
|
+
entry.profiledServices.add(source.serviceName);
|
|
4330
4334
|
} else {
|
|
4331
4335
|
byComposeDir.set(source.composeDir, {
|
|
4332
4336
|
compose: source.composeDir,
|
|
4333
|
-
services: [source.serviceName]
|
|
4337
|
+
services: [source.serviceName],
|
|
4338
|
+
profiledServices: new Set(source.profiled ? [source.serviceName] : [])
|
|
4334
4339
|
});
|
|
4335
4340
|
}
|
|
4336
4341
|
}
|
|
@@ -4404,7 +4409,7 @@ async function checkDocker(signal, discoveryResult) {
|
|
|
4404
4409
|
if (compose.cmd && dockerInfo?.code === 0) {
|
|
4405
4410
|
for (const entry of summary.byComposeDir.values()) {
|
|
4406
4411
|
const composeKey = entry.compose;
|
|
4407
|
-
const configRow = await checkComposeConfig(compose.cmd, composeKey, entry.services, signal);
|
|
4412
|
+
const configRow = await checkComposeConfig(compose.cmd, composeKey, entry.services, entry.profiledServices, signal);
|
|
4408
4413
|
rows.push(configRow);
|
|
4409
4414
|
const psRow = await checkComposePs(compose.cmd, composeKey, entry.services, signal);
|
|
4410
4415
|
rows.push(...psRow);
|
|
@@ -4412,7 +4417,7 @@ async function checkDocker(signal, discoveryResult) {
|
|
|
4412
4417
|
}
|
|
4413
4418
|
return { id: "docker", title: "Docker / Compose", rows };
|
|
4414
4419
|
}
|
|
4415
|
-
async function checkComposeConfig(cmd, composeDir, discoveredServices, signal) {
|
|
4420
|
+
async function checkComposeConfig(cmd, composeDir, discoveredServices, profiledServices, signal) {
|
|
4416
4421
|
const cacheKey = `${cmd.binary}|${composeDir}`;
|
|
4417
4422
|
const now = Date.now();
|
|
4418
4423
|
const cached = composeConfigCache.get(cacheKey);
|
|
@@ -4480,13 +4485,15 @@ async function checkComposeConfig(cmd, composeDir, discoveredServices, signal) {
|
|
|
4480
4485
|
};
|
|
4481
4486
|
}
|
|
4482
4487
|
if (services) {
|
|
4483
|
-
const missing = discoveredServices.filter((s) => !services?.includes(s));
|
|
4488
|
+
const missing = discoveredServices.filter((s) => !services?.includes(s) && !profiledServices.has(s));
|
|
4489
|
+
const skippedProfiled = discoveredServices.filter((s) => profiledServices.has(s) && !services?.includes(s));
|
|
4484
4490
|
if (missing.length === 0) {
|
|
4491
|
+
const summary = skippedProfiled.length ? `OK (${services.length} active, ${skippedProfiled.length} profile-gated)` : `OK (${services.length} services)`;
|
|
4485
4492
|
return {
|
|
4486
4493
|
id: `docker.compose-config:${composeDir}`,
|
|
4487
4494
|
title: `compose config — ${composeDir}`,
|
|
4488
4495
|
status: "ok",
|
|
4489
|
-
detail:
|
|
4496
|
+
detail: summary
|
|
4490
4497
|
};
|
|
4491
4498
|
}
|
|
4492
4499
|
return {
|
|
@@ -4494,7 +4501,7 @@ async function checkComposeConfig(cmd, composeDir, discoveredServices, signal) {
|
|
|
4494
4501
|
title: `compose config — ${composeDir}`,
|
|
4495
4502
|
status: "warn",
|
|
4496
4503
|
detail: `discovered services not resolved by compose: ${missing.join(", ")}`,
|
|
4497
|
-
hint: "These services were found by scanning the compose file but `docker compose config --services` did not return them. They may be
|
|
4504
|
+
hint: "These services were found by scanning the compose file but `docker compose config --services` did not return them. They may be overridden by a sibling compose file. (profile-gated services with `profiles:` are intentionally ignored.)"
|
|
4498
4505
|
};
|
|
4499
4506
|
}
|
|
4500
4507
|
return {
|
|
@@ -6009,10 +6016,13 @@ function sanitizeDbUiState(raw) {
|
|
|
6009
6016
|
return emptyDbUiState();
|
|
6010
6017
|
const prefs = sanitizeDbUiPrefs(raw.prefs);
|
|
6011
6018
|
const expandedTables = sanitizeDbUiExpandedTables(raw.expandedTables);
|
|
6019
|
+
const snapshotSelectedTables = sanitizeDbUiExpandedTables(raw.snapshotSelectedTables);
|
|
6012
6020
|
if (!isRecord(raw.columnWidths)) {
|
|
6013
6021
|
const out2 = emptyDbUiState();
|
|
6014
6022
|
if (expandedTables)
|
|
6015
6023
|
out2.expandedTables = expandedTables;
|
|
6024
|
+
if (snapshotSelectedTables)
|
|
6025
|
+
out2.snapshotSelectedTables = snapshotSelectedTables;
|
|
6016
6026
|
if (prefs)
|
|
6017
6027
|
out2.prefs = prefs;
|
|
6018
6028
|
return out2;
|
|
@@ -6058,6 +6068,8 @@ function sanitizeDbUiState(raw) {
|
|
|
6058
6068
|
const out = { version: 1, columnWidths };
|
|
6059
6069
|
if (expandedTables)
|
|
6060
6070
|
out.expandedTables = expandedTables;
|
|
6071
|
+
if (snapshotSelectedTables)
|
|
6072
|
+
out.snapshotSelectedTables = snapshotSelectedTables;
|
|
6061
6073
|
if (prefs)
|
|
6062
6074
|
out.prefs = prefs;
|
|
6063
6075
|
return out;
|
|
@@ -6093,12 +6105,17 @@ function mergeDbUiState(current, patch) {
|
|
|
6093
6105
|
return current;
|
|
6094
6106
|
const mergedPrefs = "prefs" in patch ? mergeDbUiPrefs(current.prefs, patch.prefs) : current.prefs;
|
|
6095
6107
|
const mergedExpandedTables = "expandedTables" in patch ? mergeDbUiExpandedTables(current.expandedTables, patch.expandedTables) : current.expandedTables;
|
|
6108
|
+
const mergedSnapshotSelectedTables = "snapshotSelectedTables" in patch ? mergeDbUiExpandedTables(current.snapshotSelectedTables, patch.snapshotSelectedTables) : current.snapshotSelectedTables;
|
|
6096
6109
|
if (!isRecord(patch.columnWidths)) {
|
|
6097
6110
|
const merged = { ...current, version: 1 };
|
|
6098
6111
|
if (mergedExpandedTables)
|
|
6099
6112
|
merged.expandedTables = mergedExpandedTables;
|
|
6100
6113
|
else
|
|
6101
6114
|
delete merged.expandedTables;
|
|
6115
|
+
if (mergedSnapshotSelectedTables)
|
|
6116
|
+
merged.snapshotSelectedTables = mergedSnapshotSelectedTables;
|
|
6117
|
+
else
|
|
6118
|
+
delete merged.snapshotSelectedTables;
|
|
6102
6119
|
if (mergedPrefs)
|
|
6103
6120
|
merged.prefs = mergedPrefs;
|
|
6104
6121
|
else
|
|
@@ -6139,6 +6156,7 @@ function mergeDbUiState(current, patch) {
|
|
|
6139
6156
|
...patch,
|
|
6140
6157
|
columnWidths,
|
|
6141
6158
|
expandedTables: mergedExpandedTables,
|
|
6159
|
+
snapshotSelectedTables: mergedSnapshotSelectedTables,
|
|
6142
6160
|
prefs: mergedPrefs,
|
|
6143
6161
|
version: 1
|
|
6144
6162
|
});
|
|
@@ -11213,17 +11231,20 @@ async function computeDiffTables(cwd, beforeId, afterId) {
|
|
|
11213
11231
|
insertedCount: 0,
|
|
11214
11232
|
updatedCount: 0,
|
|
11215
11233
|
deletedCount: 0,
|
|
11216
|
-
unchangedCount: b.row_count
|
|
11234
|
+
unchangedCount: b.row_count,
|
|
11235
|
+
coverage: "both"
|
|
11217
11236
|
});
|
|
11218
11237
|
continue;
|
|
11219
11238
|
}
|
|
11220
11239
|
if (!b) {
|
|
11221
11240
|
results.push({
|
|
11222
11241
|
tableName: table,
|
|
11223
|
-
insertedCount:
|
|
11242
|
+
insertedCount: 0,
|
|
11224
11243
|
updatedCount: 0,
|
|
11225
11244
|
deletedCount: 0,
|
|
11226
|
-
unchangedCount: 0
|
|
11245
|
+
unchangedCount: 0,
|
|
11246
|
+
coverage: "after-only",
|
|
11247
|
+
unsnapshottedRowCount: a ? a.row_count : 0
|
|
11227
11248
|
});
|
|
11228
11249
|
continue;
|
|
11229
11250
|
}
|
|
@@ -11232,8 +11253,10 @@ async function computeDiffTables(cwd, beforeId, afterId) {
|
|
|
11232
11253
|
tableName: table,
|
|
11233
11254
|
insertedCount: 0,
|
|
11234
11255
|
updatedCount: 0,
|
|
11235
|
-
deletedCount:
|
|
11236
|
-
unchangedCount: 0
|
|
11256
|
+
deletedCount: 0,
|
|
11257
|
+
unchangedCount: 0,
|
|
11258
|
+
coverage: "before-only",
|
|
11259
|
+
unsnapshottedRowCount: b.row_count
|
|
11237
11260
|
});
|
|
11238
11261
|
continue;
|
|
11239
11262
|
}
|
|
@@ -11255,7 +11278,8 @@ async function computeDiffTables(cwd, beforeId, afterId) {
|
|
|
11255
11278
|
insertedCount,
|
|
11256
11279
|
updatedCount,
|
|
11257
11280
|
deletedCount,
|
|
11258
|
-
unchangedCount: Math.max(0, unchangedCount)
|
|
11281
|
+
unchangedCount: Math.max(0, unchangedCount),
|
|
11282
|
+
coverage: "both"
|
|
11259
11283
|
});
|
|
11260
11284
|
}
|
|
11261
11285
|
results.sort((a, b) => {
|
|
@@ -11393,9 +11417,11 @@ async function runSnapshot(cwd, source, dbId, containers, note, onProgress, opti
|
|
|
11393
11417
|
const snapshotId = await createSnapshot(cwd, dbId, snapshotSource.kind, containers, note, options.schema);
|
|
11394
11418
|
try {
|
|
11395
11419
|
options.onSnapshotId?.(snapshotId);
|
|
11396
|
-
|
|
11420
|
+
const total = containers.length;
|
|
11421
|
+
for (let i = 0;i < containers.length; i++) {
|
|
11422
|
+
const container = containers[i];
|
|
11397
11423
|
throwIfAborted(options.signal, "snapshot cancelled");
|
|
11398
|
-
onProgress?.(container, false);
|
|
11424
|
+
onProgress?.({ container, done: false, index: i, total });
|
|
11399
11425
|
const collected = [];
|
|
11400
11426
|
let pkColumns = [];
|
|
11401
11427
|
if (snapshotSource.model === "sql") {
|
|
@@ -11420,7 +11446,7 @@ async function runSnapshot(cwd, source, dbId, containers, note, onProgress, opti
|
|
|
11420
11446
|
await addSnapshotTableData(cwd, snapshotId, container, pkColumns, collected);
|
|
11421
11447
|
}
|
|
11422
11448
|
await finalizeSnapshot(cwd, snapshotId);
|
|
11423
|
-
onProgress?.("", true);
|
|
11449
|
+
onProgress?.({ container: "", done: true, index: total, total });
|
|
11424
11450
|
return snapshotId;
|
|
11425
11451
|
} catch (err) {
|
|
11426
11452
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -12458,13 +12484,16 @@ async function handleSnapshotCreate(cwd, req, sendSse, omitDirNames) {
|
|
|
12458
12484
|
let activeSnapshotId;
|
|
12459
12485
|
(async () => {
|
|
12460
12486
|
try {
|
|
12461
|
-
const snapshotId = await runSnapshot(cwd, source, snapshotDbId, snapshotContainers, note, (
|
|
12487
|
+
const snapshotId = await runSnapshot(cwd, source, snapshotDbId, snapshotContainers, note, (progress) => {
|
|
12462
12488
|
sendSse?.("db-snapshot", JSON.stringify({
|
|
12463
12489
|
action: "progress",
|
|
12464
12490
|
dbId: snapshotDbId,
|
|
12465
12491
|
schema: body.schema,
|
|
12466
|
-
|
|
12467
|
-
|
|
12492
|
+
id: activeSnapshotId,
|
|
12493
|
+
table: progress.container,
|
|
12494
|
+
done: progress.done,
|
|
12495
|
+
index: progress.index,
|
|
12496
|
+
total: progress.total
|
|
12468
12497
|
}));
|
|
12469
12498
|
}, {
|
|
12470
12499
|
signal: abortController.signal,
|
|
@@ -12477,7 +12506,8 @@ async function handleSnapshotCreate(cwd, req, sendSse, omitDirNames) {
|
|
|
12477
12506
|
action: "started",
|
|
12478
12507
|
dbId: snapshotDbId,
|
|
12479
12508
|
schema: body.schema,
|
|
12480
|
-
id
|
|
12509
|
+
id,
|
|
12510
|
+
total: snapshotContainers.length
|
|
12481
12511
|
}));
|
|
12482
12512
|
}
|
|
12483
12513
|
});
|
|
@@ -12496,6 +12526,7 @@ async function handleSnapshotCreate(cwd, req, sendSse, omitDirNames) {
|
|
|
12496
12526
|
action: aborted ? "aborted" : "error",
|
|
12497
12527
|
dbId: snapshotDbId,
|
|
12498
12528
|
schema: body.schema,
|
|
12529
|
+
id: activeSnapshotId,
|
|
12499
12530
|
...aborted ? {} : { error: err instanceof Error ? err.message : String(err) }
|
|
12500
12531
|
}));
|
|
12501
12532
|
} finally {
|
|
@@ -15059,6 +15090,7 @@ data: ${watchLimitReached}
|
|
|
15059
15090
|
return text("not found", 404);
|
|
15060
15091
|
}
|
|
15061
15092
|
});
|
|
15093
|
+
listenPort = server.port;
|
|
15062
15094
|
if (openAfterStart) {
|
|
15063
15095
|
openBrowser(`http://127.0.0.1:${server.port}/`);
|
|
15064
15096
|
}
|