@warmhub/cli 0.108.0 → 0.110.0
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/wh.js +1197 -172
- package/package.json +1 -1
package/dist/wh.js
CHANGED
|
@@ -11910,7 +11910,7 @@ var require_response = __commonJS((exports, module) => {
|
|
|
11910
11910
|
var { types } = __require("node:util");
|
|
11911
11911
|
var textEncoder2 = new TextEncoder("utf-8");
|
|
11912
11912
|
|
|
11913
|
-
class
|
|
11913
|
+
class Response2 {
|
|
11914
11914
|
static error() {
|
|
11915
11915
|
const responseObject = fromInnerResponse(makeNetworkError(), "immutable");
|
|
11916
11916
|
return responseObject;
|
|
@@ -11966,11 +11966,11 @@ var require_response = __commonJS((exports, module) => {
|
|
|
11966
11966
|
initializeResponse(this, init, bodyWithType);
|
|
11967
11967
|
}
|
|
11968
11968
|
get type() {
|
|
11969
|
-
webidl.brandCheck(this,
|
|
11969
|
+
webidl.brandCheck(this, Response2);
|
|
11970
11970
|
return this[kState].type;
|
|
11971
11971
|
}
|
|
11972
11972
|
get url() {
|
|
11973
|
-
webidl.brandCheck(this,
|
|
11973
|
+
webidl.brandCheck(this, Response2);
|
|
11974
11974
|
const urlList = this[kState].urlList;
|
|
11975
11975
|
const url2 = urlList[urlList.length - 1] ?? null;
|
|
11976
11976
|
if (url2 === null) {
|
|
@@ -11979,35 +11979,35 @@ var require_response = __commonJS((exports, module) => {
|
|
|
11979
11979
|
return URLSerializer(url2, true);
|
|
11980
11980
|
}
|
|
11981
11981
|
get redirected() {
|
|
11982
|
-
webidl.brandCheck(this,
|
|
11982
|
+
webidl.brandCheck(this, Response2);
|
|
11983
11983
|
return this[kState].urlList.length > 1;
|
|
11984
11984
|
}
|
|
11985
11985
|
get status() {
|
|
11986
|
-
webidl.brandCheck(this,
|
|
11986
|
+
webidl.brandCheck(this, Response2);
|
|
11987
11987
|
return this[kState].status;
|
|
11988
11988
|
}
|
|
11989
11989
|
get ok() {
|
|
11990
|
-
webidl.brandCheck(this,
|
|
11990
|
+
webidl.brandCheck(this, Response2);
|
|
11991
11991
|
return this[kState].status >= 200 && this[kState].status <= 299;
|
|
11992
11992
|
}
|
|
11993
11993
|
get statusText() {
|
|
11994
|
-
webidl.brandCheck(this,
|
|
11994
|
+
webidl.brandCheck(this, Response2);
|
|
11995
11995
|
return this[kState].statusText;
|
|
11996
11996
|
}
|
|
11997
11997
|
get headers() {
|
|
11998
|
-
webidl.brandCheck(this,
|
|
11998
|
+
webidl.brandCheck(this, Response2);
|
|
11999
11999
|
return this[kHeaders];
|
|
12000
12000
|
}
|
|
12001
12001
|
get body() {
|
|
12002
|
-
webidl.brandCheck(this,
|
|
12002
|
+
webidl.brandCheck(this, Response2);
|
|
12003
12003
|
return this[kState].body ? this[kState].body.stream : null;
|
|
12004
12004
|
}
|
|
12005
12005
|
get bodyUsed() {
|
|
12006
|
-
webidl.brandCheck(this,
|
|
12006
|
+
webidl.brandCheck(this, Response2);
|
|
12007
12007
|
return !!this[kState].body && util.isDisturbed(this[kState].body.stream);
|
|
12008
12008
|
}
|
|
12009
12009
|
clone() {
|
|
12010
|
-
webidl.brandCheck(this,
|
|
12010
|
+
webidl.brandCheck(this, Response2);
|
|
12011
12011
|
if (bodyUnusable(this)) {
|
|
12012
12012
|
throw webidl.errors.exception({
|
|
12013
12013
|
header: "Response.clone",
|
|
@@ -12039,8 +12039,8 @@ var require_response = __commonJS((exports, module) => {
|
|
|
12039
12039
|
return `Response ${nodeUtil.formatWithOptions(options, properties)}`;
|
|
12040
12040
|
}
|
|
12041
12041
|
}
|
|
12042
|
-
mixinBody(
|
|
12043
|
-
Object.defineProperties(
|
|
12042
|
+
mixinBody(Response2);
|
|
12043
|
+
Object.defineProperties(Response2.prototype, {
|
|
12044
12044
|
type: kEnumerableProperty,
|
|
12045
12045
|
url: kEnumerableProperty,
|
|
12046
12046
|
status: kEnumerableProperty,
|
|
@@ -12056,7 +12056,7 @@ var require_response = __commonJS((exports, module) => {
|
|
|
12056
12056
|
configurable: true
|
|
12057
12057
|
}
|
|
12058
12058
|
});
|
|
12059
|
-
Object.defineProperties(
|
|
12059
|
+
Object.defineProperties(Response2, {
|
|
12060
12060
|
json: kEnumerableProperty,
|
|
12061
12061
|
redirect: kEnumerableProperty,
|
|
12062
12062
|
error: kEnumerableProperty
|
|
@@ -12182,7 +12182,7 @@ var require_response = __commonJS((exports, module) => {
|
|
|
12182
12182
|
}
|
|
12183
12183
|
}
|
|
12184
12184
|
function fromInnerResponse(innerResponse, guard) {
|
|
12185
|
-
const response = new
|
|
12185
|
+
const response = new Response2(kConstruct);
|
|
12186
12186
|
response[kState] = innerResponse;
|
|
12187
12187
|
response[kHeaders] = new Headers2(kConstruct);
|
|
12188
12188
|
setHeadersList(response[kHeaders], innerResponse.headersList);
|
|
@@ -12244,7 +12244,7 @@ var require_response = __commonJS((exports, module) => {
|
|
|
12244
12244
|
makeResponse,
|
|
12245
12245
|
makeAppropriateNetworkError,
|
|
12246
12246
|
filterResponse,
|
|
12247
|
-
Response,
|
|
12247
|
+
Response: Response2,
|
|
12248
12248
|
cloneResponse,
|
|
12249
12249
|
fromInnerResponse
|
|
12250
12250
|
};
|
|
@@ -14688,7 +14688,7 @@ var require_cache = __commonJS((exports, module) => {
|
|
|
14688
14688
|
var { urlEquals, getFieldValues } = require_util5();
|
|
14689
14689
|
var { kEnumerableProperty, isDisturbed } = require_util();
|
|
14690
14690
|
var { webidl } = require_webidl();
|
|
14691
|
-
var { Response, cloneResponse, fromInnerResponse } = require_response();
|
|
14691
|
+
var { Response: Response2, cloneResponse, fromInnerResponse } = require_response();
|
|
14692
14692
|
var { Request, fromInnerRequest } = require_request2();
|
|
14693
14693
|
var { kState } = require_symbols2();
|
|
14694
14694
|
var { fetching } = require_fetch();
|
|
@@ -15178,7 +15178,7 @@ var require_cache = __commonJS((exports, module) => {
|
|
|
15178
15178
|
converter: webidl.converters.DOMString
|
|
15179
15179
|
}
|
|
15180
15180
|
]);
|
|
15181
|
-
webidl.converters.Response = webidl.interfaceConverter(
|
|
15181
|
+
webidl.converters.Response = webidl.interfaceConverter(Response2);
|
|
15182
15182
|
webidl.converters["sequence<RequestInfo>"] = webidl.sequenceConverter(webidl.converters.RequestInfo);
|
|
15183
15183
|
module.exports = {
|
|
15184
15184
|
Cache
|
|
@@ -17301,7 +17301,7 @@ var require_eventsource_stream = __commonJS((exports, module) => {
|
|
|
17301
17301
|
var { Transform } = __require("node:stream");
|
|
17302
17302
|
var { isASCIINumber, isValidLastEventId } = require_util8();
|
|
17303
17303
|
var BOM = [239, 187, 191];
|
|
17304
|
-
var
|
|
17304
|
+
var LF3 = 10;
|
|
17305
17305
|
var CR = 13;
|
|
17306
17306
|
var COLON = 58;
|
|
17307
17307
|
var SPACE = 32;
|
|
@@ -17374,7 +17374,7 @@ var require_eventsource_stream = __commonJS((exports, module) => {
|
|
|
17374
17374
|
while (this.pos < this.buffer.length) {
|
|
17375
17375
|
if (this.eventEndCheck) {
|
|
17376
17376
|
if (this.crlfCheck) {
|
|
17377
|
-
if (this.buffer[this.pos] ===
|
|
17377
|
+
if (this.buffer[this.pos] === LF3) {
|
|
17378
17378
|
this.buffer = this.buffer.subarray(this.pos + 1);
|
|
17379
17379
|
this.pos = 0;
|
|
17380
17380
|
this.crlfCheck = false;
|
|
@@ -17382,7 +17382,7 @@ var require_eventsource_stream = __commonJS((exports, module) => {
|
|
|
17382
17382
|
}
|
|
17383
17383
|
this.crlfCheck = false;
|
|
17384
17384
|
}
|
|
17385
|
-
if (this.buffer[this.pos] ===
|
|
17385
|
+
if (this.buffer[this.pos] === LF3 || this.buffer[this.pos] === CR) {
|
|
17386
17386
|
if (this.buffer[this.pos] === CR) {
|
|
17387
17387
|
this.crlfCheck = true;
|
|
17388
17388
|
}
|
|
@@ -17397,7 +17397,7 @@ var require_eventsource_stream = __commonJS((exports, module) => {
|
|
|
17397
17397
|
this.eventEndCheck = false;
|
|
17398
17398
|
continue;
|
|
17399
17399
|
}
|
|
17400
|
-
if (this.buffer[this.pos] ===
|
|
17400
|
+
if (this.buffer[this.pos] === LF3 || this.buffer[this.pos] === CR) {
|
|
17401
17401
|
if (this.buffer[this.pos] === CR) {
|
|
17402
17402
|
this.crlfCheck = true;
|
|
17403
17403
|
}
|
|
@@ -35401,6 +35401,37 @@ var checkpointManifestFields = {
|
|
|
35401
35401
|
var checkpointManifestContentSchema = exports_external.object(checkpointManifestFields).strict();
|
|
35402
35402
|
var checkpointManifestV2Schema = checkpointManifestContentSchema.extend({ contentSha256: checkpointSha256Schema }).strict();
|
|
35403
35403
|
|
|
35404
|
+
// ../../packages/rules/src/canonical-line.ts
|
|
35405
|
+
var utf8Encoder2 = new TextEncoder;
|
|
35406
|
+
var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
|
|
35407
|
+
function encodeCanonicalLine(value) {
|
|
35408
|
+
return utf8Encoder2.encode(`${stableJson(value)}
|
|
35409
|
+
`);
|
|
35410
|
+
}
|
|
35411
|
+
function assertCanonicalLineFraming(bytes, subject) {
|
|
35412
|
+
if (bytes.length === 0 || bytes.at(-1) !== 10) {
|
|
35413
|
+
throw new Error(`${subject} must end with one LF`);
|
|
35414
|
+
}
|
|
35415
|
+
if (bytes.length >= 3 && bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) {
|
|
35416
|
+
throw new Error(`${subject} must not contain a UTF-8 BOM`);
|
|
35417
|
+
}
|
|
35418
|
+
for (let index = 0;index < bytes.length - 1; index += 1) {
|
|
35419
|
+
if (bytes[index] === 10 || bytes[index] === 13) {
|
|
35420
|
+
throw new Error(`${subject} must contain exactly one LF and no CR`);
|
|
35421
|
+
}
|
|
35422
|
+
}
|
|
35423
|
+
}
|
|
35424
|
+
function parseCanonicalLine(bytes, schema, subject) {
|
|
35425
|
+
assertCanonicalLineFraming(bytes, subject);
|
|
35426
|
+
const decoded = utf8Decoder.decode(bytes);
|
|
35427
|
+
const parsed = schema.parse(JSON.parse(decoded.slice(0, -1)));
|
|
35428
|
+
if (decoded !== `${stableJson(parsed)}
|
|
35429
|
+
`) {
|
|
35430
|
+
throw new Error(`${subject} bytes are not canonical`);
|
|
35431
|
+
}
|
|
35432
|
+
return parsed;
|
|
35433
|
+
}
|
|
35434
|
+
|
|
35404
35435
|
// ../../packages/rules/src/repository-checkpoint/paths.ts
|
|
35405
35436
|
var MAX_CHECKPOINT_PART = 10 ** CHECKPOINT_PART_DIGITS - 1;
|
|
35406
35437
|
async function checkpointShapeKey(shapeName) {
|
|
@@ -35427,7 +35458,7 @@ function assertCheckpointPart(part) {
|
|
|
35427
35458
|
}
|
|
35428
35459
|
|
|
35429
35460
|
// ../../packages/rules/src/repository-checkpoint/manifest.ts
|
|
35430
|
-
var
|
|
35461
|
+
var utf8Decoder2 = new TextDecoder("utf-8", { fatal: true });
|
|
35431
35462
|
async function validateCheckpointManifest(input) {
|
|
35432
35463
|
const manifest = checkpointManifestV2Schema.parse(input);
|
|
35433
35464
|
const { contentSha256, ...content } = manifest;
|
|
@@ -35444,8 +35475,8 @@ async function encodeCheckpointManifest(input) {
|
|
|
35444
35475
|
`);
|
|
35445
35476
|
}
|
|
35446
35477
|
async function parseCheckpointManifest(bytes) {
|
|
35447
|
-
|
|
35448
|
-
const decoded =
|
|
35478
|
+
assertCanonicalLineFraming(bytes, "Checkpoint manifest");
|
|
35479
|
+
const decoded = utf8Decoder2.decode(bytes);
|
|
35449
35480
|
const manifest = await validateCheckpointManifest(checkpointManifestV2Schema.parse(JSON.parse(decoded.slice(0, -1))));
|
|
35450
35481
|
const canonical = await encodeCheckpointManifest(manifest);
|
|
35451
35482
|
if (!bytesEqual(bytes, canonical)) {
|
|
@@ -35491,46 +35522,14 @@ function addSafeCounts(left, right) {
|
|
|
35491
35522
|
}
|
|
35492
35523
|
return total;
|
|
35493
35524
|
}
|
|
35494
|
-
function assertCanonicalManifestFraming(bytes) {
|
|
35495
|
-
if (bytes.length === 0 || bytes.at(-1) !== 10) {
|
|
35496
|
-
throw new Error("Checkpoint manifest must end with one LF");
|
|
35497
|
-
}
|
|
35498
|
-
if (bytes.length >= 3 && bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) {
|
|
35499
|
-
throw new Error("Checkpoint manifest must not contain a UTF-8 BOM");
|
|
35500
|
-
}
|
|
35501
|
-
for (let index = 0;index < bytes.length - 1; index += 1) {
|
|
35502
|
-
if (bytes[index] === 10 || bytes[index] === 13) {
|
|
35503
|
-
throw new Error("Checkpoint manifest must contain exactly one LF and no CR");
|
|
35504
|
-
}
|
|
35505
|
-
}
|
|
35506
|
-
}
|
|
35507
35525
|
function bytesEqual(left, right) {
|
|
35508
35526
|
if (left.length !== right.length)
|
|
35509
35527
|
return false;
|
|
35510
35528
|
return left.every((byte, index) => byte === right[index]);
|
|
35511
35529
|
}
|
|
35512
35530
|
// ../../packages/rules/src/repository-checkpoint/row-codec.ts
|
|
35513
|
-
var utf8Encoder2 = new TextEncoder;
|
|
35514
|
-
var utf8Decoder2 = new TextDecoder("utf-8", { fatal: true });
|
|
35515
35531
|
function parseCheckpointRowLine(bytes) {
|
|
35516
|
-
|
|
35517
|
-
throw new Error("Checkpoint row must end with one LF");
|
|
35518
|
-
}
|
|
35519
|
-
if (bytes.length >= 3 && bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) {
|
|
35520
|
-
throw new Error("Checkpoint row must not contain a UTF-8 BOM");
|
|
35521
|
-
}
|
|
35522
|
-
for (let index = 0;index < bytes.length - 1; index += 1) {
|
|
35523
|
-
if (bytes[index] === 10 || bytes[index] === 13) {
|
|
35524
|
-
throw new Error("Checkpoint row must contain exactly one LF and no CR");
|
|
35525
|
-
}
|
|
35526
|
-
}
|
|
35527
|
-
const decoded = utf8Decoder2.decode(bytes);
|
|
35528
|
-
const parsed = checkpointRowSchema.parse(JSON.parse(decoded.slice(0, -1)));
|
|
35529
|
-
if (decoded !== `${stableJson(parsed)}
|
|
35530
|
-
`) {
|
|
35531
|
-
throw new Error("Checkpoint row bytes are not canonical");
|
|
35532
|
-
}
|
|
35533
|
-
return parsed;
|
|
35532
|
+
return parseCanonicalLine(bytes, checkpointRowSchema, "Checkpoint row");
|
|
35534
35533
|
}
|
|
35535
35534
|
// ../../packages/rules/src/repository-checkpoint/streams.ts
|
|
35536
35535
|
function createCheckpointStreamValidationState(shapeName) {
|
|
@@ -35582,6 +35581,327 @@ function addOneSafe(value) {
|
|
|
35582
35581
|
}
|
|
35583
35582
|
return next;
|
|
35584
35583
|
}
|
|
35584
|
+
// ../../packages/rules/src/repository-export/types.ts
|
|
35585
|
+
var REPOSITORY_EXPORT_FORMAT_VERSION = 3;
|
|
35586
|
+
var REPOSITORY_EXPORT_MEDIA_TYPE = "application/x-ndjson";
|
|
35587
|
+
var repositoryExportSha256Schema = exports_external.string().regex(/^[0-9a-f]{64}$/);
|
|
35588
|
+
var nonnegativeSafeIntegerSchema2 = exports_external.number().int().nonnegative();
|
|
35589
|
+
var positiveSafeIntegerSchema2 = exports_external.number().int().positive();
|
|
35590
|
+
var REPOSITORY_EXPORT_ROW_KINDS = [
|
|
35591
|
+
"shape",
|
|
35592
|
+
"thing",
|
|
35593
|
+
"collection",
|
|
35594
|
+
"assertion"
|
|
35595
|
+
];
|
|
35596
|
+
var REPOSITORY_EXPORT_MODES = ["heads", "ops"];
|
|
35597
|
+
var REPOSITORY_EXPORT_SHAPE_PROVENANCES = [
|
|
35598
|
+
"captured",
|
|
35599
|
+
"migration-stamped",
|
|
35600
|
+
"reconstructed"
|
|
35601
|
+
];
|
|
35602
|
+
var repositoryExportShapeCertificateSchema = exports_external.object({
|
|
35603
|
+
name: exports_external.string().min(1),
|
|
35604
|
+
v: positiveSafeIntegerSchema2,
|
|
35605
|
+
durableId: exports_external.string().min(1),
|
|
35606
|
+
provenance: exports_external.enum(REPOSITORY_EXPORT_SHAPE_PROVENANCES),
|
|
35607
|
+
declared: exports_external.boolean()
|
|
35608
|
+
}).strict();
|
|
35609
|
+
var repositoryExportReferenceSchema = exports_external.object({
|
|
35610
|
+
wref: exports_external.string().min(1),
|
|
35611
|
+
v: positiveSafeIntegerSchema2.optional(),
|
|
35612
|
+
durableId: exports_external.string().min(1)
|
|
35613
|
+
}).strict();
|
|
35614
|
+
function refineStrictlyIncreasing(entries, key, message, context) {
|
|
35615
|
+
let previous;
|
|
35616
|
+
entries.forEach((entry, index) => {
|
|
35617
|
+
const current = key(entry);
|
|
35618
|
+
if (previous !== undefined && compareUnsignedUtf8(previous, current) >= 0) {
|
|
35619
|
+
context.addIssue({ code: "custom", path: [index], message });
|
|
35620
|
+
}
|
|
35621
|
+
previous = current;
|
|
35622
|
+
});
|
|
35623
|
+
}
|
|
35624
|
+
var shapesSchema = exports_external.array(repositoryExportShapeCertificateSchema).superRefine((shapes, context) => {
|
|
35625
|
+
refineStrictlyIncreasing(shapes, (entry) => entry.durableId, "Shape certificates must be unique and strictly increasing by durableId", context);
|
|
35626
|
+
});
|
|
35627
|
+
var affirmedSchema = exports_external.array(repositoryExportReferenceSchema).superRefine((affirmed, context) => {
|
|
35628
|
+
refineStrictlyIncreasing(affirmed, (entry) => entry.wref, "Affirmed references must be unique and strictly increasing", context);
|
|
35629
|
+
});
|
|
35630
|
+
var rowEnvelopeFields = {
|
|
35631
|
+
wref: exports_external.string().min(1),
|
|
35632
|
+
durableId: exports_external.string().min(1),
|
|
35633
|
+
version: positiveSafeIntegerSchema2
|
|
35634
|
+
};
|
|
35635
|
+
var activeRowFields = {
|
|
35636
|
+
...rowEnvelopeFields,
|
|
35637
|
+
active: exports_external.literal(true),
|
|
35638
|
+
data: exports_external.record(exports_external.string(), jsonValueSchema)
|
|
35639
|
+
};
|
|
35640
|
+
var activeRowSchema = exports_external.discriminatedUnion("kind", [
|
|
35641
|
+
exports_external.object({
|
|
35642
|
+
...activeRowFields,
|
|
35643
|
+
kind: exports_external.literal("shape"),
|
|
35644
|
+
shapes: exports_external.array(repositoryExportShapeCertificateSchema).max(0)
|
|
35645
|
+
}).strict(),
|
|
35646
|
+
exports_external.object({
|
|
35647
|
+
...activeRowFields,
|
|
35648
|
+
kind: exports_external.enum(["thing", "collection"]),
|
|
35649
|
+
shapes: shapesSchema
|
|
35650
|
+
}).strict(),
|
|
35651
|
+
exports_external.object({
|
|
35652
|
+
...activeRowFields,
|
|
35653
|
+
kind: exports_external.literal("assertion"),
|
|
35654
|
+
shapes: shapesSchema,
|
|
35655
|
+
about: repositoryExportReferenceSchema,
|
|
35656
|
+
affirmed: affirmedSchema
|
|
35657
|
+
}).strict()
|
|
35658
|
+
]);
|
|
35659
|
+
var tombstoneRowSchema = exports_external.object({
|
|
35660
|
+
...rowEnvelopeFields,
|
|
35661
|
+
kind: exports_external.enum(REPOSITORY_EXPORT_ROW_KINDS),
|
|
35662
|
+
active: exports_external.literal(false)
|
|
35663
|
+
}).strict();
|
|
35664
|
+
var repositoryExportRowSchema = exports_external.union([
|
|
35665
|
+
activeRowSchema,
|
|
35666
|
+
tombstoneRowSchema
|
|
35667
|
+
]);
|
|
35668
|
+
var repositoryExportHeaderSchema = exports_external.object({
|
|
35669
|
+
kind: exports_external.literal("header"),
|
|
35670
|
+
formatVersion: exports_external.literal(REPOSITORY_EXPORT_FORMAT_VERSION),
|
|
35671
|
+
repo: exports_external.string().regex(/^[^/\s]+\/[^/\s]+$/, 'repo must be "<org>/<repo>"'),
|
|
35672
|
+
mode: exports_external.enum(REPOSITORY_EXPORT_MODES),
|
|
35673
|
+
sinceRepoSeq: nonnegativeSafeIntegerSchema2,
|
|
35674
|
+
atRepoSeq: nonnegativeSafeIntegerSchema2
|
|
35675
|
+
}).strict().refine((header) => header.atRepoSeq >= header.sinceRepoSeq, "atRepoSeq must not precede sinceRepoSeq");
|
|
35676
|
+
var repositoryExportTrailerSchema = exports_external.object({
|
|
35677
|
+
kind: exports_external.literal("trailer"),
|
|
35678
|
+
recordCount: nonnegativeSafeIntegerSchema2,
|
|
35679
|
+
contentSha256: repositoryExportSha256Schema,
|
|
35680
|
+
atRepoSeq: nonnegativeSafeIntegerSchema2
|
|
35681
|
+
}).strict();
|
|
35682
|
+
function repositoryExportAllowsTombstones(header) {
|
|
35683
|
+
return header.sinceRepoSeq > 0;
|
|
35684
|
+
}
|
|
35685
|
+
|
|
35686
|
+
// ../../packages/rules/src/repository-export/codec.ts
|
|
35687
|
+
function encodeRepositoryExportRow(row) {
|
|
35688
|
+
return encodeCanonicalLine(repositoryExportRowSchema.parse(row));
|
|
35689
|
+
}
|
|
35690
|
+
function encodeRepositoryExportHeader(header) {
|
|
35691
|
+
return encodeCanonicalLine(repositoryExportHeaderSchema.parse(header));
|
|
35692
|
+
}
|
|
35693
|
+
function encodeRepositoryExportTrailer(trailer) {
|
|
35694
|
+
return encodeCanonicalLine(repositoryExportTrailerSchema.parse(trailer));
|
|
35695
|
+
}
|
|
35696
|
+
function parseRepositoryExportRowLine(bytes) {
|
|
35697
|
+
return parseCanonicalLine(bytes, repositoryExportRowSchema, "Repository export row");
|
|
35698
|
+
}
|
|
35699
|
+
function parseRepositoryExportHeaderLine(bytes) {
|
|
35700
|
+
return parseCanonicalLine(bytes, repositoryExportHeaderSchema, "Repository export header");
|
|
35701
|
+
}
|
|
35702
|
+
function parseRepositoryExportTrailerLine(bytes) {
|
|
35703
|
+
return parseCanonicalLine(bytes, repositoryExportTrailerSchema, "Repository export trailer");
|
|
35704
|
+
}
|
|
35705
|
+
// ../../packages/rules/src/repository-export/sha256.ts
|
|
35706
|
+
var ROUND_CONSTANTS = Uint32Array.from([
|
|
35707
|
+
1116352408,
|
|
35708
|
+
1899447441,
|
|
35709
|
+
3049323471,
|
|
35710
|
+
3921009573,
|
|
35711
|
+
961987163,
|
|
35712
|
+
1508970993,
|
|
35713
|
+
2453635748,
|
|
35714
|
+
2870763221,
|
|
35715
|
+
3624381080,
|
|
35716
|
+
310598401,
|
|
35717
|
+
607225278,
|
|
35718
|
+
1426881987,
|
|
35719
|
+
1925078388,
|
|
35720
|
+
2162078206,
|
|
35721
|
+
2614888103,
|
|
35722
|
+
3248222580,
|
|
35723
|
+
3835390401,
|
|
35724
|
+
4022224774,
|
|
35725
|
+
264347078,
|
|
35726
|
+
604807628,
|
|
35727
|
+
770255983,
|
|
35728
|
+
1249150122,
|
|
35729
|
+
1555081692,
|
|
35730
|
+
1996064986,
|
|
35731
|
+
2554220882,
|
|
35732
|
+
2821834349,
|
|
35733
|
+
2952996808,
|
|
35734
|
+
3210313671,
|
|
35735
|
+
3336571891,
|
|
35736
|
+
3584528711,
|
|
35737
|
+
113926993,
|
|
35738
|
+
338241895,
|
|
35739
|
+
666307205,
|
|
35740
|
+
773529912,
|
|
35741
|
+
1294757372,
|
|
35742
|
+
1396182291,
|
|
35743
|
+
1695183700,
|
|
35744
|
+
1986661051,
|
|
35745
|
+
2177026350,
|
|
35746
|
+
2456956037,
|
|
35747
|
+
2730485921,
|
|
35748
|
+
2820302411,
|
|
35749
|
+
3259730800,
|
|
35750
|
+
3345764771,
|
|
35751
|
+
3516065817,
|
|
35752
|
+
3600352804,
|
|
35753
|
+
4094571909,
|
|
35754
|
+
275423344,
|
|
35755
|
+
430227734,
|
|
35756
|
+
506948616,
|
|
35757
|
+
659060556,
|
|
35758
|
+
883997877,
|
|
35759
|
+
958139571,
|
|
35760
|
+
1322822218,
|
|
35761
|
+
1537002063,
|
|
35762
|
+
1747873779,
|
|
35763
|
+
1955562222,
|
|
35764
|
+
2024104815,
|
|
35765
|
+
2227730452,
|
|
35766
|
+
2361852424,
|
|
35767
|
+
2428436474,
|
|
35768
|
+
2756734187,
|
|
35769
|
+
3204031479,
|
|
35770
|
+
3329325298
|
|
35771
|
+
]);
|
|
35772
|
+
var INITIAL_STATE = Uint32Array.from([
|
|
35773
|
+
1779033703,
|
|
35774
|
+
3144134277,
|
|
35775
|
+
1013904242,
|
|
35776
|
+
2773480762,
|
|
35777
|
+
1359893119,
|
|
35778
|
+
2600822924,
|
|
35779
|
+
528734635,
|
|
35780
|
+
1541459225
|
|
35781
|
+
]);
|
|
35782
|
+
var BLOCK_BYTES = 64;
|
|
35783
|
+
function rotr(value, bits) {
|
|
35784
|
+
return (value >>> bits | value << 32 - bits) >>> 0;
|
|
35785
|
+
}
|
|
35786
|
+
|
|
35787
|
+
class Sha256 {
|
|
35788
|
+
#state = Uint32Array.from(INITIAL_STATE);
|
|
35789
|
+
#schedule = new Uint32Array(64);
|
|
35790
|
+
#block = new Uint8Array(BLOCK_BYTES);
|
|
35791
|
+
#blockLength = 0;
|
|
35792
|
+
#byteLength = 0;
|
|
35793
|
+
#finished = false;
|
|
35794
|
+
update(bytes) {
|
|
35795
|
+
if (this.#finished) {
|
|
35796
|
+
throw new Error("SHA-256 hasher is already finalized");
|
|
35797
|
+
}
|
|
35798
|
+
this.#byteLength += bytes.length;
|
|
35799
|
+
if (!Number.isSafeInteger(this.#byteLength)) {
|
|
35800
|
+
throw new RangeError("SHA-256 input length must be a safe integer");
|
|
35801
|
+
}
|
|
35802
|
+
let offset = 0;
|
|
35803
|
+
if (this.#blockLength > 0) {
|
|
35804
|
+
const take = Math.min(BLOCK_BYTES - this.#blockLength, bytes.length);
|
|
35805
|
+
this.#block.set(bytes.subarray(0, take), this.#blockLength);
|
|
35806
|
+
this.#blockLength += take;
|
|
35807
|
+
offset = take;
|
|
35808
|
+
if (this.#blockLength < BLOCK_BYTES)
|
|
35809
|
+
return;
|
|
35810
|
+
this.#compress(this.#block, 0);
|
|
35811
|
+
this.#blockLength = 0;
|
|
35812
|
+
}
|
|
35813
|
+
while (offset + BLOCK_BYTES <= bytes.length) {
|
|
35814
|
+
this.#compress(bytes, offset);
|
|
35815
|
+
offset += BLOCK_BYTES;
|
|
35816
|
+
}
|
|
35817
|
+
if (offset < bytes.length) {
|
|
35818
|
+
this.#block.set(bytes.subarray(offset), 0);
|
|
35819
|
+
this.#blockLength = bytes.length - offset;
|
|
35820
|
+
}
|
|
35821
|
+
}
|
|
35822
|
+
digestHex() {
|
|
35823
|
+
if (this.#finished) {
|
|
35824
|
+
throw new Error("SHA-256 hasher is already finalized");
|
|
35825
|
+
}
|
|
35826
|
+
this.#finished = true;
|
|
35827
|
+
const tail = new Uint8Array(this.#blockLength < 56 ? 64 : 128);
|
|
35828
|
+
tail.set(this.#block.subarray(0, this.#blockLength), 0);
|
|
35829
|
+
tail[this.#blockLength] = 128;
|
|
35830
|
+
const view = new DataView(tail.buffer);
|
|
35831
|
+
view.setUint32(tail.length - 8, Math.floor(this.#byteLength / 536870912));
|
|
35832
|
+
view.setUint32(tail.length - 4, this.#byteLength << 3 >>> 0);
|
|
35833
|
+
for (let offset = 0;offset < tail.length; offset += BLOCK_BYTES) {
|
|
35834
|
+
this.#compress(tail, offset);
|
|
35835
|
+
}
|
|
35836
|
+
return Array.from(this.#state, (word) => word.toString(16).padStart(8, "0")).join("");
|
|
35837
|
+
}
|
|
35838
|
+
#compress(bytes, offset) {
|
|
35839
|
+
const schedule = this.#schedule;
|
|
35840
|
+
for (let index = 0;index < 16; index += 1) {
|
|
35841
|
+
const at = offset + index * 4;
|
|
35842
|
+
schedule[index] = (bytes[at] << 24 | bytes[at + 1] << 16 | bytes[at + 2] << 8 | bytes[at + 3]) >>> 0;
|
|
35843
|
+
}
|
|
35844
|
+
for (let index = 16;index < 64; index += 1) {
|
|
35845
|
+
const previous = schedule[index - 15];
|
|
35846
|
+
const recent = schedule[index - 2];
|
|
35847
|
+
const s0 = (rotr(previous, 7) ^ rotr(previous, 18) ^ previous >>> 3) >>> 0;
|
|
35848
|
+
const s1 = (rotr(recent, 17) ^ rotr(recent, 19) ^ recent >>> 10) >>> 0;
|
|
35849
|
+
schedule[index] = schedule[index - 16] + s0 + schedule[index - 7] + s1 >>> 0;
|
|
35850
|
+
}
|
|
35851
|
+
const state = this.#state;
|
|
35852
|
+
let a = state[0];
|
|
35853
|
+
let b = state[1];
|
|
35854
|
+
let c = state[2];
|
|
35855
|
+
let d = state[3];
|
|
35856
|
+
let e = state[4];
|
|
35857
|
+
let f = state[5];
|
|
35858
|
+
let g = state[6];
|
|
35859
|
+
let h = state[7];
|
|
35860
|
+
for (let index = 0;index < 64; index += 1) {
|
|
35861
|
+
const s1 = (rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25)) >>> 0;
|
|
35862
|
+
const choice = (e & f ^ ~e & g) >>> 0;
|
|
35863
|
+
const temp1 = h + s1 + choice + ROUND_CONSTANTS[index] + schedule[index] >>> 0;
|
|
35864
|
+
const s0 = (rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22)) >>> 0;
|
|
35865
|
+
const majority = (a & b ^ a & c ^ b & c) >>> 0;
|
|
35866
|
+
const temp2 = s0 + majority >>> 0;
|
|
35867
|
+
h = g;
|
|
35868
|
+
g = f;
|
|
35869
|
+
f = e;
|
|
35870
|
+
e = d + temp1 >>> 0;
|
|
35871
|
+
d = c;
|
|
35872
|
+
c = b;
|
|
35873
|
+
b = a;
|
|
35874
|
+
a = temp1 + temp2 >>> 0;
|
|
35875
|
+
}
|
|
35876
|
+
state[0] = a + state[0] >>> 0;
|
|
35877
|
+
state[1] = b + state[1] >>> 0;
|
|
35878
|
+
state[2] = c + state[2] >>> 0;
|
|
35879
|
+
state[3] = d + state[3] >>> 0;
|
|
35880
|
+
state[4] = e + state[4] >>> 0;
|
|
35881
|
+
state[5] = f + state[5] >>> 0;
|
|
35882
|
+
state[6] = g + state[6] >>> 0;
|
|
35883
|
+
state[7] = h + state[7] >>> 0;
|
|
35884
|
+
}
|
|
35885
|
+
}
|
|
35886
|
+
|
|
35887
|
+
// ../../packages/rules/src/repository-export/digest.ts
|
|
35888
|
+
class RepositoryExportDigest {
|
|
35889
|
+
#hash = new Sha256;
|
|
35890
|
+
#rowCount = 0;
|
|
35891
|
+
get rowCount() {
|
|
35892
|
+
return this.#rowCount;
|
|
35893
|
+
}
|
|
35894
|
+
update(rowBytes) {
|
|
35895
|
+
this.#hash.update(rowBytes);
|
|
35896
|
+
this.#rowCount += 1;
|
|
35897
|
+
}
|
|
35898
|
+
finalize() {
|
|
35899
|
+
return this.#hash.digestHex();
|
|
35900
|
+
}
|
|
35901
|
+
}
|
|
35902
|
+
function createRepositoryExportDigest() {
|
|
35903
|
+
return new RepositoryExportDigest;
|
|
35904
|
+
}
|
|
35585
35905
|
// ../../packages/rules/src/shape-types.ts
|
|
35586
35906
|
var BASE_PRIMITIVE_TYPES = [
|
|
35587
35907
|
"number",
|
|
@@ -43355,18 +43675,6 @@ function toRepositoryCheckpointSelector(selector) {
|
|
|
43355
43675
|
}
|
|
43356
43676
|
function createRepositoryCheckpointClient(getTrpc, toWarmHubError) {
|
|
43357
43677
|
return {
|
|
43358
|
-
generate: async (orgName, repoName, options) => {
|
|
43359
|
-
try {
|
|
43360
|
-
const result = await getTrpc().repo.checkpoint.generate.mutate({
|
|
43361
|
-
orgName,
|
|
43362
|
-
repoName,
|
|
43363
|
-
atLeastRepoSeq: options?.atLeastRepoSeq
|
|
43364
|
-
});
|
|
43365
|
-
return normalizeRepositoryCheckpointStatus(result.checkpoint);
|
|
43366
|
-
} catch (error51) {
|
|
43367
|
-
throw toWarmHubError(error51);
|
|
43368
|
-
}
|
|
43369
|
-
},
|
|
43370
43678
|
status: async (orgName, repoName, selector) => {
|
|
43371
43679
|
try {
|
|
43372
43680
|
const result = await getTrpc().repo.checkpoint.status.query({
|
|
@@ -43402,22 +43710,464 @@ function createRepositoryCheckpointClient(getTrpc, toWarmHubError) {
|
|
|
43402
43710
|
} catch (error51) {
|
|
43403
43711
|
throw toWarmHubError(error51);
|
|
43404
43712
|
}
|
|
43405
|
-
}
|
|
43406
|
-
|
|
43713
|
+
}
|
|
43714
|
+
};
|
|
43715
|
+
}
|
|
43716
|
+
|
|
43717
|
+
// ../../packages/sdk-ts/src/repository-export/types.ts
|
|
43718
|
+
class RepositoryExportError extends Error {
|
|
43719
|
+
reason;
|
|
43720
|
+
name = "RepositoryExportError";
|
|
43721
|
+
constructor(reason, message) {
|
|
43722
|
+
super(message ?? REASON_MESSAGES[reason]);
|
|
43723
|
+
this.reason = reason;
|
|
43724
|
+
}
|
|
43725
|
+
}
|
|
43726
|
+
var REASON_MESSAGES = {
|
|
43727
|
+
count_mismatch: "Repository export trailer record count does not match the rows read",
|
|
43728
|
+
digest_mismatch: "Repository export content digest does not match the trailer",
|
|
43729
|
+
fence_mismatch: "Repository export header and trailer disagree about atRepoSeq",
|
|
43730
|
+
header_invalid: "Repository export header is invalid",
|
|
43731
|
+
row_invalid: "Repository export row is invalid or not canonical",
|
|
43732
|
+
row_out_of_order: "Repository export rows are not strictly increasing by durableId",
|
|
43733
|
+
since_below_epoch_floor: "Repository export delta base is below the epoch floor",
|
|
43734
|
+
trailer_invalid: "Repository export trailer is invalid",
|
|
43735
|
+
truncated: "Repository export stream ended before its trailer"
|
|
43736
|
+
};
|
|
43737
|
+
|
|
43738
|
+
class RepositoryExportSession {
|
|
43739
|
+
#streamDigest = createRepositoryExportDigest();
|
|
43740
|
+
#segmentDigest = createRepositoryExportDigest();
|
|
43741
|
+
#segmentRowCount = 0;
|
|
43742
|
+
#header;
|
|
43743
|
+
#lastDurableId;
|
|
43744
|
+
#token;
|
|
43745
|
+
#complete = false;
|
|
43746
|
+
#unverifiable = false;
|
|
43747
|
+
#contentSha256;
|
|
43748
|
+
get header() {
|
|
43749
|
+
return this.#header;
|
|
43750
|
+
}
|
|
43751
|
+
get lastDurableId() {
|
|
43752
|
+
return this.#lastDurableId;
|
|
43753
|
+
}
|
|
43754
|
+
get rowCount() {
|
|
43755
|
+
return this.#streamDigest.rowCount;
|
|
43756
|
+
}
|
|
43757
|
+
get segmentRowCount() {
|
|
43758
|
+
return this.#segmentRowCount;
|
|
43759
|
+
}
|
|
43760
|
+
get contentSha256() {
|
|
43761
|
+
return this.#contentSha256;
|
|
43762
|
+
}
|
|
43763
|
+
finalizeContentSha256() {
|
|
43764
|
+
if (this.#contentSha256 === undefined) {
|
|
43765
|
+
this.#contentSha256 = this.#streamDigest.finalize();
|
|
43766
|
+
this.#complete = true;
|
|
43767
|
+
}
|
|
43768
|
+
return this.#contentSha256;
|
|
43769
|
+
}
|
|
43770
|
+
beginSegment() {
|
|
43771
|
+
this.assertResumable();
|
|
43772
|
+
this.#segmentDigest = createRepositoryExportDigest();
|
|
43773
|
+
this.#segmentRowCount = 0;
|
|
43774
|
+
}
|
|
43775
|
+
markUnverifiable() {
|
|
43776
|
+
this.#unverifiable = true;
|
|
43777
|
+
}
|
|
43778
|
+
finalizeSegment() {
|
|
43779
|
+
return this.#segmentDigest.finalize();
|
|
43780
|
+
}
|
|
43781
|
+
get token() {
|
|
43782
|
+
return this.#token;
|
|
43783
|
+
}
|
|
43784
|
+
set token(value) {
|
|
43785
|
+
this.#token = value;
|
|
43786
|
+
}
|
|
43787
|
+
get complete() {
|
|
43788
|
+
return this.#complete;
|
|
43789
|
+
}
|
|
43790
|
+
markComplete() {
|
|
43791
|
+
this.finalizeContentSha256();
|
|
43792
|
+
}
|
|
43793
|
+
assertResumable() {
|
|
43794
|
+
if (this.#unverifiable) {
|
|
43795
|
+
throw new RepositoryExportError("digest_mismatch", "Repository export session failed verification and cannot be resumed; " + "start a new session");
|
|
43796
|
+
}
|
|
43797
|
+
if (this.#complete) {
|
|
43798
|
+
throw new RepositoryExportError("header_invalid", "Repository export session is already complete; start a new session");
|
|
43799
|
+
}
|
|
43800
|
+
}
|
|
43801
|
+
adoptHeader(header) {
|
|
43802
|
+
this.assertResumable();
|
|
43803
|
+
const previous = this.#header;
|
|
43804
|
+
if (previous !== undefined && (previous.repo !== header.repo || previous.mode !== header.mode || previous.sinceRepoSeq !== header.sinceRepoSeq || previous.atRepoSeq !== header.atRepoSeq)) {
|
|
43805
|
+
throw new RepositoryExportError("header_invalid", "Resumed repository export header does not match the opening header");
|
|
43806
|
+
}
|
|
43807
|
+
this.#header = header;
|
|
43808
|
+
}
|
|
43809
|
+
recordRow(durableId, lineBytes) {
|
|
43810
|
+
if (this.#header?.mode === "heads" && this.#lastDurableId !== undefined && compareUnsignedUtf8(this.#lastDurableId, durableId) >= 0) {
|
|
43811
|
+
throw new RepositoryExportError("row_out_of_order", `Repository export row '${durableId}' does not follow '${this.#lastDurableId}'`);
|
|
43812
|
+
}
|
|
43813
|
+
this.#streamDigest.update(lineBytes);
|
|
43814
|
+
this.#segmentDigest.update(lineBytes);
|
|
43815
|
+
this.#segmentRowCount += 1;
|
|
43816
|
+
this.#lastDurableId = durableId;
|
|
43817
|
+
}
|
|
43818
|
+
}
|
|
43819
|
+
function createRepositoryExportSession() {
|
|
43820
|
+
return new RepositoryExportSession;
|
|
43821
|
+
}
|
|
43822
|
+
|
|
43823
|
+
// ../../packages/sdk-ts/src/repository-export/stream.ts
|
|
43824
|
+
var LF = 10;
|
|
43825
|
+
var utf8 = new TextDecoder;
|
|
43826
|
+
function resumedHeader(session) {
|
|
43827
|
+
const header = session.header;
|
|
43828
|
+
if (!header) {
|
|
43829
|
+
throw new RepositoryExportError("header_invalid", "Repository export resumed without an opening header to inherit");
|
|
43830
|
+
}
|
|
43831
|
+
return header;
|
|
43832
|
+
}
|
|
43833
|
+
async function readHeader(lines, session, expected) {
|
|
43834
|
+
const first = await lines.next();
|
|
43835
|
+
if (first.done)
|
|
43836
|
+
throw new RepositoryExportError("truncated");
|
|
43837
|
+
let header;
|
|
43838
|
+
try {
|
|
43839
|
+
header = parseRepositoryExportHeaderLine(first.value);
|
|
43840
|
+
} catch (error51) {
|
|
43841
|
+
rethrowAs("header_invalid", error51);
|
|
43842
|
+
}
|
|
43843
|
+
if (header.formatVersion !== REPOSITORY_EXPORT_FORMAT_VERSION || expected !== undefined && (header.repo !== expected.repo || header.mode !== expected.mode || expected.sinceRepoSeq !== undefined && header.sinceRepoSeq !== expected.sinceRepoSeq || expected.atRepoSeq !== undefined && header.atRepoSeq !== expected.atRepoSeq)) {
|
|
43844
|
+
throw new RepositoryExportError("header_invalid", expected === undefined ? `Repository export header declares format version ${header.formatVersion}; expected ${REPOSITORY_EXPORT_FORMAT_VERSION}` : `Repository export header describes ${header.repo} (${header.mode}, ` + `${header.sinceRepoSeq}..${header.atRepoSeq}); expected ${expected.repo} ` + `(${expected.mode}${expected.sinceRepoSeq !== undefined ? `, since ${expected.sinceRepoSeq}` : ""}` + `${expected.atRepoSeq !== undefined ? `, at ${expected.atRepoSeq}` : ""})`);
|
|
43845
|
+
}
|
|
43846
|
+
session.adoptHeader(header);
|
|
43847
|
+
return header;
|
|
43848
|
+
}
|
|
43849
|
+
async function* readLines(source, tail) {
|
|
43850
|
+
let buffer = new Uint8Array(0);
|
|
43851
|
+
for await (const chunk of toAsyncIterable(source)) {
|
|
43852
|
+
const merged = new Uint8Array(buffer.length + chunk.length);
|
|
43853
|
+
merged.set(buffer);
|
|
43854
|
+
merged.set(chunk, buffer.length);
|
|
43855
|
+
buffer = merged;
|
|
43856
|
+
let index = buffer.indexOf(LF);
|
|
43857
|
+
while (index !== -1) {
|
|
43858
|
+
yield buffer.subarray(0, index + 1);
|
|
43859
|
+
buffer = buffer.subarray(index + 1);
|
|
43860
|
+
index = buffer.indexOf(LF);
|
|
43861
|
+
}
|
|
43862
|
+
}
|
|
43863
|
+
tail.unterminated = buffer.length > 0;
|
|
43864
|
+
}
|
|
43865
|
+
function toAsyncIterable(source) {
|
|
43866
|
+
if (Symbol.asyncIterator in source)
|
|
43867
|
+
return source;
|
|
43868
|
+
return {
|
|
43869
|
+
async* [Symbol.asyncIterator]() {
|
|
43870
|
+
const reader = source.getReader();
|
|
43407
43871
|
try {
|
|
43408
|
-
|
|
43409
|
-
|
|
43410
|
-
|
|
43411
|
-
|
|
43412
|
-
|
|
43413
|
-
|
|
43414
|
-
|
|
43415
|
-
|
|
43872
|
+
while (true) {
|
|
43873
|
+
const { done, value } = await reader.read();
|
|
43874
|
+
if (done)
|
|
43875
|
+
return;
|
|
43876
|
+
if (value)
|
|
43877
|
+
yield value;
|
|
43878
|
+
}
|
|
43879
|
+
} finally {
|
|
43880
|
+
reader.releaseLock();
|
|
43416
43881
|
}
|
|
43417
43882
|
}
|
|
43418
43883
|
};
|
|
43419
43884
|
}
|
|
43885
|
+
function lineKind(bytes) {
|
|
43886
|
+
try {
|
|
43887
|
+
const value = JSON.parse(utf8.decode(bytes));
|
|
43888
|
+
if (value !== null && typeof value === "object" && "kind" in value) {
|
|
43889
|
+
const kind = value.kind;
|
|
43890
|
+
if (typeof kind === "string")
|
|
43891
|
+
return kind;
|
|
43892
|
+
}
|
|
43893
|
+
} catch {}
|
|
43894
|
+
return "";
|
|
43895
|
+
}
|
|
43896
|
+
function rethrowAs(reason, error51) {
|
|
43897
|
+
if (error51 instanceof RepositoryExportError)
|
|
43898
|
+
throw error51;
|
|
43899
|
+
throw new RepositoryExportError(reason, error51 instanceof Error ? error51.message : undefined);
|
|
43900
|
+
}
|
|
43901
|
+
async function* readRepositoryExportStream(source, session, expected, options = {}) {
|
|
43902
|
+
yield* readSegment(source, session, expected, options);
|
|
43903
|
+
}
|
|
43904
|
+
async function restoreRepositoryExportSession(source, options = {}) {
|
|
43905
|
+
const session = createRepositoryExportSession();
|
|
43906
|
+
const replay = readSegment(source, session, undefined, options);
|
|
43907
|
+
let next = await replay.next();
|
|
43908
|
+
while (!next.done)
|
|
43909
|
+
next = await replay.next();
|
|
43910
|
+
return session;
|
|
43911
|
+
}
|
|
43912
|
+
async function* readSegment(source, session, expected, options) {
|
|
43913
|
+
const tail = { unterminated: false };
|
|
43914
|
+
const lines = readLines(source, tail);
|
|
43915
|
+
try {
|
|
43916
|
+
yield* readVerified(lines, tail, session, expected, options);
|
|
43917
|
+
} finally {
|
|
43918
|
+
await lines.return(undefined);
|
|
43919
|
+
}
|
|
43920
|
+
}
|
|
43921
|
+
async function* readVerified(lines, tail, session, expected, options) {
|
|
43922
|
+
session.assertResumable();
|
|
43923
|
+
const header = options.resumed === true ? resumedHeader(session) : await readHeader(lines, session, expected);
|
|
43924
|
+
const tombstonesAllowed = repositoryExportAllowsTombstones(header);
|
|
43925
|
+
session.beginSegment();
|
|
43926
|
+
while (true) {
|
|
43927
|
+
const next = await lines.next();
|
|
43928
|
+
if (next.done) {
|
|
43929
|
+
if (options.partial === true)
|
|
43930
|
+
return;
|
|
43931
|
+
throw new RepositoryExportError("truncated");
|
|
43932
|
+
}
|
|
43933
|
+
const bytes = next.value;
|
|
43934
|
+
if (lineKind(bytes) !== "trailer") {
|
|
43935
|
+
let row;
|
|
43936
|
+
try {
|
|
43937
|
+
row = parseRepositoryExportRowLine(bytes);
|
|
43938
|
+
} catch (error51) {
|
|
43939
|
+
rethrowAs("row_invalid", error51);
|
|
43940
|
+
}
|
|
43941
|
+
if (!row.active && !tombstonesAllowed) {
|
|
43942
|
+
throw new RepositoryExportError("row_invalid", "Repository export tombstone is not legal in a full export");
|
|
43943
|
+
}
|
|
43944
|
+
session.recordRow(row.durableId, bytes);
|
|
43945
|
+
yield row;
|
|
43946
|
+
continue;
|
|
43947
|
+
}
|
|
43948
|
+
let trailer;
|
|
43949
|
+
try {
|
|
43950
|
+
trailer = parseRepositoryExportTrailerLine(bytes);
|
|
43951
|
+
if (trailer.atRepoSeq !== header.atRepoSeq) {
|
|
43952
|
+
throw new RepositoryExportError("fence_mismatch");
|
|
43953
|
+
}
|
|
43954
|
+
if (trailer.recordCount !== session.segmentRowCount) {
|
|
43955
|
+
throw new RepositoryExportError("count_mismatch");
|
|
43956
|
+
}
|
|
43957
|
+
if (trailer.contentSha256 !== session.finalizeSegment()) {
|
|
43958
|
+
throw new RepositoryExportError("digest_mismatch");
|
|
43959
|
+
}
|
|
43960
|
+
} catch (error51) {
|
|
43961
|
+
session.markUnverifiable();
|
|
43962
|
+
if (error51 instanceof RepositoryExportError)
|
|
43963
|
+
throw error51;
|
|
43964
|
+
rethrowAs("trailer_invalid", error51);
|
|
43965
|
+
}
|
|
43966
|
+
if (!(await lines.next()).done || tail.unterminated) {
|
|
43967
|
+
throw new RepositoryExportError("trailer_invalid", "Repository export stream continues past its trailer");
|
|
43968
|
+
}
|
|
43969
|
+
session.markComplete();
|
|
43970
|
+
return;
|
|
43971
|
+
}
|
|
43972
|
+
}
|
|
43420
43973
|
|
|
43974
|
+
// ../../packages/sdk-ts/src/repository-export/client.ts
|
|
43975
|
+
var EPOCH_FLOOR_CODE = "since-below-epoch-floor";
|
|
43976
|
+
var DEFAULT_POLL_INTERVAL_MS = 1000;
|
|
43977
|
+
var MIN_POLL_INTERVAL_MS = 50;
|
|
43978
|
+
var MAX_DOWNLOAD_ATTEMPTS = 3;
|
|
43979
|
+
function buildPath(orgName, repoName, query) {
|
|
43980
|
+
const params = new URLSearchParams;
|
|
43981
|
+
for (const [key, value] of Object.entries(query)) {
|
|
43982
|
+
if (value !== undefined)
|
|
43983
|
+
params.set(key, String(value));
|
|
43984
|
+
}
|
|
43985
|
+
const search = params.toString();
|
|
43986
|
+
return `/api/repos/${encodeURIComponent(orgName)}/${encodeURIComponent(repoName)}/export${search ? `?${search}` : ""}`;
|
|
43987
|
+
}
|
|
43988
|
+
function abortReason(signal) {
|
|
43989
|
+
const reason = signal?.reason;
|
|
43990
|
+
return reason instanceof Error ? reason : new Error("Repository export was aborted");
|
|
43991
|
+
}
|
|
43992
|
+
function pollIntervalMs(requested) {
|
|
43993
|
+
if (requested === undefined || !Number.isFinite(requested)) {
|
|
43994
|
+
return DEFAULT_POLL_INTERVAL_MS;
|
|
43995
|
+
}
|
|
43996
|
+
return Math.max(requested, MIN_POLL_INTERVAL_MS);
|
|
43997
|
+
}
|
|
43998
|
+
async function delay(ms, signal) {
|
|
43999
|
+
if (signal?.aborted)
|
|
44000
|
+
throw abortReason(signal);
|
|
44001
|
+
await new Promise((resolve, reject) => {
|
|
44002
|
+
const onAbort = () => {
|
|
44003
|
+
clearTimeout(timer);
|
|
44004
|
+
reject(abortReason(signal));
|
|
44005
|
+
};
|
|
44006
|
+
const timer = setTimeout(() => {
|
|
44007
|
+
signal?.removeEventListener("abort", onAbort);
|
|
44008
|
+
resolve();
|
|
44009
|
+
}, ms);
|
|
44010
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
44011
|
+
});
|
|
44012
|
+
}
|
|
44013
|
+
async function exportHttpError(response, httpError) {
|
|
44014
|
+
let body;
|
|
44015
|
+
try {
|
|
44016
|
+
body = await response.clone().json();
|
|
44017
|
+
} catch {}
|
|
44018
|
+
if ((body?.code ?? body?.error?.code) === EPOCH_FLOOR_CODE) {
|
|
44019
|
+
return new RepositoryExportError("since_below_epoch_floor", body?.message);
|
|
44020
|
+
}
|
|
44021
|
+
if (body?.code !== undefined && body.error === undefined) {
|
|
44022
|
+
return await httpError(new Response(JSON.stringify({ error: body }), {
|
|
44023
|
+
status: response.status,
|
|
44024
|
+
headers: { "content-type": "application/json" }
|
|
44025
|
+
}));
|
|
44026
|
+
}
|
|
44027
|
+
return await httpError(response);
|
|
44028
|
+
}
|
|
44029
|
+
function isDownloadEnvelope(value) {
|
|
44030
|
+
const envelope = value;
|
|
44031
|
+
return typeof envelope?.url === "string" && envelope.url !== "" && typeof envelope.expiresAt === "number" && typeof envelope.atRepoSeq === "number" && typeof envelope.recordCount === "number" && typeof envelope.contentSha256 === "string";
|
|
44032
|
+
}
|
|
44033
|
+
async function readDownloadEnvelope(response) {
|
|
44034
|
+
let body;
|
|
44035
|
+
try {
|
|
44036
|
+
body = await response.json();
|
|
44037
|
+
} catch {
|
|
44038
|
+
throw new RepositoryExportError("header_invalid", "Repository export redemption did not return a JSON download envelope");
|
|
44039
|
+
}
|
|
44040
|
+
if (!isDownloadEnvelope(body)) {
|
|
44041
|
+
throw new RepositoryExportError("header_invalid", "Repository export download envelope must carry url, expiresAt, atRepoSeq, recordCount, and contentSha256");
|
|
44042
|
+
}
|
|
44043
|
+
return body;
|
|
44044
|
+
}
|
|
44045
|
+
function assertAttested(session, envelope) {
|
|
44046
|
+
const fence = session.header?.atRepoSeq;
|
|
44047
|
+
if (fence !== envelope.atRepoSeq) {
|
|
44048
|
+
throw new RepositoryExportError("fence_mismatch", `Repository export download is pinned to ${fence}; the redemption named ${envelope.atRepoSeq}`);
|
|
44049
|
+
}
|
|
44050
|
+
if (session.rowCount !== envelope.recordCount) {
|
|
44051
|
+
throw new RepositoryExportError("count_mismatch", `Repository export download carried ${session.rowCount} rows; the redemption named ${envelope.recordCount}`);
|
|
44052
|
+
}
|
|
44053
|
+
if (session.contentSha256 !== envelope.contentSha256) {
|
|
44054
|
+
throw new RepositoryExportError("digest_mismatch", "Repository export download digest does not match the digest the redemption named");
|
|
44055
|
+
}
|
|
44056
|
+
}
|
|
44057
|
+
function createRepositoryExportClient(transport, httpError, download = (url2, init) => globalThis.fetch(url2, init)) {
|
|
44058
|
+
const request = async (path, signal) => {
|
|
44059
|
+
const response = await transport(path, {
|
|
44060
|
+
method: "GET",
|
|
44061
|
+
headers: { accept: REPOSITORY_EXPORT_MEDIA_TYPE },
|
|
44062
|
+
...signal ? { signal } : {}
|
|
44063
|
+
});
|
|
44064
|
+
if (!response.ok && response.status !== 202) {
|
|
44065
|
+
throw await exportHttpError(response, httpError);
|
|
44066
|
+
}
|
|
44067
|
+
return response;
|
|
44068
|
+
};
|
|
44069
|
+
const prepare = async (orgName, repoName, options = {}) => {
|
|
44070
|
+
const response = await request(buildPath(orgName, repoName, {
|
|
44071
|
+
mode: options.mode ?? "heads",
|
|
44072
|
+
sinceRepoSeq: options.sinceRepoSeq,
|
|
44073
|
+
atRepoSeq: options.atRepoSeq,
|
|
44074
|
+
prefer: "async"
|
|
44075
|
+
}), options.signal);
|
|
44076
|
+
const accepted = await response.json();
|
|
44077
|
+
if (typeof accepted.exportToken !== "string" || typeof accepted.atRepoSeq !== "number") {
|
|
44078
|
+
throw new RepositoryExportError("header_invalid", "Repository export async request did not return an exportToken and atRepoSeq");
|
|
44079
|
+
}
|
|
44080
|
+
return { exportToken: accepted.exportToken, atRepoSeq: accepted.atRepoSeq };
|
|
44081
|
+
};
|
|
44082
|
+
const stream = (orgName, repoName, options = {}) => {
|
|
44083
|
+
const cursor = options.session?.lastDurableId ?? options.afterDurableId;
|
|
44084
|
+
if (cursor !== undefined && (options.token !== undefined || options.session?.token !== undefined || options.prefer === "async")) {
|
|
44085
|
+
throw new RepositoryExportError("header_invalid", `Repository export token download cannot continue from '${cursor}': redemption returns the whole prepared object. ` + "Start a new session and redeem the token again.");
|
|
44086
|
+
}
|
|
44087
|
+
if (options.afterDurableId !== undefined && options.session?.header === undefined) {
|
|
44088
|
+
throw new RepositoryExportError("header_invalid", "Repository export afterDurableId needs a session carrying the opening header; " + "reuse the session the broken stream wrote, or rebuild one with restoreRepositoryExportSession");
|
|
44089
|
+
}
|
|
44090
|
+
return streamExport(orgName, repoName, options);
|
|
44091
|
+
};
|
|
44092
|
+
return { prepare, stream };
|
|
44093
|
+
async function* streamExport(orgName, repoName, options) {
|
|
44094
|
+
const session = options.session ?? createRepositoryExportSession();
|
|
44095
|
+
const resumed = session.header;
|
|
44096
|
+
const signal = options.signal;
|
|
44097
|
+
const query = {
|
|
44098
|
+
mode: resumed?.mode ?? options.mode ?? "heads",
|
|
44099
|
+
sinceRepoSeq: resumed?.sinceRepoSeq ?? options.sinceRepoSeq,
|
|
44100
|
+
atRepoSeq: resumed?.atRepoSeq ?? options.atRepoSeq,
|
|
44101
|
+
afterDurableId: session.lastDurableId ?? options.afterDurableId
|
|
44102
|
+
};
|
|
44103
|
+
const expected = {
|
|
44104
|
+
repo: `${orgName}/${repoName}`,
|
|
44105
|
+
mode: query.mode,
|
|
44106
|
+
...options.sinceRepoSeq === undefined ? {} : { sinceRepoSeq: options.sinceRepoSeq },
|
|
44107
|
+
...options.atRepoSeq === undefined ? {} : { atRepoSeq: options.atRepoSeq }
|
|
44108
|
+
};
|
|
44109
|
+
if (options.token !== undefined && session.token !== undefined && options.token !== session.token) {
|
|
44110
|
+
throw new RepositoryExportError("header_invalid", `Repository export session was redeeming token ${session.token}; ` + `resuming it with token ${options.token} would splice two exports`);
|
|
44111
|
+
}
|
|
44112
|
+
const token = options.token ?? session.token;
|
|
44113
|
+
if (token !== undefined) {
|
|
44114
|
+
session.token = token;
|
|
44115
|
+
yield* downloadPrepared(token);
|
|
44116
|
+
return;
|
|
44117
|
+
}
|
|
44118
|
+
if (options.prefer === "async") {
|
|
44119
|
+
const prepared = await prepare(orgName, repoName, {
|
|
44120
|
+
mode: query.mode,
|
|
44121
|
+
...query.sinceRepoSeq === undefined ? {} : { sinceRepoSeq: query.sinceRepoSeq },
|
|
44122
|
+
...query.atRepoSeq === undefined ? {} : { atRepoSeq: query.atRepoSeq },
|
|
44123
|
+
...signal ? { signal } : {}
|
|
44124
|
+
});
|
|
44125
|
+
session.token = prepared.exportToken;
|
|
44126
|
+
yield* downloadPrepared(prepared.exportToken);
|
|
44127
|
+
return;
|
|
44128
|
+
}
|
|
44129
|
+
const response = await request(buildPath(orgName, repoName, query), signal);
|
|
44130
|
+
if (!response.body)
|
|
44131
|
+
throw new RepositoryExportError("truncated");
|
|
44132
|
+
yield* readRepositoryExportStream(response.body, session, expected, {
|
|
44133
|
+
resumed: query.afterDurableId !== undefined
|
|
44134
|
+
});
|
|
44135
|
+
async function* downloadPrepared(exportToken) {
|
|
44136
|
+
for (let attempt = 1;; attempt += 1) {
|
|
44137
|
+
const envelope = await redeem(exportToken);
|
|
44138
|
+
try {
|
|
44139
|
+
yield* readObject(envelope);
|
|
44140
|
+
return;
|
|
44141
|
+
} catch (error51) {
|
|
44142
|
+
const transportFault = !(error51 instanceof RepositoryExportError) || error51.reason === "truncated";
|
|
44143
|
+
if (!transportFault || session.rowCount > 0 || attempt >= MAX_DOWNLOAD_ATTEMPTS || signal?.aborted === true) {
|
|
44144
|
+
throw error51;
|
|
44145
|
+
}
|
|
44146
|
+
}
|
|
44147
|
+
}
|
|
44148
|
+
}
|
|
44149
|
+
async function* readObject(envelope) {
|
|
44150
|
+
const object2 = await download(envelope.url, signal ? { signal } : {});
|
|
44151
|
+
if (!object2.ok || !object2.body) {
|
|
44152
|
+
await object2.body?.cancel();
|
|
44153
|
+
throw new RepositoryExportError("truncated", `Repository export download returned HTTP ${object2.status}`);
|
|
44154
|
+
}
|
|
44155
|
+
yield* readRepositoryExportStream(object2.body, session, expected, {
|
|
44156
|
+
resumed: false
|
|
44157
|
+
});
|
|
44158
|
+
assertAttested(session, envelope);
|
|
44159
|
+
}
|
|
44160
|
+
async function redeem(exportToken) {
|
|
44161
|
+
const path = buildPath(orgName, repoName, { token: exportToken });
|
|
44162
|
+
while (true) {
|
|
44163
|
+
const pending = await request(path, signal);
|
|
44164
|
+
if (pending.status !== 202)
|
|
44165
|
+
return await readDownloadEnvelope(pending);
|
|
44166
|
+
await delay(pollIntervalMs(options.pollIntervalMs), signal);
|
|
44167
|
+
}
|
|
44168
|
+
}
|
|
44169
|
+
}
|
|
44170
|
+
}
|
|
43421
44171
|
// ../../packages/sdk-ts/src/shape-preflight.ts
|
|
43422
44172
|
function shapeDefinitionPreflightError(name, data, verb) {
|
|
43423
44173
|
const result = validateShapeDefinition(data, verb === "revise" ? { allowUnsafeFieldNamePaths: collectUnsafeShapeFieldNamePaths(data) } : undefined);
|
|
@@ -44496,7 +45246,7 @@ function createStreamingSubmissionHandle(input, deps) {
|
|
|
44496
45246
|
// ../../packages/sdk-ts/package.json
|
|
44497
45247
|
var package_default = {
|
|
44498
45248
|
name: "@warmhub/sdk-ts",
|
|
44499
|
-
version: "0.
|
|
45249
|
+
version: "0.108.0",
|
|
44500
45250
|
private: false,
|
|
44501
45251
|
type: "module",
|
|
44502
45252
|
description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -44534,6 +45284,7 @@ var package_default = {
|
|
|
44534
45284
|
sideEffects: false,
|
|
44535
45285
|
files: [
|
|
44536
45286
|
"dist",
|
|
45287
|
+
"CHANGELOG.md",
|
|
44537
45288
|
"README.md"
|
|
44538
45289
|
],
|
|
44539
45290
|
publishConfig: {
|
|
@@ -44600,6 +45351,7 @@ var package_default = {
|
|
|
44600
45351
|
"@vitest/coverage-v8": "catalog:",
|
|
44601
45352
|
"@warmhub/backend": "workspace:*",
|
|
44602
45353
|
"@warmhub/rules": "workspace:*",
|
|
45354
|
+
pako: "2.1.0",
|
|
44603
45355
|
"@types/react": "catalog:",
|
|
44604
45356
|
react: "19.2.6",
|
|
44605
45357
|
tsup: "8.5.1",
|
|
@@ -45059,6 +45811,7 @@ class WarmHubClient {
|
|
|
45059
45811
|
getToken;
|
|
45060
45812
|
compatibilityCheck;
|
|
45061
45813
|
overrideNoticePrinted = false;
|
|
45814
|
+
repositoryExport = createRepositoryExportClient((path, init) => this.fetchWithAuth(`${this.apiUrl.replace(/\/$/, "")}${path}`, init), (response) => this.httpResponseError(response), (url2, init) => (this.fetchImpl ?? globalThis.fetch)(url2, init));
|
|
45062
45815
|
noteCompatibilityOverride() {
|
|
45063
45816
|
if (this.overrideNoticePrinted)
|
|
45064
45817
|
return;
|
|
@@ -45577,6 +46330,8 @@ class WarmHubClient {
|
|
|
45577
46330
|
};
|
|
45578
46331
|
repo = {
|
|
45579
46332
|
checkpoint: createRepositoryCheckpointClient(() => this.trpc, toWarmHubError),
|
|
46333
|
+
export: (orgName, repoName, options) => this.repositoryExport.stream(orgName, repoName, options),
|
|
46334
|
+
exportPrepare: (orgName, repoName, options) => this.repositoryExport.prepare(orgName, repoName, options),
|
|
45580
46335
|
get: async (orgName, repoName) => {
|
|
45581
46336
|
try {
|
|
45582
46337
|
return await this.trpc.repo.get.query({
|
|
@@ -49363,7 +50118,7 @@ function corruptedAuthError(path, cause) {
|
|
|
49363
50118
|
function isAuthLockError(error51, authPath) {
|
|
49364
50119
|
return error51 instanceof Error && error51.code === "ELOCKED" && (error51.file === undefined || error51.file === authPath);
|
|
49365
50120
|
}
|
|
49366
|
-
function
|
|
50121
|
+
function delay2(ms) {
|
|
49367
50122
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
49368
50123
|
}
|
|
49369
50124
|
function getTokenInfo(profile) {
|
|
@@ -49485,7 +50240,7 @@ async function getValidToken(profile) {
|
|
|
49485
50240
|
duration_ms: Date.now() - refreshStarted,
|
|
49486
50241
|
error_name: err instanceof Error ? err.name : "Unknown"
|
|
49487
50242
|
});
|
|
49488
|
-
await
|
|
50243
|
+
await delay2(1000);
|
|
49489
50244
|
log.info("auth.refresh.retry", { profile: profileName, attempt: 2 });
|
|
49490
50245
|
let retryStarted = Date.now();
|
|
49491
50246
|
try {
|
|
@@ -49821,6 +50576,9 @@ function shouldGuardDomain(domainPath, canonicalVerb, args) {
|
|
|
49821
50576
|
if (domainPath[0] === "repo" && domainPath[1] === "checkpoint" && canonicalVerb === "verify") {
|
|
49822
50577
|
return false;
|
|
49823
50578
|
}
|
|
50579
|
+
if (domainPath[0] === "repo" && canonicalVerb === "verify") {
|
|
50580
|
+
return false;
|
|
50581
|
+
}
|
|
49824
50582
|
return true;
|
|
49825
50583
|
}
|
|
49826
50584
|
async function probeCapabilities(ctx) {
|
|
@@ -56640,7 +57398,7 @@ var NUL = String.fromCharCode(0);
|
|
|
56640
57398
|
function findInvalidControlByte(data, rootLabel = "data") {
|
|
56641
57399
|
const segs = [];
|
|
56642
57400
|
const pos = visit(data, segs);
|
|
56643
|
-
return pos === -1 ? null : { path:
|
|
57401
|
+
return pos === -1 ? null : { path: buildPath2(rootLabel, segs), position: pos };
|
|
56644
57402
|
}
|
|
56645
57403
|
function visit(value, segs) {
|
|
56646
57404
|
if (typeof value === "string")
|
|
@@ -56671,7 +57429,7 @@ function visit(value, segs) {
|
|
|
56671
57429
|
}
|
|
56672
57430
|
return -1;
|
|
56673
57431
|
}
|
|
56674
|
-
function
|
|
57432
|
+
function buildPath2(root, segs) {
|
|
56675
57433
|
let out = root;
|
|
56676
57434
|
for (const s of segs)
|
|
56677
57435
|
out += typeof s === "number" ? `[${s}]` : `.${s}`;
|
|
@@ -62192,7 +62950,7 @@ class StreamingByteReader {
|
|
|
62192
62950
|
#loadedBytes = 0;
|
|
62193
62951
|
position = 0;
|
|
62194
62952
|
constructor(source) {
|
|
62195
|
-
this.#iterator =
|
|
62953
|
+
this.#iterator = toAsyncIterable2(source)[Symbol.asyncIterator]();
|
|
62196
62954
|
}
|
|
62197
62955
|
async peekU32() {
|
|
62198
62956
|
const bytes = await this.readExact(4);
|
|
@@ -62279,7 +63037,7 @@ class StreamingByteReader {
|
|
|
62279
63037
|
}
|
|
62280
63038
|
}
|
|
62281
63039
|
}
|
|
62282
|
-
function
|
|
63040
|
+
function toAsyncIterable2(source) {
|
|
62283
63041
|
if (Symbol.asyncIterator in source)
|
|
62284
63042
|
return source;
|
|
62285
63043
|
return {
|
|
@@ -63018,12 +63776,6 @@ var checkpointFlags = {
|
|
|
63018
63776
|
"repo-seq": flag.number({
|
|
63019
63777
|
description: "Repository sequence for the checkpoint"
|
|
63020
63778
|
}),
|
|
63021
|
-
"at-least-repo-seq": flag.number({
|
|
63022
|
-
description: "Generate at or after this repository sequence"
|
|
63023
|
-
}),
|
|
63024
|
-
wait: flag.boolean({
|
|
63025
|
-
description: "Poll until the checkpoint completes or fails"
|
|
63026
|
-
}),
|
|
63027
63779
|
latest: flag.boolean({
|
|
63028
63780
|
description: "Use the latest completed checkpoint"
|
|
63029
63781
|
}),
|
|
@@ -63042,19 +63794,10 @@ var CHECKPOINT_ID_EXAMPLE = "0198f6d5-78aa-7000-8000-000000000001";
|
|
|
63042
63794
|
var CHECKPOINT_ACCESS_EXAMPLE = "wh repo checkpoint access acme/widgets --latest --archive";
|
|
63043
63795
|
var CHECKPOINT_DOWNLOAD_EXAMPLE = "wh repo checkpoint download acme/widgets --latest --archive --output checkpoint.zip";
|
|
63044
63796
|
var CHECKPOINT_READ_NOTE = "Requires unrestricted repo:read plus repo:checkpoint-read.";
|
|
63045
|
-
var CHECKPOINT_MANAGEMENT_NOTE = "Requires unrestricted repo:read, repo:checkpoint-read, and repo:checkpoint-generate (or repo:admin for compatibility).";
|
|
63046
|
-
var generateFlags = {
|
|
63047
|
-
"at-least-repo-seq": checkpointFlags["at-least-repo-seq"],
|
|
63048
|
-
wait: checkpointFlags.wait
|
|
63049
|
-
};
|
|
63050
63797
|
var statusFlags = {
|
|
63051
63798
|
checkpoint: checkpointFlags.checkpoint,
|
|
63052
63799
|
"repo-seq": checkpointFlags["repo-seq"]
|
|
63053
63800
|
};
|
|
63054
|
-
var retryFlags = {
|
|
63055
|
-
checkpoint: checkpointFlags.checkpoint,
|
|
63056
|
-
wait: checkpointFlags.wait
|
|
63057
|
-
};
|
|
63058
63801
|
var accessFlags = {
|
|
63059
63802
|
latest: checkpointFlags.latest,
|
|
63060
63803
|
checkpoint: checkpointFlags.checkpoint,
|
|
@@ -63070,17 +63813,17 @@ var downloadFlags = {
|
|
|
63070
63813
|
function repoFor(ctx, args) {
|
|
63071
63814
|
return parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
|
|
63072
63815
|
}
|
|
63073
|
-
function requireSequence(value
|
|
63816
|
+
function requireSequence(value) {
|
|
63074
63817
|
if (value === undefined)
|
|
63075
63818
|
return;
|
|
63076
63819
|
if (!Number.isSafeInteger(value) || value < 0) {
|
|
63077
|
-
throw new CliError(2 /* UserInput */, "USER_INPUT",
|
|
63820
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "--repo-seq must be a non-negative safe integer");
|
|
63078
63821
|
}
|
|
63079
63822
|
return value;
|
|
63080
63823
|
}
|
|
63081
63824
|
function selectCheckpoint(flags) {
|
|
63082
63825
|
const checkpointId = flags.checkpoint;
|
|
63083
|
-
const repoSeq = requireSequence(flags["repo-seq"]
|
|
63826
|
+
const repoSeq = requireSequence(flags["repo-seq"]);
|
|
63084
63827
|
if (checkpointId === undefined === (repoSeq === undefined)) {
|
|
63085
63828
|
usageError("Provide exactly one of --checkpoint or --repo-seq.", `wh repo checkpoint status acme/widgets --checkpoint ${CHECKPOINT_ID_EXAMPLE}`);
|
|
63086
63829
|
}
|
|
@@ -63144,43 +63887,6 @@ function printCheckpoint(ctx, result) {
|
|
|
63144
63887
|
ctx.out(`Failure: ${result.failureCode}`);
|
|
63145
63888
|
});
|
|
63146
63889
|
}
|
|
63147
|
-
async function waitForCompletion(ctx, org, repo2, initial) {
|
|
63148
|
-
let result = initial;
|
|
63149
|
-
let delayMs = 200;
|
|
63150
|
-
while (result.state === "queued" || result.state === "running") {
|
|
63151
|
-
ctx.status(`Checkpoint ${result.checkpointId} is ${result.state}; waiting…`);
|
|
63152
|
-
await delay2(delayMs, ctx.signal);
|
|
63153
|
-
result = await checkpointClient(ctx).status(org, repo2, {
|
|
63154
|
-
checkpointId: result.checkpointId
|
|
63155
|
-
});
|
|
63156
|
-
delayMs = Math.min(delayMs * 2, 5000);
|
|
63157
|
-
}
|
|
63158
|
-
return result;
|
|
63159
|
-
}
|
|
63160
|
-
function delay2(ms, signal) {
|
|
63161
|
-
return new Promise((resolve4, reject) => {
|
|
63162
|
-
if (signal?.aborted) {
|
|
63163
|
-
reject(new Error("CLI invocation cancelled"));
|
|
63164
|
-
return;
|
|
63165
|
-
}
|
|
63166
|
-
const onAbort = () => {
|
|
63167
|
-
clearTimeout(timer);
|
|
63168
|
-
reject(new Error("CLI invocation cancelled"));
|
|
63169
|
-
};
|
|
63170
|
-
const timer = setTimeout(() => {
|
|
63171
|
-
signal?.removeEventListener("abort", onAbort);
|
|
63172
|
-
resolve4();
|
|
63173
|
-
}, ms);
|
|
63174
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
63175
|
-
});
|
|
63176
|
-
}
|
|
63177
|
-
var handleGenerate = async (ctx, { args, flags }) => {
|
|
63178
|
-
const { org, repo: repo2 } = repoFor(ctx, args);
|
|
63179
|
-
const result = await checkpointClient(ctx).generate(org, repo2, {
|
|
63180
|
-
atLeastRepoSeq: requireSequence(flags["at-least-repo-seq"], "--at-least-repo-seq")
|
|
63181
|
-
});
|
|
63182
|
-
printCheckpoint(ctx, flags.wait ? await waitForCompletion(ctx, org, repo2, result) : result);
|
|
63183
|
-
};
|
|
63184
63890
|
var handleStatus2 = async (ctx, { args, flags }) => {
|
|
63185
63891
|
const { org, repo: repo2 } = repoFor(ctx, args);
|
|
63186
63892
|
printCheckpoint(ctx, await checkpointClient(ctx).status(org, repo2, selectCheckpoint(flags)));
|
|
@@ -63189,14 +63895,6 @@ var handleLatest = async (ctx, { args }) => {
|
|
|
63189
63895
|
const { org, repo: repo2 } = repoFor(ctx, args);
|
|
63190
63896
|
printCheckpoint(ctx, await checkpointClient(ctx).latest(org, repo2));
|
|
63191
63897
|
};
|
|
63192
|
-
var handleRetry = async (ctx, { args, flags }) => {
|
|
63193
|
-
if (!flags.checkpoint) {
|
|
63194
|
-
usageError("--checkpoint is required for retry.", `wh repo checkpoint retry acme/widgets --checkpoint ${CHECKPOINT_ID_EXAMPLE}`);
|
|
63195
|
-
}
|
|
63196
|
-
const { org, repo: repo2 } = repoFor(ctx, args);
|
|
63197
|
-
const result = await checkpointClient(ctx).retry(org, repo2, flags.checkpoint);
|
|
63198
|
-
printCheckpoint(ctx, flags.wait ? await waitForCompletion(ctx, org, repo2, result) : result);
|
|
63199
|
-
};
|
|
63200
63898
|
var handleDownload = async (ctx, { args, flags }) => {
|
|
63201
63899
|
if (!flags.output) {
|
|
63202
63900
|
usageError("--output PATH|- is required for download.", CHECKPOINT_DOWNLOAD_EXAMPLE);
|
|
@@ -63253,16 +63951,8 @@ var handleVerify = async (ctx, { args }) => {
|
|
|
63253
63951
|
};
|
|
63254
63952
|
var CHECKPOINT_SUBDOMAIN = defineDomain({
|
|
63255
63953
|
name: "checkpoint",
|
|
63256
|
-
summary: "
|
|
63954
|
+
summary: "Access, download, and verify stored repository checkpoints",
|
|
63257
63955
|
verbs: {
|
|
63258
|
-
generate: {
|
|
63259
|
-
summary: "Generate a repository checkpoint",
|
|
63260
|
-
args: "[org/repo]",
|
|
63261
|
-
flags: generateFlags,
|
|
63262
|
-
notes: [CHECKPOINT_MANAGEMENT_NOTE],
|
|
63263
|
-
examples: ["wh repo checkpoint generate acme/widgets --wait"],
|
|
63264
|
-
handler: handleGenerate
|
|
63265
|
-
},
|
|
63266
63956
|
status: {
|
|
63267
63957
|
summary: "Show one checkpoint status",
|
|
63268
63958
|
args: "[org/repo]",
|
|
@@ -63283,16 +63973,6 @@ var CHECKPOINT_SUBDOMAIN = defineDomain({
|
|
|
63283
63973
|
examples: ["wh repo checkpoint latest acme/widgets"],
|
|
63284
63974
|
handler: handleLatest
|
|
63285
63975
|
},
|
|
63286
|
-
retry: {
|
|
63287
|
-
summary: "Retry a failed checkpoint",
|
|
63288
|
-
args: "[org/repo]",
|
|
63289
|
-
flags: retryFlags,
|
|
63290
|
-
notes: [CHECKPOINT_MANAGEMENT_NOTE, "Requires --checkpoint."],
|
|
63291
|
-
examples: [
|
|
63292
|
-
`wh repo checkpoint retry acme/widgets --checkpoint ${CHECKPOINT_ID_EXAMPLE} --wait`
|
|
63293
|
-
],
|
|
63294
|
-
handler: handleRetry
|
|
63295
|
-
},
|
|
63296
63976
|
access: {
|
|
63297
63977
|
summary: "Show a short-lived checkpoint artifact URL",
|
|
63298
63978
|
args: "[org/repo]",
|
|
@@ -63684,6 +64364,346 @@ var handleCreate6 = async (ctx, { flags, args }) => {
|
|
|
63684
64364
|
});
|
|
63685
64365
|
};
|
|
63686
64366
|
|
|
64367
|
+
// ../../packages/warmhub-cli/src/domains/repo/export-file.ts
|
|
64368
|
+
import { createReadStream as createReadStream7 } from "node:fs";
|
|
64369
|
+
import { open as open5, truncate } from "node:fs/promises";
|
|
64370
|
+
var LF2 = 10;
|
|
64371
|
+
async function scanRepositoryExportFile(path2, options = {}) {
|
|
64372
|
+
const counter = { completeBytes: 0 };
|
|
64373
|
+
const session = await restoreRepositoryExportSession(countedChunks(path2, counter), options);
|
|
64374
|
+
return { session, completeBytes: counter.completeBytes };
|
|
64375
|
+
}
|
|
64376
|
+
async function openExportSink(ctx, output, resumeFrom) {
|
|
64377
|
+
if (output === "-") {
|
|
64378
|
+
const writeBinary = ctx.writeBinary;
|
|
64379
|
+
if (!writeBinary) {
|
|
64380
|
+
throw new CliError(1 /* Runtime */, "UNKNOWN", "Binary stdout is unavailable for this command context.");
|
|
64381
|
+
}
|
|
64382
|
+
return {
|
|
64383
|
+
write: async (bytes) => {
|
|
64384
|
+
if (await writeBinary(bytes))
|
|
64385
|
+
return;
|
|
64386
|
+
throw new CliError(1 /* Runtime */, "UNKNOWN", "Export output closed before the stream finished.");
|
|
64387
|
+
},
|
|
64388
|
+
close: async () => {
|
|
64389
|
+
return;
|
|
64390
|
+
}
|
|
64391
|
+
};
|
|
64392
|
+
}
|
|
64393
|
+
if (resumeFrom !== undefined)
|
|
64394
|
+
await truncate(output, resumeFrom);
|
|
64395
|
+
const handle = await openOutput(output, resumeFrom === undefined);
|
|
64396
|
+
return {
|
|
64397
|
+
write: (bytes) => writeAll(handle, bytes),
|
|
64398
|
+
close: async () => {
|
|
64399
|
+
await handle.sync();
|
|
64400
|
+
await handle.close();
|
|
64401
|
+
}
|
|
64402
|
+
};
|
|
64403
|
+
}
|
|
64404
|
+
async function openOutput(output, fresh) {
|
|
64405
|
+
try {
|
|
64406
|
+
return await open5(output, fresh ? "wx" : "a", 384);
|
|
64407
|
+
} catch (error51) {
|
|
64408
|
+
if (error51.code === "EEXIST") {
|
|
64409
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `Refusing to overwrite existing output path '${output}'.`, error51, "Delete it, choose another --output, or pass --resume to continue an interrupted export.");
|
|
64410
|
+
}
|
|
64411
|
+
throw error51;
|
|
64412
|
+
}
|
|
64413
|
+
}
|
|
64414
|
+
async function* countedChunks(path2, counter) {
|
|
64415
|
+
let read = 0;
|
|
64416
|
+
for await (const chunk of createReadStream7(path2)) {
|
|
64417
|
+
const bytes = chunk;
|
|
64418
|
+
const lastLf = bytes.lastIndexOf(LF2);
|
|
64419
|
+
if (lastLf !== -1)
|
|
64420
|
+
counter.completeBytes = read + lastLf + 1;
|
|
64421
|
+
read += bytes.byteLength;
|
|
64422
|
+
yield bytes;
|
|
64423
|
+
}
|
|
64424
|
+
}
|
|
64425
|
+
|
|
64426
|
+
// ../../packages/warmhub-cli/src/domains/repo/export.ts
|
|
64427
|
+
var exportFlags = {
|
|
64428
|
+
output: flag.string({
|
|
64429
|
+
description: "Write the export to PATH, or - for stdout",
|
|
64430
|
+
constraints: { nonEmpty: true }
|
|
64431
|
+
}),
|
|
64432
|
+
mode: flag.string({
|
|
64433
|
+
description: "Export mode: heads (default)",
|
|
64434
|
+
constraints: { choices: ["heads", "ops"] },
|
|
64435
|
+
conflictsWith: ["resume"]
|
|
64436
|
+
}),
|
|
64437
|
+
"since-repo-seq": flag.number({
|
|
64438
|
+
description: "Delta base: export only what changed after this sequence",
|
|
64439
|
+
conflictsWith: ["resume", "token"]
|
|
64440
|
+
}),
|
|
64441
|
+
"at-repo-seq": flag.number({
|
|
64442
|
+
description: "Pin the export to this repository sequence",
|
|
64443
|
+
conflictsWith: ["resume", "token"]
|
|
64444
|
+
}),
|
|
64445
|
+
async: flag.boolean({
|
|
64446
|
+
description: "Prepare the export server-side and print the token that redeems it",
|
|
64447
|
+
conflictsWith: ["resume", "token"]
|
|
64448
|
+
}),
|
|
64449
|
+
wait: flag.boolean({
|
|
64450
|
+
description: "Download the prepared export instead of printing its token",
|
|
64451
|
+
requires: [{ flag: "async", mustBeTrue: true }],
|
|
64452
|
+
conflictsWith: ["resume", "token"]
|
|
64453
|
+
}),
|
|
64454
|
+
token: flag.string({
|
|
64455
|
+
description: "Download the prepared export this token names",
|
|
64456
|
+
constraints: { nonEmpty: true },
|
|
64457
|
+
conflictsWith: ["async", "wait", "resume", "since-repo-seq", "at-repo-seq"]
|
|
64458
|
+
}),
|
|
64459
|
+
resume: flag.boolean({
|
|
64460
|
+
description: "Continue an interrupted export already at --output PATH",
|
|
64461
|
+
conflictsWith: [
|
|
64462
|
+
"async",
|
|
64463
|
+
"wait",
|
|
64464
|
+
"token",
|
|
64465
|
+
"mode",
|
|
64466
|
+
"since-repo-seq",
|
|
64467
|
+
"at-repo-seq"
|
|
64468
|
+
]
|
|
64469
|
+
})
|
|
64470
|
+
};
|
|
64471
|
+
var POLL_INTERVAL_MS = 2000;
|
|
64472
|
+
var EXPORT_EXAMPLE = "wh repo export acme/widgets --output widgets.ndjson --format json";
|
|
64473
|
+
var ASYNC_EXAMPLE = "wh repo export acme/widgets --async";
|
|
64474
|
+
function requireSequence2(value, flagName) {
|
|
64475
|
+
if (value === undefined)
|
|
64476
|
+
return;
|
|
64477
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
64478
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `${flagName} must be a non-negative safe integer`);
|
|
64479
|
+
}
|
|
64480
|
+
return value;
|
|
64481
|
+
}
|
|
64482
|
+
function printReceipt(ctx, header, session, contentSha256) {
|
|
64483
|
+
const result = {
|
|
64484
|
+
repo: header.repo,
|
|
64485
|
+
mode: header.mode,
|
|
64486
|
+
sinceRepoSeq: header.sinceRepoSeq,
|
|
64487
|
+
atRepoSeq: header.atRepoSeq,
|
|
64488
|
+
recordCount: session.rowCount,
|
|
64489
|
+
contentSha256
|
|
64490
|
+
};
|
|
64491
|
+
writeOutput(ctx, result, () => {
|
|
64492
|
+
ctx.out(`Repository: ${result.repo}`);
|
|
64493
|
+
ctx.out(`Mode: ${result.mode}`);
|
|
64494
|
+
if (result.sinceRepoSeq > 0)
|
|
64495
|
+
ctx.out(`Delta base: ${result.sinceRepoSeq}`);
|
|
64496
|
+
ctx.out(`Repository sequence: ${result.atRepoSeq}`);
|
|
64497
|
+
ctx.out(`Records: ${result.recordCount}`);
|
|
64498
|
+
ctx.out(`SHA-256: ${result.contentSha256}`);
|
|
64499
|
+
});
|
|
64500
|
+
}
|
|
64501
|
+
function exportFailure(error51, asked) {
|
|
64502
|
+
const asyncRefusal = asked.async && asked.mode !== "ops";
|
|
64503
|
+
if (error51 instanceof RepositoryExportError) {
|
|
64504
|
+
if (error51.reason === "since_below_epoch_floor") {
|
|
64505
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "The delta base has expired; run a full export.", error51, "Re-run without --since-repo-seq.");
|
|
64506
|
+
}
|
|
64507
|
+
throw new CliError(4 /* Backend */, "BACKEND", error51.message, error51);
|
|
64508
|
+
}
|
|
64509
|
+
if (error51 instanceof WarmHubError) {
|
|
64510
|
+
if (error51.status === 429) {
|
|
64511
|
+
throw new CliError(4 /* Backend */, "RATE_LIMITED", "Another repository export is already streaming for this organization.", error51, "Retry with --async --wait to queue this export instead.");
|
|
64512
|
+
}
|
|
64513
|
+
if (error51.status === 501) {
|
|
64514
|
+
throw new CliError(4 /* Backend */, "BACKEND", asyncRefusal ? "Asynchronous repository export is not enabled on this deployment." : 'Export mode "ops" is not enabled on this deployment.', error51, asyncRefusal ? "Re-run without --async." : "Use --mode heads.");
|
|
64515
|
+
}
|
|
64516
|
+
if (error51.status === 500 && (asked.async || asked.token)) {
|
|
64517
|
+
throw new CliError(4 /* Backend */, "BACKEND", "The repository export job failed.", error51, asked.token ? "The token is spent; prepare a new export with --async." : "Re-run the command; it starts a new export job.");
|
|
64518
|
+
}
|
|
64519
|
+
}
|
|
64520
|
+
throw error51;
|
|
64521
|
+
}
|
|
64522
|
+
var handleExport = async (ctx, { args, flags }) => {
|
|
64523
|
+
const output = flags.output;
|
|
64524
|
+
if (flags.async && !flags.wait) {
|
|
64525
|
+
if (output) {
|
|
64526
|
+
usageError("--output is unused when --async only prints the token. Add --wait to download now, or redeem the token later with --token.", ASYNC_EXAMPLE);
|
|
64527
|
+
}
|
|
64528
|
+
return await prepareExport(ctx, args, flags);
|
|
64529
|
+
}
|
|
64530
|
+
if (!output) {
|
|
64531
|
+
usageError("--output PATH|- is required for export.", EXPORT_EXAMPLE);
|
|
64532
|
+
}
|
|
64533
|
+
if (output === "-" && ctx.format !== "pretty") {
|
|
64534
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", "Stdout output requires --format pretty; JSON and JSONL cannot carry export bytes.");
|
|
64535
|
+
}
|
|
64536
|
+
if (flags.resume && output === "-") {
|
|
64537
|
+
usageError("--resume needs a file; stdout cannot be continued.", EXPORT_EXAMPLE);
|
|
64538
|
+
}
|
|
64539
|
+
const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
|
|
64540
|
+
let session = createRepositoryExportSession();
|
|
64541
|
+
let resumeFrom;
|
|
64542
|
+
if (flags.resume) {
|
|
64543
|
+
const scan = await resumeScan(output);
|
|
64544
|
+
session = scan.session;
|
|
64545
|
+
const opened = requireHeader(session);
|
|
64546
|
+
if (opened.repo !== `${org}/${repo2}`) {
|
|
64547
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `'${output}' is an export of ${opened.repo}, not ${org}/${repo2}.`, undefined, `Resume it as ${opened.repo}, or choose another --output.`);
|
|
64548
|
+
}
|
|
64549
|
+
if (session.complete) {
|
|
64550
|
+
printReceipt(ctx, opened, session, session.finalizeContentSha256());
|
|
64551
|
+
return;
|
|
64552
|
+
}
|
|
64553
|
+
resumeFrom = scan.completeBytes;
|
|
64554
|
+
}
|
|
64555
|
+
const rows = ctx.client.repo.export(org, repo2, {
|
|
64556
|
+
mode: flags.mode,
|
|
64557
|
+
sinceRepoSeq: requireSequence2(flags["since-repo-seq"], "--since-repo-seq"),
|
|
64558
|
+
atRepoSeq: requireSequence2(flags["at-repo-seq"], "--at-repo-seq"),
|
|
64559
|
+
...flags.async || flags.token ? {
|
|
64560
|
+
...flags.token ? { token: flags.token } : { prefer: "async" },
|
|
64561
|
+
pollIntervalMs: POLL_INTERVAL_MS
|
|
64562
|
+
} : {},
|
|
64563
|
+
session,
|
|
64564
|
+
...ctx.signal ? { signal: ctx.signal } : {}
|
|
64565
|
+
});
|
|
64566
|
+
if (flags.async || flags.token) {
|
|
64567
|
+
ctx.status("Waiting for the export to finish on the server…");
|
|
64568
|
+
}
|
|
64569
|
+
let sink;
|
|
64570
|
+
let headerWritten = resumeFrom !== undefined;
|
|
64571
|
+
const write = async (bytes) => {
|
|
64572
|
+
sink ??= await openExportSink(ctx, output, resumeFrom);
|
|
64573
|
+
await sink.write(bytes);
|
|
64574
|
+
};
|
|
64575
|
+
const writeHeader = async () => {
|
|
64576
|
+
if (headerWritten)
|
|
64577
|
+
return;
|
|
64578
|
+
headerWritten = true;
|
|
64579
|
+
await write(encodeRepositoryExportHeader(requireHeader(session)));
|
|
64580
|
+
};
|
|
64581
|
+
try {
|
|
64582
|
+
for await (const row of rows) {
|
|
64583
|
+
await writeHeader();
|
|
64584
|
+
await write(encodeRepositoryExportRow(row));
|
|
64585
|
+
}
|
|
64586
|
+
await writeHeader();
|
|
64587
|
+
const header = requireHeader(session);
|
|
64588
|
+
const contentSha256 = session.finalizeContentSha256();
|
|
64589
|
+
await write(encodeRepositoryExportTrailer({
|
|
64590
|
+
kind: "trailer",
|
|
64591
|
+
recordCount: session.rowCount,
|
|
64592
|
+
contentSha256,
|
|
64593
|
+
atRepoSeq: header.atRepoSeq
|
|
64594
|
+
}));
|
|
64595
|
+
await sink?.close();
|
|
64596
|
+
if (output === "-") {
|
|
64597
|
+
ctx.status(`Exported ${session.rowCount} records at ${header.atRepoSeq}`);
|
|
64598
|
+
return;
|
|
64599
|
+
}
|
|
64600
|
+
ctx.status(`Wrote repository export to ${output}`);
|
|
64601
|
+
printReceipt(ctx, header, session, contentSha256);
|
|
64602
|
+
} catch (error51) {
|
|
64603
|
+
try {
|
|
64604
|
+
await sink?.close();
|
|
64605
|
+
} catch (closeError) {
|
|
64606
|
+
ctx.status(`Could not flush the partial export: ${closeError instanceof Error ? closeError.message : "unknown error"}`);
|
|
64607
|
+
}
|
|
64608
|
+
exportFailure(error51, {
|
|
64609
|
+
async: flags.async === true,
|
|
64610
|
+
token: flags.token !== undefined,
|
|
64611
|
+
mode: flags.mode ?? "heads"
|
|
64612
|
+
});
|
|
64613
|
+
}
|
|
64614
|
+
};
|
|
64615
|
+
async function prepareExport(ctx, args, flags) {
|
|
64616
|
+
const { org, repo: repo2 } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
|
|
64617
|
+
let prepared;
|
|
64618
|
+
try {
|
|
64619
|
+
prepared = await ctx.client.repo.exportPrepare(org, repo2, {
|
|
64620
|
+
mode: flags.mode,
|
|
64621
|
+
sinceRepoSeq: requireSequence2(flags["since-repo-seq"], "--since-repo-seq"),
|
|
64622
|
+
atRepoSeq: requireSequence2(flags["at-repo-seq"], "--at-repo-seq"),
|
|
64623
|
+
...ctx.signal ? { signal: ctx.signal } : {}
|
|
64624
|
+
});
|
|
64625
|
+
} catch (error51) {
|
|
64626
|
+
exportFailure(error51, {
|
|
64627
|
+
async: true,
|
|
64628
|
+
token: false,
|
|
64629
|
+
mode: flags.mode ?? "heads"
|
|
64630
|
+
});
|
|
64631
|
+
}
|
|
64632
|
+
writeOutput(ctx, prepared, () => {
|
|
64633
|
+
ctx.out(`Export token: ${prepared.exportToken}`);
|
|
64634
|
+
ctx.out(`Repository sequence: ${prepared.atRepoSeq}`);
|
|
64635
|
+
});
|
|
64636
|
+
const modeFlag = (flags.mode ?? "heads") === "heads" ? "" : ` --mode ${flags.mode}`;
|
|
64637
|
+
ctx.status(`Download it with: wh repo export ${org}/${repo2} --token ${prepared.exportToken}${modeFlag} --output PATH`);
|
|
64638
|
+
}
|
|
64639
|
+
function requireHeader(session) {
|
|
64640
|
+
const header = session.header;
|
|
64641
|
+
if (!header) {
|
|
64642
|
+
throw new CliError(4 /* Backend */, "BACKEND", "Repository export ended without a header.");
|
|
64643
|
+
}
|
|
64644
|
+
return header;
|
|
64645
|
+
}
|
|
64646
|
+
async function resumeScan(output) {
|
|
64647
|
+
try {
|
|
64648
|
+
return await scanRepositoryExportFile(output, { partial: true });
|
|
64649
|
+
} catch (error51) {
|
|
64650
|
+
if (error51.code === "ENOENT") {
|
|
64651
|
+
throw new CliError(2 /* UserInput */, "USER_INPUT", `No export to resume at '${output}'.`, error51, "Re-run without --resume to start a new export.");
|
|
64652
|
+
}
|
|
64653
|
+
throw error51;
|
|
64654
|
+
}
|
|
64655
|
+
}
|
|
64656
|
+
var handleVerify2 = async (ctx, { args }) => {
|
|
64657
|
+
const file2 = args[0];
|
|
64658
|
+
if (!file2) {
|
|
64659
|
+
usageError("Usage: wh repo verify <file>", "wh repo verify widgets.ndjson");
|
|
64660
|
+
}
|
|
64661
|
+
try {
|
|
64662
|
+
const { session } = await scanRepositoryExportFile(file2);
|
|
64663
|
+
printReceipt(ctx, requireHeader(session), session, session.finalizeContentSha256());
|
|
64664
|
+
} catch (error51) {
|
|
64665
|
+
if (error51 instanceof RepositoryExportError) {
|
|
64666
|
+
throw new CliError(4 /* Backend */, "BACKEND", error51.message, error51);
|
|
64667
|
+
}
|
|
64668
|
+
if (error51.code === "ENOENT") {
|
|
64669
|
+
throw new CliError(4 /* Backend */, "BACKEND", "Repository export file could not be read", error51);
|
|
64670
|
+
}
|
|
64671
|
+
throw error51;
|
|
64672
|
+
}
|
|
64673
|
+
};
|
|
64674
|
+
var EXPORT_VERB = {
|
|
64675
|
+
summary: "Export a repository as verified NDJSON (format v3)",
|
|
64676
|
+
args: "[org/repo]",
|
|
64677
|
+
flags: exportFlags,
|
|
64678
|
+
notes: [
|
|
64679
|
+
"Requires unrestricted repo:read plus repo:checkpoint-read.",
|
|
64680
|
+
"The stream is verified as it arrives: header, canonical rows, row order, record count, and content digest.",
|
|
64681
|
+
"One synchronous export streams per organization at a time; --async queues instead.",
|
|
64682
|
+
"A bare --async prints the export token and exits; --wait downloads it now, --token downloads it later.",
|
|
64683
|
+
"Redeeming a token answers with a short-lived download link for the prepared export, which the CLI then fetches and checks against the record count and digest the server named.",
|
|
64684
|
+
"An interrupted token download restarts from the beginning; re-run the same command, since redeeming a token again is free.",
|
|
64685
|
+
"An interrupted export resumes from the same file with --resume."
|
|
64686
|
+
],
|
|
64687
|
+
examples: [
|
|
64688
|
+
EXPORT_EXAMPLE,
|
|
64689
|
+
"wh repo export acme/widgets --output delta.ndjson --since-repo-seq 120",
|
|
64690
|
+
ASYNC_EXAMPLE,
|
|
64691
|
+
"wh repo export acme/widgets --output widgets.ndjson --token TOKEN",
|
|
64692
|
+
"wh repo export acme/widgets --output widgets.ndjson --async --wait",
|
|
64693
|
+
"wh repo export acme/widgets --output widgets.ndjson --resume"
|
|
64694
|
+
],
|
|
64695
|
+
handler: handleExport
|
|
64696
|
+
};
|
|
64697
|
+
var VERIFY_VERB = {
|
|
64698
|
+
summary: "Verify a saved repository export locally",
|
|
64699
|
+
args: "<file>",
|
|
64700
|
+
notes: [
|
|
64701
|
+
"Reads only the named local file: no profile, no authentication, no server."
|
|
64702
|
+
],
|
|
64703
|
+
examples: ["wh repo verify widgets.ndjson"],
|
|
64704
|
+
handler: handleVerify2
|
|
64705
|
+
};
|
|
64706
|
+
|
|
63687
64707
|
// ../../packages/warmhub-cli/src/domains/repo/lifecycle.ts
|
|
63688
64708
|
var confirmFlags2 = {
|
|
63689
64709
|
yes: flag.boolean({ short: "y", description: "Skip confirmation prompt" })
|
|
@@ -64189,6 +65209,8 @@ var REPO_DOMAIN = defineDomain({
|
|
|
64189
65209
|
],
|
|
64190
65210
|
handler: handleUpdate3
|
|
64191
65211
|
},
|
|
65212
|
+
export: EXPORT_VERB,
|
|
65213
|
+
verify: VERIFY_VERB,
|
|
64192
65214
|
archive: {
|
|
64193
65215
|
summary: "Archive a repo (blocks new commits)",
|
|
64194
65216
|
args: "<org/repo>",
|
|
@@ -68187,6 +69209,9 @@ function isLocalOnlyInvocation(invocation) {
|
|
|
68187
69209
|
if (invocation.commandPath[0] === "repo" && invocation.commandPath[1] === "checkpoint" && invocation.commandPath[2] === "verify") {
|
|
68188
69210
|
return true;
|
|
68189
69211
|
}
|
|
69212
|
+
if (invocation.commandPath[0] === "repo" && invocation.commandPath[1] === "verify") {
|
|
69213
|
+
return true;
|
|
69214
|
+
}
|
|
68190
69215
|
return invocation.commandPath[0] === "help" && invocation.positionals[0] === "update";
|
|
68191
69216
|
}
|
|
68192
69217
|
function resolveLogLevel(flagLevel, env) {
|
|
@@ -68210,7 +69235,7 @@ function resolveLogLevel(flagLevel, env) {
|
|
|
68210
69235
|
// package.json
|
|
68211
69236
|
var package_default3 = {
|
|
68212
69237
|
name: "@warmhub/cli",
|
|
68213
|
-
version: "0.
|
|
69238
|
+
version: "0.110.0",
|
|
68214
69239
|
private: false,
|
|
68215
69240
|
type: "module",
|
|
68216
69241
|
description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
|
|
@@ -68835,5 +69860,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
|
|
|
68835
69860
|
version: package_default3.version
|
|
68836
69861
|
}) : interceptedExitCode;
|
|
68837
69862
|
|
|
68838
|
-
//# debugId=
|
|
68839
|
-
//# warmhub-cli-build-info {"cliVersion":"0.
|
|
69863
|
+
//# debugId=D94FA6CB8612CBFC64756E2164756E21
|
|
69864
|
+
//# warmhub-cli-build-info {"cliVersion":"0.110.0","sdkVersion":"0.108.0"}
|