@kubb/studio 5.10.2 → 5.10.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.cjs CHANGED
@@ -178,7 +178,7 @@ function getElapsedMs(hrStart) {
178
178
  }
179
179
  //#endregion
180
180
  //#region package.json
181
- var version = "5.10.2";
181
+ var version = "5.10.3";
182
182
  //#endregion
183
183
  //#region src/resolveConfig.ts
184
184
  /**
@@ -1179,33 +1179,154 @@ async function writeConfigEdits({ filePath, edits, extensions }) {
1179
1179
  //#endregion
1180
1180
  //#region src/diff.ts
1181
1181
  const CONTEXT_LINES = 3;
1182
- const DIFF_TIMEOUT_MS = 1e4;
1183
- function diffHunks(before, after) {
1184
- return new Promise((resolve) => {
1185
- (0, diff.structuredPatch)("", "", before, after, void 0, void 0, {
1182
+ const DIFF_TIMEOUT_MS = 1e3;
1183
+ const splitLines = (text) => text === "" ? [] : text.split(/(?<=\n)/);
1184
+ function longestIncreasing(values) {
1185
+ const tails = [];
1186
+ const prev = [];
1187
+ for (const [index, value] of values.entries()) {
1188
+ let low = 0;
1189
+ let high = tails.length;
1190
+ while (low < high) {
1191
+ const mid = low + high >> 1;
1192
+ if (values[tails[mid]] < value) low = mid + 1;
1193
+ else high = mid;
1194
+ }
1195
+ prev[index] = low > 0 ? tails[low - 1] : -1;
1196
+ tails[low] = index;
1197
+ }
1198
+ const result = [];
1199
+ for (let index = tails.at(-1) ?? -1; index !== -1; index = prev[index]) result.push(index);
1200
+ return result.reverse();
1201
+ }
1202
+ function cutPoints(before, after) {
1203
+ const counts = /* @__PURE__ */ new Map();
1204
+ for (const [index, line] of before.entries()) {
1205
+ const count = counts.get(line);
1206
+ if (count) count.before++;
1207
+ else counts.set(line, {
1208
+ before: 1,
1209
+ after: 0,
1210
+ index
1211
+ });
1212
+ }
1213
+ const afterIndex = /* @__PURE__ */ new Map();
1214
+ for (const [index, line] of after.entries()) {
1215
+ const count = counts.get(line);
1216
+ if (!count) continue;
1217
+ count.after++;
1218
+ afterIndex.set(line, index);
1219
+ }
1220
+ const unique = [...counts].filter(([, count]) => count.before === 1 && count.after === 1).map(([line, count]) => [count.index, afterIndex.get(line)]);
1221
+ const anchors = longestIncreasing(unique.map(([, index]) => index)).map((index) => unique[index]);
1222
+ const cuts = [[0, 0]];
1223
+ let run = {
1224
+ before: 0,
1225
+ after: 0,
1226
+ length: 0
1227
+ };
1228
+ const closeRun = () => {
1229
+ if (run.length > 6) cuts.push([run.before + CONTEXT_LINES, run.after + CONTEXT_LINES]);
1230
+ };
1231
+ let i = 0;
1232
+ let j = 0;
1233
+ for (const [anchorBefore, anchorAfter] of anchors) {
1234
+ const unchanged = anchorBefore - i === anchorAfter - j && before.slice(i, anchorBefore).every((line, offset) => line === after[j + offset]);
1235
+ if (unchanged && run.length && run.before + run.length === i) run.length += anchorBefore - i + 1;
1236
+ else {
1237
+ closeRun();
1238
+ run = unchanged ? {
1239
+ before: i,
1240
+ after: j,
1241
+ length: anchorBefore - i + 1
1242
+ } : {
1243
+ before: anchorBefore,
1244
+ after: anchorAfter,
1245
+ length: 1
1246
+ };
1247
+ }
1248
+ i = anchorBefore + 1;
1249
+ j = anchorAfter + 1;
1250
+ }
1251
+ closeRun();
1252
+ cuts.push([before.length, after.length]);
1253
+ return cuts;
1254
+ }
1255
+ function replaceHunk(before, after) {
1256
+ let start = 0;
1257
+ while (start < before.length && start < after.length && before[start] === after[start]) start++;
1258
+ let end = 0;
1259
+ while (end < before.length - start && end < after.length - start && before[before.length - 1 - end] === after[after.length - 1 - end]) end++;
1260
+ const removed = before.slice(start, before.length - end);
1261
+ const added = after.slice(start, after.length - end);
1262
+ if (!removed.length && !added.length) return [];
1263
+ const lines = (prefix, rows) => rows.flatMap((row) => row.endsWith("\n") ? [`${prefix}${row.slice(0, -1)}`] : [`${prefix}${row}`, "\"]);
1264
+ return [{
1265
+ oldStart: start + 1,
1266
+ oldLines: removed.length,
1267
+ newStart: start + 1,
1268
+ newLines: added.length,
1269
+ lines: [...lines("-", removed), ...lines("+", added)]
1270
+ }];
1271
+ }
1272
+ function diffHunks(before, after, timeout = DIFF_TIMEOUT_MS) {
1273
+ const beforeLines = splitLines(before);
1274
+ const afterLines = splitLines(after);
1275
+ const cuts = cutPoints(beforeLines, afterLines);
1276
+ const deadline = Date.now() + timeout;
1277
+ const hunks = [];
1278
+ let coarse = false;
1279
+ for (const [index, [beforeStart, afterStart]] of cuts.slice(0, -1).entries()) {
1280
+ const [beforeEnd, afterEnd] = cuts[index + 1];
1281
+ const segmentBefore = beforeLines.slice(beforeStart, beforeEnd);
1282
+ const segmentAfter = afterLines.slice(afterStart, afterEnd);
1283
+ const patch = (0, diff.structuredPatch)("", "", segmentBefore.join(""), segmentAfter.join(""), void 0, void 0, {
1186
1284
  context: CONTEXT_LINES,
1187
- timeout: DIFF_TIMEOUT_MS,
1188
- callback: (patch) => resolve(patch?.hunks)
1285
+ timeout: Math.max(0, deadline - Date.now())
1189
1286
  });
1190
- });
1287
+ if (!patch) coarse = true;
1288
+ for (const hunk of patch?.hunks ?? replaceHunk(segmentBefore, segmentAfter)) hunks.push({
1289
+ ...hunk,
1290
+ oldStart: hunk.oldStart + beforeStart,
1291
+ newStart: hunk.newStart + afterStart
1292
+ });
1293
+ }
1294
+ const lines = hunks.flatMap((hunk) => hunk.lines);
1295
+ return {
1296
+ hunks,
1297
+ stats: {
1298
+ additions: lines.filter((line) => line[0] === "+").length,
1299
+ deletions: lines.filter((line) => line[0] === "-").length,
1300
+ hunks: hunks.length,
1301
+ lines: lines.length,
1302
+ coarse
1303
+ }
1304
+ };
1191
1305
  }
1192
1306
  function pageHunks({ hunks, cursor, limit }) {
1193
1307
  const page = [];
1194
- const end = cursor + limit;
1308
+ let used = 0;
1195
1309
  let start = 0;
1196
1310
  for (const [index, hunk] of hunks.entries()) {
1197
- const next = start + hunk.lines.length;
1198
- if (next > cursor && start < end) page.push({
1311
+ const offset = Math.max(0, cursor - start);
1312
+ start += hunk.lines.length;
1313
+ const remaining = hunk.lines.length - offset;
1314
+ if (remaining <= 0) continue;
1315
+ if (used > 0 && remaining > limit - used) break;
1316
+ let take = Math.min(remaining, limit - used);
1317
+ if (hunk.lines[offset + take]?.startsWith("\\")) take++;
1318
+ page.push({
1199
1319
  index,
1200
- oldStart: hunk.oldStart,
1201
- newStart: hunk.newStart,
1202
- lines: hunk.lines.slice(Math.max(0, cursor - start), end - start)
1320
+ ...hunk,
1321
+ lines: hunk.lines.slice(offset, offset + take)
1203
1322
  });
1204
- start = next;
1323
+ used += take;
1324
+ if (used >= limit) break;
1205
1325
  }
1326
+ const total = hunks.reduce((sum, hunk) => sum + hunk.lines.length, 0);
1206
1327
  return {
1207
1328
  hunks: page,
1208
- nextCursor: end < start ? end : null
1329
+ nextCursor: cursor + used < total ? cursor + used : null
1209
1330
  };
1210
1331
  }
1211
1332
  //#endregion
@@ -1441,7 +1562,7 @@ function createGenerationStore({ storage, maxCount, maxMb, ttlMs, now = Date.now
1441
1562
  //#region src/generationEvents.ts
1442
1563
  const MAX_QUEUED_EVENTS = 1024;
1443
1564
  const RESERVED_EVENTS = 64;
1444
- const isDiscardable = (event) => event.type === "kubb:files:processing:update" || event.type === "kubb:info" || event.type === "kubb:success";
1565
+ const isDiscardable = (type) => type === "kubb:files:processing:update" || type === "kubb:info" || type === "kubb:success";
1445
1566
  /** Forwards selected Kubb lifecycle events to a native Cap'n Web stream. */
1446
1567
  function createGenerationStream(hooks, jobId) {
1447
1568
  const unhooks = [];
@@ -1473,7 +1594,7 @@ function createGenerationStream(hooks, jobId) {
1473
1594
  version: 1,
1474
1595
  timestamp: Date.now()
1475
1596
  };
1476
- if (controller.desiredSize <= RESERVED_EVENTS && isDiscardable(event)) return;
1597
+ if (controller.desiredSize <= RESERVED_EVENTS && isDiscardable(type)) return;
1477
1598
  if (controller.desiredSize <= 0) {
1478
1599
  fail(/* @__PURE__ */ new Error(`Generation event stream exceeded ${MAX_QUEUED_EVENTS} queued events`));
1479
1600
  return;
@@ -1577,7 +1698,10 @@ function createGenerationStream(hooks, jobId) {
1577
1698
  }]
1578
1699
  };
1579
1700
  function forward(type) {
1580
- on(type, (...args) => emitEvent(type, projections[type](...args)));
1701
+ on(type, (...args) => {
1702
+ emitEvent(type, projections[type](...args));
1703
+ if (!isDiscardable(type)) return new Promise((resolve) => setImmediate(resolve));
1704
+ });
1581
1705
  }
1582
1706
  on("kubb:build:start", ({ config }) => {
1583
1707
  root = config.root;
@@ -2087,7 +2211,14 @@ var Agent = class extends capnweb.RpcTarget {
2087
2211
  if (beforeContent === void 0) return {
2088
2212
  hunks: [],
2089
2213
  nextCursor: null,
2090
- hasBase: false
2214
+ hasBase: false,
2215
+ stats: {
2216
+ additions: 0,
2217
+ deletions: 0,
2218
+ hunks: 0,
2219
+ lines: 0,
2220
+ coarse: false
2221
+ }
2091
2222
  };
2092
2223
  const key = JSON.stringify([
2093
2224
  jobId,
@@ -2095,25 +2226,21 @@ var Agent = class extends capnweb.RpcTarget {
2095
2226
  baseSource,
2096
2227
  path
2097
2228
  ]);
2098
- let hunks = this.#diffs.get(key);
2099
- if (!hunks) {
2100
- hunks = diffHunks(beforeContent, afterContent ?? "");
2101
- this.#diffs.set(key, hunks);
2229
+ let diff = this.#diffs.get(key);
2230
+ if (!diff) {
2231
+ diff = diffHunks(beforeContent, afterContent ?? "");
2232
+ this.#diffs.set(key, diff);
2102
2233
  if (this.#diffs.size > 4) this.#diffs.delete(this.#diffs.keys().next().value);
2103
2234
  }
2104
- const all = await hunks;
2105
- if (!all) {
2106
- this.#diffs.delete(key);
2107
- return this.#refuse({ message: "The two versions differ too much to diff" });
2108
- }
2109
2235
  await this.#logCommand("readDiff", `read the diff of ${path}`);
2110
2236
  return {
2111
2237
  ...pageHunks({
2112
- hunks: all,
2238
+ hunks: diff.hunks,
2113
2239
  cursor,
2114
2240
  limit
2115
2241
  }),
2116
- hasBase: true
2242
+ hasBase: true,
2243
+ stats: diff.stats
2117
2244
  };
2118
2245
  }
2119
2246
  };