@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
@@ -1565,10 +1565,13 @@ class ValOps {
|
|
1565
1565
|
}
|
1566
1566
|
|
1567
1567
|
// #region analyzePatches
|
1568
|
-
analyzePatches(sortedPatches) {
|
1568
|
+
analyzePatches(sortedPatches, commits, currentCommitSha) {
|
1569
1569
|
const patchesByModule = {};
|
1570
1570
|
const fileLastUpdatedByPatchId = {};
|
1571
1571
|
for (const patch of sortedPatches) {
|
1572
|
+
if (patch.appliedAt) {
|
1573
|
+
continue;
|
1574
|
+
}
|
1572
1575
|
for (const op of patch.patch) {
|
1573
1576
|
if (op.op === "file") {
|
1574
1577
|
const filePath = op.filePath;
|
@@ -1607,7 +1610,7 @@ class ValOps {
|
|
1607
1610
|
const errors = {};
|
1608
1611
|
for (const patchData of analysis.patches) {
|
1609
1612
|
const path = patchData.path;
|
1610
|
-
if (
|
1613
|
+
if (sources[path] === undefined) {
|
1611
1614
|
if (!errors[path]) {
|
1612
1615
|
errors[path] = [];
|
1613
1616
|
}
|
@@ -1884,6 +1887,8 @@ class ValOps {
|
|
1884
1887
|
patchesByModule,
|
1885
1888
|
fileLastUpdatedByPatchId
|
1886
1889
|
} = patchAnalysis;
|
1890
|
+
const patchedSourceFiles = {};
|
1891
|
+
const previousSourceFiles = {};
|
1887
1892
|
const applySourceFilePatches = async (path, patches) => {
|
1888
1893
|
const sourceFileRes = await this.getSourceFile(path);
|
1889
1894
|
const errors = [];
|
@@ -1899,6 +1904,7 @@ class ValOps {
|
|
1899
1904
|
};
|
1900
1905
|
}
|
1901
1906
|
const sourceFile = sourceFileRes.data;
|
1907
|
+
previousSourceFiles[path] = sourceFile;
|
1902
1908
|
let tsSourceFile = ts__default["default"].createSourceFile("<val>", sourceFile, ts__default["default"].ScriptTarget.ES2015);
|
1903
1909
|
const appliedPatches = [];
|
1904
1910
|
const triedPatches = [];
|
@@ -1976,7 +1982,6 @@ class ValOps {
|
|
1976
1982
|
const appliedPatches = {};
|
1977
1983
|
const triedPatches = {};
|
1978
1984
|
const skippedPatches = {};
|
1979
|
-
const patchedSourceFiles = {};
|
1980
1985
|
|
1981
1986
|
//
|
1982
1987
|
const globalAppliedPatches = [];
|
@@ -2017,6 +2022,7 @@ class ValOps {
|
|
2017
2022
|
sourceFilePatchErrors,
|
2018
2023
|
binaryFilePatchErrors,
|
2019
2024
|
patchedSourceFiles,
|
2025
|
+
previousSourceFiles,
|
2020
2026
|
patchedBinaryFilesDescriptors,
|
2021
2027
|
appliedPatches,
|
2022
2028
|
skippedPatches,
|
@@ -2034,7 +2040,7 @@ class ValOps {
|
|
2034
2040
|
if (parentRef.type !== "head") {
|
2035
2041
|
// 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
|
2036
2042
|
const patchOps = await this.fetchPatches({
|
2037
|
-
|
2043
|
+
excludePatchOps: false
|
2038
2044
|
});
|
2039
2045
|
const patchAnalysis = this.analyzePatches(patchOps.patches);
|
2040
2046
|
const tree = await this.getSources({
|
@@ -2058,7 +2064,7 @@ class ValOps {
|
|
2058
2064
|
}
|
2059
2065
|
});
|
2060
2066
|
}
|
2061
|
-
if (
|
2067
|
+
if (source === undefined) {
|
2062
2068
|
console.error(`Cannot patch. Module source at path: '${path}' does not exist`);
|
2063
2069
|
return fp.result.err({
|
2064
2070
|
errorType: "other",
|
@@ -2370,6 +2376,13 @@ class ValOpsFS extends ValOps {
|
|
2370
2376
|
async onInit() {
|
2371
2377
|
// do nothing
|
2372
2378
|
}
|
2379
|
+
async getCommitSummary() {
|
2380
|
+
return {
|
2381
|
+
error: {
|
2382
|
+
message: "Val is in development / local mode. Cannot generate summary"
|
2383
|
+
}
|
2384
|
+
};
|
2385
|
+
}
|
2373
2386
|
async getStat(params) {
|
2374
2387
|
// In ValOpsFS, we don't have a websocket server to listen to file changes so we use long-polling.
|
2375
2388
|
// If a file that Val depends on changes, we break the connection and tell the client to request again to get the latest values.
|
@@ -2551,7 +2564,7 @@ class ValOpsFS extends ValOps {
|
|
2551
2564
|
}
|
2552
2565
|
patches[parsedPatch.data.patchId] = {
|
2553
2566
|
...parsedPatch.data,
|
2554
|
-
appliedAt:
|
2567
|
+
appliedAt: null
|
2555
2568
|
};
|
2556
2569
|
}
|
2557
2570
|
});
|
@@ -2571,17 +2584,9 @@ class ValOpsFS extends ValOps {
|
|
2571
2584
|
return parentRef.type === "head" ? "head" : parentRef.patchId;
|
2572
2585
|
}
|
2573
2586
|
async fetchPatches(filters) {
|
2574
|
-
const fetchPatchesRes = await this.fetchPatchesFromFS(!!filters.
|
2575
|
-
const sortedPatches = this.createPatchChain(fetchPatchesRes.patches).
|
2576
|
-
if (filters.
|
2577
|
-
return false;
|
2578
|
-
}
|
2579
|
-
if (filters.moduleFilePaths && !filters.moduleFilePaths.includes(patchData.path)) {
|
2580
|
-
return false;
|
2581
|
-
}
|
2582
|
-
return true;
|
2583
|
-
}).map(patchData => {
|
2584
|
-
if (filters.omitPatch) {
|
2587
|
+
const fetchPatchesRes = await this.fetchPatchesFromFS(!!filters.excludePatchOps);
|
2588
|
+
const sortedPatches = this.createPatchChain(fetchPatchesRes.patches).map(patchData => {
|
2589
|
+
if (filters.excludePatchOps) {
|
2585
2590
|
return {
|
2586
2591
|
...patchData,
|
2587
2592
|
patch: undefined
|
@@ -2594,7 +2599,7 @@ class ValOpsFS extends ValOps {
|
|
2594
2599
|
errors: fetchPatchesRes.errors
|
2595
2600
|
};
|
2596
2601
|
}
|
2597
|
-
async fetchPatchesFromFS(
|
2602
|
+
async fetchPatchesFromFS(excludePatchOps) {
|
2598
2603
|
const patches = {};
|
2599
2604
|
const {
|
2600
2605
|
errors,
|
@@ -2603,7 +2608,7 @@ class ValOpsFS extends ValOps {
|
|
2603
2608
|
for (const [patchIdS, patch] of Object.entries(allPatches)) {
|
2604
2609
|
const patchId = patchIdS;
|
2605
2610
|
patches[patchId] = {
|
2606
|
-
patch:
|
2611
|
+
patch: excludePatchOps ? undefined : patch.patch,
|
2607
2612
|
parentRef: patch.parentRef,
|
2608
2613
|
path: patch.path,
|
2609
2614
|
baseSha: patch.baseSha,
|
@@ -3197,7 +3202,7 @@ const textEncoder = new TextEncoder();
|
|
3197
3202
|
const PatchId = zod.z.string().refine(s => !!s); // TODO: validate
|
3198
3203
|
const CommitSha = zod.z.string().refine(s => !!s); // TODO: validate
|
3199
3204
|
zod.z.string().refine(s => !!s); // TODO: validate
|
3200
|
-
|
3205
|
+
zod.z.string().refine(s => !!s); // TODO: validate
|
3201
3206
|
const ModuleFilePath = zod.z.string().refine(s => !!s); // TODO: validate
|
3202
3207
|
const Metadata = zod.z.union([zod.z.object({
|
3203
3208
|
mimeType: zod.z.string(),
|
@@ -3211,20 +3216,28 @@ const MetadataRes = zod.z.object({
|
|
3211
3216
|
metadata: Metadata,
|
3212
3217
|
type: zod.z.union([zod.z.literal("file"), zod.z.literal("image")]).nullable()
|
3213
3218
|
});
|
3214
|
-
const
|
3215
|
-
|
3216
|
-
patchId: PatchId,
|
3217
|
-
authorId: AuthorId.nullable(),
|
3218
|
-
createdAt: zod.z.string().datetime(),
|
3219
|
-
baseSha: zod.z.string()
|
3219
|
+
const SummaryResponse = zod.z.object({
|
3220
|
+
commitSummary: zod.z.string().nullable()
|
3220
3221
|
});
|
3221
|
-
const
|
3222
|
-
patches: zod.z.array(zod.z.
|
3223
|
-
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3222
|
+
const GetApplicablePatches = zod.z.object({
|
3223
|
+
patches: zod.z.array(zod.z.object({
|
3224
|
+
path: zod.z.string(),
|
3225
|
+
patch: internal.Patch.nullable(),
|
3226
|
+
patchId: zod.z.string(),
|
3227
|
+
authorId: zod.z.string().nullable(),
|
3228
|
+
baseSha: zod.z.string(),
|
3229
|
+
createdAt: zod.z.string(),
|
3230
|
+
applied: zod.z.object({
|
3231
|
+
commitSha: zod.z.string()
|
3232
|
+
}).nullable()
|
3233
|
+
})),
|
3234
|
+
commits: zod.z.array(zod.z.object({
|
3235
|
+
commitSha: zod.z.string(),
|
3236
|
+
clientCommitSha: zod.z.string(),
|
3237
|
+
parentCommitSha: zod.z.string(),
|
3238
|
+
branch: zod.z.string(),
|
3239
|
+
creator: zod.z.string(),
|
3240
|
+
createdAt: zod.z.string()
|
3228
3241
|
})).optional()
|
3229
3242
|
});
|
3230
3243
|
const FilesResponse = zod.z.object({
|
@@ -3261,7 +3274,7 @@ const DeletePatchesResponse = zod.z.object({
|
|
3261
3274
|
patchId: PatchId
|
3262
3275
|
})).optional()
|
3263
3276
|
});
|
3264
|
-
zod.z.object({
|
3277
|
+
const SavePatchFileResponse = zod.z.object({
|
3265
3278
|
patchId: PatchId,
|
3266
3279
|
filePath: ModuleFilePath
|
3267
3280
|
});
|
@@ -3280,11 +3293,11 @@ const ProfilesResponse = zod.z.object({
|
|
3280
3293
|
}))
|
3281
3294
|
});
|
3282
3295
|
class ValOpsHttp extends ValOps {
|
3283
|
-
constructor(
|
3296
|
+
constructor(contentUrl, project, commitSha,
|
3284
3297
|
// TODO: CommitSha
|
3285
3298
|
branch, apiKey, valModules, options) {
|
3286
3299
|
super(valModules, options);
|
3287
|
-
this.
|
3300
|
+
this.contentUrl = contentUrl;
|
3288
3301
|
this.project = project;
|
3289
3302
|
this.commitSha = commitSha;
|
3290
3303
|
this.branch = branch;
|
@@ -3296,6 +3309,70 @@ class ValOpsHttp extends ValOps {
|
|
3296
3309
|
async onInit() {
|
3297
3310
|
// TODO: unused for now. Implement or remove
|
3298
3311
|
}
|
3312
|
+
async getCommitSummary(preparedCommit) {
|
3313
|
+
try {
|
3314
|
+
var _res$headers$get;
|
3315
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit-summary`, {
|
3316
|
+
method: "POST",
|
3317
|
+
headers: {
|
3318
|
+
...this.authHeaders,
|
3319
|
+
"Content-Type": "application/json"
|
3320
|
+
},
|
3321
|
+
body: JSON.stringify({
|
3322
|
+
patchedSourceFiles: preparedCommit.patchedSourceFiles,
|
3323
|
+
previousSourceFiles: preparedCommit.previousSourceFiles
|
3324
|
+
})
|
3325
|
+
});
|
3326
|
+
if (res.ok) {
|
3327
|
+
const json = await res.json();
|
3328
|
+
const parsed = SummaryResponse.safeParse(json);
|
3329
|
+
if (parsed.success) {
|
3330
|
+
return {
|
3331
|
+
commitSummary: parsed.data.commitSummary
|
3332
|
+
};
|
3333
|
+
}
|
3334
|
+
console.error(`Could not parse summary response. Error: ${zodValidationError.fromError(parsed.error).toString()}`);
|
3335
|
+
return {
|
3336
|
+
error: {
|
3337
|
+
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.`
|
3338
|
+
}
|
3339
|
+
};
|
3340
|
+
}
|
3341
|
+
if (res.status === 401) {
|
3342
|
+
console.error("Unauthorized to get summary");
|
3343
|
+
return {
|
3344
|
+
error: {
|
3345
|
+
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."
|
3346
|
+
}
|
3347
|
+
};
|
3348
|
+
}
|
3349
|
+
const unknownErrorMessage = `Could not get summary. HTTP error: ${res.status} ${res.statusText}`;
|
3350
|
+
if ((_res$headers$get = res.headers.get("Content-Type")) !== null && _res$headers$get !== void 0 && _res$headers$get.includes("application/json")) {
|
3351
|
+
const json = await res.json();
|
3352
|
+
if (json.message) {
|
3353
|
+
console.error("Summary error:", json.message);
|
3354
|
+
return {
|
3355
|
+
error: {
|
3356
|
+
message: json.message
|
3357
|
+
}
|
3358
|
+
};
|
3359
|
+
}
|
3360
|
+
}
|
3361
|
+
console.error(unknownErrorMessage);
|
3362
|
+
return {
|
3363
|
+
error: {
|
3364
|
+
message: unknownErrorMessage
|
3365
|
+
}
|
3366
|
+
};
|
3367
|
+
} catch (e) {
|
3368
|
+
console.error("Could not get summary (connection error?):", e);
|
3369
|
+
return {
|
3370
|
+
error: {
|
3371
|
+
message: `Could not get summary. Error: ${e instanceof Error ? e.message : JSON.stringify(e)}`
|
3372
|
+
}
|
3373
|
+
};
|
3374
|
+
}
|
3375
|
+
}
|
3299
3376
|
async getStat(params) {
|
3300
3377
|
if (!(params !== null && params !== void 0 && params.profileId)) {
|
3301
3378
|
return {
|
@@ -3308,11 +3385,23 @@ class ValOpsHttp extends ValOps {
|
|
3308
3385
|
const currentBaseSha = await this.getBaseSha();
|
3309
3386
|
const currentSchemaSha = await this.getSchemaSha();
|
3310
3387
|
const allPatchData = await this.fetchPatches({
|
3311
|
-
|
3312
|
-
|
3313
|
-
patchIds: undefined,
|
3314
|
-
moduleFilePaths: undefined
|
3388
|
+
excludePatchOps: true,
|
3389
|
+
patchIds: undefined
|
3315
3390
|
});
|
3391
|
+
if ("error" in allPatchData && allPatchData.error && allPatchData.unauthorized) {
|
3392
|
+
return {
|
3393
|
+
type: "error",
|
3394
|
+
error: allPatchData.error,
|
3395
|
+
unauthorized: true
|
3396
|
+
};
|
3397
|
+
}
|
3398
|
+
if ("error" in allPatchData && allPatchData.error && allPatchData.networkError) {
|
3399
|
+
return {
|
3400
|
+
type: "error",
|
3401
|
+
error: allPatchData.error,
|
3402
|
+
networkError: true
|
3403
|
+
};
|
3404
|
+
}
|
3316
3405
|
// We think these errors will be picked up else where (?), so we only return an error here if there are no patches
|
3317
3406
|
if (allPatchData.patches.length === 0) {
|
3318
3407
|
let message;
|
@@ -3359,7 +3448,7 @@ class ValOpsHttp extends ValOps {
|
|
3359
3448
|
};
|
3360
3449
|
}
|
3361
3450
|
async getWebSocketNonce(profileId) {
|
3362
|
-
return fetch(`${this.
|
3451
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/websocket/nonces`, {
|
3363
3452
|
method: "POST",
|
3364
3453
|
body: JSON.stringify({
|
3365
3454
|
branch: this.branch,
|
@@ -3436,16 +3525,12 @@ class ValOpsHttp extends ValOps {
|
|
3436
3525
|
if (patchIds === undefined || patchIds.length === 0) {
|
3437
3526
|
return this.fetchPatchesInternal({
|
3438
3527
|
patchIds: patchIds,
|
3439
|
-
|
3440
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3441
|
-
omitPatch: filters.omitPatch
|
3528
|
+
excludePatchOps: filters.excludePatchOps
|
3442
3529
|
});
|
3443
3530
|
}
|
3444
3531
|
for (const res of await Promise.all(patchIdChunks.map(patchIdChunk => this.fetchPatchesInternal({
|
3445
3532
|
patchIds: patchIdChunk,
|
3446
|
-
|
3447
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3448
|
-
omitPatch: filters.omitPatch
|
3533
|
+
excludePatchOps: filters.excludePatchOps
|
3449
3534
|
})))) {
|
3450
3535
|
if ("error" in res) {
|
3451
3536
|
return res;
|
@@ -3463,72 +3548,97 @@ class ValOpsHttp extends ValOps {
|
|
3463
3548
|
async fetchPatchesInternal(filters) {
|
3464
3549
|
const params = [];
|
3465
3550
|
params.push(["branch", this.branch]);
|
3551
|
+
params.push(["commit", this.commitSha]);
|
3466
3552
|
if (filters.patchIds) {
|
3467
3553
|
for (const patchId of filters.patchIds) {
|
3468
3554
|
params.push(["patch_id", patchId]);
|
3469
3555
|
}
|
3470
3556
|
}
|
3471
|
-
if (filters.
|
3472
|
-
|
3473
|
-
params.push(["author_id", author]);
|
3474
|
-
}
|
3475
|
-
}
|
3476
|
-
if (filters.omitPatch) {
|
3477
|
-
params.push(["omit_patch", "true"]);
|
3478
|
-
}
|
3479
|
-
if (filters.moduleFilePaths) {
|
3480
|
-
for (const moduleFilePath of filters.moduleFilePaths) {
|
3481
|
-
params.push(["module_file_path", moduleFilePath]);
|
3482
|
-
}
|
3557
|
+
if (filters.excludePatchOps) {
|
3558
|
+
params.push(["exclude_patch_ops", "true"]);
|
3483
3559
|
}
|
3484
3560
|
const searchParams = new URLSearchParams(params);
|
3485
|
-
|
3486
|
-
|
3487
|
-
|
3488
|
-
|
3489
|
-
}
|
3490
|
-
}).then(async res => {
|
3561
|
+
try {
|
3562
|
+
const patchesRes = await fetch(`${this.contentUrl}/v1/${this.project}/applicable/patches${searchParams.size > 0 ? `?${searchParams.toString()}` : ""}`, {
|
3563
|
+
headers: this.authHeaders
|
3564
|
+
});
|
3491
3565
|
const patches = [];
|
3492
|
-
if (
|
3493
|
-
const json = await
|
3494
|
-
const parsed =
|
3566
|
+
if (patchesRes.ok) {
|
3567
|
+
const json = await patchesRes.json();
|
3568
|
+
const parsed = GetApplicablePatches.safeParse(json);
|
3495
3569
|
if (parsed.success) {
|
3496
3570
|
const errors = [];
|
3497
3571
|
const data = parsed.data;
|
3498
3572
|
for (const patchesRes of data.patches) {
|
3573
|
+
var _patchesRes$applied;
|
3499
3574
|
patches.push({
|
3500
3575
|
authorId: patchesRes.authorId,
|
3501
3576
|
createdAt: patchesRes.createdAt,
|
3502
|
-
appliedAt: null,
|
3503
3577
|
patchId: patchesRes.patchId,
|
3504
3578
|
path: patchesRes.path,
|
3505
3579
|
baseSha: patchesRes.baseSha,
|
3506
|
-
patch:
|
3580
|
+
patch: patchesRes.patch,
|
3581
|
+
appliedAt: (_patchesRes$applied = patchesRes.applied) !== null && _patchesRes$applied !== void 0 && _patchesRes$applied.commitSha ? {
|
3582
|
+
commitSha: patchesRes.applied.commitSha
|
3583
|
+
} : null
|
3507
3584
|
});
|
3508
3585
|
}
|
3586
|
+
const commits = [];
|
3587
|
+
if (data.commits) {
|
3588
|
+
for (const commit of data.commits) {
|
3589
|
+
commits.push({
|
3590
|
+
commitSha: commit.commitSha,
|
3591
|
+
clientCommitSha: commit.clientCommitSha,
|
3592
|
+
parentCommitSha: commit.parentCommitSha,
|
3593
|
+
branch: commit.branch,
|
3594
|
+
creator: commit.creator,
|
3595
|
+
createdAt: commit.createdAt
|
3596
|
+
});
|
3597
|
+
}
|
3598
|
+
}
|
3509
3599
|
return {
|
3600
|
+
commits,
|
3510
3601
|
patches,
|
3511
3602
|
errors
|
3512
3603
|
};
|
3513
3604
|
}
|
3605
|
+
console.error("Could not parse patches response. Error: " + zodValidationError.fromError(parsed.error));
|
3606
|
+
return {
|
3607
|
+
patches,
|
3608
|
+
error: {
|
3609
|
+
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.`
|
3610
|
+
}
|
3611
|
+
};
|
3612
|
+
}
|
3613
|
+
console.error("Could not get patches. HTTP error: " + patchesRes.status + " " + patchesRes.statusText);
|
3614
|
+
if (patchesRes.status === 401) {
|
3514
3615
|
return {
|
3515
3616
|
patches,
|
3516
3617
|
error: {
|
3517
|
-
message:
|
3618
|
+
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."
|
3518
3619
|
}
|
3519
3620
|
};
|
3520
3621
|
}
|
3521
3622
|
return {
|
3522
3623
|
patches,
|
3523
3624
|
error: {
|
3524
|
-
message: "Could not
|
3625
|
+
message: "Could not your changes. It is most likely due to a network issue. Check your network connection and please try again."
|
3525
3626
|
}
|
3526
3627
|
};
|
3527
|
-
})
|
3628
|
+
} catch (err) {
|
3629
|
+
console.error("Could not get patches (connection error):", err instanceof Error ? err.message : JSON.stringify(err));
|
3630
|
+
return {
|
3631
|
+
patches: [],
|
3632
|
+
networkError: true,
|
3633
|
+
error: {
|
3634
|
+
message: `Error: ${err instanceof Error ? err.message : JSON.stringify(err)}`
|
3635
|
+
}
|
3636
|
+
};
|
3637
|
+
}
|
3528
3638
|
}
|
3529
3639
|
async saveSourceFilePatch(path, patch, parentRef, authorId) {
|
3530
3640
|
const baseSha = await this.getBaseSha();
|
3531
|
-
return fetch(`${this.
|
3641
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3532
3642
|
method: "POST",
|
3533
3643
|
headers: {
|
3534
3644
|
...this.authHeaders,
|
@@ -3545,7 +3655,7 @@ class ValOpsHttp extends ValOps {
|
|
3545
3655
|
coreVersion: core.Internal.VERSION.core
|
3546
3656
|
})
|
3547
3657
|
}).then(async res => {
|
3548
|
-
var _res$headers$
|
3658
|
+
var _res$headers$get2;
|
3549
3659
|
if (res.ok) {
|
3550
3660
|
const parsed = SavePatchResponse.safeParse(await res.json());
|
3551
3661
|
if (parsed.success) {
|
@@ -3564,7 +3674,7 @@ class ValOpsHttp extends ValOps {
|
|
3564
3674
|
message: "Conflict: " + (await res.text())
|
3565
3675
|
});
|
3566
3676
|
}
|
3567
|
-
if ((_res$headers$
|
3677
|
+
if ((_res$headers$get2 = res.headers.get("Content-Type")) !== null && _res$headers$get2 !== void 0 && _res$headers$get2.includes("application/json")) {
|
3568
3678
|
const json = await res.json();
|
3569
3679
|
return fp.result.err({
|
3570
3680
|
errorType: "other",
|
@@ -3583,7 +3693,45 @@ class ValOpsHttp extends ValOps {
|
|
3583
3693
|
});
|
3584
3694
|
}
|
3585
3695
|
async saveBase64EncodedBinaryFileFromPatch(filePath, parentRef, patchId, data, type, metadata) {
|
3586
|
-
|
3696
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches/${patchId}/files`, {
|
3697
|
+
method: "POST",
|
3698
|
+
headers: {
|
3699
|
+
...this.authHeaders,
|
3700
|
+
"Content-Type": "application/json"
|
3701
|
+
},
|
3702
|
+
body: JSON.stringify({
|
3703
|
+
filePath: filePath,
|
3704
|
+
data,
|
3705
|
+
type,
|
3706
|
+
metadata
|
3707
|
+
})
|
3708
|
+
}).then(async res => {
|
3709
|
+
if (res.ok) {
|
3710
|
+
const parsed = SavePatchFileResponse.safeParse(await res.json());
|
3711
|
+
if (parsed.success) {
|
3712
|
+
return {
|
3713
|
+
patchId: parsed.data.patchId,
|
3714
|
+
filePath: parsed.data.filePath
|
3715
|
+
};
|
3716
|
+
}
|
3717
|
+
return {
|
3718
|
+
error: {
|
3719
|
+
message: `Could not parse save patch file response. Error: ${zodValidationError.fromError(parsed.error)}`
|
3720
|
+
}
|
3721
|
+
};
|
3722
|
+
}
|
3723
|
+
return {
|
3724
|
+
error: {
|
3725
|
+
message: "Could not save patch file. HTTP error: " + res.status + " " + res.statusText
|
3726
|
+
}
|
3727
|
+
};
|
3728
|
+
}).catch(e => {
|
3729
|
+
return {
|
3730
|
+
error: {
|
3731
|
+
message: `Could save source binary file in patch (connection error?): ${e.toString()}`
|
3732
|
+
}
|
3733
|
+
};
|
3734
|
+
});
|
3587
3735
|
}
|
3588
3736
|
async getHttpFiles(files) {
|
3589
3737
|
const params = new URLSearchParams();
|
@@ -3594,7 +3742,7 @@ class ValOpsHttp extends ValOps {
|
|
3594
3742
|
params.set("body_sha",
|
3595
3743
|
// We use this for cache invalidation
|
3596
3744
|
core.Internal.getSHA256Hash(textEncoder.encode(stringifiedFiles)));
|
3597
|
-
return fetch(`${this.
|
3745
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/files?${params}`, {
|
3598
3746
|
method: "PUT",
|
3599
3747
|
// Yes, PUT is weird. Weirder to have a body in a GET request.
|
3600
3748
|
headers: {
|
@@ -3687,7 +3835,7 @@ class ValOpsHttp extends ValOps {
|
|
3687
3835
|
const params = new URLSearchParams();
|
3688
3836
|
params.set("file_path", filePath);
|
3689
3837
|
try {
|
3690
|
-
const metadataRes = await fetch(`${this.
|
3838
|
+
const metadataRes = await fetch(`${this.contentUrl}/v1/${this.project}/patches/${patchId}/files?${params}`, {
|
3691
3839
|
headers: {
|
3692
3840
|
...this.authHeaders,
|
3693
3841
|
"Content-Type": "application/json"
|
@@ -3741,7 +3889,7 @@ class ValOpsHttp extends ValOps {
|
|
3741
3889
|
};
|
3742
3890
|
}
|
3743
3891
|
async deletePatches(patchIds) {
|
3744
|
-
return fetch(`${this.
|
3892
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3745
3893
|
method: "DELETE",
|
3746
3894
|
headers: {
|
3747
3895
|
...this.authHeaders,
|
@@ -3787,11 +3935,44 @@ class ValOpsHttp extends ValOps {
|
|
3787
3935
|
};
|
3788
3936
|
});
|
3789
3937
|
}
|
3790
|
-
async
|
3938
|
+
async getCommitMessage(preparedCommit) {
|
3939
|
+
var _res$headers$get3;
|
3940
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit-summary`, {
|
3941
|
+
method: "POST",
|
3942
|
+
headers: {
|
3943
|
+
...this.authHeaders,
|
3944
|
+
"Content-Type": "application/json"
|
3945
|
+
},
|
3946
|
+
body: JSON.stringify({
|
3947
|
+
patchedSourceFiles: preparedCommit.patchedSourceFiles,
|
3948
|
+
previousSourceFiles: preparedCommit.previousSourceFiles
|
3949
|
+
})
|
3950
|
+
});
|
3951
|
+
if (res.ok) {
|
3952
|
+
const json = await res.json();
|
3953
|
+
return {
|
3954
|
+
commitSummary: json.commitSummary
|
3955
|
+
};
|
3956
|
+
}
|
3957
|
+
if ((_res$headers$get3 = res.headers.get("Content-Type")) !== null && _res$headers$get3 !== void 0 && _res$headers$get3.includes("application/json")) {
|
3958
|
+
const json = await res.json();
|
3959
|
+
return {
|
3960
|
+
error: {
|
3961
|
+
message: json.message
|
3962
|
+
}
|
3963
|
+
};
|
3964
|
+
}
|
3965
|
+
return {
|
3966
|
+
error: {
|
3967
|
+
message: "Could not get commit message. HTTP error: " + res.status + " " + res.statusText
|
3968
|
+
}
|
3969
|
+
};
|
3970
|
+
}
|
3971
|
+
async commit(prepared, message, committer, filesDirectory, newBranch) {
|
3791
3972
|
try {
|
3792
|
-
var _res$headers$
|
3973
|
+
var _res$headers$get4;
|
3793
3974
|
const existingBranch = this.branch;
|
3794
|
-
const res = await fetch(`${this.
|
3975
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit`, {
|
3795
3976
|
method: "POST",
|
3796
3977
|
headers: {
|
3797
3978
|
...this.authHeaders,
|
@@ -3803,6 +3984,7 @@ class ValOpsHttp extends ValOps {
|
|
3803
3984
|
appliedPatches: prepared.appliedPatches,
|
3804
3985
|
commit: this.commitSha,
|
3805
3986
|
root: this.root,
|
3987
|
+
filesDirectory,
|
3806
3988
|
baseSha: await this.getBaseSha(),
|
3807
3989
|
committer,
|
3808
3990
|
message,
|
@@ -3825,7 +4007,7 @@ class ValOpsHttp extends ValOps {
|
|
3825
4007
|
}
|
3826
4008
|
};
|
3827
4009
|
}
|
3828
|
-
if ((_res$headers$
|
4010
|
+
if ((_res$headers$get4 = res.headers.get("Content-Type")) !== null && _res$headers$get4 !== void 0 && _res$headers$get4.includes("application/json")) {
|
3829
4011
|
const json = await res.json();
|
3830
4012
|
if (json.isNotFastForward) {
|
3831
4013
|
return {
|
@@ -3857,8 +4039,8 @@ class ValOpsHttp extends ValOps {
|
|
3857
4039
|
|
3858
4040
|
// #region profiles
|
3859
4041
|
async getProfiles() {
|
3860
|
-
var _res$headers$
|
3861
|
-
const res = await fetch(`${this.
|
4042
|
+
var _res$headers$get5;
|
4043
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/profiles`, {
|
3862
4044
|
headers: {
|
3863
4045
|
...this.authHeaders,
|
3864
4046
|
"Content-Type": "application/json"
|
@@ -3872,7 +4054,7 @@ class ValOpsHttp extends ValOps {
|
|
3872
4054
|
}
|
3873
4055
|
return parsed.data.profiles;
|
3874
4056
|
}
|
3875
|
-
if ((_res$headers$
|
4057
|
+
if ((_res$headers$get5 = res.headers.get("Content-Type")) !== null && _res$headers$get5 !== void 0 && _res$headers$get5.includes("application/json")) {
|
3876
4058
|
const json = await res.json();
|
3877
4059
|
throw Error(`Could not get profiles (status: ${res.status}): ${"message" in json ? json.message : "Unknown error"}`);
|
3878
4060
|
}
|
@@ -3910,6 +4092,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
3910
4092
|
url.searchParams.set("state", token);
|
3911
4093
|
return url.toString();
|
3912
4094
|
};
|
4095
|
+
const commit = options.mode === "http" ? options.commit : undefined;
|
3913
4096
|
const getAppErrorUrl = error => {
|
3914
4097
|
if (!options.project) {
|
3915
4098
|
throw new Error("Project is not set");
|
@@ -4372,6 +4555,22 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4372
4555
|
...req.body,
|
4373
4556
|
profileId: "id" in auth ? auth.id : undefined
|
4374
4557
|
});
|
4558
|
+
if (currentStat.type === "error" && currentStat.networkError) {
|
4559
|
+
return {
|
4560
|
+
status: 503,
|
4561
|
+
json: {
|
4562
|
+
message: "Network error"
|
4563
|
+
}
|
4564
|
+
};
|
4565
|
+
}
|
4566
|
+
if (currentStat.type === "error" && currentStat.unauthorized) {
|
4567
|
+
return {
|
4568
|
+
status: 401,
|
4569
|
+
json: {
|
4570
|
+
message: "Unauthorized"
|
4571
|
+
}
|
4572
|
+
};
|
4573
|
+
}
|
4375
4574
|
if (currentStat.type === "error") {
|
4376
4575
|
return {
|
4377
4576
|
status: 500,
|
@@ -4382,6 +4581,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4382
4581
|
status: 200,
|
4383
4582
|
json: {
|
4384
4583
|
...currentStat,
|
4584
|
+
mode: serverOps instanceof ValOpsFS ? "fs" : serverOps instanceof ValOpsHttp ? "http" : "unknown",
|
4385
4585
|
config: options.config
|
4386
4586
|
}
|
4387
4587
|
};
|
@@ -4409,7 +4609,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4409
4609
|
};
|
4410
4610
|
}
|
4411
4611
|
const patches = req.body.patches;
|
4412
|
-
|
4612
|
+
let parentRef = req.body.parentRef;
|
4413
4613
|
const authorId = "id" in auth ? auth.id : null;
|
4414
4614
|
const newPatchIds = [];
|
4415
4615
|
for (const patch of patches) {
|
@@ -4440,6 +4640,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4440
4640
|
};
|
4441
4641
|
}
|
4442
4642
|
} else {
|
4643
|
+
parentRef = {
|
4644
|
+
type: "patch",
|
4645
|
+
patchId: createPatchRes.value.patchId
|
4646
|
+
};
|
4443
4647
|
newPatchIds.push(createPatchRes.value.patchId);
|
4444
4648
|
}
|
4445
4649
|
}
|
@@ -4447,10 +4651,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4447
4651
|
status: 200,
|
4448
4652
|
json: {
|
4449
4653
|
newPatchIds,
|
4450
|
-
parentRef
|
4451
|
-
type: "patch",
|
4452
|
-
patchId: newPatchIds[newPatchIds.length - 1]
|
4453
|
-
}
|
4654
|
+
parentRef
|
4454
4655
|
}
|
4455
4656
|
};
|
4456
4657
|
},
|
@@ -4475,13 +4676,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4475
4676
|
}
|
4476
4677
|
};
|
4477
4678
|
}
|
4478
|
-
const
|
4479
|
-
const authors = query.author;
|
4679
|
+
const excludePatchOps = query.exclude_patch_ops === true;
|
4480
4680
|
const fetchedPatchesRes = await serverOps.fetchPatches({
|
4481
|
-
authors,
|
4482
4681
|
patchIds: query.patch_id,
|
4483
|
-
|
4484
|
-
moduleFilePaths: query.module_file_path
|
4682
|
+
excludePatchOps: excludePatchOps
|
4485
4683
|
});
|
4486
4684
|
if (fetchedPatchesRes.error) {
|
4487
4685
|
// Error is singular
|
@@ -4662,8 +4860,17 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4662
4860
|
}
|
4663
4861
|
const patchOps = await serverOps.fetchPatches({
|
4664
4862
|
patchIds: undefined,
|
4665
|
-
|
4863
|
+
excludePatchOps: false
|
4666
4864
|
});
|
4865
|
+
// We check authorization here, because it is the first call to the backend
|
4866
|
+
if (patchOps.error && patchOps.unauthorized) {
|
4867
|
+
return {
|
4868
|
+
status: 401,
|
4869
|
+
json: {
|
4870
|
+
message: "Unauthorized"
|
4871
|
+
}
|
4872
|
+
};
|
4873
|
+
}
|
4667
4874
|
const patchAnalysis = serverOps.analyzePatches(patchOps.patches);
|
4668
4875
|
let sourcesRes = await serverOps.getSources();
|
4669
4876
|
const onlyPatchedTreeModules = await serverOps.getSources({
|
@@ -4742,17 +4949,16 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4742
4949
|
},
|
4743
4950
|
"/profiles": {
|
4744
4951
|
GET: async req => {
|
4745
|
-
|
4746
|
-
|
4747
|
-
|
4748
|
-
|
4749
|
-
|
4750
|
-
|
4751
|
-
|
4752
|
-
|
4753
|
-
|
4754
|
-
|
4755
|
-
|
4952
|
+
const cookies = req.cookies;
|
4953
|
+
const auth = getAuth(cookies);
|
4954
|
+
if (auth.error) {
|
4955
|
+
return {
|
4956
|
+
status: 401,
|
4957
|
+
json: {
|
4958
|
+
message: auth.error
|
4959
|
+
}
|
4960
|
+
};
|
4961
|
+
}
|
4756
4962
|
const profiles = await serverOps.getProfiles();
|
4757
4963
|
return {
|
4758
4964
|
status: 200,
|
@@ -4762,6 +4968,49 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4762
4968
|
};
|
4763
4969
|
}
|
4764
4970
|
},
|
4971
|
+
"/commit-summary": {
|
4972
|
+
GET: async req => {
|
4973
|
+
const cookies = req.cookies;
|
4974
|
+
const auth = getAuth(cookies);
|
4975
|
+
if (auth.error) {
|
4976
|
+
return {
|
4977
|
+
status: 401,
|
4978
|
+
json: {
|
4979
|
+
message: auth.error
|
4980
|
+
}
|
4981
|
+
};
|
4982
|
+
}
|
4983
|
+
const query = req.query;
|
4984
|
+
const patchIds = query.patch_id;
|
4985
|
+
const patches = await serverOps.fetchPatches({
|
4986
|
+
patchIds,
|
4987
|
+
excludePatchOps: false
|
4988
|
+
});
|
4989
|
+
const analysis = serverOps.analyzePatches(patches.patches, patches.commits, commit);
|
4990
|
+
const preparedCommit = await serverOps.prepare({
|
4991
|
+
...analysis,
|
4992
|
+
...patches
|
4993
|
+
});
|
4994
|
+
const res = await serverOps.getCommitSummary(preparedCommit);
|
4995
|
+
if (res.error) {
|
4996
|
+
console.error("Failed to summarize", res.error);
|
4997
|
+
return {
|
4998
|
+
status: 400,
|
4999
|
+
json: {
|
5000
|
+
message: res.error.message
|
5001
|
+
}
|
5002
|
+
};
|
5003
|
+
}
|
5004
|
+
return {
|
5005
|
+
status: 200,
|
5006
|
+
json: {
|
5007
|
+
baseSha: await serverOps.getBaseSha(),
|
5008
|
+
patchIds,
|
5009
|
+
commitSummary: res.commitSummary
|
5010
|
+
}
|
5011
|
+
};
|
5012
|
+
}
|
5013
|
+
},
|
4765
5014
|
"/save": {
|
4766
5015
|
POST: async req => {
|
4767
5016
|
const cookies = req.cookies;
|
@@ -4794,9 +5043,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4794
5043
|
} = bodyRes.data;
|
4795
5044
|
const patches = await serverOps.fetchPatches({
|
4796
5045
|
patchIds,
|
4797
|
-
|
5046
|
+
excludePatchOps: false
|
4798
5047
|
});
|
4799
|
-
const analysis = serverOps.analyzePatches(patches.patches);
|
5048
|
+
const analysis = serverOps.analyzePatches(patches.patches, patches.commits, commit);
|
4800
5049
|
const preparedCommit = await serverOps.prepare({
|
4801
5050
|
...analysis,
|
4802
5051
|
...patches
|
@@ -4828,7 +5077,24 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4828
5077
|
};
|
4829
5078
|
} else if (serverOps instanceof ValOpsHttp) {
|
4830
5079
|
if (auth.error === undefined && auth.id) {
|
4831
|
-
|
5080
|
+
var _options$config$ai, _options$config$files;
|
5081
|
+
let message = body.message || "Update content: " + Object.keys(analysis.patchesByModule) + " modules changed";
|
5082
|
+
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)) {
|
5083
|
+
const res = await serverOps.getCommitMessage(preparedCommit);
|
5084
|
+
console.log({
|
5085
|
+
res
|
5086
|
+
});
|
5087
|
+
if (res.error) {
|
5088
|
+
// ignore
|
5089
|
+
console.error("Failed to get commit message", res.error.message);
|
5090
|
+
} else {
|
5091
|
+
message = res.commitSummary;
|
5092
|
+
}
|
5093
|
+
}
|
5094
|
+
console.log({
|
5095
|
+
message
|
5096
|
+
});
|
5097
|
+
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");
|
4832
5098
|
if (commitRes.error) {
|
4833
5099
|
console.error("Failed to commit", commitRes.error);
|
4834
5100
|
if ("isNotFastForward" in commitRes && commitRes.isNotFastForward) {
|