@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.
@@ -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: `OK (${services.length} services)`
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 guarded by an inactive profile or overridden by a sibling compose file."
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: a ? a.row_count : 0,
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: b.row_count,
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
- for (const container of containers) {
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, (table, done) => {
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
- table,
12467
- done
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youtyan/code-viewer",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Local browser-based code and git diff viewer",
5
5
  "type": "module",
6
6
  "bin": {