@valbuild/server 0.68.2 → 0.69.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/valbuild-server.cjs.dev.js +378 -112
- package/dist/valbuild-server.cjs.prod.js +378 -112
- package/dist/valbuild-server.esm.js +378 -112
- package/package.json +4 -4
@@ -1536,10 +1536,13 @@ class ValOps {
|
|
1536
1536
|
}
|
1537
1537
|
|
1538
1538
|
// #region analyzePatches
|
1539
|
-
analyzePatches(sortedPatches) {
|
1539
|
+
analyzePatches(sortedPatches, commits, currentCommitSha) {
|
1540
1540
|
const patchesByModule = {};
|
1541
1541
|
const fileLastUpdatedByPatchId = {};
|
1542
1542
|
for (const patch of sortedPatches) {
|
1543
|
+
if (patch.appliedAt) {
|
1544
|
+
continue;
|
1545
|
+
}
|
1543
1546
|
for (const op of patch.patch) {
|
1544
1547
|
if (op.op === "file") {
|
1545
1548
|
const filePath = op.filePath;
|
@@ -1578,7 +1581,7 @@ class ValOps {
|
|
1578
1581
|
const errors = {};
|
1579
1582
|
for (const patchData of analysis.patches) {
|
1580
1583
|
const path = patchData.path;
|
1581
|
-
if (
|
1584
|
+
if (sources[path] === undefined) {
|
1582
1585
|
if (!errors[path]) {
|
1583
1586
|
errors[path] = [];
|
1584
1587
|
}
|
@@ -1855,6 +1858,8 @@ class ValOps {
|
|
1855
1858
|
patchesByModule,
|
1856
1859
|
fileLastUpdatedByPatchId
|
1857
1860
|
} = patchAnalysis;
|
1861
|
+
const patchedSourceFiles = {};
|
1862
|
+
const previousSourceFiles = {};
|
1858
1863
|
const applySourceFilePatches = async (path, patches) => {
|
1859
1864
|
const sourceFileRes = await this.getSourceFile(path);
|
1860
1865
|
const errors = [];
|
@@ -1870,6 +1875,7 @@ class ValOps {
|
|
1870
1875
|
};
|
1871
1876
|
}
|
1872
1877
|
const sourceFile = sourceFileRes.data;
|
1878
|
+
previousSourceFiles[path] = sourceFile;
|
1873
1879
|
let tsSourceFile = ts.createSourceFile("<val>", sourceFile, ts.ScriptTarget.ES2015);
|
1874
1880
|
const appliedPatches = [];
|
1875
1881
|
const triedPatches = [];
|
@@ -1947,7 +1953,6 @@ class ValOps {
|
|
1947
1953
|
const appliedPatches = {};
|
1948
1954
|
const triedPatches = {};
|
1949
1955
|
const skippedPatches = {};
|
1950
|
-
const patchedSourceFiles = {};
|
1951
1956
|
|
1952
1957
|
//
|
1953
1958
|
const globalAppliedPatches = [];
|
@@ -1988,6 +1993,7 @@ class ValOps {
|
|
1988
1993
|
sourceFilePatchErrors,
|
1989
1994
|
binaryFilePatchErrors,
|
1990
1995
|
patchedSourceFiles,
|
1996
|
+
previousSourceFiles,
|
1991
1997
|
patchedBinaryFilesDescriptors,
|
1992
1998
|
appliedPatches,
|
1993
1999
|
skippedPatches,
|
@@ -2005,7 +2011,7 @@ class ValOps {
|
|
2005
2011
|
if (parentRef.type !== "head") {
|
2006
2012
|
// There's room for some optimizations here: we could do this once, then re-use every time we create a patch, then again we only create one patch at a time
|
2007
2013
|
const patchOps = await this.fetchPatches({
|
2008
|
-
|
2014
|
+
excludePatchOps: false
|
2009
2015
|
});
|
2010
2016
|
const patchAnalysis = this.analyzePatches(patchOps.patches);
|
2011
2017
|
const tree = await this.getSources({
|
@@ -2029,7 +2035,7 @@ class ValOps {
|
|
2029
2035
|
}
|
2030
2036
|
});
|
2031
2037
|
}
|
2032
|
-
if (
|
2038
|
+
if (source === undefined) {
|
2033
2039
|
console.error(`Cannot patch. Module source at path: '${path}' does not exist`);
|
2034
2040
|
return result.err({
|
2035
2041
|
errorType: "other",
|
@@ -2341,6 +2347,13 @@ class ValOpsFS extends ValOps {
|
|
2341
2347
|
async onInit() {
|
2342
2348
|
// do nothing
|
2343
2349
|
}
|
2350
|
+
async getCommitSummary() {
|
2351
|
+
return {
|
2352
|
+
error: {
|
2353
|
+
message: "Val is in development / local mode. Cannot generate summary"
|
2354
|
+
}
|
2355
|
+
};
|
2356
|
+
}
|
2344
2357
|
async getStat(params) {
|
2345
2358
|
// In ValOpsFS, we don't have a websocket server to listen to file changes so we use long-polling.
|
2346
2359
|
// If a file that Val depends on changes, we break the connection and tell the client to request again to get the latest values.
|
@@ -2522,7 +2535,7 @@ class ValOpsFS extends ValOps {
|
|
2522
2535
|
}
|
2523
2536
|
patches[parsedPatch.data.patchId] = {
|
2524
2537
|
...parsedPatch.data,
|
2525
|
-
appliedAt:
|
2538
|
+
appliedAt: null
|
2526
2539
|
};
|
2527
2540
|
}
|
2528
2541
|
});
|
@@ -2542,17 +2555,9 @@ class ValOpsFS extends ValOps {
|
|
2542
2555
|
return parentRef.type === "head" ? "head" : parentRef.patchId;
|
2543
2556
|
}
|
2544
2557
|
async fetchPatches(filters) {
|
2545
|
-
const fetchPatchesRes = await this.fetchPatchesFromFS(!!filters.
|
2546
|
-
const sortedPatches = this.createPatchChain(fetchPatchesRes.patches).
|
2547
|
-
if (filters.
|
2548
|
-
return false;
|
2549
|
-
}
|
2550
|
-
if (filters.moduleFilePaths && !filters.moduleFilePaths.includes(patchData.path)) {
|
2551
|
-
return false;
|
2552
|
-
}
|
2553
|
-
return true;
|
2554
|
-
}).map(patchData => {
|
2555
|
-
if (filters.omitPatch) {
|
2558
|
+
const fetchPatchesRes = await this.fetchPatchesFromFS(!!filters.excludePatchOps);
|
2559
|
+
const sortedPatches = this.createPatchChain(fetchPatchesRes.patches).map(patchData => {
|
2560
|
+
if (filters.excludePatchOps) {
|
2556
2561
|
return {
|
2557
2562
|
...patchData,
|
2558
2563
|
patch: undefined
|
@@ -2565,7 +2570,7 @@ class ValOpsFS extends ValOps {
|
|
2565
2570
|
errors: fetchPatchesRes.errors
|
2566
2571
|
};
|
2567
2572
|
}
|
2568
|
-
async fetchPatchesFromFS(
|
2573
|
+
async fetchPatchesFromFS(excludePatchOps) {
|
2569
2574
|
const patches = {};
|
2570
2575
|
const {
|
2571
2576
|
errors,
|
@@ -2574,7 +2579,7 @@ class ValOpsFS extends ValOps {
|
|
2574
2579
|
for (const [patchIdS, patch] of Object.entries(allPatches)) {
|
2575
2580
|
const patchId = patchIdS;
|
2576
2581
|
patches[patchId] = {
|
2577
|
-
patch:
|
2582
|
+
patch: excludePatchOps ? undefined : patch.patch,
|
2578
2583
|
parentRef: patch.parentRef,
|
2579
2584
|
path: patch.path,
|
2580
2585
|
baseSha: patch.baseSha,
|
@@ -3168,7 +3173,7 @@ const textEncoder = new TextEncoder();
|
|
3168
3173
|
const PatchId = z.string().refine(s => !!s); // TODO: validate
|
3169
3174
|
const CommitSha = z.string().refine(s => !!s); // TODO: validate
|
3170
3175
|
z.string().refine(s => !!s); // TODO: validate
|
3171
|
-
|
3176
|
+
z.string().refine(s => !!s); // TODO: validate
|
3172
3177
|
const ModuleFilePath = z.string().refine(s => !!s); // TODO: validate
|
3173
3178
|
const Metadata = z.union([z.object({
|
3174
3179
|
mimeType: z.string(),
|
@@ -3182,20 +3187,28 @@ const MetadataRes = z.object({
|
|
3182
3187
|
metadata: Metadata,
|
3183
3188
|
type: z.union([z.literal("file"), z.literal("image")]).nullable()
|
3184
3189
|
});
|
3185
|
-
const
|
3186
|
-
|
3187
|
-
patchId: PatchId,
|
3188
|
-
authorId: AuthorId.nullable(),
|
3189
|
-
createdAt: z.string().datetime(),
|
3190
|
-
baseSha: z.string()
|
3190
|
+
const SummaryResponse = z.object({
|
3191
|
+
commitSummary: z.string().nullable()
|
3191
3192
|
});
|
3192
|
-
const
|
3193
|
-
patches: z.array(z.
|
3194
|
-
|
3195
|
-
|
3196
|
-
|
3197
|
-
|
3198
|
-
|
3193
|
+
const GetApplicablePatches = z.object({
|
3194
|
+
patches: z.array(z.object({
|
3195
|
+
path: z.string(),
|
3196
|
+
patch: Patch.nullable(),
|
3197
|
+
patchId: z.string(),
|
3198
|
+
authorId: z.string().nullable(),
|
3199
|
+
baseSha: z.string(),
|
3200
|
+
createdAt: z.string(),
|
3201
|
+
applied: z.object({
|
3202
|
+
commitSha: z.string()
|
3203
|
+
}).nullable()
|
3204
|
+
})),
|
3205
|
+
commits: z.array(z.object({
|
3206
|
+
commitSha: z.string(),
|
3207
|
+
clientCommitSha: z.string(),
|
3208
|
+
parentCommitSha: z.string(),
|
3209
|
+
branch: z.string(),
|
3210
|
+
creator: z.string(),
|
3211
|
+
createdAt: z.string()
|
3199
3212
|
})).optional()
|
3200
3213
|
});
|
3201
3214
|
const FilesResponse = z.object({
|
@@ -3232,7 +3245,7 @@ const DeletePatchesResponse = z.object({
|
|
3232
3245
|
patchId: PatchId
|
3233
3246
|
})).optional()
|
3234
3247
|
});
|
3235
|
-
z.object({
|
3248
|
+
const SavePatchFileResponse = z.object({
|
3236
3249
|
patchId: PatchId,
|
3237
3250
|
filePath: ModuleFilePath
|
3238
3251
|
});
|
@@ -3251,11 +3264,11 @@ const ProfilesResponse = z.object({
|
|
3251
3264
|
}))
|
3252
3265
|
});
|
3253
3266
|
class ValOpsHttp extends ValOps {
|
3254
|
-
constructor(
|
3267
|
+
constructor(contentUrl, project, commitSha,
|
3255
3268
|
// TODO: CommitSha
|
3256
3269
|
branch, apiKey, valModules, options) {
|
3257
3270
|
super(valModules, options);
|
3258
|
-
this.
|
3271
|
+
this.contentUrl = contentUrl;
|
3259
3272
|
this.project = project;
|
3260
3273
|
this.commitSha = commitSha;
|
3261
3274
|
this.branch = branch;
|
@@ -3267,6 +3280,70 @@ class ValOpsHttp extends ValOps {
|
|
3267
3280
|
async onInit() {
|
3268
3281
|
// TODO: unused for now. Implement or remove
|
3269
3282
|
}
|
3283
|
+
async getCommitSummary(preparedCommit) {
|
3284
|
+
try {
|
3285
|
+
var _res$headers$get;
|
3286
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit-summary`, {
|
3287
|
+
method: "POST",
|
3288
|
+
headers: {
|
3289
|
+
...this.authHeaders,
|
3290
|
+
"Content-Type": "application/json"
|
3291
|
+
},
|
3292
|
+
body: JSON.stringify({
|
3293
|
+
patchedSourceFiles: preparedCommit.patchedSourceFiles,
|
3294
|
+
previousSourceFiles: preparedCommit.previousSourceFiles
|
3295
|
+
})
|
3296
|
+
});
|
3297
|
+
if (res.ok) {
|
3298
|
+
const json = await res.json();
|
3299
|
+
const parsed = SummaryResponse.safeParse(json);
|
3300
|
+
if (parsed.success) {
|
3301
|
+
return {
|
3302
|
+
commitSummary: parsed.data.commitSummary
|
3303
|
+
};
|
3304
|
+
}
|
3305
|
+
console.error(`Could not parse summary response. Error: ${fromError(parsed.error).toString()}`);
|
3306
|
+
return {
|
3307
|
+
error: {
|
3308
|
+
message: `Cannot get the summary of your changes. An error has been logged. Possible cause: the current version of Val might be too old. Please try again later or contact the developers on your team.`
|
3309
|
+
}
|
3310
|
+
};
|
3311
|
+
}
|
3312
|
+
if (res.status === 401) {
|
3313
|
+
console.error("Unauthorized to get summary");
|
3314
|
+
return {
|
3315
|
+
error: {
|
3316
|
+
message: "Could not get summary. Although your user is authorized, the application has authorization issues. Contact the developers on your team and ask them to verify the api keys."
|
3317
|
+
}
|
3318
|
+
};
|
3319
|
+
}
|
3320
|
+
const unknownErrorMessage = `Could not get summary. HTTP error: ${res.status} ${res.statusText}`;
|
3321
|
+
if ((_res$headers$get = res.headers.get("Content-Type")) !== null && _res$headers$get !== void 0 && _res$headers$get.includes("application/json")) {
|
3322
|
+
const json = await res.json();
|
3323
|
+
if (json.message) {
|
3324
|
+
console.error("Summary error:", json.message);
|
3325
|
+
return {
|
3326
|
+
error: {
|
3327
|
+
message: json.message
|
3328
|
+
}
|
3329
|
+
};
|
3330
|
+
}
|
3331
|
+
}
|
3332
|
+
console.error(unknownErrorMessage);
|
3333
|
+
return {
|
3334
|
+
error: {
|
3335
|
+
message: unknownErrorMessage
|
3336
|
+
}
|
3337
|
+
};
|
3338
|
+
} catch (e) {
|
3339
|
+
console.error("Could not get summary (connection error?):", e);
|
3340
|
+
return {
|
3341
|
+
error: {
|
3342
|
+
message: `Could not get summary. Error: ${e instanceof Error ? e.message : JSON.stringify(e)}`
|
3343
|
+
}
|
3344
|
+
};
|
3345
|
+
}
|
3346
|
+
}
|
3270
3347
|
async getStat(params) {
|
3271
3348
|
if (!(params !== null && params !== void 0 && params.profileId)) {
|
3272
3349
|
return {
|
@@ -3279,11 +3356,23 @@ class ValOpsHttp extends ValOps {
|
|
3279
3356
|
const currentBaseSha = await this.getBaseSha();
|
3280
3357
|
const currentSchemaSha = await this.getSchemaSha();
|
3281
3358
|
const allPatchData = await this.fetchPatches({
|
3282
|
-
|
3283
|
-
|
3284
|
-
patchIds: undefined,
|
3285
|
-
moduleFilePaths: undefined
|
3359
|
+
excludePatchOps: true,
|
3360
|
+
patchIds: undefined
|
3286
3361
|
});
|
3362
|
+
if ("error" in allPatchData && allPatchData.error && allPatchData.unauthorized) {
|
3363
|
+
return {
|
3364
|
+
type: "error",
|
3365
|
+
error: allPatchData.error,
|
3366
|
+
unauthorized: true
|
3367
|
+
};
|
3368
|
+
}
|
3369
|
+
if ("error" in allPatchData && allPatchData.error && allPatchData.networkError) {
|
3370
|
+
return {
|
3371
|
+
type: "error",
|
3372
|
+
error: allPatchData.error,
|
3373
|
+
networkError: true
|
3374
|
+
};
|
3375
|
+
}
|
3287
3376
|
// We think these errors will be picked up else where (?), so we only return an error here if there are no patches
|
3288
3377
|
if (allPatchData.patches.length === 0) {
|
3289
3378
|
let message;
|
@@ -3330,7 +3419,7 @@ class ValOpsHttp extends ValOps {
|
|
3330
3419
|
};
|
3331
3420
|
}
|
3332
3421
|
async getWebSocketNonce(profileId) {
|
3333
|
-
return fetch(`${this.
|
3422
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/websocket/nonces`, {
|
3334
3423
|
method: "POST",
|
3335
3424
|
body: JSON.stringify({
|
3336
3425
|
branch: this.branch,
|
@@ -3407,16 +3496,12 @@ class ValOpsHttp extends ValOps {
|
|
3407
3496
|
if (patchIds === undefined || patchIds.length === 0) {
|
3408
3497
|
return this.fetchPatchesInternal({
|
3409
3498
|
patchIds: patchIds,
|
3410
|
-
|
3411
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3412
|
-
omitPatch: filters.omitPatch
|
3499
|
+
excludePatchOps: filters.excludePatchOps
|
3413
3500
|
});
|
3414
3501
|
}
|
3415
3502
|
for (const res of await Promise.all(patchIdChunks.map(patchIdChunk => this.fetchPatchesInternal({
|
3416
3503
|
patchIds: patchIdChunk,
|
3417
|
-
|
3418
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3419
|
-
omitPatch: filters.omitPatch
|
3504
|
+
excludePatchOps: filters.excludePatchOps
|
3420
3505
|
})))) {
|
3421
3506
|
if ("error" in res) {
|
3422
3507
|
return res;
|
@@ -3434,72 +3519,97 @@ class ValOpsHttp extends ValOps {
|
|
3434
3519
|
async fetchPatchesInternal(filters) {
|
3435
3520
|
const params = [];
|
3436
3521
|
params.push(["branch", this.branch]);
|
3522
|
+
params.push(["commit", this.commitSha]);
|
3437
3523
|
if (filters.patchIds) {
|
3438
3524
|
for (const patchId of filters.patchIds) {
|
3439
3525
|
params.push(["patch_id", patchId]);
|
3440
3526
|
}
|
3441
3527
|
}
|
3442
|
-
if (filters.
|
3443
|
-
|
3444
|
-
params.push(["author_id", author]);
|
3445
|
-
}
|
3446
|
-
}
|
3447
|
-
if (filters.omitPatch) {
|
3448
|
-
params.push(["omit_patch", "true"]);
|
3449
|
-
}
|
3450
|
-
if (filters.moduleFilePaths) {
|
3451
|
-
for (const moduleFilePath of filters.moduleFilePaths) {
|
3452
|
-
params.push(["module_file_path", moduleFilePath]);
|
3453
|
-
}
|
3528
|
+
if (filters.excludePatchOps) {
|
3529
|
+
params.push(["exclude_patch_ops", "true"]);
|
3454
3530
|
}
|
3455
3531
|
const searchParams = new URLSearchParams(params);
|
3456
|
-
|
3457
|
-
|
3458
|
-
|
3459
|
-
|
3460
|
-
}
|
3461
|
-
}).then(async res => {
|
3532
|
+
try {
|
3533
|
+
const patchesRes = await fetch(`${this.contentUrl}/v1/${this.project}/applicable/patches${searchParams.size > 0 ? `?${searchParams.toString()}` : ""}`, {
|
3534
|
+
headers: this.authHeaders
|
3535
|
+
});
|
3462
3536
|
const patches = [];
|
3463
|
-
if (
|
3464
|
-
const json = await
|
3465
|
-
const parsed =
|
3537
|
+
if (patchesRes.ok) {
|
3538
|
+
const json = await patchesRes.json();
|
3539
|
+
const parsed = GetApplicablePatches.safeParse(json);
|
3466
3540
|
if (parsed.success) {
|
3467
3541
|
const errors = [];
|
3468
3542
|
const data = parsed.data;
|
3469
3543
|
for (const patchesRes of data.patches) {
|
3544
|
+
var _patchesRes$applied;
|
3470
3545
|
patches.push({
|
3471
3546
|
authorId: patchesRes.authorId,
|
3472
3547
|
createdAt: patchesRes.createdAt,
|
3473
|
-
appliedAt: null,
|
3474
3548
|
patchId: patchesRes.patchId,
|
3475
3549
|
path: patchesRes.path,
|
3476
3550
|
baseSha: patchesRes.baseSha,
|
3477
|
-
patch:
|
3551
|
+
patch: patchesRes.patch,
|
3552
|
+
appliedAt: (_patchesRes$applied = patchesRes.applied) !== null && _patchesRes$applied !== void 0 && _patchesRes$applied.commitSha ? {
|
3553
|
+
commitSha: patchesRes.applied.commitSha
|
3554
|
+
} : null
|
3478
3555
|
});
|
3479
3556
|
}
|
3557
|
+
const commits = [];
|
3558
|
+
if (data.commits) {
|
3559
|
+
for (const commit of data.commits) {
|
3560
|
+
commits.push({
|
3561
|
+
commitSha: commit.commitSha,
|
3562
|
+
clientCommitSha: commit.clientCommitSha,
|
3563
|
+
parentCommitSha: commit.parentCommitSha,
|
3564
|
+
branch: commit.branch,
|
3565
|
+
creator: commit.creator,
|
3566
|
+
createdAt: commit.createdAt
|
3567
|
+
});
|
3568
|
+
}
|
3569
|
+
}
|
3480
3570
|
return {
|
3571
|
+
commits,
|
3481
3572
|
patches,
|
3482
3573
|
errors
|
3483
3574
|
};
|
3484
3575
|
}
|
3576
|
+
console.error("Could not parse patches response. Error: " + fromError(parsed.error));
|
3577
|
+
return {
|
3578
|
+
patches,
|
3579
|
+
error: {
|
3580
|
+
message: `The response that Val got from the server was not in the expected format. This might be a transient error or a configuration issue. Please try again later.`
|
3581
|
+
}
|
3582
|
+
};
|
3583
|
+
}
|
3584
|
+
console.error("Could not get patches. HTTP error: " + patchesRes.status + " " + patchesRes.statusText);
|
3585
|
+
if (patchesRes.status === 401) {
|
3485
3586
|
return {
|
3486
3587
|
patches,
|
3487
3588
|
error: {
|
3488
|
-
message:
|
3589
|
+
message: "Although your user is authorized, the application has authorization issues. Contact the developers on your team and ask them to verify the api keys."
|
3489
3590
|
}
|
3490
3591
|
};
|
3491
3592
|
}
|
3492
3593
|
return {
|
3493
3594
|
patches,
|
3494
3595
|
error: {
|
3495
|
-
message: "Could not
|
3596
|
+
message: "Could not your changes. It is most likely due to a network issue. Check your network connection and please try again."
|
3496
3597
|
}
|
3497
3598
|
};
|
3498
|
-
})
|
3599
|
+
} catch (err) {
|
3600
|
+
console.error("Could not get patches (connection error):", err instanceof Error ? err.message : JSON.stringify(err));
|
3601
|
+
return {
|
3602
|
+
patches: [],
|
3603
|
+
networkError: true,
|
3604
|
+
error: {
|
3605
|
+
message: `Error: ${err instanceof Error ? err.message : JSON.stringify(err)}`
|
3606
|
+
}
|
3607
|
+
};
|
3608
|
+
}
|
3499
3609
|
}
|
3500
3610
|
async saveSourceFilePatch(path, patch, parentRef, authorId) {
|
3501
3611
|
const baseSha = await this.getBaseSha();
|
3502
|
-
return fetch(`${this.
|
3612
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3503
3613
|
method: "POST",
|
3504
3614
|
headers: {
|
3505
3615
|
...this.authHeaders,
|
@@ -3516,7 +3626,7 @@ class ValOpsHttp extends ValOps {
|
|
3516
3626
|
coreVersion: Internal.VERSION.core
|
3517
3627
|
})
|
3518
3628
|
}).then(async res => {
|
3519
|
-
var _res$headers$
|
3629
|
+
var _res$headers$get2;
|
3520
3630
|
if (res.ok) {
|
3521
3631
|
const parsed = SavePatchResponse.safeParse(await res.json());
|
3522
3632
|
if (parsed.success) {
|
@@ -3535,7 +3645,7 @@ class ValOpsHttp extends ValOps {
|
|
3535
3645
|
message: "Conflict: " + (await res.text())
|
3536
3646
|
});
|
3537
3647
|
}
|
3538
|
-
if ((_res$headers$
|
3648
|
+
if ((_res$headers$get2 = res.headers.get("Content-Type")) !== null && _res$headers$get2 !== void 0 && _res$headers$get2.includes("application/json")) {
|
3539
3649
|
const json = await res.json();
|
3540
3650
|
return result.err({
|
3541
3651
|
errorType: "other",
|
@@ -3554,7 +3664,45 @@ class ValOpsHttp extends ValOps {
|
|
3554
3664
|
});
|
3555
3665
|
}
|
3556
3666
|
async saveBase64EncodedBinaryFileFromPatch(filePath, parentRef, patchId, data, type, metadata) {
|
3557
|
-
|
3667
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches/${patchId}/files`, {
|
3668
|
+
method: "POST",
|
3669
|
+
headers: {
|
3670
|
+
...this.authHeaders,
|
3671
|
+
"Content-Type": "application/json"
|
3672
|
+
},
|
3673
|
+
body: JSON.stringify({
|
3674
|
+
filePath: filePath,
|
3675
|
+
data,
|
3676
|
+
type,
|
3677
|
+
metadata
|
3678
|
+
})
|
3679
|
+
}).then(async res => {
|
3680
|
+
if (res.ok) {
|
3681
|
+
const parsed = SavePatchFileResponse.safeParse(await res.json());
|
3682
|
+
if (parsed.success) {
|
3683
|
+
return {
|
3684
|
+
patchId: parsed.data.patchId,
|
3685
|
+
filePath: parsed.data.filePath
|
3686
|
+
};
|
3687
|
+
}
|
3688
|
+
return {
|
3689
|
+
error: {
|
3690
|
+
message: `Could not parse save patch file response. Error: ${fromError(parsed.error)}`
|
3691
|
+
}
|
3692
|
+
};
|
3693
|
+
}
|
3694
|
+
return {
|
3695
|
+
error: {
|
3696
|
+
message: "Could not save patch file. HTTP error: " + res.status + " " + res.statusText
|
3697
|
+
}
|
3698
|
+
};
|
3699
|
+
}).catch(e => {
|
3700
|
+
return {
|
3701
|
+
error: {
|
3702
|
+
message: `Could save source binary file in patch (connection error?): ${e.toString()}`
|
3703
|
+
}
|
3704
|
+
};
|
3705
|
+
});
|
3558
3706
|
}
|
3559
3707
|
async getHttpFiles(files) {
|
3560
3708
|
const params = new URLSearchParams();
|
@@ -3565,7 +3713,7 @@ class ValOpsHttp extends ValOps {
|
|
3565
3713
|
params.set("body_sha",
|
3566
3714
|
// We use this for cache invalidation
|
3567
3715
|
Internal.getSHA256Hash(textEncoder.encode(stringifiedFiles)));
|
3568
|
-
return fetch(`${this.
|
3716
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/files?${params}`, {
|
3569
3717
|
method: "PUT",
|
3570
3718
|
// Yes, PUT is weird. Weirder to have a body in a GET request.
|
3571
3719
|
headers: {
|
@@ -3658,7 +3806,7 @@ class ValOpsHttp extends ValOps {
|
|
3658
3806
|
const params = new URLSearchParams();
|
3659
3807
|
params.set("file_path", filePath);
|
3660
3808
|
try {
|
3661
|
-
const metadataRes = await fetch(`${this.
|
3809
|
+
const metadataRes = await fetch(`${this.contentUrl}/v1/${this.project}/patches/${patchId}/files?${params}`, {
|
3662
3810
|
headers: {
|
3663
3811
|
...this.authHeaders,
|
3664
3812
|
"Content-Type": "application/json"
|
@@ -3712,7 +3860,7 @@ class ValOpsHttp extends ValOps {
|
|
3712
3860
|
};
|
3713
3861
|
}
|
3714
3862
|
async deletePatches(patchIds) {
|
3715
|
-
return fetch(`${this.
|
3863
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3716
3864
|
method: "DELETE",
|
3717
3865
|
headers: {
|
3718
3866
|
...this.authHeaders,
|
@@ -3758,11 +3906,44 @@ class ValOpsHttp extends ValOps {
|
|
3758
3906
|
};
|
3759
3907
|
});
|
3760
3908
|
}
|
3761
|
-
async
|
3909
|
+
async getCommitMessage(preparedCommit) {
|
3910
|
+
var _res$headers$get3;
|
3911
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit-summary`, {
|
3912
|
+
method: "POST",
|
3913
|
+
headers: {
|
3914
|
+
...this.authHeaders,
|
3915
|
+
"Content-Type": "application/json"
|
3916
|
+
},
|
3917
|
+
body: JSON.stringify({
|
3918
|
+
patchedSourceFiles: preparedCommit.patchedSourceFiles,
|
3919
|
+
previousSourceFiles: preparedCommit.previousSourceFiles
|
3920
|
+
})
|
3921
|
+
});
|
3922
|
+
if (res.ok) {
|
3923
|
+
const json = await res.json();
|
3924
|
+
return {
|
3925
|
+
commitSummary: json.commitSummary
|
3926
|
+
};
|
3927
|
+
}
|
3928
|
+
if ((_res$headers$get3 = res.headers.get("Content-Type")) !== null && _res$headers$get3 !== void 0 && _res$headers$get3.includes("application/json")) {
|
3929
|
+
const json = await res.json();
|
3930
|
+
return {
|
3931
|
+
error: {
|
3932
|
+
message: json.message
|
3933
|
+
}
|
3934
|
+
};
|
3935
|
+
}
|
3936
|
+
return {
|
3937
|
+
error: {
|
3938
|
+
message: "Could not get commit message. HTTP error: " + res.status + " " + res.statusText
|
3939
|
+
}
|
3940
|
+
};
|
3941
|
+
}
|
3942
|
+
async commit(prepared, message, committer, filesDirectory, newBranch) {
|
3762
3943
|
try {
|
3763
|
-
var _res$headers$
|
3944
|
+
var _res$headers$get4;
|
3764
3945
|
const existingBranch = this.branch;
|
3765
|
-
const res = await fetch(`${this.
|
3946
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit`, {
|
3766
3947
|
method: "POST",
|
3767
3948
|
headers: {
|
3768
3949
|
...this.authHeaders,
|
@@ -3774,6 +3955,7 @@ class ValOpsHttp extends ValOps {
|
|
3774
3955
|
appliedPatches: prepared.appliedPatches,
|
3775
3956
|
commit: this.commitSha,
|
3776
3957
|
root: this.root,
|
3958
|
+
filesDirectory,
|
3777
3959
|
baseSha: await this.getBaseSha(),
|
3778
3960
|
committer,
|
3779
3961
|
message,
|
@@ -3796,7 +3978,7 @@ class ValOpsHttp extends ValOps {
|
|
3796
3978
|
}
|
3797
3979
|
};
|
3798
3980
|
}
|
3799
|
-
if ((_res$headers$
|
3981
|
+
if ((_res$headers$get4 = res.headers.get("Content-Type")) !== null && _res$headers$get4 !== void 0 && _res$headers$get4.includes("application/json")) {
|
3800
3982
|
const json = await res.json();
|
3801
3983
|
if (json.isNotFastForward) {
|
3802
3984
|
return {
|
@@ -3828,8 +4010,8 @@ class ValOpsHttp extends ValOps {
|
|
3828
4010
|
|
3829
4011
|
// #region profiles
|
3830
4012
|
async getProfiles() {
|
3831
|
-
var _res$headers$
|
3832
|
-
const res = await fetch(`${this.
|
4013
|
+
var _res$headers$get5;
|
4014
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/profiles`, {
|
3833
4015
|
headers: {
|
3834
4016
|
...this.authHeaders,
|
3835
4017
|
"Content-Type": "application/json"
|
@@ -3843,7 +4025,7 @@ class ValOpsHttp extends ValOps {
|
|
3843
4025
|
}
|
3844
4026
|
return parsed.data.profiles;
|
3845
4027
|
}
|
3846
|
-
if ((_res$headers$
|
4028
|
+
if ((_res$headers$get5 = res.headers.get("Content-Type")) !== null && _res$headers$get5 !== void 0 && _res$headers$get5.includes("application/json")) {
|
3847
4029
|
const json = await res.json();
|
3848
4030
|
throw Error(`Could not get profiles (status: ${res.status}): ${"message" in json ? json.message : "Unknown error"}`);
|
3849
4031
|
}
|
@@ -3881,6 +4063,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
3881
4063
|
url.searchParams.set("state", token);
|
3882
4064
|
return url.toString();
|
3883
4065
|
};
|
4066
|
+
const commit = options.mode === "http" ? options.commit : undefined;
|
3884
4067
|
const getAppErrorUrl = error => {
|
3885
4068
|
if (!options.project) {
|
3886
4069
|
throw new Error("Project is not set");
|
@@ -4343,6 +4526,22 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4343
4526
|
...req.body,
|
4344
4527
|
profileId: "id" in auth ? auth.id : undefined
|
4345
4528
|
});
|
4529
|
+
if (currentStat.type === "error" && currentStat.networkError) {
|
4530
|
+
return {
|
4531
|
+
status: 503,
|
4532
|
+
json: {
|
4533
|
+
message: "Network error"
|
4534
|
+
}
|
4535
|
+
};
|
4536
|
+
}
|
4537
|
+
if (currentStat.type === "error" && currentStat.unauthorized) {
|
4538
|
+
return {
|
4539
|
+
status: 401,
|
4540
|
+
json: {
|
4541
|
+
message: "Unauthorized"
|
4542
|
+
}
|
4543
|
+
};
|
4544
|
+
}
|
4346
4545
|
if (currentStat.type === "error") {
|
4347
4546
|
return {
|
4348
4547
|
status: 500,
|
@@ -4353,6 +4552,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4353
4552
|
status: 200,
|
4354
4553
|
json: {
|
4355
4554
|
...currentStat,
|
4555
|
+
mode: serverOps instanceof ValOpsFS ? "fs" : serverOps instanceof ValOpsHttp ? "http" : "unknown",
|
4356
4556
|
config: options.config
|
4357
4557
|
}
|
4358
4558
|
};
|
@@ -4380,7 +4580,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4380
4580
|
};
|
4381
4581
|
}
|
4382
4582
|
const patches = req.body.patches;
|
4383
|
-
|
4583
|
+
let parentRef = req.body.parentRef;
|
4384
4584
|
const authorId = "id" in auth ? auth.id : null;
|
4385
4585
|
const newPatchIds = [];
|
4386
4586
|
for (const patch of patches) {
|
@@ -4411,6 +4611,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4411
4611
|
};
|
4412
4612
|
}
|
4413
4613
|
} else {
|
4614
|
+
parentRef = {
|
4615
|
+
type: "patch",
|
4616
|
+
patchId: createPatchRes.value.patchId
|
4617
|
+
};
|
4414
4618
|
newPatchIds.push(createPatchRes.value.patchId);
|
4415
4619
|
}
|
4416
4620
|
}
|
@@ -4418,10 +4622,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4418
4622
|
status: 200,
|
4419
4623
|
json: {
|
4420
4624
|
newPatchIds,
|
4421
|
-
parentRef
|
4422
|
-
type: "patch",
|
4423
|
-
patchId: newPatchIds[newPatchIds.length - 1]
|
4424
|
-
}
|
4625
|
+
parentRef
|
4425
4626
|
}
|
4426
4627
|
};
|
4427
4628
|
},
|
@@ -4446,13 +4647,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4446
4647
|
}
|
4447
4648
|
};
|
4448
4649
|
}
|
4449
|
-
const
|
4450
|
-
const authors = query.author;
|
4650
|
+
const excludePatchOps = query.exclude_patch_ops === true;
|
4451
4651
|
const fetchedPatchesRes = await serverOps.fetchPatches({
|
4452
|
-
authors,
|
4453
4652
|
patchIds: query.patch_id,
|
4454
|
-
|
4455
|
-
moduleFilePaths: query.module_file_path
|
4653
|
+
excludePatchOps: excludePatchOps
|
4456
4654
|
});
|
4457
4655
|
if (fetchedPatchesRes.error) {
|
4458
4656
|
// Error is singular
|
@@ -4633,8 +4831,17 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4633
4831
|
}
|
4634
4832
|
const patchOps = await serverOps.fetchPatches({
|
4635
4833
|
patchIds: undefined,
|
4636
|
-
|
4834
|
+
excludePatchOps: false
|
4637
4835
|
});
|
4836
|
+
// We check authorization here, because it is the first call to the backend
|
4837
|
+
if (patchOps.error && patchOps.unauthorized) {
|
4838
|
+
return {
|
4839
|
+
status: 401,
|
4840
|
+
json: {
|
4841
|
+
message: "Unauthorized"
|
4842
|
+
}
|
4843
|
+
};
|
4844
|
+
}
|
4638
4845
|
const patchAnalysis = serverOps.analyzePatches(patchOps.patches);
|
4639
4846
|
let sourcesRes = await serverOps.getSources();
|
4640
4847
|
const onlyPatchedTreeModules = await serverOps.getSources({
|
@@ -4713,17 +4920,16 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4713
4920
|
},
|
4714
4921
|
"/profiles": {
|
4715
4922
|
GET: async req => {
|
4716
|
-
|
4717
|
-
|
4718
|
-
|
4719
|
-
|
4720
|
-
|
4721
|
-
|
4722
|
-
|
4723
|
-
|
4724
|
-
|
4725
|
-
|
4726
|
-
|
4923
|
+
const cookies = req.cookies;
|
4924
|
+
const auth = getAuth(cookies);
|
4925
|
+
if (auth.error) {
|
4926
|
+
return {
|
4927
|
+
status: 401,
|
4928
|
+
json: {
|
4929
|
+
message: auth.error
|
4930
|
+
}
|
4931
|
+
};
|
4932
|
+
}
|
4727
4933
|
const profiles = await serverOps.getProfiles();
|
4728
4934
|
return {
|
4729
4935
|
status: 200,
|
@@ -4733,6 +4939,49 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4733
4939
|
};
|
4734
4940
|
}
|
4735
4941
|
},
|
4942
|
+
"/commit-summary": {
|
4943
|
+
GET: async req => {
|
4944
|
+
const cookies = req.cookies;
|
4945
|
+
const auth = getAuth(cookies);
|
4946
|
+
if (auth.error) {
|
4947
|
+
return {
|
4948
|
+
status: 401,
|
4949
|
+
json: {
|
4950
|
+
message: auth.error
|
4951
|
+
}
|
4952
|
+
};
|
4953
|
+
}
|
4954
|
+
const query = req.query;
|
4955
|
+
const patchIds = query.patch_id;
|
4956
|
+
const patches = await serverOps.fetchPatches({
|
4957
|
+
patchIds,
|
4958
|
+
excludePatchOps: false
|
4959
|
+
});
|
4960
|
+
const analysis = serverOps.analyzePatches(patches.patches, patches.commits, commit);
|
4961
|
+
const preparedCommit = await serverOps.prepare({
|
4962
|
+
...analysis,
|
4963
|
+
...patches
|
4964
|
+
});
|
4965
|
+
const res = await serverOps.getCommitSummary(preparedCommit);
|
4966
|
+
if (res.error) {
|
4967
|
+
console.error("Failed to summarize", res.error);
|
4968
|
+
return {
|
4969
|
+
status: 400,
|
4970
|
+
json: {
|
4971
|
+
message: res.error.message
|
4972
|
+
}
|
4973
|
+
};
|
4974
|
+
}
|
4975
|
+
return {
|
4976
|
+
status: 200,
|
4977
|
+
json: {
|
4978
|
+
baseSha: await serverOps.getBaseSha(),
|
4979
|
+
patchIds,
|
4980
|
+
commitSummary: res.commitSummary
|
4981
|
+
}
|
4982
|
+
};
|
4983
|
+
}
|
4984
|
+
},
|
4736
4985
|
"/save": {
|
4737
4986
|
POST: async req => {
|
4738
4987
|
const cookies = req.cookies;
|
@@ -4765,9 +5014,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4765
5014
|
} = bodyRes.data;
|
4766
5015
|
const patches = await serverOps.fetchPatches({
|
4767
5016
|
patchIds,
|
4768
|
-
|
5017
|
+
excludePatchOps: false
|
4769
5018
|
});
|
4770
|
-
const analysis = serverOps.analyzePatches(patches.patches);
|
5019
|
+
const analysis = serverOps.analyzePatches(patches.patches, patches.commits, commit);
|
4771
5020
|
const preparedCommit = await serverOps.prepare({
|
4772
5021
|
...analysis,
|
4773
5022
|
...patches
|
@@ -4799,7 +5048,24 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4799
5048
|
};
|
4800
5049
|
} else if (serverOps instanceof ValOpsHttp) {
|
4801
5050
|
if (auth.error === undefined && auth.id) {
|
4802
|
-
|
5051
|
+
var _options$config$ai, _options$config$files;
|
5052
|
+
let message = body.message || "Update content: " + Object.keys(analysis.patchesByModule) + " modules changed";
|
5053
|
+
if (!((_options$config$ai = options.config.ai) !== null && _options$config$ai !== void 0 && (_options$config$ai = _options$config$ai.commitMessages) !== null && _options$config$ai !== void 0 && _options$config$ai.disabled)) {
|
5054
|
+
const res = await serverOps.getCommitMessage(preparedCommit);
|
5055
|
+
console.log({
|
5056
|
+
res
|
5057
|
+
});
|
5058
|
+
if (res.error) {
|
5059
|
+
// ignore
|
5060
|
+
console.error("Failed to get commit message", res.error.message);
|
5061
|
+
} else {
|
5062
|
+
message = res.commitSummary;
|
5063
|
+
}
|
5064
|
+
}
|
5065
|
+
console.log({
|
5066
|
+
message
|
5067
|
+
});
|
5068
|
+
const commitRes = await serverOps.commit(preparedCommit, message, auth.id, ((_options$config$files = options.config.files) === null || _options$config$files === void 0 ? void 0 : _options$config$files.directory) || "/public/val");
|
4803
5069
|
if (commitRes.error) {
|
4804
5070
|
console.error("Failed to commit", commitRes.error);
|
4805
5071
|
if ("isNotFastForward" in commitRes && commitRes.isNotFastForward) {
|