gitifact 0.6.0 → 0.6.1
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/browser/assets/Grid-BgyoU_D4.js +1 -0
- package/dist/browser/assets/{Markdown-Bc6pMi97.js → Markdown-d1SaIOZk.js} +1 -1
- package/dist/browser/assets/{MetadataListItem-BjA4nmg3.js → MetadataListItem-BTW_ggUY.js} +1 -1
- package/dist/browser/assets/Table-7eL9Hctc.js +3 -0
- package/dist/browser/assets/about-Dyn0BeO0.js +3 -0
- package/dist/browser/assets/{activity-BF4_xkCU.js → activity-Cgw5nLJm.js} +1 -1
- package/dist/browser/assets/appearance-DgDbwXAm.js +1 -0
- package/dist/browser/assets/changelog-DjXt1_80.js +2 -0
- package/dist/browser/assets/{contributors._email-C99eiup4.js → contributors._email-BNMR_dTN.js} +1 -1
- package/dist/browser/assets/{contributors.index-BzPuT_XG.js → contributors.index-G5f2IyP0.js} +1 -1
- package/dist/browser/assets/document-Dx4gYX9t.js +11 -0
- package/dist/browser/assets/{features._featureId-BVMBUbIc.js → features._featureId-BazwZKuA.js} +1 -1
- package/dist/browser/assets/{features.index-DAF_MoVe.js → features.index-BJB0VCMw.js} +1 -1
- package/dist/browser/assets/git-CuSufflq.js +1 -0
- package/dist/browser/assets/{index-CiEgP5lo.css → index-BSZEm1y4.css} +1 -1
- package/dist/browser/assets/index-Cgka-Zmz.js +48 -0
- package/dist/browser/assets/page-header-BxP70prH.js +124 -0
- package/dist/browser/assets/page-header-ClRsIf4A.css +1 -0
- package/dist/browser/assets/product-DLraSF3D.css +1 -0
- package/dist/browser/assets/product-Df-TRcl5.js +8 -0
- package/dist/browser/assets/{product.index-Fb5sQw1w.js → product.index-68tq-tnH.js} +1 -1
- package/dist/browser/assets/request-state-BR8vtOZQ.js +1 -0
- package/dist/browser/assets/{requirements-DGx4_rNJ.js → requirements-C6bYGbsR.js} +1 -1
- package/dist/browser/assets/settings-DHKMQuFF.js +1 -0
- package/dist/browser/assets/{wiki-k4dXogJF.js → wiki-C-iMsNey.js} +1 -1
- package/dist/browser/index.html +13 -13
- package/dist/i18n/ko/changelog.md +17 -0
- package/dist/main.js +1327 -696
- package/package.json +3 -3
- package/dist/browser/assets/Grid-C9rNT-fL.js +0 -1
- package/dist/browser/assets/Table-DodMTw3P.js +0 -3
- package/dist/browser/assets/about-CmwTK0Rl.js +0 -3
- package/dist/browser/assets/appearance-pAOSjMU4.js +0 -1
- package/dist/browser/assets/changelog-Dm-wCZt4.js +0 -2
- package/dist/browser/assets/document-DcPjYojg.js +0 -11
- package/dist/browser/assets/git-CuBxy8Rl.js +0 -1
- package/dist/browser/assets/index-w5oyNndb.js +0 -48
- package/dist/browser/assets/page-header-DPWfThZo.js +0 -124
- package/dist/browser/assets/page-header-DZvVAckA.css +0 -1
- package/dist/browser/assets/product-BR5KVGuJ.css +0 -1
- package/dist/browser/assets/product-BmoIKtGm.js +0 -8
- package/dist/browser/assets/request-state-B7pKmdbJ.js +0 -1
- package/dist/browser/assets/settings-5JQQOYMj.js +0 -1
package/dist/main.js
CHANGED
|
@@ -4205,11 +4205,11 @@ function parseChangelog(text2) {
|
|
|
4205
4205
|
let previous;
|
|
4206
4206
|
let entry2;
|
|
4207
4207
|
let section;
|
|
4208
|
-
const
|
|
4208
|
+
const fail9 = (line, key, values = {}) => new InitError("INVALID_CHANGELOG", t("changelog.atLine", { line, reason: t(key, values) }));
|
|
4209
4209
|
const lines = text2.replace(/\r\n/g, "\n").split("\n");
|
|
4210
4210
|
const close = (line) => {
|
|
4211
4211
|
if (entry2 && changelogSections.every((name) => entry2[name].length === 0))
|
|
4212
|
-
throw
|
|
4212
|
+
throw fail9(line, "changelog.emptyVersion", { version: entry2.version });
|
|
4213
4213
|
};
|
|
4214
4214
|
lines.forEach((raw, index) => {
|
|
4215
4215
|
const line = index + 1;
|
|
@@ -4220,9 +4220,9 @@ function parseChangelog(text2) {
|
|
|
4220
4220
|
close(line);
|
|
4221
4221
|
const core = [Number(version2[1]), Number(version2[2]), Number(version2[3])];
|
|
4222
4222
|
if (!realDate(Number(version2[4]), Number(version2[5]), Number(version2[6])))
|
|
4223
|
-
throw
|
|
4223
|
+
throw fail9(line, "changelog.invalidDate", { text: raw });
|
|
4224
4224
|
if (previous && !(core[0] < previous[0] || core[0] === previous[0] && (core[1] < previous[1] || core[1] === previous[1] && core[2] < previous[2]))) {
|
|
4225
|
-
throw
|
|
4225
|
+
throw fail9(line, "changelog.order", { version: core.join(".") });
|
|
4226
4226
|
}
|
|
4227
4227
|
previous = core;
|
|
4228
4228
|
section = void 0;
|
|
@@ -4233,25 +4233,25 @@ function parseChangelog(text2) {
|
|
|
4233
4233
|
const heading = sectionLine.exec(raw);
|
|
4234
4234
|
if (heading) {
|
|
4235
4235
|
if (!entry2)
|
|
4236
|
-
throw
|
|
4236
|
+
throw fail9(line, "changelog.sectionBeforeVersion");
|
|
4237
4237
|
const name = heading[1].toLowerCase();
|
|
4238
4238
|
if (entry2[name].length > 0)
|
|
4239
|
-
throw
|
|
4239
|
+
throw fail9(line, "changelog.duplicateSection", { section: heading[1] });
|
|
4240
4240
|
section = name;
|
|
4241
4241
|
return;
|
|
4242
4242
|
}
|
|
4243
4243
|
const item = itemLine.exec(raw);
|
|
4244
4244
|
if (item) {
|
|
4245
4245
|
if (!entry2 || !section)
|
|
4246
|
-
throw
|
|
4246
|
+
throw fail9(line, "changelog.itemOutsideSection");
|
|
4247
4247
|
entry2[section].push(item[1].trimEnd());
|
|
4248
4248
|
return;
|
|
4249
4249
|
}
|
|
4250
|
-
throw
|
|
4250
|
+
throw fail9(line, "changelog.unknownLine", { text: raw });
|
|
4251
4251
|
});
|
|
4252
4252
|
close(lines.length);
|
|
4253
4253
|
if (entries.length === 0)
|
|
4254
|
-
throw
|
|
4254
|
+
throw fail9(1, "changelog.noVersions");
|
|
4255
4255
|
return entries;
|
|
4256
4256
|
}
|
|
4257
4257
|
|
|
@@ -4591,10 +4591,10 @@ function decodeGitLine(buffer) {
|
|
|
4591
4591
|
if (!value || value.includes("\0")) return invalid();
|
|
4592
4592
|
return value;
|
|
4593
4593
|
}
|
|
4594
|
-
function fieldsAndPath(record3,
|
|
4594
|
+
function fieldsAndPath(record3, count2) {
|
|
4595
4595
|
const fields2 = [];
|
|
4596
4596
|
let start = 0;
|
|
4597
|
-
for (let index = 0; index <
|
|
4597
|
+
for (let index = 0; index < count2; index++) {
|
|
4598
4598
|
const end = record3.indexOf(" ", start);
|
|
4599
4599
|
if (end <= start) return invalid();
|
|
4600
4600
|
fields2.push(record3.slice(start, end));
|
|
@@ -4645,7 +4645,7 @@ function parsePorcelain(buffer, format) {
|
|
|
4645
4645
|
const modes = fields2.slice(3, conflict ? 7 : 6);
|
|
4646
4646
|
if (modes.some((mode) => !/^(000000|100644|100755|120000|160000)$/.test(mode))) return invalid();
|
|
4647
4647
|
const oids = fields2.slice(conflict ? 7 : 6);
|
|
4648
|
-
if (oids.some((
|
|
4648
|
+
if (oids.some((oid3) => !oidPattern.test(oid3))) return invalid();
|
|
4649
4649
|
change2 = { kind: conflict ? "unmerged" : "tracked", path: path3, xy, submodule: submodule(fields2[2]) };
|
|
4650
4650
|
} else return invalid();
|
|
4651
4651
|
if (seen.has(change2.path)) return invalid();
|
|
@@ -6023,14 +6023,14 @@ function codePointLength(str) {
|
|
|
6023
6023
|
const units = str.length;
|
|
6024
6024
|
if (!highSurrogate.test(str))
|
|
6025
6025
|
return units;
|
|
6026
|
-
let
|
|
6026
|
+
let count2 = units;
|
|
6027
6027
|
for (let i = 0; i < units - 1; i++) {
|
|
6028
6028
|
if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
|
|
6029
|
-
|
|
6029
|
+
count2--;
|
|
6030
6030
|
i++;
|
|
6031
6031
|
}
|
|
6032
6032
|
}
|
|
6033
|
-
return
|
|
6033
|
+
return count2;
|
|
6034
6034
|
}
|
|
6035
6035
|
function getLengthableOrigin(input2) {
|
|
6036
6036
|
if (Array.isArray(input2))
|
|
@@ -8571,16 +8571,16 @@ var $ZodUnion = /* @__PURE__ */ $constructor("$ZodUnion", (inst, def) => {
|
|
|
8571
8571
|
};
|
|
8572
8572
|
});
|
|
8573
8573
|
function handleExclusiveUnionResults(results, final, inst, ctx) {
|
|
8574
|
-
const
|
|
8574
|
+
const matches2 = [];
|
|
8575
8575
|
for (let i = 0; i < results.length; i++) {
|
|
8576
8576
|
if (results[i].issues.length === 0)
|
|
8577
|
-
|
|
8577
|
+
matches2.push(i);
|
|
8578
8578
|
}
|
|
8579
|
-
if (
|
|
8580
|
-
final.value = results[
|
|
8579
|
+
if (matches2.length === 1) {
|
|
8580
|
+
final.value = results[matches2[0]].value;
|
|
8581
8581
|
return final;
|
|
8582
8582
|
}
|
|
8583
|
-
if (
|
|
8583
|
+
if (matches2.length === 0) {
|
|
8584
8584
|
final.issues.push({
|
|
8585
8585
|
code: "invalid_union",
|
|
8586
8586
|
input: final.value,
|
|
@@ -8594,7 +8594,7 @@ function handleExclusiveUnionResults(results, final, inst, ctx) {
|
|
|
8594
8594
|
inst,
|
|
8595
8595
|
errors: [],
|
|
8596
8596
|
inclusive: false,
|
|
8597
|
-
matches
|
|
8597
|
+
matches: matches2
|
|
8598
8598
|
});
|
|
8599
8599
|
}
|
|
8600
8600
|
return final;
|
|
@@ -10385,8 +10385,8 @@ function az_default() {
|
|
|
10385
10385
|
}
|
|
10386
10386
|
|
|
10387
10387
|
// ../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/locales/be.js
|
|
10388
|
-
function getBelarusianPlural(
|
|
10389
|
-
const absCount = Math.abs(
|
|
10388
|
+
function getBelarusianPlural(count2, one, few, many) {
|
|
10389
|
+
const absCount = Math.abs(count2);
|
|
10390
10390
|
const lastDigit = absCount % 10;
|
|
10391
10391
|
const lastTwoDigits = absCount % 100;
|
|
10392
10392
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -13033,8 +13033,8 @@ function hu_default() {
|
|
|
13033
13033
|
}
|
|
13034
13034
|
|
|
13035
13035
|
// ../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/locales/hy.js
|
|
13036
|
-
function getArmenianPlural(
|
|
13037
|
-
return Math.abs(
|
|
13036
|
+
function getArmenianPlural(count2, one, many) {
|
|
13037
|
+
return Math.abs(count2) === 1 ? one : many;
|
|
13038
13038
|
}
|
|
13039
13039
|
function withDefiniteArticle(word) {
|
|
13040
13040
|
if (!word)
|
|
@@ -15772,8 +15772,8 @@ function ro_default() {
|
|
|
15772
15772
|
}
|
|
15773
15773
|
|
|
15774
15774
|
// ../../node_modules/.pnpm/zod@4.6.4/node_modules/zod/v4/locales/ru.js
|
|
15775
|
-
function getRussianPlural(
|
|
15776
|
-
const absCount = Math.abs(
|
|
15775
|
+
function getRussianPlural(count2, one, few, many) {
|
|
15776
|
+
const absCount = Math.abs(count2);
|
|
15777
15777
|
const lastDigit = absCount % 10;
|
|
15778
15778
|
const lastTwoDigits = absCount % 100;
|
|
15779
15779
|
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
@@ -20407,13 +20407,13 @@ function initializeContext(params) {
|
|
|
20407
20407
|
external: params?.external ?? void 0
|
|
20408
20408
|
};
|
|
20409
20409
|
}
|
|
20410
|
-
function handleUnrepresentable(schema, ctx,
|
|
20410
|
+
function handleUnrepresentable(schema, ctx, json3, params, message) {
|
|
20411
20411
|
const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({ zodSchema: schema, path: params.path, message }) : ctx.unrepresentable;
|
|
20412
20412
|
if (result === "any")
|
|
20413
20413
|
return false;
|
|
20414
20414
|
if (result === void 0 || result === "throw")
|
|
20415
20415
|
throw new Error(message);
|
|
20416
|
-
Object.assign(
|
|
20416
|
+
Object.assign(json3, result);
|
|
20417
20417
|
return true;
|
|
20418
20418
|
}
|
|
20419
20419
|
function processSchema(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
@@ -20649,12 +20649,12 @@ function foldObjects(members2) {
|
|
|
20649
20649
|
}
|
|
20650
20650
|
return folded;
|
|
20651
20651
|
}
|
|
20652
|
-
function foldIntersection(
|
|
20653
|
-
const allOf =
|
|
20652
|
+
function foldIntersection(json3) {
|
|
20653
|
+
const allOf = json3.allOf;
|
|
20654
20654
|
if (!Array.isArray(allOf) || allOf.length < 2)
|
|
20655
20655
|
return;
|
|
20656
20656
|
for (const key of FOLDABLE_KEYS)
|
|
20657
|
-
if (key in
|
|
20657
|
+
if (key in json3)
|
|
20658
20658
|
return;
|
|
20659
20659
|
const unions = allOf.filter((m) => UNION_KEYS.some((k) => Array.isArray(m[k])));
|
|
20660
20660
|
let folded = null;
|
|
@@ -20673,8 +20673,8 @@ function foldIntersection(json2) {
|
|
|
20673
20673
|
}
|
|
20674
20674
|
if (!folded)
|
|
20675
20675
|
return;
|
|
20676
|
-
delete
|
|
20677
|
-
assignProps(
|
|
20676
|
+
delete json3.allOf;
|
|
20677
|
+
assignProps(json3, folded);
|
|
20678
20678
|
}
|
|
20679
20679
|
function finalize(ctx, schema) {
|
|
20680
20680
|
const root = ctx.seen.get(schema);
|
|
@@ -20756,20 +20756,20 @@ function finalize(ctx, schema) {
|
|
|
20756
20756
|
if (ctx.intersections.length) {
|
|
20757
20757
|
const carriers = /* @__PURE__ */ new Map();
|
|
20758
20758
|
for (const seen of ctx.seen.values()) {
|
|
20759
|
-
for (const
|
|
20760
|
-
const allOf =
|
|
20759
|
+
for (const json3 of [seen.schema, seen.def]) {
|
|
20760
|
+
const allOf = json3?.allOf;
|
|
20761
20761
|
if (!Array.isArray(allOf))
|
|
20762
20762
|
continue;
|
|
20763
20763
|
const existing = carriers.get(allOf);
|
|
20764
20764
|
if (existing)
|
|
20765
|
-
existing.push(
|
|
20765
|
+
existing.push(json3);
|
|
20766
20766
|
else
|
|
20767
|
-
carriers.set(allOf, [
|
|
20767
|
+
carriers.set(allOf, [json3]);
|
|
20768
20768
|
}
|
|
20769
20769
|
}
|
|
20770
20770
|
for (const allOf of ctx.intersections) {
|
|
20771
|
-
for (const
|
|
20772
|
-
foldIntersection(
|
|
20771
|
+
for (const json3 of carriers.get(allOf) ?? [])
|
|
20772
|
+
foldIntersection(json3);
|
|
20773
20773
|
}
|
|
20774
20774
|
}
|
|
20775
20775
|
}
|
|
@@ -21004,29 +21004,29 @@ var exactPatterns = /* @__PURE__ */ new Map([
|
|
|
21004
21004
|
]);
|
|
21005
21005
|
var exactPattern = (p) => exactPatterns.get(p) ?? p;
|
|
21006
21006
|
var stringProcessor = (schema, ctx, _json, _params) => {
|
|
21007
|
-
const
|
|
21008
|
-
|
|
21007
|
+
const json3 = _json;
|
|
21008
|
+
json3.type = "string";
|
|
21009
21009
|
const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);
|
|
21010
21010
|
if (typeof minimum === "number")
|
|
21011
|
-
|
|
21011
|
+
json3.minLength = minimum;
|
|
21012
21012
|
if (typeof maximum === "number")
|
|
21013
|
-
|
|
21013
|
+
json3.maxLength = maximum;
|
|
21014
21014
|
if (format) {
|
|
21015
|
-
|
|
21016
|
-
if (
|
|
21017
|
-
delete
|
|
21015
|
+
json3.format = formatMap[format] ?? format;
|
|
21016
|
+
if (json3.format === "")
|
|
21017
|
+
delete json3.format;
|
|
21018
21018
|
if (format === "time" || laxFormat) {
|
|
21019
|
-
delete
|
|
21019
|
+
delete json3.format;
|
|
21020
21020
|
}
|
|
21021
21021
|
}
|
|
21022
21022
|
if (contentEncoding)
|
|
21023
|
-
|
|
21023
|
+
json3.contentEncoding = contentEncoding;
|
|
21024
21024
|
if (patterns && patterns.size > 0) {
|
|
21025
21025
|
const patternList = [...patterns].map(exactPattern);
|
|
21026
21026
|
if (patternList.length === 1)
|
|
21027
|
-
|
|
21027
|
+
json3.pattern = patternList[0].source;
|
|
21028
21028
|
else if (patternList.length > 1) {
|
|
21029
|
-
|
|
21029
|
+
json3.allOf = [
|
|
21030
21030
|
...patternList.map((regex) => ({
|
|
21031
21031
|
...ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0" ? { type: "string" } : {},
|
|
21032
21032
|
pattern: regex.source
|
|
@@ -21036,31 +21036,31 @@ var stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
21036
21036
|
}
|
|
21037
21037
|
};
|
|
21038
21038
|
var numberProcessor = (schema, ctx, _json, params) => {
|
|
21039
|
-
const
|
|
21039
|
+
const json3 = _json;
|
|
21040
21040
|
const { minimum, maximum, multipleOf, exclusiveMaximum, exclusiveMinimum, isInt } = aggregateChecks(schema);
|
|
21041
|
-
|
|
21041
|
+
json3.type = isInt ? "integer" : "number";
|
|
21042
21042
|
const exMin = typeof exclusiveMinimum === "number" && exclusiveMinimum >= (minimum ?? Number.NEGATIVE_INFINITY);
|
|
21043
21043
|
const exMax = typeof exclusiveMaximum === "number" && exclusiveMaximum <= (maximum ?? Number.POSITIVE_INFINITY);
|
|
21044
21044
|
const legacy = ctx.target === "draft-04" || ctx.target === "openapi-3.0";
|
|
21045
21045
|
if (exMin) {
|
|
21046
21046
|
if (legacy) {
|
|
21047
|
-
|
|
21048
|
-
|
|
21047
|
+
json3.minimum = exclusiveMinimum;
|
|
21048
|
+
json3.exclusiveMinimum = true;
|
|
21049
21049
|
} else {
|
|
21050
|
-
|
|
21050
|
+
json3.exclusiveMinimum = exclusiveMinimum;
|
|
21051
21051
|
}
|
|
21052
21052
|
} else if (typeof minimum === "number") {
|
|
21053
|
-
|
|
21053
|
+
json3.minimum = minimum;
|
|
21054
21054
|
}
|
|
21055
21055
|
if (exMax) {
|
|
21056
21056
|
if (legacy) {
|
|
21057
|
-
|
|
21058
|
-
|
|
21057
|
+
json3.maximum = exclusiveMaximum;
|
|
21058
|
+
json3.exclusiveMaximum = true;
|
|
21059
21059
|
} else {
|
|
21060
|
-
|
|
21060
|
+
json3.exclusiveMaximum = exclusiveMaximum;
|
|
21061
21061
|
}
|
|
21062
21062
|
} else if (typeof maximum === "number") {
|
|
21063
|
-
|
|
21063
|
+
json3.maximum = maximum;
|
|
21064
21064
|
}
|
|
21065
21065
|
if (multipleOf) {
|
|
21066
21066
|
const divisors = /* @__PURE__ */ new Set();
|
|
@@ -21068,75 +21068,75 @@ var numberProcessor = (schema, ctx, _json, params) => {
|
|
|
21068
21068
|
if (Number.isFinite(divisor) && divisor !== 0)
|
|
21069
21069
|
divisors.add(Math.abs(divisor));
|
|
21070
21070
|
else
|
|
21071
|
-
handleUnrepresentable(schema, ctx,
|
|
21071
|
+
handleUnrepresentable(schema, ctx, json3, params, `A multipleOf divisor of ${divisor} cannot be represented in JSON Schema`);
|
|
21072
21072
|
}
|
|
21073
21073
|
const [first, ...rest] = divisors;
|
|
21074
21074
|
if (first !== void 0)
|
|
21075
|
-
|
|
21075
|
+
json3.multipleOf = first;
|
|
21076
21076
|
if (rest.length)
|
|
21077
|
-
|
|
21077
|
+
json3.allOf = [...json3.allOf ?? [], ...rest.map((m) => ({ multipleOf: m }))];
|
|
21078
21078
|
}
|
|
21079
21079
|
};
|
|
21080
|
-
var booleanProcessor = (_schema, _ctx,
|
|
21081
|
-
|
|
21080
|
+
var booleanProcessor = (_schema, _ctx, json3, _params) => {
|
|
21081
|
+
json3.type = "boolean";
|
|
21082
21082
|
};
|
|
21083
|
-
var bigintProcessor = (schema, ctx,
|
|
21084
|
-
handleUnrepresentable(schema, ctx,
|
|
21083
|
+
var bigintProcessor = (schema, ctx, json3, params) => {
|
|
21084
|
+
handleUnrepresentable(schema, ctx, json3, params, "BigInt cannot be represented in JSON Schema");
|
|
21085
21085
|
};
|
|
21086
|
-
var symbolProcessor = (schema, ctx,
|
|
21087
|
-
handleUnrepresentable(schema, ctx,
|
|
21086
|
+
var symbolProcessor = (schema, ctx, json3, params) => {
|
|
21087
|
+
handleUnrepresentable(schema, ctx, json3, params, "Symbols cannot be represented in JSON Schema");
|
|
21088
21088
|
};
|
|
21089
|
-
var nullProcessor = (_schema, ctx,
|
|
21089
|
+
var nullProcessor = (_schema, ctx, json3, _params) => {
|
|
21090
21090
|
if (ctx.target === "openapi-3.0") {
|
|
21091
|
-
|
|
21092
|
-
|
|
21093
|
-
|
|
21091
|
+
json3.type = "string";
|
|
21092
|
+
json3.nullable = true;
|
|
21093
|
+
json3.enum = [null];
|
|
21094
21094
|
} else {
|
|
21095
|
-
|
|
21095
|
+
json3.type = "null";
|
|
21096
21096
|
}
|
|
21097
21097
|
};
|
|
21098
|
-
var undefinedProcessor = (schema, ctx,
|
|
21099
|
-
handleUnrepresentable(schema, ctx,
|
|
21098
|
+
var undefinedProcessor = (schema, ctx, json3, params) => {
|
|
21099
|
+
handleUnrepresentable(schema, ctx, json3, params, "Undefined cannot be represented in JSON Schema");
|
|
21100
21100
|
};
|
|
21101
|
-
var voidProcessor = (schema, ctx,
|
|
21102
|
-
handleUnrepresentable(schema, ctx,
|
|
21101
|
+
var voidProcessor = (schema, ctx, json3, params) => {
|
|
21102
|
+
handleUnrepresentable(schema, ctx, json3, params, "Void cannot be represented in JSON Schema");
|
|
21103
21103
|
};
|
|
21104
|
-
var neverProcessor = (_schema, _ctx,
|
|
21105
|
-
|
|
21104
|
+
var neverProcessor = (_schema, _ctx, json3, _params) => {
|
|
21105
|
+
json3.not = {};
|
|
21106
21106
|
};
|
|
21107
21107
|
var anyProcessor = (_schema, _ctx, _json, _params) => {
|
|
21108
21108
|
};
|
|
21109
21109
|
var unknownProcessor = (_schema, _ctx, _json, _params) => {
|
|
21110
21110
|
};
|
|
21111
|
-
var dateProcessor = (schema, ctx,
|
|
21112
|
-
handleUnrepresentable(schema, ctx,
|
|
21111
|
+
var dateProcessor = (schema, ctx, json3, params) => {
|
|
21112
|
+
handleUnrepresentable(schema, ctx, json3, params, "Date cannot be represented in JSON Schema");
|
|
21113
21113
|
};
|
|
21114
|
-
var enumProcessor = (schema, _ctx,
|
|
21114
|
+
var enumProcessor = (schema, _ctx, json3, _params) => {
|
|
21115
21115
|
const def = schema._zod.def;
|
|
21116
21116
|
const values = getEnumValues(def.entries);
|
|
21117
21117
|
if (values.length === 0) {
|
|
21118
|
-
|
|
21118
|
+
json3.not = {};
|
|
21119
21119
|
return;
|
|
21120
21120
|
}
|
|
21121
21121
|
if (values.every((v) => typeof v === "number"))
|
|
21122
|
-
|
|
21122
|
+
json3.type = "number";
|
|
21123
21123
|
if (values.every((v) => typeof v === "string"))
|
|
21124
|
-
|
|
21125
|
-
|
|
21124
|
+
json3.type = "string";
|
|
21125
|
+
json3.enum = values;
|
|
21126
21126
|
};
|
|
21127
|
-
var literalProcessor = (schema, ctx,
|
|
21127
|
+
var literalProcessor = (schema, ctx, json3, params) => {
|
|
21128
21128
|
const def = schema._zod.def;
|
|
21129
21129
|
if (def.values.length === 0) {
|
|
21130
|
-
|
|
21130
|
+
json3.not = {};
|
|
21131
21131
|
return;
|
|
21132
21132
|
}
|
|
21133
21133
|
const vals = [];
|
|
21134
21134
|
for (const val of def.values) {
|
|
21135
21135
|
if (val === void 0) {
|
|
21136
|
-
if (handleUnrepresentable(schema, ctx,
|
|
21136
|
+
if (handleUnrepresentable(schema, ctx, json3, params, "Literal `undefined` cannot be represented in JSON Schema"))
|
|
21137
21137
|
return;
|
|
21138
21138
|
} else if (typeof val === "bigint") {
|
|
21139
|
-
if (handleUnrepresentable(schema, ctx,
|
|
21139
|
+
if (handleUnrepresentable(schema, ctx, json3, params, "BigInt literals cannot be represented in JSON Schema"))
|
|
21140
21140
|
return;
|
|
21141
21141
|
vals.push(Number(val));
|
|
21142
21142
|
} else {
|
|
@@ -21146,37 +21146,37 @@ var literalProcessor = (schema, ctx, json2, params) => {
|
|
|
21146
21146
|
if (vals.length === 0) {
|
|
21147
21147
|
} else if (vals.length === 1) {
|
|
21148
21148
|
const val = vals[0];
|
|
21149
|
-
|
|
21149
|
+
json3.type = val === null ? "null" : typeof val;
|
|
21150
21150
|
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
|
|
21151
|
-
|
|
21151
|
+
json3.enum = [val];
|
|
21152
21152
|
} else {
|
|
21153
|
-
|
|
21153
|
+
json3.const = val;
|
|
21154
21154
|
}
|
|
21155
21155
|
} else {
|
|
21156
21156
|
if (vals.every((v) => typeof v === "number"))
|
|
21157
|
-
|
|
21157
|
+
json3.type = "number";
|
|
21158
21158
|
if (vals.every((v) => typeof v === "string"))
|
|
21159
|
-
|
|
21159
|
+
json3.type = "string";
|
|
21160
21160
|
if (vals.every((v) => typeof v === "boolean"))
|
|
21161
|
-
|
|
21161
|
+
json3.type = "boolean";
|
|
21162
21162
|
if (vals.every((v) => v === null))
|
|
21163
|
-
|
|
21164
|
-
|
|
21163
|
+
json3.type = "null";
|
|
21164
|
+
json3.enum = vals;
|
|
21165
21165
|
}
|
|
21166
21166
|
};
|
|
21167
|
-
var nanProcessor = (schema, ctx,
|
|
21168
|
-
handleUnrepresentable(schema, ctx,
|
|
21167
|
+
var nanProcessor = (schema, ctx, json3, params) => {
|
|
21168
|
+
handleUnrepresentable(schema, ctx, json3, params, "NaN cannot be represented in JSON Schema");
|
|
21169
21169
|
};
|
|
21170
|
-
var templateLiteralProcessor = (schema, _ctx,
|
|
21171
|
-
const _json =
|
|
21170
|
+
var templateLiteralProcessor = (schema, _ctx, json3, _params) => {
|
|
21171
|
+
const _json = json3;
|
|
21172
21172
|
const pattern = schema._zod.pattern;
|
|
21173
21173
|
if (!pattern)
|
|
21174
21174
|
throw new Error("Pattern not found in template literal");
|
|
21175
21175
|
_json.type = "string";
|
|
21176
21176
|
_json.pattern = pattern.source;
|
|
21177
21177
|
};
|
|
21178
|
-
var fileProcessor = (schema, _ctx,
|
|
21179
|
-
const _json =
|
|
21178
|
+
var fileProcessor = (schema, _ctx, json3, _params) => {
|
|
21179
|
+
const _json = json3;
|
|
21180
21180
|
_json.type = "string";
|
|
21181
21181
|
_json.format = "binary";
|
|
21182
21182
|
_json.contentEncoding = "binary";
|
|
@@ -21194,34 +21194,34 @@ var fileProcessor = (schema, _ctx, json2, _params) => {
|
|
|
21194
21194
|
else
|
|
21195
21195
|
_json.anyOf = mime.map((m) => ({ contentMediaType: m }));
|
|
21196
21196
|
};
|
|
21197
|
-
var successProcessor = (_schema, _ctx,
|
|
21198
|
-
|
|
21197
|
+
var successProcessor = (_schema, _ctx, json3, _params) => {
|
|
21198
|
+
json3.type = "boolean";
|
|
21199
21199
|
};
|
|
21200
|
-
var customProcessor = (schema, ctx,
|
|
21201
|
-
handleUnrepresentable(schema, ctx,
|
|
21200
|
+
var customProcessor = (schema, ctx, json3, params) => {
|
|
21201
|
+
handleUnrepresentable(schema, ctx, json3, params, "Custom types cannot be represented in JSON Schema");
|
|
21202
21202
|
};
|
|
21203
|
-
var functionProcessor = (schema, ctx,
|
|
21204
|
-
handleUnrepresentable(schema, ctx,
|
|
21203
|
+
var functionProcessor = (schema, ctx, json3, params) => {
|
|
21204
|
+
handleUnrepresentable(schema, ctx, json3, params, "Function types cannot be represented in JSON Schema");
|
|
21205
21205
|
};
|
|
21206
|
-
var transformProcessor = (schema, ctx,
|
|
21207
|
-
handleUnrepresentable(schema, ctx,
|
|
21206
|
+
var transformProcessor = (schema, ctx, json3, params) => {
|
|
21207
|
+
handleUnrepresentable(schema, ctx, json3, params, "Transforms cannot be represented in JSON Schema");
|
|
21208
21208
|
};
|
|
21209
|
-
var mapProcessor = (schema, ctx,
|
|
21210
|
-
handleUnrepresentable(schema, ctx,
|
|
21209
|
+
var mapProcessor = (schema, ctx, json3, params) => {
|
|
21210
|
+
handleUnrepresentable(schema, ctx, json3, params, "Map cannot be represented in JSON Schema");
|
|
21211
21211
|
};
|
|
21212
|
-
var setProcessor = (schema, ctx,
|
|
21213
|
-
handleUnrepresentable(schema, ctx,
|
|
21212
|
+
var setProcessor = (schema, ctx, json3, params) => {
|
|
21213
|
+
handleUnrepresentable(schema, ctx, json3, params, "Set cannot be represented in JSON Schema");
|
|
21214
21214
|
};
|
|
21215
21215
|
var arrayProcessor = (schema, ctx, _json, params) => {
|
|
21216
|
-
const
|
|
21216
|
+
const json3 = _json;
|
|
21217
21217
|
const def = schema._zod.def;
|
|
21218
21218
|
const { minimum, maximum } = aggregateChecks(schema);
|
|
21219
21219
|
if (typeof minimum === "number")
|
|
21220
|
-
|
|
21220
|
+
json3.minItems = minimum;
|
|
21221
21221
|
if (typeof maximum === "number")
|
|
21222
|
-
|
|
21223
|
-
|
|
21224
|
-
|
|
21222
|
+
json3.maxItems = maximum;
|
|
21223
|
+
json3.type = "array";
|
|
21224
|
+
json3.items = processSchema(def.element, ctx, {
|
|
21225
21225
|
...params,
|
|
21226
21226
|
path: [...params.path, "items"]
|
|
21227
21227
|
});
|
|
@@ -21237,17 +21237,17 @@ function inputOptin(schema) {
|
|
|
21237
21237
|
return schema._zod.optin;
|
|
21238
21238
|
}
|
|
21239
21239
|
var objectProcessor = (schema, ctx, _json, params) => {
|
|
21240
|
-
const
|
|
21240
|
+
const json3 = _json;
|
|
21241
21241
|
const def = schema._zod.def;
|
|
21242
21242
|
const shape = def.shape;
|
|
21243
21243
|
const symbolKeys = Object.getOwnPropertySymbols(shape);
|
|
21244
|
-
if (symbolKeys.length && handleUnrepresentable(schema, ctx,
|
|
21244
|
+
if (symbolKeys.length && handleUnrepresentable(schema, ctx, json3, params, "Symbol keys cannot be represented in JSON Schema")) {
|
|
21245
21245
|
return;
|
|
21246
21246
|
}
|
|
21247
|
-
|
|
21248
|
-
|
|
21247
|
+
json3.type = "object";
|
|
21248
|
+
json3.properties = {};
|
|
21249
21249
|
for (const key in shape) {
|
|
21250
|
-
assignProp(
|
|
21250
|
+
assignProp(json3.properties, key, processSchema(shape[key], ctx, {
|
|
21251
21251
|
...params,
|
|
21252
21252
|
path: [...params.path, "properties", key]
|
|
21253
21253
|
}));
|
|
@@ -21260,21 +21260,21 @@ var objectProcessor = (schema, ctx, _json, params) => {
|
|
|
21260
21260
|
}
|
|
21261
21261
|
}
|
|
21262
21262
|
if (requiredKeys.length > 0) {
|
|
21263
|
-
|
|
21263
|
+
json3.required = requiredKeys;
|
|
21264
21264
|
}
|
|
21265
21265
|
if (def.catchall?._zod.def.type === "never") {
|
|
21266
|
-
|
|
21266
|
+
json3.additionalProperties = false;
|
|
21267
21267
|
} else if (!def.catchall) {
|
|
21268
21268
|
if (ctx.io === "output")
|
|
21269
|
-
|
|
21269
|
+
json3.additionalProperties = false;
|
|
21270
21270
|
} else if (def.catchall) {
|
|
21271
|
-
|
|
21271
|
+
json3.additionalProperties = processSchema(def.catchall, ctx, {
|
|
21272
21272
|
...params,
|
|
21273
21273
|
path: [...params.path, "additionalProperties"]
|
|
21274
21274
|
});
|
|
21275
21275
|
}
|
|
21276
21276
|
};
|
|
21277
|
-
var unionProcessor = (schema, ctx,
|
|
21277
|
+
var unionProcessor = (schema, ctx, json3, params) => {
|
|
21278
21278
|
const def = schema._zod.def;
|
|
21279
21279
|
const isExclusive = def.inclusive === false;
|
|
21280
21280
|
const options = def.options.map((x, i) => processSchema(x, ctx, {
|
|
@@ -21282,12 +21282,12 @@ var unionProcessor = (schema, ctx, json2, params) => {
|
|
|
21282
21282
|
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i]
|
|
21283
21283
|
}));
|
|
21284
21284
|
if (isExclusive) {
|
|
21285
|
-
|
|
21285
|
+
json3.oneOf = options;
|
|
21286
21286
|
} else {
|
|
21287
|
-
|
|
21287
|
+
json3.anyOf = options;
|
|
21288
21288
|
}
|
|
21289
21289
|
};
|
|
21290
|
-
var intersectionProcessor = (schema, ctx,
|
|
21290
|
+
var intersectionProcessor = (schema, ctx, json3, params) => {
|
|
21291
21291
|
const def = schema._zod.def;
|
|
21292
21292
|
const a = processSchema(def.left, ctx, {
|
|
21293
21293
|
...params,
|
|
@@ -21302,13 +21302,13 @@ var intersectionProcessor = (schema, ctx, json2, params) => {
|
|
|
21302
21302
|
...isSimpleIntersection(a) ? a.allOf : [a],
|
|
21303
21303
|
...isSimpleIntersection(b) ? b.allOf : [b]
|
|
21304
21304
|
];
|
|
21305
|
-
|
|
21305
|
+
json3.allOf = allOf;
|
|
21306
21306
|
ctx.intersections.push(allOf);
|
|
21307
21307
|
};
|
|
21308
21308
|
var tupleProcessor = (schema, ctx, _json, params) => {
|
|
21309
|
-
const
|
|
21309
|
+
const json3 = _json;
|
|
21310
21310
|
const def = schema._zod.def;
|
|
21311
|
-
|
|
21311
|
+
json3.type = "array";
|
|
21312
21312
|
const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
|
|
21313
21313
|
const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
|
|
21314
21314
|
const prefixItems = def.items.map((x, i) => processSchema(x, ctx, {
|
|
@@ -21330,70 +21330,70 @@ var tupleProcessor = (schema, ctx, _json, params) => {
|
|
|
21330
21330
|
const maxItems = def.items.length;
|
|
21331
21331
|
const isClosed = !def.rest;
|
|
21332
21332
|
if (ctx.target === "draft-2020-12") {
|
|
21333
|
-
|
|
21333
|
+
json3.prefixItems = prefixItems;
|
|
21334
21334
|
if (isClosed) {
|
|
21335
|
-
|
|
21335
|
+
json3.items = false;
|
|
21336
21336
|
} else if (rest) {
|
|
21337
|
-
|
|
21337
|
+
json3.items = rest;
|
|
21338
21338
|
}
|
|
21339
21339
|
if (minItems > 0)
|
|
21340
|
-
|
|
21340
|
+
json3.minItems = minItems;
|
|
21341
21341
|
if (isClosed)
|
|
21342
|
-
|
|
21342
|
+
json3.maxItems = maxItems;
|
|
21343
21343
|
} else if (ctx.target === "openapi-3.0") {
|
|
21344
|
-
|
|
21344
|
+
json3.items = {
|
|
21345
21345
|
anyOf: prefixItems
|
|
21346
21346
|
};
|
|
21347
21347
|
if (rest) {
|
|
21348
|
-
|
|
21348
|
+
json3.items.anyOf.push(rest);
|
|
21349
21349
|
}
|
|
21350
21350
|
if (minItems > 0)
|
|
21351
|
-
|
|
21351
|
+
json3.minItems = minItems;
|
|
21352
21352
|
if (isClosed)
|
|
21353
|
-
|
|
21353
|
+
json3.maxItems = maxItems;
|
|
21354
21354
|
} else {
|
|
21355
|
-
|
|
21355
|
+
json3.items = prefixItems;
|
|
21356
21356
|
if (isClosed) {
|
|
21357
|
-
|
|
21357
|
+
json3.additionalItems = false;
|
|
21358
21358
|
} else if (rest) {
|
|
21359
|
-
|
|
21359
|
+
json3.additionalItems = rest;
|
|
21360
21360
|
}
|
|
21361
21361
|
if (minItems > 0)
|
|
21362
|
-
|
|
21362
|
+
json3.minItems = minItems;
|
|
21363
21363
|
if (isClosed)
|
|
21364
|
-
|
|
21364
|
+
json3.maxItems = maxItems;
|
|
21365
21365
|
}
|
|
21366
21366
|
const { minimum, maximum } = aggregateChecks(schema);
|
|
21367
21367
|
if (typeof minimum === "number")
|
|
21368
|
-
|
|
21368
|
+
json3.minItems = minimum;
|
|
21369
21369
|
if (typeof maximum === "number")
|
|
21370
|
-
|
|
21370
|
+
json3.maxItems = maximum;
|
|
21371
21371
|
};
|
|
21372
|
-
function stringifyKeyNames(bySchema,
|
|
21373
|
-
if (
|
|
21374
|
-
if (visited.has(
|
|
21375
|
-
return
|
|
21376
|
-
visited.add(
|
|
21377
|
-
const def = bySchema.get(
|
|
21372
|
+
function stringifyKeyNames(bySchema, json3, visited) {
|
|
21373
|
+
if (json3.$ref) {
|
|
21374
|
+
if (visited.has(json3))
|
|
21375
|
+
return json3;
|
|
21376
|
+
visited.add(json3);
|
|
21377
|
+
const def = bySchema.get(json3)?.def;
|
|
21378
21378
|
if (!def)
|
|
21379
|
-
return
|
|
21379
|
+
return json3;
|
|
21380
21380
|
const inlined = stringifyKeyNames(bySchema, def, visited);
|
|
21381
|
-
return inlined === def ?
|
|
21381
|
+
return inlined === def ? json3 : inlined;
|
|
21382
21382
|
}
|
|
21383
21383
|
for (const keyword of ["anyOf", "oneOf"]) {
|
|
21384
|
-
const branches =
|
|
21384
|
+
const branches = json3[keyword];
|
|
21385
21385
|
if (!Array.isArray(branches))
|
|
21386
21386
|
continue;
|
|
21387
21387
|
const mapped = branches.map((branch) => stringifyKeyNames(bySchema, branch, visited));
|
|
21388
21388
|
if (mapped.some((branch, i) => branch !== branches[i]))
|
|
21389
|
-
|
|
21389
|
+
json3 = { ...json3, [keyword]: mapped };
|
|
21390
21390
|
}
|
|
21391
|
-
const types = Array.isArray(
|
|
21391
|
+
const types = Array.isArray(json3.type) ? json3.type : [json3.type];
|
|
21392
21392
|
const numericType = !types.includes("string") && types.some((t3) => t3 === "number" || t3 === "integer");
|
|
21393
|
-
const values =
|
|
21393
|
+
const values = json3.enum ?? (json3.const !== void 0 ? [json3.const] : void 0);
|
|
21394
21394
|
if (!numericType && !values?.some((v) => typeof v === "number"))
|
|
21395
|
-
return
|
|
21396
|
-
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } =
|
|
21395
|
+
return json3;
|
|
21396
|
+
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json3;
|
|
21397
21397
|
if (rest.enum)
|
|
21398
21398
|
rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
|
|
21399
21399
|
else if (typeof rest.const === "number")
|
|
@@ -21433,9 +21433,9 @@ function rewriteKeyNames(ctx) {
|
|
|
21433
21433
|
}
|
|
21434
21434
|
}
|
|
21435
21435
|
var recordProcessor = (schema, ctx, _json, params) => {
|
|
21436
|
-
const
|
|
21436
|
+
const json3 = _json;
|
|
21437
21437
|
const def = schema._zod.def;
|
|
21438
|
-
|
|
21438
|
+
json3.type = "object";
|
|
21439
21439
|
const keyType = def.keyType;
|
|
21440
21440
|
const patterns = aggregateChecks(keyType).patterns;
|
|
21441
21441
|
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
@@ -21443,13 +21443,13 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
21443
21443
|
...params,
|
|
21444
21444
|
path: [...params.path, "patternProperties", "*"]
|
|
21445
21445
|
});
|
|
21446
|
-
|
|
21446
|
+
json3.patternProperties = {};
|
|
21447
21447
|
for (const pattern of patterns) {
|
|
21448
|
-
assignProp(
|
|
21448
|
+
assignProp(json3.patternProperties, exactPattern(pattern).source, valueSchema);
|
|
21449
21449
|
}
|
|
21450
21450
|
} else {
|
|
21451
21451
|
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
21452
|
-
|
|
21452
|
+
json3.propertyNames = processSchema(def.keyType, ctx, {
|
|
21453
21453
|
...params,
|
|
21454
21454
|
path: [...params.path, "propertyNames"]
|
|
21455
21455
|
});
|
|
@@ -21461,7 +21461,7 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
21461
21461
|
}
|
|
21462
21462
|
pending.push(schema);
|
|
21463
21463
|
}
|
|
21464
|
-
|
|
21464
|
+
json3.additionalProperties = processSchema(def.valueType, ctx, {
|
|
21465
21465
|
...params,
|
|
21466
21466
|
path: [...params.path, "additionalProperties"]
|
|
21467
21467
|
});
|
|
@@ -21471,19 +21471,19 @@ var recordProcessor = (schema, ctx, _json, params) => {
|
|
|
21471
21471
|
if (keyValues && !def.partial && !omittableOnInput) {
|
|
21472
21472
|
const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
|
|
21473
21473
|
if (validKeyValues.length > 0) {
|
|
21474
|
-
|
|
21474
|
+
json3.required = validKeyValues.map(String);
|
|
21475
21475
|
}
|
|
21476
21476
|
}
|
|
21477
21477
|
};
|
|
21478
|
-
var nullableProcessor = (schema, ctx,
|
|
21478
|
+
var nullableProcessor = (schema, ctx, json3, params) => {
|
|
21479
21479
|
const def = schema._zod.def;
|
|
21480
21480
|
const inner = processSchema(def.innerType, ctx, params);
|
|
21481
21481
|
const seen = ctx.seen.get(schema);
|
|
21482
21482
|
if (ctx.target === "openapi-3.0") {
|
|
21483
21483
|
seen.ref = def.innerType;
|
|
21484
|
-
|
|
21484
|
+
json3.nullable = true;
|
|
21485
21485
|
} else {
|
|
21486
|
-
|
|
21486
|
+
json3.anyOf = [inner, { type: "null" }];
|
|
21487
21487
|
}
|
|
21488
21488
|
};
|
|
21489
21489
|
var nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
@@ -21493,7 +21493,7 @@ var nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
|
21493
21493
|
seen.ref = def.innerType;
|
|
21494
21494
|
};
|
|
21495
21495
|
var UNREPRESENTABLE_DEFAULT = /* @__PURE__ */ Symbol();
|
|
21496
|
-
function serializeDefaultValue(value, schema, ctx,
|
|
21496
|
+
function serializeDefaultValue(value, schema, ctx, json3, params) {
|
|
21497
21497
|
let unrepresentable = false;
|
|
21498
21498
|
const serialized = JSON.stringify(value, (_, val) => {
|
|
21499
21499
|
if (typeof val !== "bigint")
|
|
@@ -21503,30 +21503,30 @@ function serializeDefaultValue(value, schema, ctx, json2, params) {
|
|
|
21503
21503
|
});
|
|
21504
21504
|
if (!unrepresentable)
|
|
21505
21505
|
return JSON.parse(serialized);
|
|
21506
|
-
handleUnrepresentable(schema, ctx,
|
|
21506
|
+
handleUnrepresentable(schema, ctx, json3, params, "BigInt defaults cannot be represented in JSON Schema");
|
|
21507
21507
|
return UNREPRESENTABLE_DEFAULT;
|
|
21508
21508
|
}
|
|
21509
|
-
var defaultProcessor = (schema, ctx,
|
|
21509
|
+
var defaultProcessor = (schema, ctx, json3, params) => {
|
|
21510
21510
|
const def = schema._zod.def;
|
|
21511
21511
|
processSchema(def.innerType, ctx, params);
|
|
21512
21512
|
const seen = ctx.seen.get(schema);
|
|
21513
21513
|
seen.ref = def.innerType;
|
|
21514
|
-
const value = serializeDefaultValue(def.defaultValue, schema, ctx,
|
|
21514
|
+
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json3, params);
|
|
21515
21515
|
if (value !== UNREPRESENTABLE_DEFAULT)
|
|
21516
|
-
|
|
21516
|
+
json3.default = value;
|
|
21517
21517
|
};
|
|
21518
|
-
var prefaultProcessor = (schema, ctx,
|
|
21518
|
+
var prefaultProcessor = (schema, ctx, json3, params) => {
|
|
21519
21519
|
const def = schema._zod.def;
|
|
21520
21520
|
processSchema(def.innerType, ctx, params);
|
|
21521
21521
|
const seen = ctx.seen.get(schema);
|
|
21522
21522
|
seen.ref = def.innerType;
|
|
21523
21523
|
if (ctx.io !== "input")
|
|
21524
21524
|
return;
|
|
21525
|
-
const value = serializeDefaultValue(def.defaultValue, schema, ctx,
|
|
21525
|
+
const value = serializeDefaultValue(def.defaultValue, schema, ctx, json3, params);
|
|
21526
21526
|
if (value !== UNREPRESENTABLE_DEFAULT)
|
|
21527
|
-
|
|
21527
|
+
json3._prefault = value;
|
|
21528
21528
|
};
|
|
21529
|
-
var catchProcessor = (schema, ctx,
|
|
21529
|
+
var catchProcessor = (schema, ctx, json3, params) => {
|
|
21530
21530
|
const def = schema._zod.def;
|
|
21531
21531
|
processSchema(def.innerType, ctx, params);
|
|
21532
21532
|
const seen = ctx.seen.get(schema);
|
|
@@ -21535,10 +21535,10 @@ var catchProcessor = (schema, ctx, json2, params) => {
|
|
|
21535
21535
|
try {
|
|
21536
21536
|
catchValue = def.catchValue(void 0);
|
|
21537
21537
|
} catch {
|
|
21538
|
-
handleUnrepresentable(schema, ctx,
|
|
21538
|
+
handleUnrepresentable(schema, ctx, json3, params, "Dynamic catch values are not supported in JSON Schema");
|
|
21539
21539
|
return;
|
|
21540
21540
|
}
|
|
21541
|
-
|
|
21541
|
+
json3.default = catchValue;
|
|
21542
21542
|
};
|
|
21543
21543
|
var pipeProcessor = (schema, ctx, _json, params) => {
|
|
21544
21544
|
const def = schema._zod.def;
|
|
@@ -21548,12 +21548,12 @@ var pipeProcessor = (schema, ctx, _json, params) => {
|
|
|
21548
21548
|
const seen = ctx.seen.get(schema);
|
|
21549
21549
|
seen.ref = innerType;
|
|
21550
21550
|
};
|
|
21551
|
-
var readonlyProcessor = (schema, ctx,
|
|
21551
|
+
var readonlyProcessor = (schema, ctx, json3, params) => {
|
|
21552
21552
|
const def = schema._zod.def;
|
|
21553
21553
|
processSchema(def.innerType, ctx, params);
|
|
21554
21554
|
const seen = ctx.seen.get(schema);
|
|
21555
21555
|
seen.ref = def.innerType;
|
|
21556
|
-
|
|
21556
|
+
json3.readOnly = true;
|
|
21557
21557
|
};
|
|
21558
21558
|
var promiseProcessor = (schema, ctx, _json, params) => {
|
|
21559
21559
|
const def = schema._zod.def;
|
|
@@ -22195,7 +22195,7 @@ var _ZodString = /* @__PURE__ */ $constructor(
|
|
|
22195
22195
|
(inst, def) => {
|
|
22196
22196
|
$ZodString.init(inst, def);
|
|
22197
22197
|
ZodType.init(inst, def);
|
|
22198
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22198
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => stringProcessor(inst, ctx, json3, params);
|
|
22199
22199
|
},
|
|
22200
22200
|
/* @__PURE__ */ util_exports.derived({
|
|
22201
22201
|
format: (inst) => aggregateChecks(inst).format ?? null,
|
|
@@ -22554,7 +22554,7 @@ var ZodNumber = /* @__PURE__ */ $constructor(
|
|
|
22554
22554
|
(inst, def) => {
|
|
22555
22555
|
$ZodNumber.init(inst, def);
|
|
22556
22556
|
ZodType.init(inst, def);
|
|
22557
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22557
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => numberProcessor(inst, ctx, json3, params);
|
|
22558
22558
|
inst.isFinite = true;
|
|
22559
22559
|
},
|
|
22560
22560
|
/* @__PURE__ */ util_exports.derived({
|
|
@@ -22644,7 +22644,7 @@ function uint32(params) {
|
|
|
22644
22644
|
var ZodBoolean = /* @__PURE__ */ $constructor("ZodBoolean", (inst, def) => {
|
|
22645
22645
|
$ZodBoolean.init(inst, def);
|
|
22646
22646
|
ZodType.init(inst, def);
|
|
22647
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22647
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => booleanProcessor(inst, ctx, json3, params);
|
|
22648
22648
|
});
|
|
22649
22649
|
function boolean2(params) {
|
|
22650
22650
|
return _boolean(ZodBoolean, params);
|
|
@@ -22654,7 +22654,7 @@ var ZodBigInt = /* @__PURE__ */ $constructor(
|
|
|
22654
22654
|
(inst, def) => {
|
|
22655
22655
|
$ZodBigInt.init(inst, def);
|
|
22656
22656
|
ZodType.init(inst, def);
|
|
22657
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22657
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => bigintProcessor(inst, ctx, json3, params);
|
|
22658
22658
|
},
|
|
22659
22659
|
/* @__PURE__ */ util_exports.derived({
|
|
22660
22660
|
minValue: (inst) => aggregateChecks(inst).minimum ?? null,
|
|
@@ -22712,7 +22712,7 @@ function uint64(params) {
|
|
|
22712
22712
|
var ZodSymbol = /* @__PURE__ */ $constructor("ZodSymbol", (inst, def) => {
|
|
22713
22713
|
$ZodSymbol.init(inst, def);
|
|
22714
22714
|
ZodType.init(inst, def);
|
|
22715
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22715
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => symbolProcessor(inst, ctx, json3, params);
|
|
22716
22716
|
});
|
|
22717
22717
|
function symbol(params) {
|
|
22718
22718
|
return _symbol(ZodSymbol, params);
|
|
@@ -22720,7 +22720,7 @@ function symbol(params) {
|
|
|
22720
22720
|
var ZodUndefined = /* @__PURE__ */ $constructor("ZodUndefined", (inst, def) => {
|
|
22721
22721
|
$ZodUndefined.init(inst, def);
|
|
22722
22722
|
ZodType.init(inst, def);
|
|
22723
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22723
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => undefinedProcessor(inst, ctx, json3, params);
|
|
22724
22724
|
});
|
|
22725
22725
|
function _undefined3(params) {
|
|
22726
22726
|
return _undefined2(ZodUndefined, params);
|
|
@@ -22728,7 +22728,7 @@ function _undefined3(params) {
|
|
|
22728
22728
|
var ZodNull = /* @__PURE__ */ $constructor("ZodNull", (inst, def) => {
|
|
22729
22729
|
$ZodNull.init(inst, def);
|
|
22730
22730
|
ZodType.init(inst, def);
|
|
22731
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22731
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nullProcessor(inst, ctx, json3, params);
|
|
22732
22732
|
});
|
|
22733
22733
|
function _null3(params) {
|
|
22734
22734
|
return _null2(ZodNull, params);
|
|
@@ -22736,7 +22736,7 @@ function _null3(params) {
|
|
|
22736
22736
|
var ZodAny = /* @__PURE__ */ $constructor("ZodAny", (inst, def) => {
|
|
22737
22737
|
$ZodAny.init(inst, def);
|
|
22738
22738
|
ZodType.init(inst, def);
|
|
22739
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22739
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => anyProcessor(inst, ctx, json3, params);
|
|
22740
22740
|
});
|
|
22741
22741
|
function any() {
|
|
22742
22742
|
return _any(ZodAny);
|
|
@@ -22744,7 +22744,7 @@ function any() {
|
|
|
22744
22744
|
var ZodUnknown = /* @__PURE__ */ $constructor("ZodUnknown", (inst, def) => {
|
|
22745
22745
|
$ZodUnknown.init(inst, def);
|
|
22746
22746
|
ZodType.init(inst, def);
|
|
22747
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22747
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => unknownProcessor(inst, ctx, json3, params);
|
|
22748
22748
|
});
|
|
22749
22749
|
function unknown() {
|
|
22750
22750
|
return _unknown(ZodUnknown);
|
|
@@ -22752,7 +22752,7 @@ function unknown() {
|
|
|
22752
22752
|
var ZodNever = /* @__PURE__ */ $constructor("ZodNever", (inst, def) => {
|
|
22753
22753
|
$ZodNever.init(inst, def);
|
|
22754
22754
|
ZodType.init(inst, def);
|
|
22755
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22755
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => neverProcessor(inst, ctx, json3, params);
|
|
22756
22756
|
});
|
|
22757
22757
|
function never(params) {
|
|
22758
22758
|
return _never(ZodNever, params);
|
|
@@ -22760,7 +22760,7 @@ function never(params) {
|
|
|
22760
22760
|
var ZodVoid = /* @__PURE__ */ $constructor("ZodVoid", (inst, def) => {
|
|
22761
22761
|
$ZodVoid.init(inst, def);
|
|
22762
22762
|
ZodType.init(inst, def);
|
|
22763
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22763
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => voidProcessor(inst, ctx, json3, params);
|
|
22764
22764
|
});
|
|
22765
22765
|
function _void2(params) {
|
|
22766
22766
|
return _void(ZodVoid, params);
|
|
@@ -22770,7 +22770,7 @@ var ZodDate = /* @__PURE__ */ $constructor(
|
|
|
22770
22770
|
(inst, def) => {
|
|
22771
22771
|
$ZodDate.init(inst, def);
|
|
22772
22772
|
ZodType.init(inst, def);
|
|
22773
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22773
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => dateProcessor(inst, ctx, json3, params);
|
|
22774
22774
|
inst.min = (value, params) => inst.check(_gte(value, params));
|
|
22775
22775
|
inst.max = (value, params) => inst.check(_lte(value, params));
|
|
22776
22776
|
},
|
|
@@ -22792,7 +22792,7 @@ var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
|
|
|
22792
22792
|
_ensureDefaultMemoizer();
|
|
22793
22793
|
$ZodArray.init(inst, def);
|
|
22794
22794
|
ZodType.init(inst, def);
|
|
22795
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22795
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => arrayProcessor(inst, ctx, json3, params);
|
|
22796
22796
|
inst.element = def.element;
|
|
22797
22797
|
}, {
|
|
22798
22798
|
min(n, params) {
|
|
@@ -22822,7 +22822,7 @@ var ZodObject = /* @__PURE__ */ $constructor("ZodObject", (inst, def) => {
|
|
|
22822
22822
|
_ensureDefaultMemoizer();
|
|
22823
22823
|
$ZodObjectJIT.init(inst, def);
|
|
22824
22824
|
ZodType.init(inst, def);
|
|
22825
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22825
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => objectProcessor(inst, ctx, json3, params);
|
|
22826
22826
|
util_exports.installLazyProp(inst, "shape", (self) => self._zod.def.shape, false);
|
|
22827
22827
|
}, {
|
|
22828
22828
|
keyof() {
|
|
@@ -22895,7 +22895,7 @@ function looseObject(shape, params) {
|
|
|
22895
22895
|
var ZodUnion = /* @__PURE__ */ $constructor("ZodUnion", (inst, def) => {
|
|
22896
22896
|
$ZodUnion.init(inst, def);
|
|
22897
22897
|
ZodType.init(inst, def);
|
|
22898
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22898
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => unionProcessor(inst, ctx, json3, params);
|
|
22899
22899
|
inst.options = def.options;
|
|
22900
22900
|
});
|
|
22901
22901
|
function union(options, params) {
|
|
@@ -22908,7 +22908,7 @@ function union(options, params) {
|
|
|
22908
22908
|
var ZodXor = /* @__PURE__ */ $constructor("ZodXor", (inst, def) => {
|
|
22909
22909
|
ZodUnion.init(inst, def);
|
|
22910
22910
|
$ZodXor.init(inst, def);
|
|
22911
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22911
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => unionProcessor(inst, ctx, json3, params);
|
|
22912
22912
|
inst.options = def.options;
|
|
22913
22913
|
});
|
|
22914
22914
|
function xor(options, params) {
|
|
@@ -22934,7 +22934,7 @@ function discriminatedUnion(discriminator, options, params) {
|
|
|
22934
22934
|
var ZodIntersection = /* @__PURE__ */ $constructor("ZodIntersection", (inst, def) => {
|
|
22935
22935
|
$ZodIntersection.init(inst, def);
|
|
22936
22936
|
ZodType.init(inst, def);
|
|
22937
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22937
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => intersectionProcessor(inst, ctx, json3, params);
|
|
22938
22938
|
});
|
|
22939
22939
|
function intersection(left, right) {
|
|
22940
22940
|
return new ZodIntersection({
|
|
@@ -22947,7 +22947,7 @@ var ZodTuple = /* @__PURE__ */ $constructor("ZodTuple", (inst, def) => {
|
|
|
22947
22947
|
_ensureDefaultMemoizer();
|
|
22948
22948
|
$ZodTuple.init(inst, def);
|
|
22949
22949
|
ZodType.init(inst, def);
|
|
22950
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22950
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => tupleProcessor(inst, ctx, json3, params);
|
|
22951
22951
|
}, {
|
|
22952
22952
|
rest(rest) {
|
|
22953
22953
|
return this.clone({
|
|
@@ -22980,7 +22980,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
|
22980
22980
|
_ensureDefaultMemoizer();
|
|
22981
22981
|
$ZodRecord.init(inst, def);
|
|
22982
22982
|
ZodType.init(inst, def);
|
|
22983
|
-
inst._zod.processJSONSchema = (ctx,
|
|
22983
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => recordProcessor(inst, ctx, json3, params);
|
|
22984
22984
|
inst.keyType = def.keyType;
|
|
22985
22985
|
inst.valueType = def.valueType;
|
|
22986
22986
|
});
|
|
@@ -23022,7 +23022,7 @@ var ZodMap = /* @__PURE__ */ $constructor("ZodMap", (inst, def) => {
|
|
|
23022
23022
|
_ensureDefaultMemoizer();
|
|
23023
23023
|
$ZodMap.init(inst, def);
|
|
23024
23024
|
ZodType.init(inst, def);
|
|
23025
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23025
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => mapProcessor(inst, ctx, json3, params);
|
|
23026
23026
|
inst.keyType = def.keyType;
|
|
23027
23027
|
inst.valueType = def.valueType;
|
|
23028
23028
|
inst.min = (...args) => inst.check(_minSize(...args));
|
|
@@ -23042,7 +23042,7 @@ var ZodSet = /* @__PURE__ */ $constructor("ZodSet", (inst, def) => {
|
|
|
23042
23042
|
_ensureDefaultMemoizer();
|
|
23043
23043
|
$ZodSet.init(inst, def);
|
|
23044
23044
|
ZodType.init(inst, def);
|
|
23045
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23045
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => setProcessor(inst, ctx, json3, params);
|
|
23046
23046
|
inst.min = (...args) => inst.check(_minSize(...args));
|
|
23047
23047
|
inst.nonempty = (params) => inst.check(_minSize(1, params));
|
|
23048
23048
|
inst.max = (...args) => inst.check(_maxSize(...args));
|
|
@@ -23058,7 +23058,7 @@ function set(valueType, params) {
|
|
|
23058
23058
|
var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
23059
23059
|
$ZodEnum.init(inst, def);
|
|
23060
23060
|
ZodType.init(inst, def);
|
|
23061
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23061
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => enumProcessor(inst, ctx, json3, params);
|
|
23062
23062
|
inst.enum = def.entries;
|
|
23063
23063
|
inst.options = [...inst._zod.values];
|
|
23064
23064
|
const keys2 = new Set(Object.keys(def.entries));
|
|
@@ -23111,7 +23111,7 @@ function nativeEnum(entries, params) {
|
|
|
23111
23111
|
var ZodLiteral = /* @__PURE__ */ $constructor("ZodLiteral", (inst, def) => {
|
|
23112
23112
|
$ZodLiteral.init(inst, def);
|
|
23113
23113
|
ZodType.init(inst, def);
|
|
23114
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23114
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => literalProcessor(inst, ctx, json3, params);
|
|
23115
23115
|
inst.values = new Set(def.values);
|
|
23116
23116
|
Object.defineProperty(inst, "value", {
|
|
23117
23117
|
get() {
|
|
@@ -23132,7 +23132,7 @@ function literal(value, params) {
|
|
|
23132
23132
|
var ZodFile = /* @__PURE__ */ $constructor("ZodFile", (inst, def) => {
|
|
23133
23133
|
$ZodFile.init(inst, def);
|
|
23134
23134
|
ZodType.init(inst, def);
|
|
23135
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23135
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => fileProcessor(inst, ctx, json3, params);
|
|
23136
23136
|
inst.min = (size, params) => inst.check(_minSize(size, params));
|
|
23137
23137
|
inst.max = (size, params) => inst.check(_maxSize(size, params));
|
|
23138
23138
|
inst.mime = (types, params) => inst.check(_mime(Array.isArray(types) ? types : [types], params));
|
|
@@ -23144,7 +23144,7 @@ var ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) => {
|
|
|
23144
23144
|
_ensureDefaultMemoizer();
|
|
23145
23145
|
$ZodTransform.init(inst, def);
|
|
23146
23146
|
ZodType.init(inst, def);
|
|
23147
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23147
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => transformProcessor(inst, ctx, json3, params);
|
|
23148
23148
|
inst._zod.parse = (payload, _ctx) => {
|
|
23149
23149
|
if (_ctx.direction === "backward") {
|
|
23150
23150
|
throw new $ZodEncodeError(inst.constructor.name);
|
|
@@ -23183,7 +23183,7 @@ function transform(fn) {
|
|
|
23183
23183
|
var ZodOptional = /* @__PURE__ */ $constructor("ZodOptional", (inst, def) => {
|
|
23184
23184
|
$ZodOptional.init(inst, def);
|
|
23185
23185
|
ZodType.init(inst, def);
|
|
23186
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23186
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => optionalProcessor(inst, ctx, json3, params);
|
|
23187
23187
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23188
23188
|
});
|
|
23189
23189
|
function optional(innerType) {
|
|
@@ -23195,7 +23195,7 @@ function optional(innerType) {
|
|
|
23195
23195
|
var ZodExactOptional = /* @__PURE__ */ $constructor("ZodExactOptional", (inst, def) => {
|
|
23196
23196
|
$ZodExactOptional.init(inst, def);
|
|
23197
23197
|
ZodType.init(inst, def);
|
|
23198
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23198
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => optionalProcessor(inst, ctx, json3, params);
|
|
23199
23199
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23200
23200
|
});
|
|
23201
23201
|
function exactOptional(innerType) {
|
|
@@ -23207,7 +23207,7 @@ function exactOptional(innerType) {
|
|
|
23207
23207
|
var ZodNullable = /* @__PURE__ */ $constructor("ZodNullable", (inst, def) => {
|
|
23208
23208
|
$ZodNullable.init(inst, def);
|
|
23209
23209
|
ZodType.init(inst, def);
|
|
23210
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23210
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nullableProcessor(inst, ctx, json3, params);
|
|
23211
23211
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23212
23212
|
});
|
|
23213
23213
|
function nullable(innerType) {
|
|
@@ -23222,7 +23222,7 @@ function nullish2(innerType) {
|
|
|
23222
23222
|
var ZodDefault = /* @__PURE__ */ $constructor("ZodDefault", (inst, def) => {
|
|
23223
23223
|
$ZodDefault.init(inst, def);
|
|
23224
23224
|
ZodType.init(inst, def);
|
|
23225
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23225
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => defaultProcessor(inst, ctx, json3, params);
|
|
23226
23226
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23227
23227
|
inst.removeDefault = inst.unwrap;
|
|
23228
23228
|
});
|
|
@@ -23238,7 +23238,7 @@ function _default2(innerType, defaultValue) {
|
|
|
23238
23238
|
var ZodPrefault = /* @__PURE__ */ $constructor("ZodPrefault", (inst, def) => {
|
|
23239
23239
|
$ZodPrefault.init(inst, def);
|
|
23240
23240
|
ZodType.init(inst, def);
|
|
23241
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23241
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => prefaultProcessor(inst, ctx, json3, params);
|
|
23242
23242
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23243
23243
|
});
|
|
23244
23244
|
function prefault(innerType, defaultValue) {
|
|
@@ -23253,7 +23253,7 @@ function prefault(innerType, defaultValue) {
|
|
|
23253
23253
|
var ZodNonOptional = /* @__PURE__ */ $constructor("ZodNonOptional", (inst, def) => {
|
|
23254
23254
|
$ZodNonOptional.init(inst, def);
|
|
23255
23255
|
ZodType.init(inst, def);
|
|
23256
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23256
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nonoptionalProcessor(inst, ctx, json3, params);
|
|
23257
23257
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23258
23258
|
});
|
|
23259
23259
|
function nonoptional(innerType, params) {
|
|
@@ -23266,7 +23266,7 @@ function nonoptional(innerType, params) {
|
|
|
23266
23266
|
var ZodSuccess = /* @__PURE__ */ $constructor("ZodSuccess", (inst, def) => {
|
|
23267
23267
|
$ZodSuccess.init(inst, def);
|
|
23268
23268
|
ZodType.init(inst, def);
|
|
23269
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23269
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => successProcessor(inst, ctx, json3, params);
|
|
23270
23270
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23271
23271
|
});
|
|
23272
23272
|
function success(innerType) {
|
|
@@ -23278,7 +23278,7 @@ function success(innerType) {
|
|
|
23278
23278
|
var ZodCatch = /* @__PURE__ */ $constructor("ZodCatch", (inst, def) => {
|
|
23279
23279
|
$ZodCatch.init(inst, def);
|
|
23280
23280
|
ZodType.init(inst, def);
|
|
23281
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23281
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => catchProcessor(inst, ctx, json3, params);
|
|
23282
23282
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23283
23283
|
inst.removeCatch = inst.unwrap;
|
|
23284
23284
|
});
|
|
@@ -23292,7 +23292,7 @@ function _catch2(innerType, catchValue) {
|
|
|
23292
23292
|
var ZodNaN = /* @__PURE__ */ $constructor("ZodNaN", (inst, def) => {
|
|
23293
23293
|
$ZodNaN.init(inst, def);
|
|
23294
23294
|
ZodType.init(inst, def);
|
|
23295
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23295
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => nanProcessor(inst, ctx, json3, params);
|
|
23296
23296
|
});
|
|
23297
23297
|
function nan(params) {
|
|
23298
23298
|
return _nan(ZodNaN, params);
|
|
@@ -23300,7 +23300,7 @@ function nan(params) {
|
|
|
23300
23300
|
var ZodPipe = /* @__PURE__ */ $constructor("ZodPipe", (inst, def) => {
|
|
23301
23301
|
$ZodPipe.init(inst, def);
|
|
23302
23302
|
ZodType.init(inst, def);
|
|
23303
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23303
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => pipeProcessor(inst, ctx, json3, params);
|
|
23304
23304
|
inst.in = def.in;
|
|
23305
23305
|
inst.out = def.out;
|
|
23306
23306
|
});
|
|
@@ -23342,7 +23342,7 @@ var ZodPreprocess = /* @__PURE__ */ $constructor("ZodPreprocess", (inst, def) =>
|
|
|
23342
23342
|
var ZodReadonly = /* @__PURE__ */ $constructor("ZodReadonly", (inst, def) => {
|
|
23343
23343
|
$ZodReadonly.init(inst, def);
|
|
23344
23344
|
ZodType.init(inst, def);
|
|
23345
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23345
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => readonlyProcessor(inst, ctx, json3, params);
|
|
23346
23346
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23347
23347
|
});
|
|
23348
23348
|
function readonly(innerType) {
|
|
@@ -23354,7 +23354,7 @@ function readonly(innerType) {
|
|
|
23354
23354
|
var ZodTemplateLiteral = /* @__PURE__ */ $constructor("ZodTemplateLiteral", (inst, def) => {
|
|
23355
23355
|
$ZodTemplateLiteral.init(inst, def);
|
|
23356
23356
|
ZodType.init(inst, def);
|
|
23357
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23357
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => templateLiteralProcessor(inst, ctx, json3, params);
|
|
23358
23358
|
});
|
|
23359
23359
|
function templateLiteral(parts, params) {
|
|
23360
23360
|
return new ZodTemplateLiteral({
|
|
@@ -23366,7 +23366,7 @@ function templateLiteral(parts, params) {
|
|
|
23366
23366
|
var ZodLazy = /* @__PURE__ */ $constructor("ZodLazy", (inst, def) => {
|
|
23367
23367
|
$ZodLazy.init(inst, def);
|
|
23368
23368
|
ZodType.init(inst, def);
|
|
23369
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23369
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => lazyProcessor(inst, ctx, json3, params);
|
|
23370
23370
|
inst.unwrap = () => inst._zod.def.getter();
|
|
23371
23371
|
});
|
|
23372
23372
|
function lazy(getter) {
|
|
@@ -23378,7 +23378,7 @@ function lazy(getter) {
|
|
|
23378
23378
|
var ZodPromise = /* @__PURE__ */ $constructor("ZodPromise", (inst, def) => {
|
|
23379
23379
|
$ZodPromise.init(inst, def);
|
|
23380
23380
|
ZodType.init(inst, def);
|
|
23381
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23381
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => promiseProcessor(inst, ctx, json3, params);
|
|
23382
23382
|
inst.unwrap = () => inst._zod.def.innerType;
|
|
23383
23383
|
});
|
|
23384
23384
|
function promise(innerType) {
|
|
@@ -23390,7 +23390,7 @@ function promise(innerType) {
|
|
|
23390
23390
|
var ZodFunction = /* @__PURE__ */ $constructor("ZodFunction", (inst, def) => {
|
|
23391
23391
|
$ZodFunction.init(inst, def);
|
|
23392
23392
|
ZodType.init(inst, def);
|
|
23393
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23393
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => functionProcessor(inst, ctx, json3, params);
|
|
23394
23394
|
});
|
|
23395
23395
|
function _function(params) {
|
|
23396
23396
|
return new ZodFunction({
|
|
@@ -23402,7 +23402,7 @@ function _function(params) {
|
|
|
23402
23402
|
var ZodCustom = /* @__PURE__ */ $constructor("ZodCustom", (inst, def) => {
|
|
23403
23403
|
$ZodCustom.init(inst, def);
|
|
23404
23404
|
ZodType.init(inst, def);
|
|
23405
|
-
inst._zod.processJSONSchema = (ctx,
|
|
23405
|
+
inst._zod.processJSONSchema = (ctx, json3, params) => customProcessor(inst, ctx, json3, params);
|
|
23406
23406
|
});
|
|
23407
23407
|
function check(fn) {
|
|
23408
23408
|
const ch = new $ZodCheck({
|
|
@@ -23793,20 +23793,20 @@ function checkArrayGuards(arraySchema, guards) {
|
|
|
23793
23793
|
if (guards.containsSchema) {
|
|
23794
23794
|
const minContains = guards.minContains ?? 1;
|
|
23795
23795
|
const ceiling = guards.maxContains !== void 0 ? guards.maxContains + 1 : Number.POSITIVE_INFINITY;
|
|
23796
|
-
let
|
|
23796
|
+
let matches2 = 0;
|
|
23797
23797
|
for (const item of items2) {
|
|
23798
|
-
if (guards.containsSchema.safeParse(item).success && ++
|
|
23798
|
+
if (guards.containsSchema.safeParse(item).success && ++matches2 >= ceiling)
|
|
23799
23799
|
break;
|
|
23800
23800
|
}
|
|
23801
|
-
if (
|
|
23801
|
+
if (matches2 < minContains) {
|
|
23802
23802
|
payload.issues.push({
|
|
23803
23803
|
code: "custom",
|
|
23804
|
-
message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${
|
|
23804
|
+
message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${matches2}`,
|
|
23805
23805
|
input: items2,
|
|
23806
23806
|
continue: true
|
|
23807
23807
|
});
|
|
23808
23808
|
}
|
|
23809
|
-
if (guards.maxContains !== void 0 &&
|
|
23809
|
+
if (guards.maxContains !== void 0 && matches2 > guards.maxContains) {
|
|
23810
23810
|
payload.issues.push({
|
|
23811
23811
|
code: "custom",
|
|
23812
23812
|
message: `Array must contain at most ${guards.maxContains} matching ${plural(guards.maxContains)}`,
|
|
@@ -24631,7 +24631,7 @@ var projectInitV5 = external_exports.discriminatedUnion("ok", [
|
|
|
24631
24631
|
external_exports.strictObject({ contract: external_exports.literal("project-init"), version: external_exports.literal(5), ok: external_exports.literal(false), error: external_exports.strictObject({ code: external_exports.string(), message: external_exports.string() }) })
|
|
24632
24632
|
]);
|
|
24633
24633
|
|
|
24634
|
-
// ../../packages/contracts/dist/versions/browser-specs-
|
|
24634
|
+
// ../../packages/contracts/dist/versions/browser-specs-v4.js
|
|
24635
24635
|
var requirement = external_exports.strictObject({ id: external_exports.string(), title: external_exports.string(), body: external_exports.string() });
|
|
24636
24636
|
var contributor = external_exports.strictObject({ email: external_exports.string(), name: external_exports.string(), commits: external_exports.number().int().nonnegative(), latest: external_exports.string() });
|
|
24637
24637
|
var source = external_exports.strictObject({ title: external_exports.string(), path: external_exports.string().optional(), url: external_exports.string().optional(), note: external_exports.string().optional() });
|
|
@@ -24646,45 +24646,103 @@ var feature = external_exports.strictObject({
|
|
|
24646
24646
|
contributors: external_exports.array(contributor),
|
|
24647
24647
|
updatedAt: external_exports.string().nullable()
|
|
24648
24648
|
});
|
|
24649
|
-
var snapshot = requirement.extend({ specId: external_exports.string(), path: external_exports.string(), sources: external_exports.array(source).optional() }).nullable();
|
|
24650
24649
|
var document = external_exports.strictObject({ id: external_exports.string(), path: external_exports.string(), title: external_exports.string(), body: external_exports.string(), updatedAt: external_exports.string().nullable() });
|
|
24650
|
+
var oid2 = external_exports.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/);
|
|
24651
|
+
var browserSpecsV4 = external_exports.strictObject({
|
|
24652
|
+
contract: external_exports.literal("browser-specs"),
|
|
24653
|
+
version: external_exports.literal(4),
|
|
24654
|
+
sessionId: external_exports.string(),
|
|
24655
|
+
head: oid2.nullable(),
|
|
24656
|
+
observedAt: external_exports.string(),
|
|
24657
|
+
working: external_exports.boolean(),
|
|
24658
|
+
features: external_exports.array(feature),
|
|
24659
|
+
documents: external_exports.array(document),
|
|
24660
|
+
contributors: external_exports.array(contributor),
|
|
24661
|
+
contributorsLimited: external_exports.boolean()
|
|
24662
|
+
});
|
|
24663
|
+
var reference = external_exports.strictObject({ id: external_exports.string(), title: external_exports.string(), specId: external_exports.string(), path: external_exports.string() }).nullable();
|
|
24664
|
+
var snapshot = requirement.extend({ specId: external_exports.string(), path: external_exports.string(), sources: external_exports.array(source).optional() }).nullable();
|
|
24665
|
+
var changeType = external_exports.enum(["created", "modified", "moved", "deleted"]);
|
|
24651
24666
|
var event = external_exports.strictObject({
|
|
24652
24667
|
key: external_exports.string(),
|
|
24653
|
-
commit:
|
|
24668
|
+
commit: oid2,
|
|
24654
24669
|
date: external_exports.string(),
|
|
24655
24670
|
author: external_exports.string(),
|
|
24656
24671
|
email: external_exports.string(),
|
|
24657
24672
|
committer: external_exports.string(),
|
|
24658
24673
|
message: external_exports.string(),
|
|
24659
24674
|
id: external_exports.string(),
|
|
24660
|
-
kind: external_exports.enum(["requirement", "design", "wiki"])
|
|
24661
|
-
types: external_exports.array(
|
|
24662
|
-
before:
|
|
24663
|
-
after:
|
|
24675
|
+
kind: external_exports.enum(["requirement", "design", "wiki"]),
|
|
24676
|
+
types: external_exports.array(changeType),
|
|
24677
|
+
before: reference,
|
|
24678
|
+
after: reference,
|
|
24664
24679
|
reasons: external_exports.array(external_exports.string())
|
|
24665
24680
|
});
|
|
24666
|
-
var
|
|
24667
|
-
contract: external_exports.literal("browser-
|
|
24668
|
-
version: external_exports.literal(
|
|
24681
|
+
var browserHistoryV1 = external_exports.strictObject({
|
|
24682
|
+
contract: external_exports.literal("browser-history"),
|
|
24683
|
+
version: external_exports.literal(1),
|
|
24669
24684
|
sessionId: external_exports.string(),
|
|
24670
|
-
head:
|
|
24671
|
-
|
|
24685
|
+
head: oid2,
|
|
24686
|
+
// Matching changes in all of history, not in this page; `offset` is where this page starts among them.
|
|
24687
|
+
total: external_exports.number().int().nonnegative(),
|
|
24688
|
+
offset: external_exports.number().int().nonnegative(),
|
|
24672
24689
|
events: external_exports.array(event),
|
|
24673
|
-
|
|
24674
|
-
boundary: external_exports.boolean()
|
|
24675
|
-
|
|
24676
|
-
|
|
24677
|
-
|
|
24678
|
-
|
|
24679
|
-
|
|
24690
|
+
// History reaches back to records in the legacy JSON format, which it does not read.
|
|
24691
|
+
boundary: external_exports.boolean()
|
|
24692
|
+
});
|
|
24693
|
+
var browserHistorySummaryV1 = external_exports.strictObject({
|
|
24694
|
+
contract: external_exports.literal("browser-history-summary"),
|
|
24695
|
+
version: external_exports.literal(1),
|
|
24696
|
+
sessionId: external_exports.string(),
|
|
24697
|
+
head: oid2,
|
|
24698
|
+
total: external_exports.number().int().nonnegative(),
|
|
24699
|
+
byType: external_exports.strictObject({ created: external_exports.number().int().nonnegative(), modified: external_exports.number().int().nonnegative(), moved: external_exports.number().int().nonnegative(), deleted: external_exports.number().int().nonnegative() }),
|
|
24700
|
+
// One entry per commit within three weeks of the newest change, so the reader can count by its own calendar day.
|
|
24701
|
+
pulse: external_exports.array(external_exports.strictObject({ date: external_exports.string(), count: external_exports.number().int().positive() })),
|
|
24702
|
+
// The newest commits: a few of their changes each and how many there are in all.
|
|
24703
|
+
recent: external_exports.array(external_exports.strictObject({ commit: oid2, count: external_exports.number().int().positive(), events: external_exports.array(event) }))
|
|
24704
|
+
});
|
|
24705
|
+
var browserChangeV1 = external_exports.strictObject({
|
|
24706
|
+
contract: external_exports.literal("browser-change"),
|
|
24707
|
+
version: external_exports.literal(1),
|
|
24708
|
+
sessionId: external_exports.string(),
|
|
24709
|
+
event,
|
|
24710
|
+
before: snapshot,
|
|
24711
|
+
after: snapshot
|
|
24712
|
+
});
|
|
24713
|
+
var browserSearchV1 = external_exports.strictObject({
|
|
24714
|
+
contract: external_exports.literal("browser-search"),
|
|
24715
|
+
version: external_exports.literal(1),
|
|
24716
|
+
sessionId: external_exports.string(),
|
|
24717
|
+
query: external_exports.string(),
|
|
24718
|
+
hits: external_exports.array(external_exports.strictObject({
|
|
24719
|
+
id: external_exports.string(),
|
|
24720
|
+
kind: external_exports.enum(["feature", "requirement", "design", "document", "history"]),
|
|
24721
|
+
title: external_exports.string(),
|
|
24722
|
+
where: external_exports.string(),
|
|
24723
|
+
line: external_exports.string(),
|
|
24724
|
+
// What the hit opens: a feature (with the requirement or design tab), a wiki page, or one change in the activity.
|
|
24725
|
+
featureId: external_exports.string().optional(),
|
|
24726
|
+
documentId: external_exports.string().optional(),
|
|
24727
|
+
key: external_exports.string().optional()
|
|
24728
|
+
}))
|
|
24680
24729
|
});
|
|
24681
|
-
var
|
|
24682
|
-
|
|
24683
|
-
|
|
24684
|
-
|
|
24685
|
-
|
|
24686
|
-
|
|
24730
|
+
var headQuery = oid2;
|
|
24731
|
+
var count = (max) => external_exports.string().regex(/^(0|[1-9]\d{0,6})$/).transform(Number).pipe(external_exports.number().int().min(0).max(max));
|
|
24732
|
+
var browserHistoryQueryV1 = external_exports.strictObject({
|
|
24733
|
+
head: headQuery,
|
|
24734
|
+
offset: count(1e6).optional(),
|
|
24735
|
+
limit: count(100).pipe(external_exports.number().min(1)).optional(),
|
|
24736
|
+
kind: changeType.optional(),
|
|
24737
|
+
document: external_exports.enum(["requirement", "design", "wiki"]).optional(),
|
|
24738
|
+
feature: external_exports.string().regex(/^S-[a-z2-7]{10}$/).optional(),
|
|
24739
|
+
author: external_exports.string().min(1).max(320).optional(),
|
|
24740
|
+
q: external_exports.string().max(200).optional()
|
|
24687
24741
|
});
|
|
24742
|
+
var browserHistorySummaryQueryV1 = external_exports.strictObject({ head: headQuery });
|
|
24743
|
+
var browserChangeQueryV1 = external_exports.strictObject({ key: external_exports.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64}):[RSW]-[a-z2-7]{10}$/) });
|
|
24744
|
+
var browserSearchQueryV1 = external_exports.strictObject({ q: external_exports.string().min(1).max(200), head: headQuery.optional() });
|
|
24745
|
+
var changelogQueryV1 = external_exports.strictObject({ lang: external_exports.string().regex(/^[a-z]{2}(?:-[A-Z]{2})?$/).optional() });
|
|
24688
24746
|
|
|
24689
24747
|
// ../../packages/contracts/dist/versions/changelog-v1.js
|
|
24690
24748
|
var items = external_exports.array(external_exports.string().min(1));
|
|
@@ -24862,6 +24920,7 @@ var messages_default2 = {
|
|
|
24862
24920
|
"server.apiNotFound": "API\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24863
24921
|
"server.sessionChanged": "\uC11C\uBC84 \uC138\uC158\uC774 \uBCC0\uACBD\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC5F0\uACB0\uD558\uC138\uC694.",
|
|
24864
24922
|
"server.badRange": "\uC870\uD68C \uBC94\uC704\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24923
|
+
"server.changeNotFound": "\uADF8 \uCEE4\uBC0B\uC5D0 \uD574\uB2F9 \uBCC0\uACBD\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
24865
24924
|
"server.specsUnreadable": "\uBA85\uC138\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24866
24925
|
"server.refreshOrigin": "\uC0C8\uB85C\uACE0\uCE68\uC5D0\uB294 \uAC19\uC740 \uCD9C\uCC98\uC758 Origin\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24867
24926
|
"server.fileNotFound": "\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
@@ -24934,7 +24993,6 @@ var messages_default2 = {
|
|
|
24934
24993
|
"agentBlock.duplicateStart": "GITIFACT \uC2DC\uC791 \uB9C8\uCEE4\uAC00 \uC5EC\uB7EC \uAC1C\uC785\uB2C8\uB2E4. \uC911\uBCF5 \uBE14\uB85D\uC744 \uC815\uB9AC\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.",
|
|
24935
24994
|
"specReader.headUnreadable": "HEAD\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24936
24995
|
"specReader.schemaRequired": "\uC0C8 \uC2A4\uD0A4\uB9C8 \uD504\uB85C\uC81D\uD2B8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
24937
|
-
"specReader.historyChanged": "\uC774\uB825\uC774 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uC0C8\uB85C\uACE0\uCE68 \uD6C4 \uB2E4\uC2DC \uC870\uD68C\uD558\uC138\uC694.",
|
|
24938
24996
|
"specReader.authorUnreadable": "Git \uC791\uC131\uC790\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24939
24997
|
"specReader.historyUnreadable": "Git \uC774\uB825 \uD615\uC2DD\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24940
24998
|
"specReader.projectChanged": "\uC870\uD68C \uC911 \uD504\uB85C\uC81D\uD2B8\uAC00 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uC0C8\uB85C\uACE0\uCE68\uD558\uC138\uC694.",
|
|
@@ -24954,7 +25012,6 @@ var messages_default2 = {
|
|
|
24954
25012
|
"help.browserNoUpdateCheck": "\uC0C8 \uBC84\uC804 \uD655\uC778\uC744 \uC704\uD55C npm \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uB054 (GITIFACT_NO_UPDATE_CHECK\uC640 \uAC19\uC74C)",
|
|
24955
25013
|
"help.updateCommit": "\uAC31\uC2E0\uD55C GITIFACT \uBE14\uB85D\uC774 HEAD\uC640 \uBE14\uB85D \uC548\uC5D0\uC11C\uB9CC \uB2E4\uB974\uBA74 \uADF8 \uD30C\uC77C\uB9CC \uACE0\uC815 \uBA54\uC2DC\uC9C0\uB85C \uCEE4\uBC0B",
|
|
24956
25014
|
"help.update": "\uC0C8 \uBC84\uC804 \uD655\uC778\uACFC \uC124\uCE58 \uBC29\uBC95 \uC548\uB0B4, \uD504\uB85C\uC81D\uD2B8 \uC9C0\uCE68 \uD30C\uC77C\uC758 GITIFACT \uBE14\uB85D\uC744 \uD604\uC7AC \uBC84\uC804\uC73C\uB85C \uAC31\uC2E0",
|
|
24957
|
-
"server.badLanguage": "\uC5B8\uC5B4 \uCF54\uB4DC\uB97C \uD655\uC778\uD558\uC138\uC694.",
|
|
24958
25015
|
"server.changelogNotFound": "\uD328\uCE58\uB178\uD2B8\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24959
25016
|
"server.changelogUnreadable": "\uD328\uCE58\uB178\uD2B8\uB97C \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.",
|
|
24960
25017
|
"update.text.current": "\uD604\uC7AC \uBC84\uC804: {version}",
|
|
@@ -25056,43 +25113,7 @@ async function runStatus(format) {
|
|
|
25056
25113
|
import { createServer } from "node:http";
|
|
25057
25114
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
25058
25115
|
import { fileURLToPath } from "node:url";
|
|
25059
|
-
import {
|
|
25060
|
-
import { join as join5 } from "node:path";
|
|
25061
|
-
|
|
25062
|
-
// src/server/assets.ts
|
|
25063
|
-
import { readdir, readFile } from "node:fs/promises";
|
|
25064
|
-
import { join } from "node:path";
|
|
25065
|
-
async function loadBrowserAssets(directory) {
|
|
25066
|
-
const assets = /* @__PURE__ */ new Map();
|
|
25067
|
-
async function walk(current, prefix) {
|
|
25068
|
-
for (const entry2 of await readdir(current, { withFileTypes: true })) {
|
|
25069
|
-
if (entry2.isSymbolicLink()) throw new Error(t2("browser.assetSymlink"));
|
|
25070
|
-
const name = prefix + entry2.name;
|
|
25071
|
-
if (entry2.isDirectory()) await walk(join(current, entry2.name), name + "/");
|
|
25072
|
-
else if (entry2.isFile()) assets.set("/" + name, await readFile(join(current, entry2.name)));
|
|
25073
|
-
}
|
|
25074
|
-
}
|
|
25075
|
-
try {
|
|
25076
|
-
await walk(directory, "");
|
|
25077
|
-
if (!assets.has("/index.html")) throw new Error("missing index");
|
|
25078
|
-
} catch {
|
|
25079
|
-
throw new Error(t2("browser.assetsUnreadable"));
|
|
25080
|
-
}
|
|
25081
|
-
return assets;
|
|
25082
|
-
}
|
|
25083
|
-
function contentType(path3) {
|
|
25084
|
-
if (path3.endsWith(".html")) return "text/html; charset=utf-8";
|
|
25085
|
-
if (path3.endsWith(".js")) return "text/javascript; charset=utf-8";
|
|
25086
|
-
if (path3.endsWith(".css")) return "text/css; charset=utf-8";
|
|
25087
|
-
if (path3.endsWith(".svg")) return "image/svg+xml";
|
|
25088
|
-
if (path3.endsWith(".woff2")) return "font/woff2";
|
|
25089
|
-
if (path3.endsWith(".png")) return "image/png";
|
|
25090
|
-
if (/\.jpe?g$/.test(path3)) return "image/jpeg";
|
|
25091
|
-
if (path3.endsWith(".gif")) return "image/gif";
|
|
25092
|
-
if (path3.endsWith(".webp")) return "image/webp";
|
|
25093
|
-
if (path3.endsWith(".pdf")) return "application/pdf";
|
|
25094
|
-
return "application/octet-stream";
|
|
25095
|
-
}
|
|
25116
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
25096
25117
|
|
|
25097
25118
|
// src/server/status-session.ts
|
|
25098
25119
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -25180,6 +25201,172 @@ function createStatusSession(initial, read, cliVersion = "0.0.0") {
|
|
|
25180
25201
|
};
|
|
25181
25202
|
}
|
|
25182
25203
|
|
|
25204
|
+
// src/server/http/respond.ts
|
|
25205
|
+
var HttpError = class extends Error {
|
|
25206
|
+
constructor(status, code, message) {
|
|
25207
|
+
super(message);
|
|
25208
|
+
this.status = status;
|
|
25209
|
+
this.code = code;
|
|
25210
|
+
}
|
|
25211
|
+
status;
|
|
25212
|
+
code;
|
|
25213
|
+
};
|
|
25214
|
+
function json2(response, status, value) {
|
|
25215
|
+
response.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
|
|
25216
|
+
response.end(JSON.stringify(value) + "\n");
|
|
25217
|
+
}
|
|
25218
|
+
function fail4(response, status, code, message) {
|
|
25219
|
+
json2(response, status, browserHttpErrorV1.parse({ contract: "browser-http-error", version: 1, error: { code, message } }));
|
|
25220
|
+
}
|
|
25221
|
+
|
|
25222
|
+
// src/server/http/guard.ts
|
|
25223
|
+
function admit(request, response, origin, dev) {
|
|
25224
|
+
response.setHeader("X-Content-Type-Options", "nosniff");
|
|
25225
|
+
response.setHeader("X-Frame-Options", "DENY");
|
|
25226
|
+
response.setHeader("Referrer-Policy", "no-referrer");
|
|
25227
|
+
response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'");
|
|
25228
|
+
if (request.headers.host !== new URL(origin).host) {
|
|
25229
|
+
fail4(response, 403, "FORBIDDEN", t2("server.forbiddenHost"));
|
|
25230
|
+
return;
|
|
25231
|
+
}
|
|
25232
|
+
const requestOrigin = request.headers.origin;
|
|
25233
|
+
const allowedOrigin = requestOrigin === origin || dev && requestOrigin === "http://127.0.0.1:5173";
|
|
25234
|
+
if (requestOrigin && !allowedOrigin) {
|
|
25235
|
+
fail4(response, 403, "FORBIDDEN", t2("server.forbiddenOrigin"));
|
|
25236
|
+
return;
|
|
25237
|
+
}
|
|
25238
|
+
const raw = request.url ?? "/";
|
|
25239
|
+
if (!raw.startsWith("/") || raw.startsWith("//") || raw.includes("\\")) {
|
|
25240
|
+
fail4(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25241
|
+
return;
|
|
25242
|
+
}
|
|
25243
|
+
let url2;
|
|
25244
|
+
let path3;
|
|
25245
|
+
try {
|
|
25246
|
+
url2 = new URL(raw, origin);
|
|
25247
|
+
path3 = decodeURIComponent(url2.pathname);
|
|
25248
|
+
} catch {
|
|
25249
|
+
fail4(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25250
|
+
return;
|
|
25251
|
+
}
|
|
25252
|
+
if (path3.includes("\0") || path3.includes("\\") || path3.split("/").some((part) => part === ".." || part === ".")) {
|
|
25253
|
+
fail4(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25254
|
+
return;
|
|
25255
|
+
}
|
|
25256
|
+
if (request.headers["transfer-encoding"] || request.headers["content-length"] && request.headers["content-length"] !== "0") {
|
|
25257
|
+
request.resume();
|
|
25258
|
+
fail4(response, 400, "BAD_REQUEST", t2("server.noBody"));
|
|
25259
|
+
return;
|
|
25260
|
+
}
|
|
25261
|
+
const api = path3 === "/api" || path3.startsWith("/api/");
|
|
25262
|
+
if (api && request.headers["sec-fetch-site"] === "cross-site" && !allowedOrigin) {
|
|
25263
|
+
fail4(response, 403, "FORBIDDEN", t2("server.crossSite"));
|
|
25264
|
+
return;
|
|
25265
|
+
}
|
|
25266
|
+
return { url: url2, path: path3, api, allowedOrigin: !!allowedOrigin };
|
|
25267
|
+
}
|
|
25268
|
+
|
|
25269
|
+
// src/server/http/router.ts
|
|
25270
|
+
var route = (value) => value;
|
|
25271
|
+
var ok = (body) => ({ status: 200, body });
|
|
25272
|
+
var matches = (route2, path3) => route2.path.endsWith("/*") ? path3.startsWith(route2.path.slice(0, -1)) : route2.path === path3;
|
|
25273
|
+
async function dispatch(routes, sessionId, url2, path3, request, response, allowedOrigin) {
|
|
25274
|
+
const candidates2 = routes.filter((r) => matches(r, path3));
|
|
25275
|
+
if (!candidates2.length) return fail4(response, 404, "NOT_FOUND", t2("server.apiNotFound"));
|
|
25276
|
+
const found = candidates2.find((r) => r.method === request.method);
|
|
25277
|
+
if (!found) {
|
|
25278
|
+
response.setHeader("Allow", candidates2.map((r) => r.method).join(", "));
|
|
25279
|
+
return fail4(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25280
|
+
}
|
|
25281
|
+
let query = {};
|
|
25282
|
+
if (found.query) {
|
|
25283
|
+
const keys2 = [...url2.searchParams.keys()];
|
|
25284
|
+
if (new Set(keys2).size !== keys2.length) return fail4(response, 400, "BAD_REQUEST", t2("server.badRange"));
|
|
25285
|
+
const parsed = found.query.safeParse(Object.fromEntries(url2.searchParams));
|
|
25286
|
+
if (!parsed.success) return fail4(response, 400, "BAD_REQUEST", t2("server.badRange"));
|
|
25287
|
+
query = parsed.data;
|
|
25288
|
+
} else if (url2.search) return fail4(response, 400, "BAD_REQUEST", t2("server.noQuery"));
|
|
25289
|
+
if (found.session && request.headers["x-gitifact-session"] !== sessionId) return fail4(response, 409, "SESSION_CHANGED", t2("server.sessionChanged"));
|
|
25290
|
+
try {
|
|
25291
|
+
const reply = await found.handle({ query, path: path3, request, response, allowedOrigin });
|
|
25292
|
+
if (reply && !response.destroyed) json2(response, reply.status, reply.body);
|
|
25293
|
+
} catch (error62) {
|
|
25294
|
+
if (error62 instanceof HttpError) return fail4(response, error62.status, error62.code, error62.message);
|
|
25295
|
+
fail4(response, 503, "INTERNAL_ERROR", error62 instanceof Error && error62.message ? error62.message : found.unreadable ?? t2("server.internal"));
|
|
25296
|
+
}
|
|
25297
|
+
}
|
|
25298
|
+
|
|
25299
|
+
// src/server/http/static-files.ts
|
|
25300
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
25301
|
+
import { join } from "node:path";
|
|
25302
|
+
async function loadBrowserAssets(directory) {
|
|
25303
|
+
const assets = /* @__PURE__ */ new Map();
|
|
25304
|
+
async function walk(current, prefix) {
|
|
25305
|
+
for (const entry2 of await readdir(current, { withFileTypes: true })) {
|
|
25306
|
+
if (entry2.isSymbolicLink()) throw new Error(t2("browser.assetSymlink"));
|
|
25307
|
+
const name = prefix + entry2.name;
|
|
25308
|
+
if (entry2.isDirectory()) await walk(join(current, entry2.name), name + "/");
|
|
25309
|
+
else if (entry2.isFile()) assets.set("/" + name, await readFile(join(current, entry2.name)));
|
|
25310
|
+
}
|
|
25311
|
+
}
|
|
25312
|
+
try {
|
|
25313
|
+
await walk(directory, "");
|
|
25314
|
+
if (!assets.has("/index.html")) throw new Error("missing index");
|
|
25315
|
+
} catch {
|
|
25316
|
+
throw new Error(t2("browser.assetsUnreadable"));
|
|
25317
|
+
}
|
|
25318
|
+
return assets;
|
|
25319
|
+
}
|
|
25320
|
+
function contentType(path3) {
|
|
25321
|
+
if (path3.endsWith(".html")) return "text/html; charset=utf-8";
|
|
25322
|
+
if (path3.endsWith(".js")) return "text/javascript; charset=utf-8";
|
|
25323
|
+
if (path3.endsWith(".css")) return "text/css; charset=utf-8";
|
|
25324
|
+
if (path3.endsWith(".svg")) return "image/svg+xml";
|
|
25325
|
+
if (path3.endsWith(".woff2")) return "font/woff2";
|
|
25326
|
+
if (path3.endsWith(".png")) return "image/png";
|
|
25327
|
+
if (/\.jpe?g$/.test(path3)) return "image/jpeg";
|
|
25328
|
+
if (path3.endsWith(".gif")) return "image/gif";
|
|
25329
|
+
if (path3.endsWith(".webp")) return "image/webp";
|
|
25330
|
+
if (path3.endsWith(".pdf")) return "application/pdf";
|
|
25331
|
+
return "application/octet-stream";
|
|
25332
|
+
}
|
|
25333
|
+
function serveStatic(request, response, path3, assets) {
|
|
25334
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
25335
|
+
response.setHeader("Allow", "GET, HEAD");
|
|
25336
|
+
return fail4(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25337
|
+
}
|
|
25338
|
+
let assetPath = path3 === "/" ? "/index.html" : path3;
|
|
25339
|
+
let asset = assets.get(assetPath);
|
|
25340
|
+
if (!asset && !path3.startsWith("/assets/") && !path3.split("/").some((part) => part.includes(".")) && request.headers.accept?.includes("text/html")) {
|
|
25341
|
+
asset = assets.get("/index.html");
|
|
25342
|
+
assetPath = "/index.html";
|
|
25343
|
+
}
|
|
25344
|
+
if (!asset) return fail4(response, 404, "NOT_FOUND", t2("server.fileNotFound"));
|
|
25345
|
+
response.writeHead(200, { "Content-Type": contentType(assetPath), "Cache-Control": "no-cache", "Content-Length": asset.length });
|
|
25346
|
+
response.end(request.method === "HEAD" ? void 0 : asset);
|
|
25347
|
+
}
|
|
25348
|
+
|
|
25349
|
+
// src/server/routes/project-routes.ts
|
|
25350
|
+
function projectRoutes(store, readChangelog) {
|
|
25351
|
+
return [
|
|
25352
|
+
// Re-reading the session never contacts the registry; it returns the state the single startup check left.
|
|
25353
|
+
route({ method: "GET", path: "/api/v1/session", session: false, handle: () => ok(store.session) }),
|
|
25354
|
+
route({ method: "GET", path: "/api/v1/status", session: true, handle: () => ({ status: store.latest.ok ? 200 : 503, body: store.latest }) }),
|
|
25355
|
+
route({ method: "POST", path: "/api/v1/status/refresh", session: true, handle: async ({ allowedOrigin }) => {
|
|
25356
|
+
if (!allowedOrigin) throw new HttpError(403, "FORBIDDEN", t2("server.refreshOrigin"));
|
|
25357
|
+
const value = await store.refresh();
|
|
25358
|
+
return { status: value.ok ? 200 : 503, body: value };
|
|
25359
|
+
} }),
|
|
25360
|
+
route({ method: "GET", path: "/api/v1/changelog", session: true, query: changelogQueryV1, unreadable: t2("server.changelogUnreadable"), handle: async ({ query }) => {
|
|
25361
|
+
const language = query.lang ?? defaultLanguage2;
|
|
25362
|
+
const own2 = await readChangelog(language);
|
|
25363
|
+
const text2 = own2 ?? (language === defaultLanguage2 ? null : await readChangelog(defaultLanguage2));
|
|
25364
|
+
if (text2 === null) throw new HttpError(404, "NOT_FOUND", t2("server.changelogNotFound"));
|
|
25365
|
+
return ok(changelogV1.parse({ contract: "changelog", version: 1, language: own2 === null ? defaultLanguage2 : language, fallback: own2 === null, entries: parseChangelog(text2) }));
|
|
25366
|
+
} })
|
|
25367
|
+
];
|
|
25368
|
+
}
|
|
25369
|
+
|
|
25183
25370
|
// src/adapters/git/command-scope.ts
|
|
25184
25371
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
25185
25372
|
var storage = new AsyncLocalStorage();
|
|
@@ -25222,19 +25409,24 @@ function specPreviewReader(cwd) {
|
|
|
25222
25409
|
}
|
|
25223
25410
|
};
|
|
25224
25411
|
return {
|
|
25412
|
+
/** Git under the same guarded environment, for readers that shape their own commands (the browser's history). */
|
|
25413
|
+
run(args, input2) {
|
|
25414
|
+
return git(args, input2);
|
|
25415
|
+
},
|
|
25416
|
+
decode: decode5,
|
|
25225
25417
|
async index() {
|
|
25226
25418
|
const output2 = decode5(await git(["ls-files", "--stage", "-z", "--", ...RECORD_PATHSPECS]));
|
|
25227
25419
|
const files = /* @__PURE__ */ new Map();
|
|
25228
25420
|
for (const row of output2.split("\0").filter(Boolean)) {
|
|
25229
25421
|
const match = /^(\d+) ([a-f0-9]+) ([0-3])\t([\s\S]+)$/.exec(row);
|
|
25230
25422
|
if (!match) throw new SpecPreviewError(t2("reader.invalidIndexEntry"));
|
|
25231
|
-
const [, mode,
|
|
25423
|
+
const [, mode, oid3, stage, path3] = match;
|
|
25232
25424
|
if (!["100644", "100755"].includes(mode) || stage !== "0") throw new SpecPreviewError(t2("reader.stagingConflictOrLink"));
|
|
25233
25425
|
if (!recordPathPattern.test(path3)) {
|
|
25234
25426
|
if (path3.startsWith(WIKI_DIR + "/")) continue;
|
|
25235
25427
|
throw new SpecPreviewError(t2("reader.stagingUnsupported"));
|
|
25236
25428
|
}
|
|
25237
|
-
files.set(path3,
|
|
25429
|
+
files.set(path3, oid3);
|
|
25238
25430
|
}
|
|
25239
25431
|
return files;
|
|
25240
25432
|
},
|
|
@@ -25267,12 +25459,12 @@ function specPreviewReader(cwd) {
|
|
|
25267
25459
|
});
|
|
25268
25460
|
},
|
|
25269
25461
|
async resolve(ref) {
|
|
25270
|
-
const
|
|
25271
|
-
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(
|
|
25272
|
-
return
|
|
25462
|
+
const oid3 = (await git(["rev-parse", "--verify", "--end-of-options", ref + "^{commit}"])).toString("ascii").trim();
|
|
25463
|
+
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(oid3)) throw new SpecPreviewError(t2("reader.commitUnknown"));
|
|
25464
|
+
return oid3;
|
|
25273
25465
|
},
|
|
25274
|
-
async files(
|
|
25275
|
-
const entries = decode5(await git(["ls-tree", "--full-tree", "-r", "-z",
|
|
25466
|
+
async files(oid3, allowLegacyBaseline = false) {
|
|
25467
|
+
const entries = decode5(await git(["ls-tree", "--full-tree", "-r", "-z", oid3, "--", ...RECORD_PATHSPECS]));
|
|
25276
25468
|
const files = /* @__PURE__ */ new Map();
|
|
25277
25469
|
let legacy;
|
|
25278
25470
|
for (const row of entries.split("\0").filter(Boolean)) {
|
|
@@ -25292,7 +25484,7 @@ function specPreviewReader(cwd) {
|
|
|
25292
25484
|
if (new Set([...files.keys()].map((p) => p.split("/")[0])).size > 1) throw new SpecPreviewError(t2("reader.mixedStores"));
|
|
25293
25485
|
if (legacy) {
|
|
25294
25486
|
if (files.size) throw new SpecPreviewError(t2("reader.mixedFormats"));
|
|
25295
|
-
parseProjectConfig(decode5(await git(["show", `${
|
|
25487
|
+
parseProjectConfig(decode5(await git(["show", `${oid3}:${legacy}/config.json`])));
|
|
25296
25488
|
}
|
|
25297
25489
|
if (files.size > 2e3) throw new SpecPreviewError(t2("reader.fileLimit"));
|
|
25298
25490
|
const blobs = /* @__PURE__ */ new Map();
|
|
@@ -25316,12 +25508,12 @@ function specPreviewReader(cwd) {
|
|
|
25316
25508
|
}
|
|
25317
25509
|
return new Map([...files].map(([path3, id]) => [path3, blobs.get(id)]));
|
|
25318
25510
|
},
|
|
25319
|
-
async read(
|
|
25320
|
-
const files = await this.files(
|
|
25511
|
+
async read(oid3) {
|
|
25512
|
+
const files = await this.files(oid3);
|
|
25321
25513
|
return parsePreviewFiles(files);
|
|
25322
25514
|
},
|
|
25323
|
-
async readBundle(
|
|
25324
|
-
return parsePreviewBundle(await this.files(
|
|
25515
|
+
async readBundle(oid3) {
|
|
25516
|
+
return parsePreviewBundle(await this.files(oid3));
|
|
25325
25517
|
}
|
|
25326
25518
|
};
|
|
25327
25519
|
}
|
|
@@ -25455,7 +25647,7 @@ async function publishConfig(root, text2, recheck, beforePublish, replace = fals
|
|
|
25455
25647
|
}
|
|
25456
25648
|
|
|
25457
25649
|
// src/adapters/filesystem/spec-preview-store.ts
|
|
25458
|
-
var
|
|
25650
|
+
var fail5 = (message) => {
|
|
25459
25651
|
throw new SpecPreviewError(message);
|
|
25460
25652
|
};
|
|
25461
25653
|
var info2 = async (path3) => lstat3(path3).catch((e) => {
|
|
@@ -25465,7 +25657,7 @@ var info2 = async (path3) => lstat3(path3).catch((e) => {
|
|
|
25465
25657
|
var digest = (value) => createHash2("sha256").update(value).digest("hex");
|
|
25466
25658
|
var LEGACY_LOCKS = ["tryce-spec-preview.lock", "tryce-spec-commit.lock"];
|
|
25467
25659
|
async function failOnLegacyLock(gitDir) {
|
|
25468
|
-
for (const name of LEGACY_LOCKS) if (await info2(join4(gitDir, name)))
|
|
25660
|
+
for (const name of LEGACY_LOCKS) if (await info2(join4(gitDir, name))) fail5(t2("store.legacyLock", { path: join4(gitDir, name) }));
|
|
25469
25661
|
}
|
|
25470
25662
|
var decode3 = (bytes) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
25471
25663
|
var generatePreviewId = (prefix) => prefix + "-" + [...randomBytes(10)].map((n) => "abcdefghijklmnopqrstuvwxyz234567"[n & 31]).join("");
|
|
@@ -25473,29 +25665,29 @@ var PreservedPreviewError = class extends SpecPreviewError {
|
|
|
25473
25665
|
};
|
|
25474
25666
|
async function snapshot2(root) {
|
|
25475
25667
|
const files = /* @__PURE__ */ new Map();
|
|
25476
|
-
let
|
|
25668
|
+
let count2 = 0;
|
|
25477
25669
|
let bytes = 0;
|
|
25478
25670
|
const parent = await info2(join4(root, ".gitifact"));
|
|
25479
|
-
if (parent && (!parent.isDirectory() || parent.isSymbolicLink()))
|
|
25480
|
-
if (!parent && await info2(join4(root, ".tryce")))
|
|
25671
|
+
if (parent && (!parent.isDirectory() || parent.isSymbolicLink())) fail5(t2("store.storeNotDirectory"));
|
|
25672
|
+
if (!parent && await info2(join4(root, ".tryce"))) fail5(t2("store.migrateFirst"));
|
|
25481
25673
|
const config2 = await readConfigFile(root);
|
|
25482
|
-
if (config2 !== void 0 && !("schemaVersion" in parseManagedConfig(config2)) || await info2(join4(root, "specs")))
|
|
25674
|
+
if (config2 !== void 0 && !("schemaVersion" in parseManagedConfig(config2)) || await info2(join4(root, "specs"))) fail5(t2("store.legacyProject"));
|
|
25483
25675
|
async function visit2(path3, depth, documents) {
|
|
25484
25676
|
const stat3 = await info2(join4(root, path3));
|
|
25485
25677
|
if (!stat3) return;
|
|
25486
|
-
if (stat3.isSymbolicLink() || !stat3.isDirectory() && !stat3.isFile())
|
|
25487
|
-
if (++
|
|
25678
|
+
if (stat3.isSymbolicLink() || !stat3.isDirectory() && !stat3.isFile()) fail5(t2("store.linkOrSpecial", { path: path3 }));
|
|
25679
|
+
if (++count2 > 4e3) fail5(t2("store.tooManyFiles"));
|
|
25488
25680
|
if (stat3.isDirectory()) {
|
|
25489
|
-
if (depth > (documents ? 8 : 1))
|
|
25681
|
+
if (depth > (documents ? 8 : 1)) fail5(t2("store.tooDeep", { path: path3 }));
|
|
25490
25682
|
for (const name of (await readdir3(join4(root, path3))).sort()) await visit2(path3 + "/" + name, depth + 1, documents);
|
|
25491
25683
|
} else {
|
|
25492
|
-
if (path3.endsWith("/tryce.json"))
|
|
25684
|
+
if (path3.endsWith("/tryce.json")) fail5(t2("store.legacyJson"));
|
|
25493
25685
|
if (documents ? !(path3.endsWith(".md") || depth === 1 && path3.endsWith("/history.jsonl")) : !/\/(requirements\.md|design\.md|history\.jsonl)$/.test(path3)) return;
|
|
25494
|
-
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/"))
|
|
25495
|
-
if (stat3.nlink !== 1 || stat3.size > 1024 * 1024)
|
|
25686
|
+
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/")) fail5(t2("store.unsupportedPath", { path: path3 }));
|
|
25687
|
+
if (stat3.nlink !== 1 || stat3.size > 1024 * 1024) fail5(t2("store.hardLinkOrSize"));
|
|
25496
25688
|
const raw = await readFile3(join4(root, path3));
|
|
25497
25689
|
bytes += raw.length;
|
|
25498
|
-
if (raw.length > 1024 * 1024 || bytes > 16 * 1024 * 1024)
|
|
25690
|
+
if (raw.length > 1024 * 1024 || bytes > 16 * 1024 * 1024) fail5(t2("store.sizeLimit"));
|
|
25499
25691
|
files.set(path3, decode3(raw));
|
|
25500
25692
|
}
|
|
25501
25693
|
}
|
|
@@ -25507,11 +25699,11 @@ async function snapshot2(root) {
|
|
|
25507
25699
|
async function readWorkingPreviewState(cwd) {
|
|
25508
25700
|
const { root, gitDir } = await specPreviewReader(cwd).location();
|
|
25509
25701
|
await failOnLegacyLock(gitDir);
|
|
25510
|
-
if (await info2(join4(gitDir, "gitifact-spec-preview.lock")))
|
|
25702
|
+
if (await info2(join4(gitDir, "gitifact-spec-preview.lock"))) fail5(t2("store.locked"));
|
|
25511
25703
|
const first = await snapshot2(root);
|
|
25512
25704
|
const second = await snapshot2(root);
|
|
25513
|
-
if (first.stamp !== second.stamp)
|
|
25514
|
-
if (await info2(join4(gitDir, "gitifact-spec-preview.lock")))
|
|
25705
|
+
if (first.stamp !== second.stamp) fail5(t2("store.changedWhileReading"));
|
|
25706
|
+
if (await info2(join4(gitDir, "gitifact-spec-preview.lock"))) fail5(t2("store.lockedWhileReading"));
|
|
25515
25707
|
return first;
|
|
25516
25708
|
}
|
|
25517
25709
|
async function readWorkingPreview(cwd) {
|
|
@@ -25519,9 +25711,9 @@ async function readWorkingPreview(cwd) {
|
|
|
25519
25711
|
return { stamp, specs, wiki, warnings: await workingWarnings(root, bundle) };
|
|
25520
25712
|
}
|
|
25521
25713
|
async function saveWorkingPreview(cwd, input2, publish = rename2) {
|
|
25522
|
-
if (!input2 || typeof input2 !== "object" || Array.isArray(input2))
|
|
25714
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) fail5(t2("store.invalidInput"));
|
|
25523
25715
|
const request = input2;
|
|
25524
|
-
if (Object.keys(request).sort().join(",") !== "expected,operations" || typeof request.expected !== "string")
|
|
25716
|
+
if (Object.keys(request).sort().join(",") !== "expected,operations" || typeof request.expected !== "string") fail5(t2("store.expectedOperations"));
|
|
25525
25717
|
return previewTransaction(cwd, request.expected, async (before) => {
|
|
25526
25718
|
const result = editSpecPreview(before.bundle, request.operations, generatePreviewId);
|
|
25527
25719
|
const writes = /* @__PURE__ */ new Map();
|
|
@@ -25549,7 +25741,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
|
|
|
25549
25741
|
try {
|
|
25550
25742
|
await mkdir2(lock);
|
|
25551
25743
|
} catch (e) {
|
|
25552
|
-
if (e.code === "EEXIST")
|
|
25744
|
+
if (e.code === "EEXIST") fail5(t2("store.locked"));
|
|
25553
25745
|
throw e;
|
|
25554
25746
|
}
|
|
25555
25747
|
const createdDirs = [];
|
|
@@ -25560,7 +25752,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
|
|
|
25560
25752
|
async function directory(path3) {
|
|
25561
25753
|
const stat3 = await info2(path3);
|
|
25562
25754
|
if (stat3) {
|
|
25563
|
-
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
25755
|
+
if (!stat3.isDirectory() || stat3.isSymbolicLink()) fail5(t2("store.notDirectory", { path: path3 }));
|
|
25564
25756
|
return;
|
|
25565
25757
|
}
|
|
25566
25758
|
await directory(dirname(path3));
|
|
@@ -25569,11 +25761,11 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
|
|
|
25569
25761
|
}
|
|
25570
25762
|
try {
|
|
25571
25763
|
const before = await snapshot2(root);
|
|
25572
|
-
if (before.stamp !== expected2)
|
|
25764
|
+
if (before.stamp !== expected2) fail5(t2("store.staleExpected"));
|
|
25573
25765
|
const result = await build(before);
|
|
25574
25766
|
for (const [path3, after2] of result.writes) {
|
|
25575
|
-
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/") || path3.split("/").some((p) => p === ".." || p === "." || /[\\:\0]/.test(p)))
|
|
25576
|
-
if (after2 !== null && Buffer.byteLength(after2) > 1024 * 1024)
|
|
25767
|
+
if (!recordPathPattern.test(path3) || path3.startsWith(".tryce/") || path3.split("/").some((p) => p === ".." || p === "." || /[\\:\0]/.test(p))) fail5(t2("store.unsupportedSavePath"));
|
|
25768
|
+
if (after2 !== null && Buffer.byteLength(after2) > 1024 * 1024) fail5(t2("store.fileSizeLimit"));
|
|
25577
25769
|
changed.push({ path: path3, before: before.files.get(path3) ?? null, after: after2 });
|
|
25578
25770
|
}
|
|
25579
25771
|
const finalFiles = new Map(before.files);
|
|
@@ -25581,7 +25773,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
|
|
|
25581
25773
|
if (c.after === null) finalFiles.delete(c.path);
|
|
25582
25774
|
else finalFiles.set(c.path, c.after);
|
|
25583
25775
|
}
|
|
25584
|
-
if (finalFiles.size > 2e3 || [...finalFiles.values()].reduce((n, s) => n + Buffer.byteLength(s), 0) > 16 * 1024 * 1024)
|
|
25776
|
+
if (finalFiles.size > 2e3 || [...finalFiles.values()].reduce((n, s) => n + Buffer.byteLength(s), 0) > 16 * 1024 * 1024) fail5(t2("store.totalLimit"));
|
|
25585
25777
|
await writeFile(join4(lock, "recovery.json"), JSON.stringify({ root, changed }), { flag: "wx" });
|
|
25586
25778
|
for (const c of changed) {
|
|
25587
25779
|
if (c.after === null) {
|
|
@@ -25593,19 +25785,19 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
|
|
|
25593
25785
|
await writeFile(temp, c.after, { flag: "wx" });
|
|
25594
25786
|
temporary.push(temp);
|
|
25595
25787
|
}
|
|
25596
|
-
if ((await snapshot2(root)).stamp !== before.stamp)
|
|
25788
|
+
if ((await snapshot2(root)).stamp !== before.stamp) fail5(t2("store.changedPreparing"));
|
|
25597
25789
|
await result.recheck?.();
|
|
25598
25790
|
for (let i = 0; i < changed.length; i++) {
|
|
25599
25791
|
const c = changed[i];
|
|
25600
25792
|
const path3 = join4(root, c.path);
|
|
25601
25793
|
const stat3 = await info2(path3);
|
|
25602
|
-
if (stat3?.isSymbolicLink() || stat3 && !stat3.isFile() || (stat3 ? decode3(await readFile3(path3)) : null) !== c.before)
|
|
25794
|
+
if (stat3?.isSymbolicLink() || stat3 && !stat3.isFile() || (stat3 ? decode3(await readFile3(path3)) : null) !== c.before) fail5(t2("store.changedBeforeWrite"));
|
|
25603
25795
|
if (c.after === null) await unlink2(path3);
|
|
25604
25796
|
else await publish(temporary[i], path3);
|
|
25605
25797
|
published.push(c);
|
|
25606
25798
|
}
|
|
25607
25799
|
const after = await snapshot2(root);
|
|
25608
|
-
if (after.stamp !== digest(JSON.stringify([...finalFiles].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) + (before.config ?? "")))
|
|
25800
|
+
if (after.stamp !== digest(JSON.stringify([...finalFiles].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) + (before.config ?? ""))) fail5(t2("store.changedWhileWriting"));
|
|
25609
25801
|
await result.recheck?.();
|
|
25610
25802
|
await afterPublish?.(after);
|
|
25611
25803
|
return { ...result.data, stamp: after.stamp, paths: changed.map((c) => c.path), specs: after.specs, wiki: after.wiki, warnings: await workingWarnings(root, after.bundle) };
|
|
@@ -25633,7 +25825,7 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
|
|
|
25633
25825
|
keepRecovery = true;
|
|
25634
25826
|
}
|
|
25635
25827
|
}
|
|
25636
|
-
if (keepRecovery)
|
|
25828
|
+
if (keepRecovery) fail5(t2("store.recoveryIncomplete", { path: lock }));
|
|
25637
25829
|
throw error62;
|
|
25638
25830
|
} finally {
|
|
25639
25831
|
for (const path3 of temporary.filter(Boolean)) await unlink2(path3).catch((e) => {
|
|
@@ -25650,144 +25842,686 @@ async function previewTransaction(cwd, expected2, build, publish = rename2, afte
|
|
|
25650
25842
|
}
|
|
25651
25843
|
}
|
|
25652
25844
|
|
|
25653
|
-
// src/server/
|
|
25654
|
-
|
|
25845
|
+
// src/server/checkout/checkout-reader.ts
|
|
25846
|
+
var tally = (people, name, email3, latest) => {
|
|
25847
|
+
const person = people.get(email3);
|
|
25848
|
+
if (person) person.commits++;
|
|
25849
|
+
else people.set(email3, { name, email: email3, latest, commits: 1 });
|
|
25850
|
+
};
|
|
25851
|
+
async function settled(reads) {
|
|
25852
|
+
const results = await Promise.allSettled(reads);
|
|
25853
|
+
const failure2 = results.find((r) => r.status === "rejected");
|
|
25854
|
+
if (failure2) throw failure2.reason;
|
|
25855
|
+
return results.map((r) => r.value);
|
|
25856
|
+
}
|
|
25857
|
+
function createCheckoutReader(root, sessionId, inherited = process.env) {
|
|
25655
25858
|
const reader = specPreviewReader(root);
|
|
25656
25859
|
const runner = createGitRunner();
|
|
25657
25860
|
const env = { ...inherited, GIT_OPTIONAL_LOCKS: "0", GIT_NO_REPLACE_OBJECTS: "1", GIT_TERMINAL_PROMPT: "0", LC_ALL: "C" };
|
|
25658
|
-
const git = async (args, acceptedExitCodes = [0]) => (await runner(["--no-optional-locks", ...args], { cwd: root, env, timeoutMs: 15e3, maxBytes:
|
|
25861
|
+
const git = async (args, acceptedExitCodes = [0]) => (await runner(["--no-optional-locks", ...args], { cwd: root, env, timeoutMs: 15e3, maxBytes: 32 * 1024 * 1024, acceptedExitCodes })).toString("utf8");
|
|
25659
25862
|
const readHead = async () => {
|
|
25660
25863
|
const head = (await git(["rev-parse", "--verify", "--quiet", "HEAD"], [0, 1])).trim();
|
|
25661
25864
|
if (head && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) throw new SpecPreviewError(t2("specReader.headUnreadable"));
|
|
25662
25865
|
if (!head) await reader.baseline();
|
|
25663
25866
|
return head || null;
|
|
25664
25867
|
};
|
|
25665
|
-
const snapshots = /* @__PURE__ */ new Map();
|
|
25666
|
-
const snapshot3 = (oid2) => {
|
|
25667
|
-
let value = snapshots.get(oid2);
|
|
25668
|
-
if (!value) {
|
|
25669
|
-
value = reader.readBundle(oid2).catch((e) => {
|
|
25670
|
-
snapshots.delete(oid2);
|
|
25671
|
-
throw e;
|
|
25672
|
-
});
|
|
25673
|
-
snapshots.set(oid2, value);
|
|
25674
|
-
}
|
|
25675
|
-
if (snapshots.size > 128) snapshots.delete(snapshots.keys().next().value);
|
|
25676
|
-
return value;
|
|
25677
|
-
};
|
|
25678
|
-
let peopleCache;
|
|
25679
25868
|
const pending = /* @__PURE__ */ new Map();
|
|
25680
|
-
async function
|
|
25869
|
+
async function storeAuthors(head) {
|
|
25870
|
+
const text2 = await git(["log", "--format=%x1e%aN%x00%aE%x00%aI", "-z", "--name-only", "--no-renames", "--max-count=20000", head, "--", ".gitifact", ".tryce"]);
|
|
25871
|
+
const folders = /* @__PURE__ */ new Map();
|
|
25872
|
+
const pages = /* @__PURE__ */ new Map();
|
|
25873
|
+
for (const chunk of text2.split("")) {
|
|
25874
|
+
if (!chunk) continue;
|
|
25875
|
+
const [name, email3, date5, ...paths2] = chunk.split("\0");
|
|
25876
|
+
if (!name || !email3 || !date5) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
|
|
25877
|
+
const seen = /* @__PURE__ */ new Set();
|
|
25878
|
+
for (const raw of paths2) {
|
|
25879
|
+
const path3 = raw.replace(/^\n/, "");
|
|
25880
|
+
if (!path3) continue;
|
|
25881
|
+
const folder = /^\.(?:gitifact|tryce)\/(spec\/[^/]+)\//.exec(path3)?.[1];
|
|
25882
|
+
if (folder && !seen.has(folder)) {
|
|
25883
|
+
seen.add(folder);
|
|
25884
|
+
let entry2 = folders.get(folder);
|
|
25885
|
+
if (!entry2) folders.set(folder, entry2 = { people: /* @__PURE__ */ new Map(), count: 0, latest: date5 });
|
|
25886
|
+
if (entry2.count < 2e3) {
|
|
25887
|
+
entry2.count++;
|
|
25888
|
+
tally(entry2.people, name, email3, date5);
|
|
25889
|
+
}
|
|
25890
|
+
}
|
|
25891
|
+
if (path3.startsWith(WIKI_DIR + "/") && !pages.has(path3)) pages.set(path3, date5);
|
|
25892
|
+
}
|
|
25893
|
+
}
|
|
25894
|
+
return { folders, pages };
|
|
25895
|
+
}
|
|
25896
|
+
async function read() {
|
|
25681
25897
|
const raw = await readConfigFile(root);
|
|
25682
25898
|
if (!raw || !("schemaVersion" in parseManagedConfig(raw))) throw new SpecPreviewError(t2("specReader.schemaRequired"));
|
|
25683
|
-
const
|
|
25684
|
-
|
|
25685
|
-
|
|
25686
|
-
|
|
25687
|
-
|
|
25688
|
-
|
|
25689
|
-
|
|
25690
|
-
const first = cursor === 0;
|
|
25691
|
-
const features = !first ? void 0 : await Promise.all(bare.map(async (feature2) => {
|
|
25692
|
-
const folder = feature2.path.replace(/^\.(?:gitifact|tryce)\/(spec\/[^/]+)\/requirements\.md$/, "$1");
|
|
25693
|
-
const lines = (await git(["log", "--format=%aN%x00%aE%x00%aI", "--max-count=2000", head, "--", `.gitifact/${folder}`, `.tryce/${folder}`])).trim().split("\n").filter(Boolean);
|
|
25694
|
-
const people = /* @__PURE__ */ new Map();
|
|
25695
|
-
for (const line of lines) {
|
|
25696
|
-
const [name, email3, latest] = line.split("\0");
|
|
25697
|
-
if (!name || !email3 || !latest) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
|
|
25698
|
-
const person = people.get(email3);
|
|
25699
|
-
if (person) person.commits++;
|
|
25700
|
-
else people.set(email3, { name, email: email3, latest, commits: 1 });
|
|
25701
|
-
}
|
|
25702
|
-
return { ...feature2, contributors: [...people.values()].sort((a, b) => b.commits - a.commits), updatedAt: lines[0]?.split("\0")[2] ?? null };
|
|
25703
|
-
}));
|
|
25704
|
-
const documents = !first ? void 0 : await Promise.all(bareDocuments.map(async (doc) => ({ ...doc, updatedAt: (await git(["log", "--format=%aI", "--max-count=1", head, "--", doc.path])).trim() || null })));
|
|
25705
|
-
const documentDirs = [WIKI_DIR];
|
|
25706
|
-
const [rows, dirty] = await Promise.all([
|
|
25707
|
-
git([
|
|
25708
|
-
"log",
|
|
25709
|
-
"--first-parent",
|
|
25710
|
-
"--date-order",
|
|
25711
|
-
"--format=%H%x00%P%x00%aN%x00%aE%x00%aI%x00%cN%x00%s",
|
|
25712
|
-
"--max-count=11",
|
|
25713
|
-
"--skip=" + cursor,
|
|
25714
|
-
head,
|
|
25715
|
-
"--",
|
|
25716
|
-
...[".gitifact", ".tryce"].flatMap((d) => [`:(glob)${d}/spec/*/requirements.md`, `:(glob)${d}/spec/*/design.md`, `:(glob)${d}/spec/*/history.jsonl`]),
|
|
25717
|
-
...documentDirs.flatMap((d) => [`:(glob)${d}/**/*.md`, `:(glob)${d}/history.jsonl`])
|
|
25718
|
-
]),
|
|
25719
|
-
first ? git(["status", "--porcelain=v1", "--", ".gitifact/spec", ...documentDirs]) : Promise.resolve("")
|
|
25899
|
+
const head = await readHead();
|
|
25900
|
+
const [current, dirty, authors, everyone] = await settled([
|
|
25901
|
+
readWorkingPreviewState(root),
|
|
25902
|
+
head ? git(["status", "--porcelain=v1", "--", ".gitifact/spec", WIKI_DIR]) : Promise.resolve(""),
|
|
25903
|
+
head ? storeAuthors(head) : Promise.resolve(void 0),
|
|
25904
|
+
// Git mailmap may change without a new HEAD; refresh names with every observation that carries them.
|
|
25905
|
+
head ? git(["log", "--format=%aN%x00%aE%x00%aI", "--max-count=10001", head]) : Promise.resolve("")
|
|
25720
25906
|
]);
|
|
25721
|
-
|
|
25722
|
-
|
|
25723
|
-
|
|
25724
|
-
|
|
25725
|
-
|
|
25726
|
-
|
|
25727
|
-
|
|
25728
|
-
|
|
25729
|
-
|
|
25730
|
-
}
|
|
25731
|
-
|
|
25732
|
-
}
|
|
25733
|
-
|
|
25734
|
-
|
|
25735
|
-
const groups = await Promise.all(commits.slice(0, 10).map(async (row) => {
|
|
25736
|
-
const [commit, parents, author, email3, date5, committer, message] = row.split("\0");
|
|
25737
|
-
if (!commit || author === void 0 || email3 === void 0 || !date5 || committer === void 0 || message === void 0) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
|
|
25738
|
-
const after = await snapshot3(commit);
|
|
25739
|
-
let before = emptyBundle();
|
|
25740
|
-
const parent = parents?.split(" ")[0];
|
|
25741
|
-
if (parent) {
|
|
25742
|
-
try {
|
|
25743
|
-
before = await snapshot3(parent);
|
|
25744
|
-
} catch (error62) {
|
|
25745
|
-
if (error62 instanceof LegacyBaselineError) boundary = true;
|
|
25746
|
-
else throw error62;
|
|
25747
|
-
}
|
|
25748
|
-
}
|
|
25749
|
-
return comparePreviewBundles(before, after).changes.map((c) => ({
|
|
25750
|
-
key: commit + ":" + c.id,
|
|
25751
|
-
commit,
|
|
25752
|
-
author,
|
|
25753
|
-
email: email3,
|
|
25754
|
-
date: date5,
|
|
25755
|
-
committer,
|
|
25756
|
-
message,
|
|
25757
|
-
id: c.id,
|
|
25758
|
-
kind: c.kind,
|
|
25759
|
-
types: c.types,
|
|
25760
|
-
before: c.before,
|
|
25761
|
-
after: c.after,
|
|
25762
|
-
reasons: c.reasons.map((r) => r.reason)
|
|
25763
|
-
}));
|
|
25764
|
-
}));
|
|
25765
|
-
if (await readHead() !== head || (await readWorkingPreviewState(root)).stamp !== current.stamp) throw new SpecPreviewError(t2("specReader.projectChanged"));
|
|
25766
|
-
return browserSpecsV3.parse({
|
|
25907
|
+
const people = /* @__PURE__ */ new Map();
|
|
25908
|
+
const lines = everyone.trim().split("\n").filter(Boolean);
|
|
25909
|
+
for (const line of lines.slice(0, 1e4)) {
|
|
25910
|
+
const [name, email3, latest] = line.split("\0");
|
|
25911
|
+
if (!name || !email3 || !latest) throw new SpecPreviewError(t2("specReader.authorUnreadable"));
|
|
25912
|
+
tally(people, name, email3, latest);
|
|
25913
|
+
}
|
|
25914
|
+
const features = current.specs.map(({ history: _history, ...feature2 }) => {
|
|
25915
|
+
const entry2 = authors?.folders.get(feature2.path.replace(/^\.(?:gitifact|tryce)\/(spec\/[^/]+)\/requirements\.md$/, "$1"));
|
|
25916
|
+
return { ...feature2, contributors: entry2 ? [...entry2.people.values()].sort((a, b) => b.commits - a.commits) : [], updatedAt: entry2?.latest ?? null };
|
|
25917
|
+
});
|
|
25918
|
+
const documents = current.wiki.documents.map((doc) => ({ ...doc, updatedAt: authors?.pages.get(doc.path) ?? null }));
|
|
25919
|
+
if (await readHead() !== head) throw new SpecPreviewError(t2("specReader.projectChanged"));
|
|
25920
|
+
const checkout = browserSpecsV4.parse({
|
|
25767
25921
|
contract: "browser-specs",
|
|
25768
|
-
version:
|
|
25922
|
+
version: 4,
|
|
25769
25923
|
sessionId,
|
|
25770
25924
|
head,
|
|
25771
25925
|
observedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25772
|
-
|
|
25773
|
-
|
|
25774
|
-
|
|
25775
|
-
|
|
25926
|
+
working: head ? !!dirty.trim() : features.length > 0 || documents.length > 0,
|
|
25927
|
+
features,
|
|
25928
|
+
documents,
|
|
25929
|
+
contributors: [...people.values()].sort((a, b) => b.commits - a.commits),
|
|
25930
|
+
contributorsLimited: lines.length > 1e4
|
|
25931
|
+
});
|
|
25932
|
+
const search = features.flatMap((f) => [
|
|
25933
|
+
{ kind: "feature", ref: f.id, title: f.title, where: f.path.replace(/^\.gitifact\//, ""), body: f.description, featureId: f.id },
|
|
25934
|
+
...f.requirements.map((r) => ({ kind: "requirement", ref: r.id, title: r.title, where: f.title, body: r.body, featureId: f.id })),
|
|
25935
|
+
...f.design ? [{ kind: "design", ref: f.id + ":design", title: f.design.title, where: f.title, body: f.design.body, featureId: f.id }] : []
|
|
25936
|
+
]).concat(documents.map((d) => ({ kind: "document", ref: d.id, title: d.title, where: d.path.replace(/^\.gitifact\/wiki\//, ""), body: d.body, documentId: d.id })));
|
|
25937
|
+
return { checkout, stamp: current.stamp, search };
|
|
25938
|
+
}
|
|
25939
|
+
return () => {
|
|
25940
|
+
let value = pending.get("");
|
|
25941
|
+
if (!value) {
|
|
25942
|
+
value = read().finally(() => pending.delete(""));
|
|
25943
|
+
pending.set("", value);
|
|
25944
|
+
}
|
|
25945
|
+
return value;
|
|
25946
|
+
};
|
|
25947
|
+
}
|
|
25948
|
+
|
|
25949
|
+
// src/server/history/commit-changes.ts
|
|
25950
|
+
var HISTORY_PATHSPECS = [
|
|
25951
|
+
...STORE_DIRS.flatMap((d) => [`:(glob)${d}/spec/*/requirements.md`, `:(glob)${d}/spec/*/design.md`, `:(glob)${d}/spec/*/history.jsonl`]),
|
|
25952
|
+
`:(glob)${WIKI_DIR}/**/*.md`,
|
|
25953
|
+
`:(glob)${WIKI_HISTORY_PATH}`
|
|
25954
|
+
];
|
|
25955
|
+
var RECORD_ROOTS = [...STORE_DIRS.map((d) => d + "/spec/"), WIKI_DIR + "/"];
|
|
25956
|
+
var isLegacy = (path3) => RECORD_ROOTS.some((root) => path3.startsWith(root)) && path3.endsWith("/tryce.json");
|
|
25957
|
+
var isZero = (oid3) => /^0+$/.test(oid3);
|
|
25958
|
+
var FORMAT = "%x1e%H%x00%P%x00%aN%x00%aE%x00%aI%x00%cN%x00%s";
|
|
25959
|
+
var BATCH = 100;
|
|
25960
|
+
function createCommitChanges(root, snapshot3) {
|
|
25961
|
+
const reader = specPreviewReader(root);
|
|
25962
|
+
function parseLog(text2) {
|
|
25963
|
+
return text2.split("").filter((chunk) => chunk.length).map((chunk) => {
|
|
25964
|
+
const parts = chunk.split("\0");
|
|
25965
|
+
const [commit, parents, author, email3, date5, committer, message] = parts;
|
|
25966
|
+
if (!commit || parents === void 0 || author === void 0 || email3 === void 0 || !date5 || committer === void 0 || message === void 0) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
|
|
25967
|
+
const entries = [];
|
|
25968
|
+
for (let i = 7; i < parts.length; i++) {
|
|
25969
|
+
const meta3 = parts[i].replace(/^\n/, "");
|
|
25970
|
+
if (!meta3.startsWith(":")) continue;
|
|
25971
|
+
const [, , oldBlob, newBlob] = meta3.split(" ");
|
|
25972
|
+
const path3 = parts[++i];
|
|
25973
|
+
if (!oldBlob || !newBlob || path3 === void 0) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
|
|
25974
|
+
if (recordPathPattern.test(path3) || isLegacy(path3)) entries.push({ oldBlob, newBlob, path: path3 });
|
|
25975
|
+
}
|
|
25976
|
+
return { commit, parent: parents.split(" ")[0] || void 0, author, email: email3, date: date5, committer, message, entries };
|
|
25977
|
+
});
|
|
25978
|
+
}
|
|
25979
|
+
function wanted(entries) {
|
|
25980
|
+
const folders = /* @__PURE__ */ new Set();
|
|
25981
|
+
const pages = /* @__PURE__ */ new Set();
|
|
25982
|
+
for (const { path: path3 } of entries) {
|
|
25983
|
+
if (isLegacy(path3)) continue;
|
|
25984
|
+
if (path3.startsWith(WIKI_DIR + "/")) {
|
|
25985
|
+
pages.add(path3);
|
|
25986
|
+
pages.add(WIKI_HISTORY_PATH);
|
|
25987
|
+
continue;
|
|
25988
|
+
}
|
|
25989
|
+
folders.add(path3.replace(/\/[^/]+$/, ""));
|
|
25990
|
+
}
|
|
25991
|
+
return [...[...folders].flatMap((f) => ["requirements.md", "design.md", "history.jsonl"].map((n) => f + "/" + n)), ...pages];
|
|
25992
|
+
}
|
|
25993
|
+
async function readBlobs(names) {
|
|
25994
|
+
const found = /* @__PURE__ */ new Map();
|
|
25995
|
+
if (!names.length) return found;
|
|
25996
|
+
const output2 = await reader.run(["cat-file", "--batch"], Buffer.from(names.join("\n") + "\n"));
|
|
25997
|
+
let offset = 0;
|
|
25998
|
+
let total = 0;
|
|
25999
|
+
for (const name of names) {
|
|
26000
|
+
const end = output2.indexOf(10, offset);
|
|
26001
|
+
if (end < 0) throw new SpecPreviewError(t2("reader.blobBoundary"));
|
|
26002
|
+
const header = output2.subarray(offset, end).toString("utf8");
|
|
26003
|
+
if (header.endsWith(" missing")) {
|
|
26004
|
+
offset = end + 1;
|
|
26005
|
+
continue;
|
|
26006
|
+
}
|
|
26007
|
+
const [, type, sizeText] = header.split(" ");
|
|
26008
|
+
const size = Number(sizeText);
|
|
26009
|
+
if (type !== "blob" || !Number.isSafeInteger(size) || size < 0 || size > 1024 * 1024 || output2[end + size + 1] !== 10) throw new SpecPreviewError(t2("reader.blobShape"));
|
|
26010
|
+
total += size;
|
|
26011
|
+
if (total > 64 * 1024 * 1024) throw new SpecPreviewError(t2("reader.totalLimit"));
|
|
26012
|
+
found.set(name, reader.decode(output2.subarray(end + 1, end + 1 + size)));
|
|
26013
|
+
offset = end + size + 2;
|
|
26014
|
+
}
|
|
26015
|
+
if (offset !== output2.length) throw new SpecPreviewError(t2("reader.blobBoundary"));
|
|
26016
|
+
return found;
|
|
26017
|
+
}
|
|
26018
|
+
const eventsOf = (c, changes) => changes.map((change2) => ({
|
|
26019
|
+
key: c.commit + ":" + change2.id,
|
|
26020
|
+
commit: c.commit,
|
|
26021
|
+
author: c.author,
|
|
26022
|
+
email: c.email,
|
|
26023
|
+
date: c.date,
|
|
26024
|
+
committer: c.committer,
|
|
26025
|
+
message: c.message,
|
|
26026
|
+
id: change2.id,
|
|
26027
|
+
kind: change2.kind,
|
|
26028
|
+
types: change2.types,
|
|
26029
|
+
before: change2.before,
|
|
26030
|
+
after: change2.after,
|
|
26031
|
+
reasons: change2.reasons.map((r) => r.reason)
|
|
26032
|
+
}));
|
|
26033
|
+
async function wholeStore(c) {
|
|
26034
|
+
const after = await snapshot3(c.commit);
|
|
26035
|
+
let before = emptyBundle();
|
|
26036
|
+
let boundary = false;
|
|
26037
|
+
if (c.parent) {
|
|
26038
|
+
try {
|
|
26039
|
+
before = await snapshot3(c.parent);
|
|
26040
|
+
} catch (error62) {
|
|
26041
|
+
if (error62 instanceof LegacyBaselineError) boundary = true;
|
|
26042
|
+
else throw error62;
|
|
26043
|
+
}
|
|
26044
|
+
}
|
|
26045
|
+
return { commit: c.commit, events: eventsOf(c, comparePreviewBundles(before, after).changes), boundary };
|
|
26046
|
+
}
|
|
26047
|
+
async function batch(commits) {
|
|
26048
|
+
const names = /* @__PURE__ */ new Map();
|
|
26049
|
+
for (const c of commits.filter((c2) => !c2.entries.some((e) => isLegacy(e.path) && !isZero(e.newBlob)))) {
|
|
26050
|
+
const files = wanted(c.entries);
|
|
26051
|
+
const boundary = c.entries.some((e) => isLegacy(e.path) && !isZero(e.oldBlob));
|
|
26052
|
+
names.set(c, { after: files.map((f) => c.commit + ":" + f), before: c.parent && !boundary ? files.map((f) => c.parent + ":" + f) : [], boundary });
|
|
26053
|
+
}
|
|
26054
|
+
let blobs;
|
|
26055
|
+
try {
|
|
26056
|
+
blobs = await readBlobs([...names.values()].flatMap((n) => [...n.before, ...n.after]));
|
|
26057
|
+
} catch {
|
|
26058
|
+
blobs = void 0;
|
|
26059
|
+
}
|
|
26060
|
+
const result = [];
|
|
26061
|
+
for (const c of commits) {
|
|
26062
|
+
let value;
|
|
26063
|
+
const want = names.get(c);
|
|
26064
|
+
if (want && blobs) {
|
|
26065
|
+
try {
|
|
26066
|
+
const side = (list, rev) => new Map(list.filter((name) => blobs.has(name)).map((name) => [name.slice(rev.length + 1), blobs.get(name)]));
|
|
26067
|
+
const after = parsePreviewBundle(side(want.after, c.commit));
|
|
26068
|
+
const before = want.before.length ? parsePreviewBundle(side(want.before, c.parent)) : emptyBundle();
|
|
26069
|
+
value = { commit: c.commit, events: eventsOf(c, comparePreviewBundles(before, after).changes), boundary: want.boundary };
|
|
26070
|
+
} catch {
|
|
26071
|
+
value = void 0;
|
|
26072
|
+
}
|
|
26073
|
+
}
|
|
26074
|
+
result.push(value ?? await wholeStore(c));
|
|
26075
|
+
}
|
|
26076
|
+
return result;
|
|
26077
|
+
}
|
|
26078
|
+
return {
|
|
26079
|
+
/** The commits of `head`'s first-parent history that touched records, newest first. One Git process. */
|
|
26080
|
+
async lineage(head) {
|
|
26081
|
+
const text2 = reader.decode(await reader.run(["rev-list", "--first-parent", head, "--", ...HISTORY_PATHSPECS]));
|
|
26082
|
+
return text2.split("\n").filter(Boolean);
|
|
26083
|
+
},
|
|
26084
|
+
/** The changes of the given commits, in the given order; two Git processes per hundred commits. */
|
|
26085
|
+
async of(commits) {
|
|
26086
|
+
const out = [];
|
|
26087
|
+
for (let i = 0; i < commits.length; i += BATCH) {
|
|
26088
|
+
const slice = commits.slice(i, i + BATCH);
|
|
26089
|
+
const raw = parseLog(reader.decode(await reader.run(
|
|
26090
|
+
["log", "--stdin", "--no-walk=unsorted", "--diff-merges=first-parent", "--raw", "-z", "--no-renames", "--no-abbrev", `--format=${FORMAT}`],
|
|
26091
|
+
Buffer.from(slice.join("\n") + "\n")
|
|
26092
|
+
)));
|
|
26093
|
+
const byCommit = new Map(raw.map((c) => [c.commit, c]));
|
|
26094
|
+
const missing2 = slice.find((oid3) => !byCommit.has(oid3));
|
|
26095
|
+
if (missing2) throw new SpecPreviewError(t2("specReader.historyUnreadable"));
|
|
26096
|
+
out.push(...await batch(slice.map((oid3) => byCommit.get(oid3))));
|
|
26097
|
+
}
|
|
26098
|
+
return out;
|
|
26099
|
+
}
|
|
26100
|
+
};
|
|
26101
|
+
}
|
|
26102
|
+
|
|
26103
|
+
// src/server/history/index-database.ts
|
|
26104
|
+
import { DatabaseSync } from "node:sqlite";
|
|
26105
|
+
import { mkdir as mkdir3, rm } from "node:fs/promises";
|
|
26106
|
+
import { join as join5 } from "node:path";
|
|
26107
|
+
var INDEX_FORMAT = 1;
|
|
26108
|
+
var SCHEMA = `
|
|
26109
|
+
-- Commits already read, and whether the commit's parent was legacy JSON the history does not read past.
|
|
26110
|
+
CREATE TABLE commits (oid TEXT PRIMARY KEY, boundary INTEGER NOT NULL);
|
|
26111
|
+
-- One row per change. 'row' is the list shape as JSON; 'detail' the text on both sides.
|
|
26112
|
+
CREATE TABLE changes (
|
|
26113
|
+
key TEXT PRIMARY KEY, oid TEXT NOT NULL, ord INTEGER NOT NULL,
|
|
26114
|
+
id TEXT NOT NULL, kind TEXT NOT NULL, types TEXT NOT NULL, email TEXT NOT NULL, date TEXT NOT NULL,
|
|
26115
|
+
before_spec TEXT, after_spec TEXT, needle TEXT NOT NULL, row TEXT NOT NULL, detail TEXT NOT NULL);
|
|
26116
|
+
CREATE INDEX changes_by_commit ON changes (oid, ord);
|
|
26117
|
+
-- The commits of one HEAD's first-parent history that touched records, newest first (pos 0).
|
|
26118
|
+
CREATE TABLE lineage (head TEXT NOT NULL, pos INTEGER NOT NULL, oid TEXT NOT NULL, PRIMARY KEY (head, pos));
|
|
26119
|
+
CREATE INDEX lineage_by_commit ON lineage (head, oid);
|
|
26120
|
+
CREATE TABLE heads (head TEXT PRIMARY KEY, seen INTEGER NOT NULL);
|
|
26121
|
+
-- Which checkout of which worktree the search rows describe.
|
|
26122
|
+
CREATE TABLE checkouts (scope TEXT PRIMARY KEY, stamp TEXT NOT NULL);
|
|
26123
|
+
-- Everything the search box finds. The searched columns hold lower-cased text; trigram lets LIKE '%...%' use the
|
|
26124
|
+
-- index from three characters on and scan below that. The rest is carried for display and navigation.
|
|
26125
|
+
CREATE VIRTUAL TABLE search USING fts5(
|
|
26126
|
+
scope UNINDEXED, kind UNINDEXED, ref UNINDEXED, oid UNINDEXED, payload UNINDEXED,
|
|
26127
|
+
title, place, body, tokenize = 'trigram');
|
|
26128
|
+
`;
|
|
26129
|
+
function prepare(db) {
|
|
26130
|
+
db.exec("PRAGMA busy_timeout = 5000; PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL;");
|
|
26131
|
+
const version2 = db.prepare("PRAGMA user_version").get().user_version;
|
|
26132
|
+
if (version2 === INDEX_FORMAT) return;
|
|
26133
|
+
db.exec("BEGIN IMMEDIATE");
|
|
26134
|
+
try {
|
|
26135
|
+
for (const { name, type } of db.prepare("SELECT name, type FROM sqlite_master WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' AND name NOT LIKE 'search_%'").all()) {
|
|
26136
|
+
db.exec(`DROP ${type === "view" ? "VIEW" : "TABLE"} IF EXISTS "${name}"`);
|
|
26137
|
+
}
|
|
26138
|
+
db.exec(SCHEMA);
|
|
26139
|
+
db.exec(`PRAGMA user_version = ${INDEX_FORMAT}`);
|
|
26140
|
+
db.exec("COMMIT");
|
|
26141
|
+
} catch (error62) {
|
|
26142
|
+
db.exec("ROLLBACK");
|
|
26143
|
+
throw error62;
|
|
26144
|
+
}
|
|
26145
|
+
}
|
|
26146
|
+
function createIndexDatabase(root) {
|
|
26147
|
+
let path3;
|
|
26148
|
+
let memory;
|
|
26149
|
+
const usable = (file2) => {
|
|
26150
|
+
try {
|
|
26151
|
+
const probe = new DatabaseSync(file2);
|
|
26152
|
+
try {
|
|
26153
|
+
prepare(probe);
|
|
26154
|
+
} finally {
|
|
26155
|
+
probe.close();
|
|
26156
|
+
}
|
|
26157
|
+
return true;
|
|
26158
|
+
} catch {
|
|
26159
|
+
return false;
|
|
26160
|
+
}
|
|
26161
|
+
};
|
|
26162
|
+
const locate = () => path3 ??= (async () => {
|
|
26163
|
+
try {
|
|
26164
|
+
const git = specPreviewReader(root);
|
|
26165
|
+
const common = git.decode(await git.run(["rev-parse", "--path-format=absolute", "--git-common-dir"])).trim();
|
|
26166
|
+
const folder = join5(common, "gitifact");
|
|
26167
|
+
await mkdir3(folder, { recursive: true });
|
|
26168
|
+
const file2 = join5(folder, "index.sqlite");
|
|
26169
|
+
if (usable(file2)) return file2;
|
|
26170
|
+
for (const leftover of [file2, file2 + "-wal", file2 + "-shm"]) await rm(leftover, { force: true });
|
|
26171
|
+
return usable(file2) ? file2 : void 0;
|
|
26172
|
+
} catch {
|
|
26173
|
+
return void 0;
|
|
26174
|
+
}
|
|
26175
|
+
})();
|
|
26176
|
+
return {
|
|
26177
|
+
/** Runs `use` on an open database. Everything inside is synchronous, so the connection never outlives the call. */
|
|
26178
|
+
async with(use) {
|
|
26179
|
+
const file2 = await locate();
|
|
26180
|
+
if (!file2) {
|
|
26181
|
+
if (!memory) {
|
|
26182
|
+
memory = new DatabaseSync(":memory:");
|
|
26183
|
+
prepare(memory);
|
|
26184
|
+
}
|
|
26185
|
+
return use(memory);
|
|
26186
|
+
}
|
|
26187
|
+
const db = new DatabaseSync(file2);
|
|
26188
|
+
try {
|
|
26189
|
+
prepare(db);
|
|
26190
|
+
return use(db);
|
|
26191
|
+
} finally {
|
|
26192
|
+
db.close();
|
|
26193
|
+
}
|
|
26194
|
+
},
|
|
26195
|
+
/** Where the index is kept, or undefined when it lives in memory. */
|
|
26196
|
+
location: () => locate()
|
|
26197
|
+
};
|
|
26198
|
+
}
|
|
26199
|
+
function transaction(db, write) {
|
|
26200
|
+
db.exec("BEGIN IMMEDIATE");
|
|
26201
|
+
try {
|
|
26202
|
+
const value = write();
|
|
26203
|
+
db.exec("COMMIT");
|
|
26204
|
+
return value;
|
|
26205
|
+
} catch (error62) {
|
|
26206
|
+
db.exec("ROLLBACK");
|
|
26207
|
+
throw error62;
|
|
26208
|
+
}
|
|
26209
|
+
}
|
|
26210
|
+
|
|
26211
|
+
// src/server/history/search-text.ts
|
|
26212
|
+
function plain(body) {
|
|
26213
|
+
return body.replace(/```[\s\S]*?```/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/^\s*[#>]+\s*/gm, " ").replace(/^\s*[-*+]\s+/gm, " ").replace(/^\s*\|/gm, " ").replace(/\|/g, " ").replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/[*_`]/g, "").replace(/\s+/g, " ").trim();
|
|
26214
|
+
}
|
|
26215
|
+
function snippet(text2, query) {
|
|
26216
|
+
const at = text2.toLowerCase().indexOf(query);
|
|
26217
|
+
if (at < 0) return text2.slice(0, 90);
|
|
26218
|
+
const from = Math.max(0, at - 30);
|
|
26219
|
+
return (from > 0 ? "\u2026" : "") + text2.slice(from, at + query.length + 70).trim() + (at + query.length + 70 < text2.length ? "\u2026" : "");
|
|
26220
|
+
}
|
|
26221
|
+
var containing = (query) => "%" + query.replace(/[\\%_]/g, (c) => "\\" + c) + "%";
|
|
26222
|
+
|
|
26223
|
+
// src/server/history/history-index.ts
|
|
26224
|
+
var listed = (e) => {
|
|
26225
|
+
const reference2 = (s) => s ? { id: s.id, title: s.title, specId: s.specId, path: s.path } : null;
|
|
26226
|
+
return { ...e, before: reference2(e.before), after: reference2(e.after) };
|
|
26227
|
+
};
|
|
26228
|
+
var titleOf = (e) => (e.after ?? e.before)?.title ?? e.id;
|
|
26229
|
+
var DAY = 864e5;
|
|
26230
|
+
var KEPT_HEADS = 4;
|
|
26231
|
+
var RECENT_COMMITS = 3;
|
|
26232
|
+
var RECENT_CHANGES = 12;
|
|
26233
|
+
function createHistoryIndex(root, snapshot3) {
|
|
26234
|
+
const changes = createCommitChanges(root, snapshot3);
|
|
26235
|
+
const database = createIndexDatabase(root);
|
|
26236
|
+
const building = /* @__PURE__ */ new Map();
|
|
26237
|
+
const built = /* @__PURE__ */ new Set();
|
|
26238
|
+
function insert(db, commits) {
|
|
26239
|
+
const commit = db.prepare("INSERT OR IGNORE INTO commits (oid, boundary) VALUES (?, ?)");
|
|
26240
|
+
const change2 = db.prepare("INSERT OR IGNORE INTO changes (key, oid, ord, id, kind, types, email, date, before_spec, after_spec, needle, row, detail) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
|
26241
|
+
const search = db.prepare("INSERT INTO search (scope, kind, ref, oid, payload, title, place, body) VALUES (?,?,?,?,?,?,?,?)");
|
|
26242
|
+
transaction(db, () => {
|
|
26243
|
+
for (const c of commits) {
|
|
26244
|
+
if (!Number(commit.run(c.commit, c.boundary ? 1 : 0).changes)) continue;
|
|
26245
|
+
c.events.forEach((e, ord) => {
|
|
26246
|
+
change2.run(
|
|
26247
|
+
e.key,
|
|
26248
|
+
e.commit,
|
|
26249
|
+
ord,
|
|
26250
|
+
e.id,
|
|
26251
|
+
e.kind,
|
|
26252
|
+
e.types.join(","),
|
|
26253
|
+
e.email,
|
|
26254
|
+
e.date,
|
|
26255
|
+
e.before?.specId ?? null,
|
|
26256
|
+
e.after?.specId ?? null,
|
|
26257
|
+
[e.id, e.before?.title ?? "", e.after?.title ?? ""].join(" ").toLowerCase(),
|
|
26258
|
+
JSON.stringify(listed(e)),
|
|
26259
|
+
JSON.stringify({ before: e.before, after: e.after })
|
|
26260
|
+
);
|
|
26261
|
+
const line = e.reasons.length ? e.reasons.join(" \xB7 ") : e.message;
|
|
26262
|
+
const where2 = e.commit.slice(0, 7) + " \xB7 " + e.author;
|
|
26263
|
+
search.run(
|
|
26264
|
+
"history",
|
|
26265
|
+
"history",
|
|
26266
|
+
e.key,
|
|
26267
|
+
e.commit,
|
|
26268
|
+
JSON.stringify({ title: titleOf(e), where: where2, line }),
|
|
26269
|
+
titleOf(e).toLowerCase(),
|
|
26270
|
+
where2.toLowerCase(),
|
|
26271
|
+
[line, e.message, e.id].join(" ").toLowerCase()
|
|
26272
|
+
);
|
|
26273
|
+
});
|
|
26274
|
+
}
|
|
25776
26275
|
});
|
|
25777
26276
|
}
|
|
25778
|
-
|
|
25779
|
-
const
|
|
25780
|
-
|
|
26277
|
+
async function build(head) {
|
|
26278
|
+
const lineage = await changes.lineage(head);
|
|
26279
|
+
const known = await database.with((db) => new Set(db.prepare("SELECT oid FROM commits").all().map((r) => r.oid)));
|
|
26280
|
+
const missing2 = lineage.filter((oid3) => !known.has(oid3));
|
|
26281
|
+
for (let i = 0; i < missing2.length; i += 100) {
|
|
26282
|
+
const read = await changes.of(missing2.slice(i, i + 100));
|
|
26283
|
+
await database.with((db) => insert(db, read));
|
|
26284
|
+
}
|
|
26285
|
+
await database.with((db) => transaction(db, () => {
|
|
26286
|
+
db.prepare("DELETE FROM lineage WHERE head = ?").run(head);
|
|
26287
|
+
const row = db.prepare("INSERT INTO lineage (head, pos, oid) VALUES (?, ?, ?)");
|
|
26288
|
+
lineage.forEach((oid3, pos) => row.run(head, pos, oid3));
|
|
26289
|
+
db.prepare("INSERT INTO heads (head, seen) VALUES (?, ?) ON CONFLICT (head) DO UPDATE SET seen = excluded.seen").run(head, Date.now());
|
|
26290
|
+
for (const { head: old } of db.prepare("SELECT head FROM heads ORDER BY seen DESC LIMIT -1 OFFSET ?").all(KEPT_HEADS)) {
|
|
26291
|
+
db.prepare("DELETE FROM lineage WHERE head = ?").run(old);
|
|
26292
|
+
db.prepare("DELETE FROM heads WHERE head = ?").run(old);
|
|
26293
|
+
}
|
|
26294
|
+
}));
|
|
26295
|
+
}
|
|
26296
|
+
function ensure(head) {
|
|
26297
|
+
if (built.has(head)) return Promise.resolve();
|
|
26298
|
+
let pending = building.get(head);
|
|
26299
|
+
if (!pending) {
|
|
26300
|
+
pending = build(head).then(() => {
|
|
26301
|
+
built.add(head);
|
|
26302
|
+
}).finally(() => building.delete(head));
|
|
26303
|
+
building.set(head, pending);
|
|
26304
|
+
}
|
|
26305
|
+
return pending;
|
|
26306
|
+
}
|
|
26307
|
+
function where(filter) {
|
|
26308
|
+
const clauses = [];
|
|
26309
|
+
const params = [];
|
|
26310
|
+
if (filter.kind) {
|
|
26311
|
+
clauses.push("instr(',' || c.types || ',', ?) > 0");
|
|
26312
|
+
params.push("," + filter.kind + ",");
|
|
26313
|
+
}
|
|
26314
|
+
if (filter.document) {
|
|
26315
|
+
clauses.push("c.kind = ?");
|
|
26316
|
+
params.push(filter.document);
|
|
26317
|
+
}
|
|
26318
|
+
if (filter.feature) {
|
|
26319
|
+
clauses.push("(c.before_spec = ? OR c.after_spec = ?)");
|
|
26320
|
+
params.push(filter.feature, filter.feature);
|
|
26321
|
+
}
|
|
26322
|
+
if (filter.author) {
|
|
26323
|
+
clauses.push("c.email = ?");
|
|
26324
|
+
params.push(filter.author);
|
|
26325
|
+
}
|
|
26326
|
+
if (filter.q?.trim()) {
|
|
26327
|
+
clauses.push("instr(c.needle, ?) > 0");
|
|
26328
|
+
params.push(filter.q.trim().toLowerCase());
|
|
26329
|
+
}
|
|
26330
|
+
return { sql: clauses.map((c) => " AND " + c).join(""), params };
|
|
26331
|
+
}
|
|
26332
|
+
return {
|
|
26333
|
+
ensure,
|
|
26334
|
+
/** One page of the changes that match, newest first, with how many match in all. */
|
|
26335
|
+
async page(head, filter, offset, limit) {
|
|
26336
|
+
await ensure(head);
|
|
26337
|
+
return database.with((db) => {
|
|
26338
|
+
const { sql, params } = where(filter);
|
|
26339
|
+
const from = "FROM lineage l JOIN changes c ON c.oid = l.oid WHERE l.head = ?" + sql;
|
|
26340
|
+
const total = Number(db.prepare("SELECT count(*) AS n " + from).get(head, ...params).n);
|
|
26341
|
+
const rows = db.prepare(`SELECT c.row ${from} ORDER BY l.pos, c.ord LIMIT ? OFFSET ?`).all(head, ...params, limit, offset);
|
|
26342
|
+
const boundary = !!db.prepare("SELECT 1 FROM lineage l JOIN commits m ON m.oid = l.oid WHERE l.head = ? AND m.boundary = 1 LIMIT 1").get(head);
|
|
26343
|
+
return { total, events: rows.map((r) => JSON.parse(r.row)), boundary };
|
|
26344
|
+
});
|
|
26345
|
+
},
|
|
26346
|
+
/** Counts over all of history and its newest commits, for the overview. */
|
|
26347
|
+
async summary(head) {
|
|
26348
|
+
await ensure(head);
|
|
26349
|
+
return database.with((db) => {
|
|
26350
|
+
const from = "FROM lineage l JOIN changes c ON c.oid = l.oid WHERE l.head = ?";
|
|
26351
|
+
const count2 = (type) => Number(db.prepare(`SELECT count(*) AS n ${from} AND instr(',' || c.types || ',', ?) > 0`).get(head, "," + type + ",").n);
|
|
26352
|
+
const total = Number(db.prepare(`SELECT count(*) AS n ${from}`).get(head).n);
|
|
26353
|
+
const commits = db.prepare(`SELECT l.oid AS oid, max(c.date) AS date, count(*) AS n ${from} GROUP BY l.pos, l.oid ORDER BY l.pos`).all(head);
|
|
26354
|
+
const newest = Math.max(0, ...commits.map((c) => Date.parse(c.date)).filter(Number.isFinite));
|
|
26355
|
+
const pulse = commits.filter((c) => Date.parse(c.date) >= newest - 22 * DAY).map((c) => ({ date: c.date, count: Number(c.n) }));
|
|
26356
|
+
const recent = commits.slice(0, RECENT_COMMITS).map((c) => ({
|
|
26357
|
+
commit: c.oid,
|
|
26358
|
+
count: Number(c.n),
|
|
26359
|
+
events: db.prepare("SELECT row FROM changes WHERE oid = ? ORDER BY ord LIMIT ?").all(c.oid, RECENT_CHANGES).map((r) => JSON.parse(r.row))
|
|
26360
|
+
}));
|
|
26361
|
+
return { total, byType: { created: count2("created"), modified: count2("modified"), moved: count2("moved"), deleted: count2("deleted") }, pulse, recent };
|
|
26362
|
+
});
|
|
26363
|
+
},
|
|
26364
|
+
/** One change with the text on both sides; a commit the index has not read yet is read now. */
|
|
26365
|
+
async change(key) {
|
|
26366
|
+
const lookup = () => database.with((db) => db.prepare("SELECT row, detail FROM changes WHERE key = ?").get(key));
|
|
26367
|
+
let found = await lookup();
|
|
26368
|
+
if (!found) {
|
|
26369
|
+
const commit = key.slice(0, key.indexOf(":"));
|
|
26370
|
+
const known = await database.with((db) => !!db.prepare("SELECT 1 FROM commits WHERE oid = ?").get(commit));
|
|
26371
|
+
if (known) return void 0;
|
|
26372
|
+
const read = await changes.of([commit]).catch(() => void 0);
|
|
26373
|
+
if (!read) return void 0;
|
|
26374
|
+
await database.with((db) => insert(db, read));
|
|
26375
|
+
found = await lookup();
|
|
26376
|
+
}
|
|
26377
|
+
if (!found) return void 0;
|
|
26378
|
+
const detail = JSON.parse(found.detail);
|
|
26379
|
+
return { event: JSON.parse(found.row), before: detail.before, after: detail.after };
|
|
26380
|
+
},
|
|
26381
|
+
/** Replaces the search rows of one worktree's checkout when it changed since they were written. */
|
|
26382
|
+
async syncCheckout(scope, stamp, documents) {
|
|
26383
|
+
await database.with((db) => {
|
|
26384
|
+
const current = db.prepare("SELECT stamp FROM checkouts WHERE scope = ?").get(scope);
|
|
26385
|
+
if (current?.stamp === stamp) return;
|
|
26386
|
+
transaction(db, () => {
|
|
26387
|
+
db.prepare("DELETE FROM search WHERE scope = ?").run(scope);
|
|
26388
|
+
const row = db.prepare("INSERT INTO search (scope, kind, ref, oid, payload, title, place, body) VALUES (?,?,?,?,?,?,?,?)");
|
|
26389
|
+
for (const d of documents) {
|
|
26390
|
+
const body = plain(d.body);
|
|
26391
|
+
row.run(
|
|
26392
|
+
scope,
|
|
26393
|
+
d.kind,
|
|
26394
|
+
d.ref,
|
|
26395
|
+
null,
|
|
26396
|
+
JSON.stringify({ title: d.title, where: d.where, body, featureId: d.featureId, documentId: d.documentId }),
|
|
26397
|
+
d.title.toLowerCase(),
|
|
26398
|
+
d.where.toLowerCase(),
|
|
26399
|
+
body.toLowerCase()
|
|
26400
|
+
);
|
|
26401
|
+
}
|
|
26402
|
+
db.prepare("INSERT INTO checkouts (scope, stamp) VALUES (?, ?) ON CONFLICT (scope) DO UPDATE SET stamp = excluded.stamp").run(scope, stamp);
|
|
26403
|
+
});
|
|
26404
|
+
});
|
|
26405
|
+
},
|
|
26406
|
+
/**
|
|
26407
|
+
* Records whose title, place or text holds the query. The checkout comes first — a title match before a place
|
|
26408
|
+
* match before a text match — then past changes of `head`'s history, newest first.
|
|
26409
|
+
*/
|
|
26410
|
+
async search(scope, head, raw) {
|
|
26411
|
+
const query = raw.trim().toLowerCase();
|
|
26412
|
+
if (!query) return [];
|
|
26413
|
+
if (head) await ensure(head);
|
|
26414
|
+
return database.with((db) => {
|
|
26415
|
+
const literal2 = /[\\%_]/.test(query);
|
|
26416
|
+
const match = (column) => literal2 ? `instr(${column}, ?) > 0` : `${column} LIKE ?`;
|
|
26417
|
+
const needle = literal2 ? query : containing(query);
|
|
26418
|
+
const found = db.prepare(`SELECT kind, ref, payload, title, place, body FROM search WHERE scope = ? AND (${match("title")} OR ${match("place")} OR ${match("body")}) LIMIT 400`).all(scope, needle, needle, needle);
|
|
26419
|
+
const documents = found.map((r) => {
|
|
26420
|
+
const at = r.title.indexOf(query);
|
|
26421
|
+
const rank = at === 0 ? 0 : at > 0 ? 1 : r.place.includes(query) ? 2 : 3;
|
|
26422
|
+
const p = JSON.parse(r.payload);
|
|
26423
|
+
const hit = {
|
|
26424
|
+
id: r.ref,
|
|
26425
|
+
kind: r.kind,
|
|
26426
|
+
title: p.title,
|
|
26427
|
+
where: p.where,
|
|
26428
|
+
line: snippet(p.body, query),
|
|
26429
|
+
...p.featureId ? { featureId: p.featureId } : {},
|
|
26430
|
+
...p.documentId ? { documentId: p.documentId } : {}
|
|
26431
|
+
};
|
|
26432
|
+
return { rank, hit };
|
|
26433
|
+
}).sort((a, b) => a.rank - b.rank || a.hit.title.localeCompare(b.hit.title)).slice(0, 24).map((r) => r.hit);
|
|
26434
|
+
const past = !head ? [] : db.prepare(`SELECT s.ref AS ref, s.payload AS payload FROM search s JOIN lineage l ON l.head = ? AND l.oid = s.oid
|
|
26435
|
+
WHERE s.scope = 'history' AND (${match("s.title")} OR ${match("s.body")}) ORDER BY l.pos LIMIT 8`).all(head, needle, needle).map((r) => {
|
|
26436
|
+
const p = JSON.parse(r.payload);
|
|
26437
|
+
return { id: r.ref, kind: "history", title: p.title, where: p.where, line: snippet(p.line, query), key: r.ref };
|
|
26438
|
+
});
|
|
26439
|
+
return [...documents, ...past];
|
|
26440
|
+
});
|
|
26441
|
+
}
|
|
26442
|
+
};
|
|
26443
|
+
}
|
|
26444
|
+
|
|
26445
|
+
// src/server/routes/record-routes.ts
|
|
26446
|
+
var PAGE = 50;
|
|
26447
|
+
function recordRoutes(root, sessionId, env) {
|
|
26448
|
+
const reader = specPreviewReader(root);
|
|
26449
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
26450
|
+
const snapshot3 = (oid3) => {
|
|
26451
|
+
let value = snapshots.get(oid3);
|
|
25781
26452
|
if (!value) {
|
|
25782
|
-
value =
|
|
25783
|
-
|
|
26453
|
+
value = reader.readBundle(oid3).catch((e) => {
|
|
26454
|
+
snapshots.delete(oid3);
|
|
26455
|
+
throw e;
|
|
26456
|
+
});
|
|
26457
|
+
snapshots.set(oid3, value);
|
|
25784
26458
|
}
|
|
26459
|
+
if (snapshots.size > 128) snapshots.delete(snapshots.keys().next().value);
|
|
25785
26460
|
return value;
|
|
25786
26461
|
};
|
|
26462
|
+
const readCheckout = createCheckoutReader(root, sessionId, env);
|
|
26463
|
+
const history = createHistoryIndex(root, snapshot3);
|
|
26464
|
+
const scope = "checkout:" + root;
|
|
26465
|
+
const unreadable = t2("server.specsUnreadable");
|
|
26466
|
+
let synced;
|
|
26467
|
+
const checkout = async () => {
|
|
26468
|
+
const read = await readCheckout();
|
|
26469
|
+
synced = history.syncCheckout(scope, read.stamp, read.search);
|
|
26470
|
+
await synced;
|
|
26471
|
+
return read.checkout;
|
|
26472
|
+
};
|
|
26473
|
+
return [
|
|
26474
|
+
route({ method: "GET", path: "/api/v1/specs", session: true, unreadable, handle: async () => {
|
|
26475
|
+
return ok(await checkout());
|
|
26476
|
+
} }),
|
|
26477
|
+
route({ method: "GET", path: "/api/v1/history", session: true, query: browserHistoryQueryV1, unreadable, handle: async ({ query }) => {
|
|
26478
|
+
const offset = query.offset ?? 0;
|
|
26479
|
+
const page = await history.page(query.head, { kind: query.kind, document: query.document, feature: query.feature, author: query.author, q: query.q }, offset, query.limit ?? PAGE);
|
|
26480
|
+
return ok(browserHistoryV1.parse({ contract: "browser-history", version: 1, sessionId, head: query.head, offset, ...page }));
|
|
26481
|
+
} }),
|
|
26482
|
+
route({ method: "GET", path: "/api/v1/history/summary", session: true, query: browserHistorySummaryQueryV1, unreadable, handle: async ({ query }) => ok(browserHistorySummaryV1.parse({ contract: "browser-history-summary", version: 1, sessionId, head: query.head, ...await history.summary(query.head) })) }),
|
|
26483
|
+
route({ method: "GET", path: "/api/v1/change", session: true, query: browserChangeQueryV1, unreadable, handle: async ({ query }) => {
|
|
26484
|
+
const change2 = await history.change(query.key);
|
|
26485
|
+
if (!change2) throw new HttpError(404, "NOT_FOUND", t2("server.changeNotFound"));
|
|
26486
|
+
return ok(browserChangeV1.parse({ contract: "browser-change", version: 1, sessionId, ...change2 }));
|
|
26487
|
+
} }),
|
|
26488
|
+
route({ method: "GET", path: "/api/v1/search", session: true, query: browserSearchQueryV1, unreadable, handle: async ({ query }) => {
|
|
26489
|
+
await (synced ?? checkout()).catch(() => void 0);
|
|
26490
|
+
return ok(browserSearchV1.parse({ contract: "browser-search", version: 1, sessionId, query: query.q, hits: await history.search(scope, query.head ?? null, query.q) }));
|
|
26491
|
+
} })
|
|
26492
|
+
];
|
|
26493
|
+
}
|
|
26494
|
+
|
|
26495
|
+
// src/server/routes/asset-routes.ts
|
|
26496
|
+
import { lstat as lstat4, readFile as readFile4 } from "node:fs/promises";
|
|
26497
|
+
import { join as join6 } from "node:path";
|
|
26498
|
+
function assetRoutes(root) {
|
|
26499
|
+
return [
|
|
26500
|
+
route({ method: "GET", path: "/api/v1/assets/*", session: false, handle: async ({ path: path3, response }) => {
|
|
26501
|
+
const relative = path3.slice("/api/v1/assets/".length);
|
|
26502
|
+
const assetPath = ASSETS_DIR + "/" + relative;
|
|
26503
|
+
if (!isAssetPath(assetPath)) throw new HttpError(404, "NOT_FOUND", t2("server.assetNotFound"));
|
|
26504
|
+
const file2 = join6(root, ...assetPath.split("/"));
|
|
26505
|
+
const stat3 = await lstat4(file2).catch(() => void 0);
|
|
26506
|
+
if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > 20 * 1024 * 1024) throw new HttpError(404, "NOT_FOUND", t2("server.assetNotFound"));
|
|
26507
|
+
const bytes = await readFile4(file2);
|
|
26508
|
+
const extension = assetExtension(relative);
|
|
26509
|
+
const inline = ["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension);
|
|
26510
|
+
response.writeHead(200, {
|
|
26511
|
+
"Content-Type": contentType("." + extension),
|
|
26512
|
+
"Cache-Control": "no-cache",
|
|
26513
|
+
"Content-Length": bytes.length,
|
|
26514
|
+
"Content-Security-Policy": "default-src 'none'; sandbox",
|
|
26515
|
+
"Content-Disposition": inline ? "inline" : 'attachment; filename="' + encodeURIComponent(relative.split("/").pop()) + '"'
|
|
26516
|
+
});
|
|
26517
|
+
response.end(bytes);
|
|
26518
|
+
return void 0;
|
|
26519
|
+
} })
|
|
26520
|
+
];
|
|
25787
26521
|
}
|
|
25788
26522
|
|
|
25789
26523
|
// src/server/browser-server.ts
|
|
25790
|
-
var readBundledChangelog = (language) =>
|
|
26524
|
+
var readBundledChangelog = (language) => readFile5(new URL("./i18n/" + language + "/changelog.md", import.meta.url), "utf8").catch((error62) => {
|
|
25791
26525
|
if (error62.code === "ENOENT") return null;
|
|
25792
26526
|
throw error62;
|
|
25793
26527
|
});
|
|
@@ -25812,127 +26546,24 @@ async function startBrowserServer(options) {
|
|
|
25812
26546
|
}
|
|
25813
26547
|
const store = createStatusSession(initial, () => read(controller.signal), options.cliVersion);
|
|
25814
26548
|
const sessionId = store.session.sessionId;
|
|
25815
|
-
const
|
|
26549
|
+
const root = initial.repository.rootPath;
|
|
26550
|
+
const routes = [
|
|
26551
|
+
...projectRoutes(store, options.readChangelog ?? readBundledChangelog),
|
|
26552
|
+
...recordRoutes(root, sessionId, options.env),
|
|
26553
|
+
...assetRoutes(root)
|
|
26554
|
+
];
|
|
25816
26555
|
let updatePending;
|
|
25817
26556
|
let closing = false;
|
|
25818
26557
|
let origin = "";
|
|
25819
|
-
const readSpecs = createSpecBrowserReader(initial.repository.rootPath, sessionId, options.env);
|
|
25820
|
-
function json2(response, status, value) {
|
|
25821
|
-
response.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
|
|
25822
|
-
response.end(JSON.stringify(value) + "\n");
|
|
25823
|
-
}
|
|
25824
|
-
function fail8(response, status, code, message) {
|
|
25825
|
-
json2(response, status, browserHttpErrorV1.parse({ contract: "browser-http-error", version: 1, error: { code, message } }));
|
|
25826
|
-
}
|
|
25827
|
-
async function handle(request, response) {
|
|
25828
|
-
response.setHeader("X-Content-Type-Options", "nosniff");
|
|
25829
|
-
response.setHeader("X-Frame-Options", "DENY");
|
|
25830
|
-
response.setHeader("Referrer-Policy", "no-referrer");
|
|
25831
|
-
response.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'");
|
|
25832
|
-
if (closing) return fail8(response, 503, "SERVER_CLOSING", t2("server.closing"));
|
|
25833
|
-
if (request.headers.host !== new URL(origin).host) return fail8(response, 403, "FORBIDDEN", t2("server.forbiddenHost"));
|
|
25834
|
-
const requestOrigin = request.headers.origin;
|
|
25835
|
-
const allowedOrigin = requestOrigin === origin || options.dev && requestOrigin === "http://127.0.0.1:5173";
|
|
25836
|
-
if (requestOrigin && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.forbiddenOrigin"));
|
|
25837
|
-
const raw = request.url ?? "/";
|
|
25838
|
-
if (!raw.startsWith("/") || raw.startsWith("//") || raw.includes("\\")) return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25839
|
-
let url2;
|
|
25840
|
-
let path3;
|
|
25841
|
-
try {
|
|
25842
|
-
url2 = new URL(raw, origin);
|
|
25843
|
-
path3 = decodeURIComponent(url2.pathname);
|
|
25844
|
-
} catch {
|
|
25845
|
-
return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25846
|
-
}
|
|
25847
|
-
if (path3.includes("\0") || path3.includes("\\") || path3.split("/").some((part) => part === ".." || part === ".")) {
|
|
25848
|
-
return fail8(response, 400, "BAD_REQUEST", t2("server.badPath"));
|
|
25849
|
-
}
|
|
25850
|
-
if (request.headers["transfer-encoding"] || request.headers["content-length"] && request.headers["content-length"] !== "0") {
|
|
25851
|
-
request.resume();
|
|
25852
|
-
return fail8(response, 400, "BAD_REQUEST", t2("server.noBody"));
|
|
25853
|
-
}
|
|
25854
|
-
const api = path3 === "/api" || path3.startsWith("/api/");
|
|
25855
|
-
if (api) {
|
|
25856
|
-
if (request.headers["sec-fetch-site"] === "cross-site" && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.crossSite"));
|
|
25857
|
-
if (url2.search && path3 !== "/api/v1/specs" && path3 !== "/api/v1/changelog") return fail8(response, 400, "BAD_REQUEST", t2("server.noQuery"));
|
|
25858
|
-
if (path3.startsWith("/api/v1/assets/")) {
|
|
25859
|
-
const relative = path3.slice("/api/v1/assets/".length);
|
|
25860
|
-
const assetPath2 = ASSETS_DIR + "/" + relative;
|
|
25861
|
-
if (request.method !== "GET") {
|
|
25862
|
-
response.setHeader("Allow", "GET");
|
|
25863
|
-
return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25864
|
-
}
|
|
25865
|
-
if (!isAssetPath(assetPath2)) return fail8(response, 404, "NOT_FOUND", t2("server.assetNotFound"));
|
|
25866
|
-
const file2 = join5(initial.repository.rootPath, ...assetPath2.split("/"));
|
|
25867
|
-
const stat3 = await lstat4(file2).catch(() => void 0);
|
|
25868
|
-
if (!stat3?.isFile() || stat3.isSymbolicLink() || stat3.size > 20 * 1024 * 1024) return fail8(response, 404, "NOT_FOUND", t2("server.assetNotFound"));
|
|
25869
|
-
const bytes = await readFile4(file2);
|
|
25870
|
-
const extension = assetExtension(relative);
|
|
25871
|
-
const inline = ["png", "jpg", "jpeg", "gif", "webp", "svg"].includes(extension);
|
|
25872
|
-
response.writeHead(200, {
|
|
25873
|
-
"Content-Type": contentType("." + extension),
|
|
25874
|
-
"Cache-Control": "no-cache",
|
|
25875
|
-
"Content-Length": bytes.length,
|
|
25876
|
-
"Content-Security-Policy": "default-src 'none'; sandbox",
|
|
25877
|
-
"Content-Disposition": inline ? "inline" : 'attachment; filename="' + encodeURIComponent(relative.split("/").pop()) + '"'
|
|
25878
|
-
});
|
|
25879
|
-
response.end(bytes);
|
|
25880
|
-
return;
|
|
25881
|
-
}
|
|
25882
|
-
const method = path3 === "/api/v1/status/refresh" ? "POST" : "GET";
|
|
25883
|
-
if (!["/api/v1/session", "/api/v1/status", "/api/v1/status/refresh", "/api/v1/specs", "/api/v1/changelog"].includes(path3)) return fail8(response, 404, "NOT_FOUND", t2("server.apiNotFound"));
|
|
25884
|
-
if (request.method !== method) {
|
|
25885
|
-
response.setHeader("Allow", method);
|
|
25886
|
-
return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25887
|
-
}
|
|
25888
|
-
if (path3 === "/api/v1/session") return json2(response, 200, store.session);
|
|
25889
|
-
if (request.headers["x-gitifact-session"] !== sessionId) return fail8(response, 409, "SESSION_CHANGED", t2("server.sessionChanged"));
|
|
25890
|
-
if (path3 === "/api/v1/specs") {
|
|
25891
|
-
const cursor = url2.searchParams.get("cursor") ?? "0";
|
|
25892
|
-
const head = url2.searchParams.get("head");
|
|
25893
|
-
if ([...url2.searchParams.keys()].some((k) => !["cursor", "head"].includes(k)) || url2.searchParams.getAll("cursor").length > 1 || url2.searchParams.getAll("head").length > 1 || !/^(0|[1-9]\d{0,5})$/.test(cursor) || head !== null && !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head)) return fail8(response, 400, "BAD_REQUEST", t2("server.badRange"));
|
|
25894
|
-
try {
|
|
25895
|
-
json2(response, 200, await readSpecs(Number(cursor), head ?? void 0));
|
|
25896
|
-
} catch (error62) {
|
|
25897
|
-
fail8(response, 503, "INTERNAL_ERROR", error62 instanceof Error ? error62.message : t2("server.specsUnreadable"));
|
|
25898
|
-
}
|
|
25899
|
-
return;
|
|
25900
|
-
}
|
|
25901
|
-
if (path3 === "/api/v1/changelog") {
|
|
25902
|
-
const language = url2.searchParams.get("lang") ?? defaultLanguage2;
|
|
25903
|
-
if ([...url2.searchParams.keys()].some((key) => key !== "lang") || url2.searchParams.getAll("lang").length > 1 || !/^[a-z]{2}(?:-[A-Z]{2})?$/.test(language)) return fail8(response, 400, "BAD_REQUEST", t2("server.badLanguage"));
|
|
25904
|
-
try {
|
|
25905
|
-
const own2 = await readChangelog(language);
|
|
25906
|
-
const text2 = own2 ?? (language === defaultLanguage2 ? null : await readChangelog(defaultLanguage2));
|
|
25907
|
-
if (text2 === null) return fail8(response, 404, "NOT_FOUND", t2("server.changelogNotFound"));
|
|
25908
|
-
json2(response, 200, changelogV1.parse({ contract: "changelog", version: 1, language: own2 === null ? defaultLanguage2 : language, fallback: own2 === null, entries: parseChangelog(text2) }));
|
|
25909
|
-
} catch (error62) {
|
|
25910
|
-
fail8(response, 503, "INTERNAL_ERROR", error62 instanceof Error ? error62.message : t2("server.changelogUnreadable"));
|
|
25911
|
-
}
|
|
25912
|
-
return;
|
|
25913
|
-
}
|
|
25914
|
-
if (method === "POST" && !allowedOrigin) return fail8(response, 403, "FORBIDDEN", t2("server.refreshOrigin"));
|
|
25915
|
-
const value = method === "POST" ? await store.refresh() : store.latest;
|
|
25916
|
-
if (!response.destroyed) json2(response, value.ok ? 200 : 503, value);
|
|
25917
|
-
return;
|
|
25918
|
-
}
|
|
25919
|
-
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
25920
|
-
response.setHeader("Allow", "GET, HEAD");
|
|
25921
|
-
return fail8(response, 405, "METHOD_NOT_ALLOWED", t2("server.methodNotAllowed"));
|
|
25922
|
-
}
|
|
25923
|
-
let asset = assets.get(path3 === "/" ? "/index.html" : path3);
|
|
25924
|
-
let assetPath = path3 === "/" ? "/index.html" : path3;
|
|
25925
|
-
if (!asset && !path3.startsWith("/assets/") && !path3.split("/").some((part) => part.includes(".")) && request.headers.accept?.includes("text/html")) {
|
|
25926
|
-
asset = assets.get("/index.html");
|
|
25927
|
-
assetPath = "/index.html";
|
|
25928
|
-
}
|
|
25929
|
-
if (!asset) return fail8(response, 404, "NOT_FOUND", t2("server.fileNotFound"));
|
|
25930
|
-
response.writeHead(200, { "Content-Type": contentType(assetPath), "Cache-Control": "no-cache", "Content-Length": asset.length });
|
|
25931
|
-
response.end(request.method === "HEAD" ? void 0 : asset);
|
|
25932
|
-
}
|
|
25933
26558
|
const server = createServer({ requestTimeout: 5e3, headersTimeout: 5e3, maxHeaderSize: 8192 }, (request, response) => {
|
|
25934
|
-
void
|
|
25935
|
-
if (
|
|
26559
|
+
void (async () => {
|
|
26560
|
+
if (closing) return fail4(response, 503, "SERVER_CLOSING", t2("server.closing"));
|
|
26561
|
+
const admitted = admit(request, response, origin, !!options.dev);
|
|
26562
|
+
if (!admitted) return;
|
|
26563
|
+
if (admitted.api) return dispatch(routes, sessionId, admitted.url, admitted.path, request, response, admitted.allowedOrigin);
|
|
26564
|
+
return serveStatic(request, response, admitted.path, assets);
|
|
26565
|
+
})().catch(() => {
|
|
26566
|
+
if (!response.headersSent && !response.destroyed) fail4(response, 500, "INTERNAL_ERROR", t2("server.internal"));
|
|
25936
26567
|
else response.destroy();
|
|
25937
26568
|
});
|
|
25938
26569
|
});
|
|
@@ -26039,13 +26670,13 @@ async function runBrowser(options, version2) {
|
|
|
26039
26670
|
}
|
|
26040
26671
|
|
|
26041
26672
|
// src/commands/spec-init.ts
|
|
26042
|
-
import { mkdir as
|
|
26043
|
-
import { join as
|
|
26673
|
+
import { mkdir as mkdir5, readdir as readdir4, writeFile as writeFile2 } from "node:fs/promises";
|
|
26674
|
+
import { join as join10 } from "node:path";
|
|
26044
26675
|
|
|
26045
26676
|
// src/adapters/git/init-repository.ts
|
|
26046
26677
|
import { createHash as createHash3 } from "node:crypto";
|
|
26047
|
-
import { readFile as
|
|
26048
|
-
import { join as
|
|
26678
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
26679
|
+
import { join as join7 } from "node:path";
|
|
26049
26680
|
function initRepository(cwd, inherited = process.env) {
|
|
26050
26681
|
const env = { ...inherited, GIT_OPTIONAL_LOCKS: "0", GIT_NO_LAZY_FETCH: "1", GIT_TERMINAL_PROMPT: "0", GIT_LITERAL_PATHSPECS: "1", LC_ALL: "C" };
|
|
26051
26682
|
const runner = createGitRunner();
|
|
@@ -26065,10 +26696,10 @@ function initRepository(cwd, inherited = process.env) {
|
|
|
26065
26696
|
const gitDir = locations.length === 2 ? locations[0] : decodeGitLine(await git(["rev-parse", "--absolute-git-dir"], root));
|
|
26066
26697
|
const indexPath = locations.length === 2 ? locations[1] : decodeGitLine(await git(["rev-parse", "--path-format=absolute", "--git-path", "index"], root));
|
|
26067
26698
|
for (const marker2 of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"]) {
|
|
26068
|
-
if (await fileInfo(
|
|
26699
|
+
if (await fileInfo(join7(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
26069
26700
|
}
|
|
26070
26701
|
if (state.changes.some((change2) => change2.kind === "unmerged")) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
26071
|
-
const index = await
|
|
26702
|
+
const index = await readFile6(indexPath).catch((error62) => {
|
|
26072
26703
|
if (error62.code === "ENOENT") return Buffer.alloc(0);
|
|
26073
26704
|
throw error62;
|
|
26074
26705
|
});
|
|
@@ -26102,18 +26733,18 @@ function initRepository(cwd, inherited = process.env) {
|
|
|
26102
26733
|
}
|
|
26103
26734
|
|
|
26104
26735
|
// src/adapters/filesystem/managed-file.ts
|
|
26105
|
-
import { open as open3, readFile as
|
|
26106
|
-
import { join as
|
|
26736
|
+
import { open as open3, readFile as readFile7, mkdir as mkdir4, realpath as realpath2, rename as rename3, link as link2, unlink as unlink3 } from "node:fs/promises";
|
|
26737
|
+
import { join as join8, dirname as dirname2 } from "node:path";
|
|
26107
26738
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
26108
26739
|
var DEFAULT_LIMIT = 1024 * 1024;
|
|
26109
26740
|
async function managedPath(root, path3, create = false) {
|
|
26110
26741
|
let full = root;
|
|
26111
26742
|
const parts = path3.split("/");
|
|
26112
26743
|
for (let i = 0; i < parts.length; i++) {
|
|
26113
|
-
full =
|
|
26744
|
+
full = join8(full, parts[i]);
|
|
26114
26745
|
let info7 = await fileInfo(full);
|
|
26115
26746
|
if (!info7 && create && i < parts.length - 1) {
|
|
26116
|
-
await
|
|
26747
|
+
await mkdir4(full).catch((error62) => {
|
|
26117
26748
|
if (error62.code !== "EEXIST") throw error62;
|
|
26118
26749
|
});
|
|
26119
26750
|
info7 = await fileInfo(full);
|
|
@@ -26129,7 +26760,7 @@ async function managedRead(root, path3, limit = DEFAULT_LIMIT) {
|
|
|
26129
26760
|
const before = await fileInfo(full);
|
|
26130
26761
|
if (!before) return null;
|
|
26131
26762
|
if (before.size > limit) throw new InitError("FILE_TOO_LARGE", t2("managedFile.tooLarge", { kib: limit / 1024, path: path3 }));
|
|
26132
|
-
const bytes = await
|
|
26763
|
+
const bytes = await readFile7(full);
|
|
26133
26764
|
await managedPath(root, path3);
|
|
26134
26765
|
const after = await fileInfo(full);
|
|
26135
26766
|
if (!after || before.ino !== after.ino || before.dev !== after.dev || before.mtimeMs !== after.mtimeMs || bytes.length > limit) {
|
|
@@ -26158,7 +26789,7 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
26158
26789
|
if (previous !== null) await unlink3(full);
|
|
26159
26790
|
return;
|
|
26160
26791
|
}
|
|
26161
|
-
const temp =
|
|
26792
|
+
const temp = join8(directory, ".gitifact-managed-" + randomUUID5() + ".tmp");
|
|
26162
26793
|
const handle = await open3(temp, "wx", 384);
|
|
26163
26794
|
const tempOwner = await handle.stat();
|
|
26164
26795
|
try {
|
|
@@ -26170,7 +26801,7 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
26170
26801
|
}
|
|
26171
26802
|
await recheck();
|
|
26172
26803
|
await unchanged();
|
|
26173
|
-
if (await managedRead(root, path3) !== previous || await
|
|
26804
|
+
if (await managedRead(root, path3) !== previous || await readFile7(temp, "utf8") !== next) throw new InitError("INPUT_CHANGED", t2("managedFile.publishTargetChanged", { path: path3 }));
|
|
26174
26805
|
if (previous === null) await link2(temp, full);
|
|
26175
26806
|
else await rename3(temp, full);
|
|
26176
26807
|
} finally {
|
|
@@ -26181,14 +26812,14 @@ async function managedWrite(root, path3, previous, next, recheck) {
|
|
|
26181
26812
|
}
|
|
26182
26813
|
|
|
26183
26814
|
// src/commands/agent-block.ts
|
|
26184
|
-
import { readFile as
|
|
26815
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
26185
26816
|
|
|
26186
26817
|
// src/commands/docs.ts
|
|
26187
|
-
import { lstat as lstat5, readFile as
|
|
26188
|
-
import { dirname as dirname3, join as
|
|
26818
|
+
import { lstat as lstat5, readFile as readFile8 } from "node:fs/promises";
|
|
26819
|
+
import { dirname as dirname3, join as join9 } from "node:path";
|
|
26189
26820
|
var docTopics = ["workflow", "spec", "design", "wiki", "writing", "commit"];
|
|
26190
26821
|
var isDocTopic = (value) => docTopics.includes(value);
|
|
26191
|
-
var readBundledDoc = (name, lang) =>
|
|
26822
|
+
var readBundledDoc = (name, lang) => readFile8(new URL("./i18n/" + lang + "/docs/" + name + ".md", import.meta.url), "utf8");
|
|
26192
26823
|
var info3 = (path3) => lstat5(path3).catch((e) => {
|
|
26193
26824
|
if (e.code === "ENOENT") return void 0;
|
|
26194
26825
|
throw e;
|
|
@@ -26199,16 +26830,16 @@ function listDocTopics(lang = defaultLanguage2) {
|
|
|
26199
26830
|
}
|
|
26200
26831
|
async function findProjectRoot(cwd) {
|
|
26201
26832
|
for (let dir = cwd; ; dir = dirname3(dir)) {
|
|
26202
|
-
if ((await info3(
|
|
26833
|
+
if ((await info3(join9(dir, ".gitifact", "config.json")))?.isFile()) return dir;
|
|
26203
26834
|
if (dirname3(dir) === dir) return void 0;
|
|
26204
26835
|
}
|
|
26205
26836
|
}
|
|
26206
26837
|
async function readWikiPolicy(root) {
|
|
26207
26838
|
if (!root) return void 0;
|
|
26208
|
-
const path3 =
|
|
26839
|
+
const path3 = join9(root, ...WIKI_ENTRY_PATH.split("/"));
|
|
26209
26840
|
const stat3 = await info3(path3);
|
|
26210
26841
|
if (!stat3?.isFile() || stat3.size > 1024 * 1024) return void 0;
|
|
26211
|
-
const lines = (await
|
|
26842
|
+
const lines = (await readFile8(path3, "utf8")).replace(/\r\n/g, "\n").split("\n");
|
|
26212
26843
|
if (lines[0] === "---") {
|
|
26213
26844
|
const end = lines.indexOf("---", 1);
|
|
26214
26845
|
if (end > 0) lines.splice(0, end + 1);
|
|
@@ -26260,7 +26891,7 @@ function boilerplateFor(path3) {
|
|
|
26260
26891
|
const name = path3 === "AGENTS.md" ? path3 : path3.split("/").pop().replace(/^\./, "").replace(/\.md$/, "");
|
|
26261
26892
|
return "# " + name + "\n\nProject-specific guidance for AI coding agents.\n";
|
|
26262
26893
|
}
|
|
26263
|
-
var readBundledBlock = (lang) =>
|
|
26894
|
+
var readBundledBlock = (lang) => readFile9(new URL("./i18n/" + lang + "/block.md", import.meta.url), "utf8");
|
|
26264
26895
|
async function renderAgentBlock(version2, controls = {}, lang = defaultLanguage2) {
|
|
26265
26896
|
const body = await (controls.readBlock ?? readBundledBlock)(lang);
|
|
26266
26897
|
const filled = body.trimEnd().replace(/\{(version|language|topics)\}/g, (_whole, name) => name === "version" ? version2 : name === "language" ? lang : docTopics.join(", "));
|
|
@@ -26419,8 +27050,8 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
26419
27050
|
const text2 = JSON.stringify(config2, null, 2) + "\n";
|
|
26420
27051
|
const replaceLegacy = async (before, version2) => {
|
|
26421
27052
|
const onlyConfig = async () => {
|
|
26422
|
-
const entries = await readdir4(
|
|
26423
|
-
if (await fileInfo(
|
|
27053
|
+
const entries = await readdir4(join10(root, ".gitifact"));
|
|
27054
|
+
if (await fileInfo(join10(root, "specs")) || entries.some((name) => name !== "config.json" && !/^\.init-[a-f0-9-]+\.tmp$/.test(name))) {
|
|
26424
27055
|
throw new InitError("UNSUPPORTED_SCHEMA", t2("init.legacyRecords", { version: String(version2) }));
|
|
26425
27056
|
}
|
|
26426
27057
|
};
|
|
@@ -26451,8 +27082,8 @@ async function initializeSpecProject(cwd, dryRun = false, env = process.env, bef
|
|
|
26451
27082
|
}
|
|
26452
27083
|
if (first.trackedConfig) throw new InitError("CONFIG_DELETED", t2("init.configDeleted"));
|
|
26453
27084
|
const checkRecords = async () => {
|
|
26454
|
-
if (await fileInfo(
|
|
26455
|
-
const entries = await readdir4(
|
|
27085
|
+
if (await fileInfo(join10(root, "specs"))) throw new InitError("EXISTING_RECORDS", t2("init.existingSpecs"));
|
|
27086
|
+
const entries = await readdir4(join10(root, ".gitifact")).catch((e) => {
|
|
26456
27087
|
if (e.code === "ENOENT") return [];
|
|
26457
27088
|
throw e;
|
|
26458
27089
|
});
|
|
@@ -26489,7 +27120,7 @@ function legacySchemaVersion(text2) {
|
|
|
26489
27120
|
return Number.isInteger(version2) && version2 < SCHEMA_VERSION ? version2 : void 0;
|
|
26490
27121
|
}
|
|
26491
27122
|
async function writeWikiPolicy(root, readDoc) {
|
|
26492
|
-
if (await fileInfo(
|
|
27123
|
+
if (await fileInfo(join10(root, ...WIKI_DIR.split("/")))) return;
|
|
26493
27124
|
const template = await readDoc("wiki.default").catch((e) => {
|
|
26494
27125
|
if (e.code === "ENOENT") return void 0;
|
|
26495
27126
|
throw e;
|
|
@@ -26498,8 +27129,8 @@ async function writeWikiPolicy(root, readDoc) {
|
|
|
26498
27129
|
const doc = { id: generatePreviewId("W"), path: WIKI_ENTRY_PATH, title: t2("init.wikiReadmeTitle"), body: template.trim() };
|
|
26499
27130
|
const text2 = renderDocument(doc);
|
|
26500
27131
|
parseDocument(doc.path, text2);
|
|
26501
|
-
await
|
|
26502
|
-
await writeFile2(
|
|
27132
|
+
await mkdir5(join10(root, ...WIKI_DIR.split("/")), { recursive: true });
|
|
27133
|
+
await writeFile2(join10(root, ...WIKI_ENTRY_PATH.split("/")), text2, { flag: "wx" });
|
|
26503
27134
|
}
|
|
26504
27135
|
|
|
26505
27136
|
// src/commands/init.ts
|
|
@@ -26674,14 +27305,14 @@ async function runUpdate(options, version2) {
|
|
|
26674
27305
|
}
|
|
26675
27306
|
|
|
26676
27307
|
// src/commands/spec-preview.ts
|
|
26677
|
-
import { join as
|
|
26678
|
-
import { readFile as
|
|
27308
|
+
import { join as join15 } from "node:path";
|
|
27309
|
+
import { readFile as readFile12, stat as stat2 } from "node:fs/promises";
|
|
26679
27310
|
|
|
26680
27311
|
// src/adapters/filesystem/spec-preview-context.ts
|
|
26681
27312
|
import { lstat as lstat6 } from "node:fs/promises";
|
|
26682
|
-
import { join as
|
|
27313
|
+
import { join as join11 } from "node:path";
|
|
26683
27314
|
import { createHash as createHash4 } from "node:crypto";
|
|
26684
|
-
var
|
|
27315
|
+
var fail6 = (message) => {
|
|
26685
27316
|
throw new SpecPreviewError(message);
|
|
26686
27317
|
};
|
|
26687
27318
|
var same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
@@ -26692,11 +27323,11 @@ async function readPreviewContext(cwd) {
|
|
|
26692
27323
|
const { gitDir } = await reader.location();
|
|
26693
27324
|
const checkOperation = async () => {
|
|
26694
27325
|
for (const name of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply"]) {
|
|
26695
|
-
const exists = await lstat6(
|
|
27326
|
+
const exists = await lstat6(join11(gitDir, name)).catch((e) => {
|
|
26696
27327
|
if (e.code === "ENOENT") return void 0;
|
|
26697
27328
|
throw e;
|
|
26698
27329
|
});
|
|
26699
|
-
if (exists)
|
|
27330
|
+
if (exists) fail6(t2("prepare.integrationInProgress"));
|
|
26700
27331
|
}
|
|
26701
27332
|
};
|
|
26702
27333
|
await checkOperation();
|
|
@@ -26707,7 +27338,7 @@ async function readPreviewContext(cwd) {
|
|
|
26707
27338
|
const specs = bundle.specs;
|
|
26708
27339
|
const recheck = async () => {
|
|
26709
27340
|
await checkOperation();
|
|
26710
|
-
if (!same(base, await reader.baseline()))
|
|
27341
|
+
if (!same(base, await reader.baseline())) fail6(t2("prepare.headChanged"));
|
|
26711
27342
|
};
|
|
26712
27343
|
return { reader, base, files, specs, bundle, recheck, working };
|
|
26713
27344
|
}
|
|
@@ -26723,9 +27354,9 @@ async function readFinalPreviewChanges(cwd) {
|
|
|
26723
27354
|
|
|
26724
27355
|
// src/adapters/filesystem/agent-inputs.ts
|
|
26725
27356
|
import { createHash as createHash5, randomBytes as randomBytes2 } from "node:crypto";
|
|
26726
|
-
import { lstat as lstat7, mkdir as
|
|
27357
|
+
import { lstat as lstat7, mkdir as mkdir6, readdir as readdir5, realpath as realpath3, unlink as unlink4, writeFile as writeFile3 } from "node:fs/promises";
|
|
26727
27358
|
import { tmpdir } from "node:os";
|
|
26728
|
-
import { basename, dirname as dirname4, join as
|
|
27359
|
+
import { basename, dirname as dirname4, join as join12 } from "node:path";
|
|
26729
27360
|
var maxAge = 7 * 24 * 60 * 60 * 1e3;
|
|
26730
27361
|
var info4 = (path3) => lstat7(path3).catch((e) => {
|
|
26731
27362
|
if (e.code === "ENOENT") return void 0;
|
|
@@ -26734,14 +27365,14 @@ var info4 = (path3) => lstat7(path3).catch((e) => {
|
|
|
26734
27365
|
var comparable = (path3) => process.platform === "win32" ? path3.toLowerCase() : path3;
|
|
26735
27366
|
async function candidates(root, controls) {
|
|
26736
27367
|
const key = createHash5("sha256").update(comparable(await realpath3(root))).digest("hex").slice(0, 16);
|
|
26737
|
-
return { system:
|
|
27368
|
+
return { system: join12((controls.tmpdir ?? tmpdir)(), "gitifact", key), project: join12(root, ".gitifact", "tmp") };
|
|
26738
27369
|
}
|
|
26739
27370
|
async function writable(directory) {
|
|
26740
27371
|
try {
|
|
26741
|
-
await
|
|
27372
|
+
await mkdir6(directory, { recursive: true });
|
|
26742
27373
|
const stat3 = await info4(directory);
|
|
26743
27374
|
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) return false;
|
|
26744
|
-
const probe =
|
|
27375
|
+
const probe = join12(directory, ".probe-" + randomBytes2(8).toString("hex"));
|
|
26745
27376
|
await writeFile3(probe, "", { flag: "wx" });
|
|
26746
27377
|
await unlink4(probe);
|
|
26747
27378
|
return true;
|
|
@@ -26755,7 +27386,7 @@ async function prepareAgentInputs(root, controls = {}) {
|
|
|
26755
27386
|
if (await writable(system)) directory = system;
|
|
26756
27387
|
else if (await writable(project)) {
|
|
26757
27388
|
directory = project;
|
|
26758
|
-
await writeFile3(
|
|
27389
|
+
await writeFile3(join12(project, ".gitignore"), "*\n", { flag: "wx" }).catch((e) => {
|
|
26759
27390
|
if (e.code !== "EEXIST") throw e;
|
|
26760
27391
|
});
|
|
26761
27392
|
}
|
|
@@ -26763,10 +27394,10 @@ async function prepareAgentInputs(root, controls = {}) {
|
|
|
26763
27394
|
const now = (controls.now ?? Date.now)();
|
|
26764
27395
|
for (const name of await readdir5(directory).catch(() => [])) {
|
|
26765
27396
|
if (name === ".gitignore") continue;
|
|
26766
|
-
const stat3 = await info4(
|
|
26767
|
-
if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(
|
|
27397
|
+
const stat3 = await info4(join12(directory, name)).catch(() => void 0);
|
|
27398
|
+
if (stat3?.isFile() && now - stat3.mtimeMs > maxAge) await unlink4(join12(directory, name)).catch(() => void 0);
|
|
26768
27399
|
}
|
|
26769
|
-
return { save:
|
|
27400
|
+
return { save: join12(directory, "save.json"), commit: join12(directory, "commit.json") };
|
|
26770
27401
|
}
|
|
26771
27402
|
async function discardAgentInput(root, file2, controls = {}) {
|
|
26772
27403
|
try {
|
|
@@ -26788,18 +27419,18 @@ async function discardAgentInput(root, file2, controls = {}) {
|
|
|
26788
27419
|
|
|
26789
27420
|
// src/commands/spec-commit.ts
|
|
26790
27421
|
import { createHash as createHash7, randomUUID as randomUUID6 } from "node:crypto";
|
|
26791
|
-
import { mkdir as
|
|
26792
|
-
import { join as
|
|
27422
|
+
import { mkdir as mkdir7, open as open4, readFile as readFile11, rename as rename4, rmdir as rmdir2, unlink as unlink5, writeFile as writeFile4 } from "node:fs/promises";
|
|
27423
|
+
import { join as join14 } from "node:path";
|
|
26793
27424
|
|
|
26794
27425
|
// src/commands/spec-commit-files.ts
|
|
26795
27426
|
import { createHash as createHash6 } from "node:crypto";
|
|
26796
|
-
import { lstat as lstat8, readFile as
|
|
26797
|
-
import { join as
|
|
26798
|
-
var
|
|
27427
|
+
import { lstat as lstat8, readFile as readFile10 } from "node:fs/promises";
|
|
27428
|
+
import { join as join13 } from "node:path";
|
|
27429
|
+
var fail7 = (message) => {
|
|
26799
27430
|
throw new SpecPreviewError(message);
|
|
26800
27431
|
};
|
|
26801
27432
|
var hash2 = (value) => createHash6("sha256").update(value).digest("hex");
|
|
26802
|
-
var optional2 = (path3) =>
|
|
27433
|
+
var optional2 = (path3) => readFile10(path3).catch((e) => {
|
|
26803
27434
|
if (e.code === "ENOENT") return null;
|
|
26804
27435
|
throw e;
|
|
26805
27436
|
});
|
|
@@ -26809,34 +27440,34 @@ var info5 = (path3) => lstat8(path3).catch((e) => {
|
|
|
26809
27440
|
});
|
|
26810
27441
|
var record2 = (path3) => recordPathPattern.test(path3);
|
|
26811
27442
|
function validPath2(path3) {
|
|
26812
|
-
if (typeof path3 !== "string" || path3.length > 1e3 || /[\\:\x00-\x1f\x7f]/.test(path3) || path3.split("/").some((p) => !p || p === "." || p === ".." || p.toLowerCase() === ".git"))
|
|
27443
|
+
if (typeof path3 !== "string" || path3.length > 1e3 || /[\\:\x00-\x1f\x7f]/.test(path3) || path3.split("/").some((p) => !p || p === "." || p === ".." || p.toLowerCase() === ".git")) fail7(t2("commitFiles.relativePath"));
|
|
26813
27444
|
}
|
|
26814
27445
|
async function fingerprint(root, path3) {
|
|
26815
27446
|
validPath2(path3);
|
|
26816
27447
|
const parts = path3.split("/");
|
|
26817
27448
|
for (let i = 1; i <= parts.length; i++) {
|
|
26818
|
-
const target =
|
|
27449
|
+
const target = join13(root, ...parts.slice(0, i));
|
|
26819
27450
|
const stat3 = await info5(target);
|
|
26820
27451
|
if (!stat3) return null;
|
|
26821
|
-
if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile()))
|
|
26822
|
-
if (i < parts.length && await info5(
|
|
27452
|
+
if (stat3.isSymbolicLink() || (i < parts.length ? !stat3.isDirectory() : !stat3.isFile())) fail7(t2("commitFiles.linkOrDirectory"));
|
|
27453
|
+
if (i < parts.length && await info5(join13(target, ".git"))) fail7(t2("commitFiles.nestedRepository"));
|
|
26823
27454
|
if (i === parts.length) {
|
|
26824
|
-
if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024)
|
|
26825
|
-
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await
|
|
27455
|
+
if (stat3.nlink !== 1 || stat3.size > 16 * 1024 * 1024) fail7(t2("commitFiles.hardLinkOrSize"));
|
|
27456
|
+
return hash2(Buffer.concat([Buffer.from(String(stat3.mode & 73) + "\0"), await readFile10(target)]));
|
|
26826
27457
|
}
|
|
26827
27458
|
}
|
|
26828
27459
|
return null;
|
|
26829
27460
|
}
|
|
26830
27461
|
function object3(input2) {
|
|
26831
|
-
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) return
|
|
27462
|
+
if (!input2 || typeof input2 !== "object" || Array.isArray(input2)) return fail7(t2("commitFiles.invalidInput"));
|
|
26832
27463
|
return input2;
|
|
26833
27464
|
}
|
|
26834
27465
|
function text(value, limit) {
|
|
26835
|
-
if (typeof value !== "string" || !value.trim() || value.length > limit || value.includes("\0")) return
|
|
27466
|
+
if (typeof value !== "string" || !value.trim() || value.length > limit || value.includes("\0")) return fail7(t2("commitFiles.emptyOrTooLong"));
|
|
26836
27467
|
return value;
|
|
26837
27468
|
}
|
|
26838
27469
|
function paths(value, limit = 128) {
|
|
26839
|
-
if (!Array.isArray(value) || !value.length || value.length > limit || value.some((p) => typeof p !== "string")) return
|
|
27470
|
+
if (!Array.isArray(value) || !value.length || value.length > limit || value.some((p) => typeof p !== "string")) return fail7(t2("commitFiles.invalidPaths"));
|
|
26840
27471
|
const list = [...new Set(value)].sort();
|
|
26841
27472
|
list.forEach(validPath2);
|
|
26842
27473
|
return list;
|
|
@@ -26853,10 +27484,10 @@ async function checkLegacySelection(root, selected) {
|
|
|
26853
27484
|
const legacyJson = /^\.(?:gitifact|tryce)\/(?:spec\/[^/]+\/tryce\.json|notes\/N-[a-f0-9-]+\.json|mode-[a-f0-9-]+\.json|config\.(?:init-1|prototype-1)\.[a-f0-9]+\.json)$|^\.gitifact\/(?:product|guides|overrides)\/.+$/;
|
|
26854
27485
|
for (const p of selected.filter((p2) => p2.startsWith(".gitifact/") && !record2(p2) && p2 !== ".gitifact/config.json")) {
|
|
26855
27486
|
if (isAssetPath(p)) continue;
|
|
26856
|
-
if (!legacyJson.test(p) || await fingerprint(root, p) !== null)
|
|
27487
|
+
if (!legacyJson.test(p) || await fingerprint(root, p) !== null) fail7(t2("commitFiles.legacyDeleteOnly", { path: p }));
|
|
26857
27488
|
}
|
|
26858
27489
|
for (const p of selected.filter((p2) => p2.startsWith(".tryce/"))) {
|
|
26859
|
-
if (!(record2(p) || p === ".tryce/config.json" || legacyJson.test(p)) || await fingerprint(root, p) !== null)
|
|
27490
|
+
if (!(record2(p) || p === ".tryce/config.json" || legacyJson.test(p)) || await fingerprint(root, p) !== null) fail7(t2("commitFiles.tryceDeleteOnly", { path: p }));
|
|
26860
27491
|
}
|
|
26861
27492
|
}
|
|
26862
27493
|
|
|
@@ -26866,17 +27497,17 @@ var integration = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merg
|
|
|
26866
27497
|
var same2 = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
26867
27498
|
async function specCommit(cwd, input2, dryRun) {
|
|
26868
27499
|
const request = object3(input2);
|
|
26869
|
-
if (Object.keys(request).some((k) => !fields.includes(k)))
|
|
27500
|
+
if (Object.keys(request).some((k) => !fields.includes(k))) fail7(t2("commit.unknownField"));
|
|
26870
27501
|
const selected = paths(request.paths);
|
|
26871
27502
|
const authorization = object3(request.authorization);
|
|
26872
|
-
if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis)))
|
|
27503
|
+
if (Object.keys(authorization).sort().join(",") !== "basis,evidence" || !["user-request", "project-policy"].includes(String(authorization.basis))) fail7(t2("commit.authorizationRequired"));
|
|
26873
27504
|
text(authorization.evidence, 2e3);
|
|
26874
27505
|
const message = text(request.message, 4e3);
|
|
26875
|
-
if (/^\s*Gitifact-/im.test(message))
|
|
27506
|
+
if (/^\s*Gitifact-/im.test(message)) fail7(t2("commit.trailerInMessage"));
|
|
26876
27507
|
const references = request.requirements ?? [];
|
|
26877
|
-
if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string"))
|
|
27508
|
+
if (!Array.isArray(references) || references.length > 1e3 || references.some((r) => typeof r !== "string")) fail7(t2("commit.invalidReferences"));
|
|
26878
27509
|
const extra = request.policyFiles === void 0 ? [] : paths(request.policyFiles, 1024);
|
|
26879
|
-
if (request.expected !== void 0 && typeof request.expected !== "string")
|
|
27510
|
+
if (request.expected !== void 0 && typeof request.expected !== "string") fail7(t2("commit.expectedType"));
|
|
26880
27511
|
const c = await readPreviewContext(cwd);
|
|
26881
27512
|
const { root, gitDir, indexPath, objectFormat } = await c.reader.location();
|
|
26882
27513
|
const runner = createGitRunner();
|
|
@@ -26899,13 +27530,13 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26899
27530
|
...stdin ? { input: stdin } : {}
|
|
26900
27531
|
});
|
|
26901
27532
|
const staged = async (index) => (await git(["diff", "--cached", "--ita-visible-in-index", "--name-only", "--no-renames", "-z"], index)).toString("utf8").split("\0").filter(Boolean).sort();
|
|
26902
|
-
const busy =
|
|
27533
|
+
const busy = join14(gitDir, "gitifact-spec-commit.lock");
|
|
26903
27534
|
await failOnLegacyLock(gitDir);
|
|
26904
|
-
if (await info5(busy))
|
|
26905
|
-
if ((await staged()).length)
|
|
27535
|
+
if (await info5(busy)) fail7(t2("commit.busy", { path: busy }));
|
|
27536
|
+
if ((await staged()).length) fail7(t2("commit.existingStaging"));
|
|
26906
27537
|
const indexHash = hash2(await optional2(indexPath) ?? Buffer.alloc(0));
|
|
26907
27538
|
const current = c.working;
|
|
26908
|
-
if (request.expected !== void 0 && request.expected !== previewExpected(c.base, current.stamp))
|
|
27539
|
+
if (request.expected !== void 0 && request.expected !== previewExpected(c.base, current.stamp)) fail7(t2("commit.staleInput"));
|
|
26909
27540
|
const reasons = request.reasons ?? pendingPreviewReasons(c.bundle, current.bundle).map((h) => ({ requirements: h.requirements, ...h.designs ? { designs: h.designs } : {}, ...h.documents ? { documents: h.documents } : {}, reason: h.reason }));
|
|
26910
27541
|
const prepared = prepareSpecPreview(c.bundle, current.bundle, c.files, current.files, reasons, () => generatePreviewId("H"));
|
|
26911
27542
|
const blobId = (text2) => {
|
|
@@ -26913,14 +27544,14 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26913
27544
|
return createHash7(objectFormat).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
|
|
26914
27545
|
};
|
|
26915
27546
|
const present = [...current.files.keys()];
|
|
26916
|
-
if (present.some((p) => p.includes("\n")))
|
|
27547
|
+
if (present.some((p) => p.includes("\n"))) fail7(t2("commit.newlinePath"));
|
|
26917
27548
|
const stored = present.length ? (await git(["hash-object", "--stdin-paths"], void 0, Buffer.from(present.join("\n") + "\n"))).toString("utf8").split("\n") : [""];
|
|
26918
|
-
if (stored.length !== present.length + 1)
|
|
27549
|
+
if (stored.length !== present.length + 1) fail7(t2("commit.storedShape"));
|
|
26919
27550
|
const workingIds = new Map(present.map((p, i) => [p, stored[i]]));
|
|
26920
27551
|
const writes = new Map([...prepared.writes].filter(([p, next]) => next === null || workingIds.get(p) !== blobId(next)));
|
|
26921
27552
|
const finalId = (p) => writes.has(p) ? writes.get(p) === null ? void 0 : blobId(writes.get(p)) : workingIds.get(p);
|
|
26922
27553
|
const pending = [.../* @__PURE__ */ new Set([...c.files.keys(), ...present, ...writes.keys()])].filter((p) => (c.files.has(p) ? blobId(c.files.get(p)) : void 0) !== finalId(p));
|
|
26923
|
-
if (pending.some((p) => !selected.includes(p)))
|
|
27554
|
+
if (pending.some((p) => !selected.includes(p))) fail7(t2("commit.selectPending"));
|
|
26924
27555
|
const finalFiles = new Map(current.files);
|
|
26925
27556
|
for (const [path3, next] of writes) {
|
|
26926
27557
|
if (next === null) finalFiles.delete(path3);
|
|
@@ -26929,7 +27560,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26929
27560
|
await checkLegacySelection(root, selected);
|
|
26930
27561
|
const stageable = selected.filter((p) => !record2(p) || finalFiles.has(p) || c.files.has(p));
|
|
26931
27562
|
const known = /* @__PURE__ */ new Set([...current.specs.flatMap((s) => s.requirements.map((r) => r.id)), ...prepared.changes.filter((x) => x.kind === "requirement").map((x) => x.id)]);
|
|
26932
|
-
if (references.some((r) => !known.has(r)))
|
|
27563
|
+
if (references.some((r) => !known.has(r))) fail7(t2("commit.unknownRequirement"));
|
|
26933
27564
|
const requirements = [.../* @__PURE__ */ new Set([...references, ...prepared.changes.filter((x) => x.kind === "requirement").map((x) => x.id)])].sort();
|
|
26934
27565
|
const contextPaths = [.../* @__PURE__ */ new Set([...policyPaths(selected), ...extra])].sort();
|
|
26935
27566
|
const hashes = async (list) => new Map(await Promise.all(list.map(async (p) => [p, await fingerprint(root, p)])));
|
|
@@ -26953,17 +27584,17 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26953
27584
|
...prepared.changes.filter((c2) => c2.kind === "design").map((c2) => "Gitifact-Design: " + c2.id),
|
|
26954
27585
|
...prepared.changes.filter((c2) => c2.kind === "wiki").map((c2) => "Gitifact-Doc: " + c2.id)
|
|
26955
27586
|
];
|
|
26956
|
-
const temporary =
|
|
27587
|
+
const temporary = join14(gitDir, "gitifact-commit-index-" + randomUUID6());
|
|
26957
27588
|
let owned = false;
|
|
26958
27589
|
let uncertain = false;
|
|
26959
27590
|
let indexLock;
|
|
26960
27591
|
let committed;
|
|
26961
27592
|
try {
|
|
26962
27593
|
try {
|
|
26963
|
-
await
|
|
27594
|
+
await mkdir7(busy);
|
|
26964
27595
|
owned = true;
|
|
26965
27596
|
} catch (e) {
|
|
26966
|
-
if (e.code === "EEXIST")
|
|
27597
|
+
if (e.code === "EEXIST") fail7(t2("commit.busy", { path: busy }));
|
|
26967
27598
|
throw e;
|
|
26968
27599
|
}
|
|
26969
27600
|
await previewTransaction(cwd, current.stamp, async () => ({ writes, data: {}, recheck: c.recheck }), rename4, async (published) => {
|
|
@@ -26971,15 +27602,15 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26971
27602
|
try {
|
|
26972
27603
|
const lock = indexLock = await open4(indexPath + ".lock", "wx", 384);
|
|
26973
27604
|
const original = await optional2(indexPath);
|
|
26974
|
-
if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length)
|
|
27605
|
+
if (hash2(original ?? Buffer.alloc(0)) !== indexHash || (await staged()).length) fail7(t2("commit.indexChanged"));
|
|
26975
27606
|
const locked = await hashes([.../* @__PURE__ */ new Set([...selected, ...contextPaths])]);
|
|
26976
|
-
for (const [path3, value] of started) if (locked.get(path3) !== value)
|
|
26977
|
-
await writeFile4(
|
|
27607
|
+
for (const [path3, value] of started) if (locked.get(path3) !== value) fail7(t2("commit.fileChangedRunning", { path: path3 }));
|
|
27608
|
+
await writeFile4(join14(busy, "recovery.json"), JSON.stringify({ before: c.base, originalIndex: original?.toString("base64") ?? null, temporary, paths: selected, message, requirements }));
|
|
26978
27609
|
if (original) await writeFile4(temporary, original, { flag: "wx" });
|
|
26979
27610
|
else await git(["read-tree", "--empty"], temporary);
|
|
26980
27611
|
await git(["add", "--", ...stageable], temporary);
|
|
26981
27612
|
const actual = await staged(temporary);
|
|
26982
|
-
if (!actual.length || actual.some((p) => !selected.includes(p)))
|
|
27613
|
+
if (!actual.length || actual.some((p) => !selected.includes(p))) fail7(t2("commit.unexpectedFiles"));
|
|
26983
27614
|
const records = selected.filter((p) => record2(p) && locked.get(p) !== null);
|
|
26984
27615
|
if (records.length) {
|
|
26985
27616
|
const output2 = await git(["cat-file", "--batch"], temporary, Buffer.from(records.map((p) => ":" + p).join("\n") + "\n"));
|
|
@@ -26988,32 +27619,32 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
26988
27619
|
const end = output2.indexOf(10, offset);
|
|
26989
27620
|
const header = output2.subarray(offset, end).toString("utf8").split(" ");
|
|
26990
27621
|
const size = Number(header[2]);
|
|
26991
|
-
if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10)
|
|
27622
|
+
if (end < 0 || header[1] !== "blob" || !Number.isSafeInteger(size) || output2[end + 1 + size] !== 10) fail7(t2("commit.stagedUnreadable", { path: path3 }));
|
|
26992
27623
|
const staged2 = output2.subarray(end + 1, end + 1 + size);
|
|
26993
|
-
const file2 = await
|
|
26994
|
-
if (!staged2.equals(file2) && !staged2.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1")))
|
|
27624
|
+
const file2 = await readFile11(join14(root, path3));
|
|
27625
|
+
if (!staged2.equals(file2) && !staged2.equals(Buffer.from(file2.toString("latin1").replace(/\r\n/g, "\n"), "latin1"))) fail7(t2("commit.filterChanged"));
|
|
26995
27626
|
offset = end + size + 2;
|
|
26996
27627
|
}
|
|
26997
27628
|
}
|
|
26998
27629
|
const again = await hashes([...locked.keys()]);
|
|
26999
|
-
for (const [path3, value] of locked) if (again.get(path3) !== value)
|
|
27000
|
-
if ((await readLockedPreviewState(root)).stamp !== published.stamp)
|
|
27001
|
-
for (const name of integration) if (await info5(
|
|
27002
|
-
if (!same2(c.base, await c.reader.baseline()))
|
|
27630
|
+
for (const [path3, value] of locked) if (again.get(path3) !== value) fail7(t2("commit.fileChangedPreparing", { path: path3 }));
|
|
27631
|
+
if ((await readLockedPreviewState(root)).stamp !== published.stamp) fail7(t2("commit.specsChangedPreparing"));
|
|
27632
|
+
for (const name of integration) if (await info5(join14(gitDir, name))) fail7(t2("commit.integrationStarted"));
|
|
27633
|
+
if (!same2(c.base, await c.reader.baseline())) fail7(t2("commit.headChanged"));
|
|
27003
27634
|
const tree = (await git(["write-tree"], temporary)).toString("utf8").trim();
|
|
27004
27635
|
commitStarted = true;
|
|
27005
27636
|
await git(["commit", "-m", message.trim() + (trailers.length ? "\n\n" + trailers.join("\n") : "")], temporary);
|
|
27006
27637
|
const after = await c.reader.baseline();
|
|
27007
|
-
if (!after.head) return
|
|
27638
|
+
if (!after.head) return fail7(t2("commit.resultUnknown"));
|
|
27008
27639
|
const raw = (await git(["cat-file", "commit", after.head])).toString("utf8");
|
|
27009
27640
|
const split = raw.indexOf("\n\n");
|
|
27010
27641
|
const headers = raw.slice(0, split < 0 ? raw.length : split).split("\n");
|
|
27011
27642
|
const body = split < 0 ? "" : raw.slice(split + 2);
|
|
27012
27643
|
const parents = headers.filter((h) => h.startsWith("parent ")).map((h) => h.slice(7));
|
|
27013
|
-
if (headers[0] !== "tree " + tree || after.branch !== c.base.branch || !same2(parents, c.base.head ? [c.base.head] : []) || trailers.some((t3) => !body.split(/\r?\n/).includes(t3)))
|
|
27014
|
-
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash)
|
|
27015
|
-
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree)
|
|
27016
|
-
await lock.writeFile(await
|
|
27644
|
+
if (headers[0] !== "tree " + tree || after.branch !== c.base.branch || !same2(parents, c.base.head ? [c.base.head] : []) || trailers.some((t3) => !body.split(/\r?\n/).includes(t3))) fail7(t2("commit.resultAltered"));
|
|
27645
|
+
if (hash2(await optional2(indexPath) ?? Buffer.alloc(0)) !== indexHash) fail7(t2("commit.indexChangedAfter"));
|
|
27646
|
+
if ((await git(["write-tree"], temporary)).toString("utf8").trim() !== tree) fail7(t2("commit.hookChangedStaging"));
|
|
27647
|
+
await lock.writeFile(await readFile11(temporary));
|
|
27017
27648
|
await lock.sync();
|
|
27018
27649
|
await lock.close();
|
|
27019
27650
|
await rename4(indexPath + ".lock", indexPath);
|
|
@@ -27040,7 +27671,7 @@ async function specCommit(cwd, input2, dryRun) {
|
|
|
27040
27671
|
await unlink5(temporary).catch(() => {
|
|
27041
27672
|
});
|
|
27042
27673
|
if (owned) {
|
|
27043
|
-
await unlink5(
|
|
27674
|
+
await unlink5(join14(busy, "recovery.json")).catch(() => {
|
|
27044
27675
|
});
|
|
27045
27676
|
await rmdir2(busy);
|
|
27046
27677
|
}
|
|
@@ -27057,7 +27688,7 @@ async function execute(action, options, controls) {
|
|
|
27057
27688
|
try {
|
|
27058
27689
|
const guard = specPreviewReader(process.cwd());
|
|
27059
27690
|
const { root, gitDir, objectFormat } = await guard.location();
|
|
27060
|
-
for (const marker2 of operations) if (await fileInfo(
|
|
27691
|
+
for (const marker2 of operations) if (await fileInfo(join15(gitDir, marker2))) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker2 }));
|
|
27061
27692
|
if (await guard.hasUnmerged()) throw new InitError("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
27062
27693
|
const raw = await readConfigFile(root);
|
|
27063
27694
|
if (raw === void 0) throw new SpecPreviewError(t2("preview.notInitialized"));
|
|
@@ -27104,7 +27735,7 @@ async function execute(action, options, controls) {
|
|
|
27104
27735
|
async function readInputFile(path3) {
|
|
27105
27736
|
const source2 = await stat2(path3);
|
|
27106
27737
|
if (!source2.isFile() || source2.size > 1024 * 1024) throw new SpecPreviewError(t2("preview.inputFile"));
|
|
27107
|
-
return
|
|
27738
|
+
return readFile12(path3);
|
|
27108
27739
|
}
|
|
27109
27740
|
async function readStdin(stream) {
|
|
27110
27741
|
const chunks = [];
|
|
@@ -27136,8 +27767,8 @@ function narrowWorking(working, options, inputs) {
|
|
|
27136
27767
|
}
|
|
27137
27768
|
|
|
27138
27769
|
// src/commands/migrate.ts
|
|
27139
|
-
import { lstat as lstat9, readdir as readdir6, readFile as
|
|
27140
|
-
import { join as
|
|
27770
|
+
import { lstat as lstat9, readdir as readdir6, readFile as readFile13, rename as rename5, writeFile as writeFile5, unlink as unlink6 } from "node:fs/promises";
|
|
27771
|
+
import { join as join16 } from "node:path";
|
|
27141
27772
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
27142
27773
|
var operations2 = ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD", "rebase-merge", "rebase-apply", "sequencer", "BISECT_START", "index.lock"];
|
|
27143
27774
|
var info6 = (path3) => lstat9(path3).catch((e) => {
|
|
@@ -27145,46 +27776,46 @@ var info6 = (path3) => lstat9(path3).catch((e) => {
|
|
|
27145
27776
|
throw e;
|
|
27146
27777
|
});
|
|
27147
27778
|
var decode4 = (bytes) => new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
27148
|
-
var
|
|
27779
|
+
var fail8 = (code, message) => {
|
|
27149
27780
|
throw new InitError(code, message);
|
|
27150
27781
|
};
|
|
27151
27782
|
async function migrateStore(cwd, dryRun = false) {
|
|
27152
27783
|
const reader = specPreviewReader(cwd);
|
|
27153
27784
|
const { root, gitDir } = await reader.location();
|
|
27154
|
-
for (const marker3 of operations2) if (await info6(
|
|
27155
|
-
if (await reader.hasUnmerged())
|
|
27156
|
-
for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await info6(
|
|
27157
|
-
const from =
|
|
27158
|
-
const to =
|
|
27785
|
+
for (const marker3 of operations2) if (await info6(join16(gitDir, marker3))) fail8("GIT_OPERATION_IN_PROGRESS", t2("git.operationInProgress", { marker: marker3 }));
|
|
27786
|
+
if (await reader.hasUnmerged()) fail8("GIT_OPERATION_IN_PROGRESS", t2("git.resolveConflicts"));
|
|
27787
|
+
for (const name of [...LEGACY_LOCKS, "gitifact-spec-preview.lock", "gitifact-spec-commit.lock"]) if (await info6(join16(gitDir, name))) fail8("LOCKED", t2("migrate.locked", { path: join16(gitDir, name) }));
|
|
27788
|
+
const from = join16(root, ".tryce");
|
|
27789
|
+
const to = join16(root, ".gitifact");
|
|
27159
27790
|
const fromInfo = await info6(from);
|
|
27160
|
-
if (await info6(to))
|
|
27161
|
-
if (!fromInfo) return
|
|
27162
|
-
if (!fromInfo.isDirectory() || fromInfo.isSymbolicLink())
|
|
27163
|
-
const configInfo = await info6(
|
|
27164
|
-
if (!configInfo?.isFile() || configInfo.isSymbolicLink())
|
|
27165
|
-
const config2 = parseManagedConfig(decode4(await
|
|
27166
|
-
if (!("schemaVersion" in config2))
|
|
27791
|
+
if (await info6(to)) fail8("ALREADY_MIGRATED", t2("migrate.alreadyMigrated"));
|
|
27792
|
+
if (!fromInfo) return fail8("NOTHING_TO_MIGRATE", t2("migrate.nothingToMigrate"));
|
|
27793
|
+
if (!fromInfo.isDirectory() || fromInfo.isSymbolicLink()) fail8("PATH_CONFLICT", t2("migrate.notDirectory"));
|
|
27794
|
+
const configInfo = await info6(join16(from, "config.json"));
|
|
27795
|
+
if (!configInfo?.isFile() || configInfo.isSymbolicLink()) fail8("NOT_INITIALIZED", t2("migrate.noConfig"));
|
|
27796
|
+
const config2 = parseManagedConfig(decode4(await readFile13(join16(from, "config.json"))));
|
|
27797
|
+
if (!("schemaVersion" in config2)) fail8("UNSUPPORTED_FORMAT", t2("migrate.legacyJson"));
|
|
27167
27798
|
const top = (await readdir6(from)).sort();
|
|
27168
|
-
if (top.some((name) => name !== "config.json" && name !== "spec"))
|
|
27799
|
+
if (top.some((name) => name !== "config.json" && name !== "spec")) fail8("UNSUPPORTED_FORMAT", t2("migrate.extraEntries"));
|
|
27169
27800
|
const files = /* @__PURE__ */ new Map();
|
|
27170
27801
|
const rewrites = [];
|
|
27171
27802
|
const legacyRecords = [];
|
|
27172
27803
|
const marker2 = /^<!-- tryce-(spec|req|design|ref): /;
|
|
27173
27804
|
if (top.includes("spec")) {
|
|
27174
|
-
for (const feature2 of (await readdir6(
|
|
27175
|
-
const dir =
|
|
27805
|
+
for (const feature2 of (await readdir6(join16(from, "spec"))).sort()) {
|
|
27806
|
+
const dir = join16(from, "spec", feature2);
|
|
27176
27807
|
const stat3 = await info6(dir);
|
|
27177
|
-
if (!stat3?.isDirectory() || stat3.isSymbolicLink())
|
|
27808
|
+
if (!stat3?.isDirectory() || stat3.isSymbolicLink()) fail8("UNSUPPORTED_FORMAT", t2("migrate.notSpecFolder", { feature: feature2 }));
|
|
27178
27809
|
for (const name of (await readdir6(dir)).sort()) {
|
|
27179
|
-
if (!["requirements.md", "design.md", "history.jsonl", "tryce.json"].includes(name))
|
|
27180
|
-
const fileStat = await info6(
|
|
27181
|
-
if (!fileStat?.isFile() || fileStat.isSymbolicLink() || fileStat.nlink !== 1 || fileStat.size > 1024 * 1024)
|
|
27810
|
+
if (!["requirements.md", "design.md", "history.jsonl", "tryce.json"].includes(name)) fail8("UNSUPPORTED_FORMAT", t2("migrate.unsupportedFile", { feature: feature2, name }));
|
|
27811
|
+
const fileStat = await info6(join16(dir, name));
|
|
27812
|
+
if (!fileStat?.isFile() || fileStat.isSymbolicLink() || fileStat.nlink !== 1 || fileStat.size > 1024 * 1024) fail8("UNSUPPORTED_FORMAT", t2("migrate.fileTooLarge", { name }));
|
|
27182
27813
|
const newPath = `.gitifact/spec/${feature2}/${name}`;
|
|
27183
27814
|
if (name === "tryce.json") {
|
|
27184
27815
|
legacyRecords.push(newPath);
|
|
27185
27816
|
continue;
|
|
27186
27817
|
}
|
|
27187
|
-
const text2 = decode4(await
|
|
27818
|
+
const text2 = decode4(await readFile13(join16(dir, name)));
|
|
27188
27819
|
if (name === "history.jsonl") {
|
|
27189
27820
|
files.set(newPath, text2);
|
|
27190
27821
|
continue;
|
|
@@ -27229,8 +27860,8 @@ async function migrateStore(cwd, dryRun = false) {
|
|
|
27229
27860
|
if (dryRun) return result("planned");
|
|
27230
27861
|
await rename5(from, to);
|
|
27231
27862
|
for (const r of rewrites) {
|
|
27232
|
-
const full =
|
|
27233
|
-
const temp =
|
|
27863
|
+
const full = join16(root, r.path);
|
|
27864
|
+
const temp = join16(root, ".gitifact", "spec", ".gitifact-migrate-" + randomBytes3(8).toString("hex"));
|
|
27234
27865
|
await writeFile5(temp, r.content, { flag: "wx" });
|
|
27235
27866
|
try {
|
|
27236
27867
|
await rename5(temp, full);
|
|
@@ -27253,16 +27884,16 @@ async function runMigrate(options) {
|
|
|
27253
27884
|
}
|
|
27254
27885
|
|
|
27255
27886
|
// src/main.ts
|
|
27256
|
-
var program2 = new Command().name("gitifact").description(t2("help.program")).version("0.6.
|
|
27887
|
+
var program2 = new Command().name("gitifact").description(t2("help.program")).version("0.6.1").allowExcessArguments(false).addHelpText("after", "\n" + t2("help.notYet")).action(() => program2.outputHelp());
|
|
27257
27888
|
program2.command("status").description(t2("help.status")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action(async (options) => {
|
|
27258
27889
|
await runStatus(options.format);
|
|
27259
27890
|
});
|
|
27260
|
-
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).option("--no-update-check", t2("help.browserNoUpdateCheck")).action((options) => runBrowser(options, "0.6.
|
|
27261
|
-
program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.6.
|
|
27891
|
+
program2.command("browser").description(t2("help.browser")).allowExcessArguments(false).option("--port <port>", t2("help.browserPort"), parsePort, 0).option("--dev", t2("help.browserDev")).option("--no-update-check", t2("help.browserNoUpdateCheck")).action((options) => runBrowser(options, "0.6.1"));
|
|
27892
|
+
program2.command("init").description(t2("help.init")).allowExcessArguments(false).option("--dry-run", t2("help.initDryRun")).addOption(new Option("--agent <agent>", t2("help.initAgent")).choices([...agentPresetNames])).addOption(new Option("--remove-agents", t2("help.initRemoveAgents")).conflicts("skipAgents")).option("--skip-agents", t2("help.initSkipAgents")).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).action((options) => runInit(options, "0.6.1"));
|
|
27262
27893
|
program2.command("docs").description(t2("help.docs")).argument("[topic]", t2("help.docsTopic")).allowExcessArguments(false).action(async (topic) => {
|
|
27263
27894
|
await runDocs(topic);
|
|
27264
27895
|
});
|
|
27265
|
-
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).option("--commit", t2("help.updateCommit")).action((options) => runUpdate(options, "0.6.
|
|
27896
|
+
program2.command("update").description(t2("help.update")).allowExcessArguments(false).addOption(new Option("--format <format>", t2("help.format")).choices(["json", "text"]).default("json")).option("--commit", t2("help.updateCommit")).action((options) => runUpdate(options, "0.6.1"));
|
|
27266
27897
|
program2.command("migrate").description(t2("help.migrate")).allowExcessArguments(false).option("--dry-run", t2("help.migrateDryRun")).action(runMigrate);
|
|
27267
27898
|
var spec = program2.command("spec").description(t2("help.spec"));
|
|
27268
27899
|
spec.command("commit").description(t2("help.specCommit")).allowExcessArguments(false).requiredOption("--file <path>", t2("help.specCommitFile")).option("--dry-run", t2("help.specCommitDryRun")).action((o) => runSpecPreview("commit", o));
|