@valbuild/server 0.68.1 → 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 +380 -113
- package/dist/valbuild-server.cjs.prod.js +380 -113
- package/dist/valbuild-server.esm.js +380 -113
- 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,
|
@@ -3075,7 +3080,8 @@ class ValOpsFS extends ValOps {
|
|
3075
3080
|
|
3076
3081
|
// #region profiles
|
3077
3082
|
async getProfiles() {
|
3078
|
-
|
3083
|
+
// We do not have profiles in FS mode
|
3084
|
+
return [];
|
3079
3085
|
}
|
3080
3086
|
|
3081
3087
|
// #region fs file path helpers
|
@@ -3196,7 +3202,7 @@ const textEncoder = new TextEncoder();
|
|
3196
3202
|
const PatchId = zod.z.string().refine(s => !!s); // TODO: validate
|
3197
3203
|
const CommitSha = zod.z.string().refine(s => !!s); // TODO: validate
|
3198
3204
|
zod.z.string().refine(s => !!s); // TODO: validate
|
3199
|
-
|
3205
|
+
zod.z.string().refine(s => !!s); // TODO: validate
|
3200
3206
|
const ModuleFilePath = zod.z.string().refine(s => !!s); // TODO: validate
|
3201
3207
|
const Metadata = zod.z.union([zod.z.object({
|
3202
3208
|
mimeType: zod.z.string(),
|
@@ -3210,20 +3216,28 @@ const MetadataRes = zod.z.object({
|
|
3210
3216
|
metadata: Metadata,
|
3211
3217
|
type: zod.z.union([zod.z.literal("file"), zod.z.literal("image")]).nullable()
|
3212
3218
|
});
|
3213
|
-
const
|
3214
|
-
|
3215
|
-
patchId: PatchId,
|
3216
|
-
authorId: AuthorId.nullable(),
|
3217
|
-
createdAt: zod.z.string().datetime(),
|
3218
|
-
baseSha: zod.z.string()
|
3219
|
+
const SummaryResponse = zod.z.object({
|
3220
|
+
commitSummary: zod.z.string().nullable()
|
3219
3221
|
});
|
3220
|
-
const
|
3221
|
-
patches: zod.z.array(zod.z.
|
3222
|
-
|
3223
|
-
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
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()
|
3227
3241
|
})).optional()
|
3228
3242
|
});
|
3229
3243
|
const FilesResponse = zod.z.object({
|
@@ -3260,7 +3274,7 @@ const DeletePatchesResponse = zod.z.object({
|
|
3260
3274
|
patchId: PatchId
|
3261
3275
|
})).optional()
|
3262
3276
|
});
|
3263
|
-
zod.z.object({
|
3277
|
+
const SavePatchFileResponse = zod.z.object({
|
3264
3278
|
patchId: PatchId,
|
3265
3279
|
filePath: ModuleFilePath
|
3266
3280
|
});
|
@@ -3279,11 +3293,11 @@ const ProfilesResponse = zod.z.object({
|
|
3279
3293
|
}))
|
3280
3294
|
});
|
3281
3295
|
class ValOpsHttp extends ValOps {
|
3282
|
-
constructor(
|
3296
|
+
constructor(contentUrl, project, commitSha,
|
3283
3297
|
// TODO: CommitSha
|
3284
3298
|
branch, apiKey, valModules, options) {
|
3285
3299
|
super(valModules, options);
|
3286
|
-
this.
|
3300
|
+
this.contentUrl = contentUrl;
|
3287
3301
|
this.project = project;
|
3288
3302
|
this.commitSha = commitSha;
|
3289
3303
|
this.branch = branch;
|
@@ -3295,6 +3309,70 @@ class ValOpsHttp extends ValOps {
|
|
3295
3309
|
async onInit() {
|
3296
3310
|
// TODO: unused for now. Implement or remove
|
3297
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
|
+
}
|
3298
3376
|
async getStat(params) {
|
3299
3377
|
if (!(params !== null && params !== void 0 && params.profileId)) {
|
3300
3378
|
return {
|
@@ -3307,11 +3385,23 @@ class ValOpsHttp extends ValOps {
|
|
3307
3385
|
const currentBaseSha = await this.getBaseSha();
|
3308
3386
|
const currentSchemaSha = await this.getSchemaSha();
|
3309
3387
|
const allPatchData = await this.fetchPatches({
|
3310
|
-
|
3311
|
-
|
3312
|
-
patchIds: undefined,
|
3313
|
-
moduleFilePaths: undefined
|
3388
|
+
excludePatchOps: true,
|
3389
|
+
patchIds: undefined
|
3314
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
|
+
}
|
3315
3405
|
// We think these errors will be picked up else where (?), so we only return an error here if there are no patches
|
3316
3406
|
if (allPatchData.patches.length === 0) {
|
3317
3407
|
let message;
|
@@ -3358,7 +3448,7 @@ class ValOpsHttp extends ValOps {
|
|
3358
3448
|
};
|
3359
3449
|
}
|
3360
3450
|
async getWebSocketNonce(profileId) {
|
3361
|
-
return fetch(`${this.
|
3451
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/websocket/nonces`, {
|
3362
3452
|
method: "POST",
|
3363
3453
|
body: JSON.stringify({
|
3364
3454
|
branch: this.branch,
|
@@ -3435,16 +3525,12 @@ class ValOpsHttp extends ValOps {
|
|
3435
3525
|
if (patchIds === undefined || patchIds.length === 0) {
|
3436
3526
|
return this.fetchPatchesInternal({
|
3437
3527
|
patchIds: patchIds,
|
3438
|
-
|
3439
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3440
|
-
omitPatch: filters.omitPatch
|
3528
|
+
excludePatchOps: filters.excludePatchOps
|
3441
3529
|
});
|
3442
3530
|
}
|
3443
3531
|
for (const res of await Promise.all(patchIdChunks.map(patchIdChunk => this.fetchPatchesInternal({
|
3444
3532
|
patchIds: patchIdChunk,
|
3445
|
-
|
3446
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3447
|
-
omitPatch: filters.omitPatch
|
3533
|
+
excludePatchOps: filters.excludePatchOps
|
3448
3534
|
})))) {
|
3449
3535
|
if ("error" in res) {
|
3450
3536
|
return res;
|
@@ -3462,72 +3548,97 @@ class ValOpsHttp extends ValOps {
|
|
3462
3548
|
async fetchPatchesInternal(filters) {
|
3463
3549
|
const params = [];
|
3464
3550
|
params.push(["branch", this.branch]);
|
3551
|
+
params.push(["commit", this.commitSha]);
|
3465
3552
|
if (filters.patchIds) {
|
3466
3553
|
for (const patchId of filters.patchIds) {
|
3467
3554
|
params.push(["patch_id", patchId]);
|
3468
3555
|
}
|
3469
3556
|
}
|
3470
|
-
if (filters.
|
3471
|
-
|
3472
|
-
params.push(["author_id", author]);
|
3473
|
-
}
|
3474
|
-
}
|
3475
|
-
if (filters.omitPatch) {
|
3476
|
-
params.push(["omit_patch", "true"]);
|
3477
|
-
}
|
3478
|
-
if (filters.moduleFilePaths) {
|
3479
|
-
for (const moduleFilePath of filters.moduleFilePaths) {
|
3480
|
-
params.push(["module_file_path", moduleFilePath]);
|
3481
|
-
}
|
3557
|
+
if (filters.excludePatchOps) {
|
3558
|
+
params.push(["exclude_patch_ops", "true"]);
|
3482
3559
|
}
|
3483
3560
|
const searchParams = new URLSearchParams(params);
|
3484
|
-
|
3485
|
-
|
3486
|
-
|
3487
|
-
|
3488
|
-
}
|
3489
|
-
}).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
|
+
});
|
3490
3565
|
const patches = [];
|
3491
|
-
if (
|
3492
|
-
const json = await
|
3493
|
-
const parsed =
|
3566
|
+
if (patchesRes.ok) {
|
3567
|
+
const json = await patchesRes.json();
|
3568
|
+
const parsed = GetApplicablePatches.safeParse(json);
|
3494
3569
|
if (parsed.success) {
|
3495
3570
|
const errors = [];
|
3496
3571
|
const data = parsed.data;
|
3497
3572
|
for (const patchesRes of data.patches) {
|
3573
|
+
var _patchesRes$applied;
|
3498
3574
|
patches.push({
|
3499
3575
|
authorId: patchesRes.authorId,
|
3500
3576
|
createdAt: patchesRes.createdAt,
|
3501
|
-
appliedAt: null,
|
3502
3577
|
patchId: patchesRes.patchId,
|
3503
3578
|
path: patchesRes.path,
|
3504
3579
|
baseSha: patchesRes.baseSha,
|
3505
|
-
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
|
3506
3584
|
});
|
3507
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
|
+
}
|
3508
3599
|
return {
|
3600
|
+
commits,
|
3509
3601
|
patches,
|
3510
3602
|
errors
|
3511
3603
|
};
|
3512
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) {
|
3513
3615
|
return {
|
3514
3616
|
patches,
|
3515
3617
|
error: {
|
3516
|
-
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."
|
3517
3619
|
}
|
3518
3620
|
};
|
3519
3621
|
}
|
3520
3622
|
return {
|
3521
3623
|
patches,
|
3522
3624
|
error: {
|
3523
|
-
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."
|
3524
3626
|
}
|
3525
3627
|
};
|
3526
|
-
})
|
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
|
+
}
|
3527
3638
|
}
|
3528
3639
|
async saveSourceFilePatch(path, patch, parentRef, authorId) {
|
3529
3640
|
const baseSha = await this.getBaseSha();
|
3530
|
-
return fetch(`${this.
|
3641
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3531
3642
|
method: "POST",
|
3532
3643
|
headers: {
|
3533
3644
|
...this.authHeaders,
|
@@ -3544,7 +3655,7 @@ class ValOpsHttp extends ValOps {
|
|
3544
3655
|
coreVersion: core.Internal.VERSION.core
|
3545
3656
|
})
|
3546
3657
|
}).then(async res => {
|
3547
|
-
var _res$headers$
|
3658
|
+
var _res$headers$get2;
|
3548
3659
|
if (res.ok) {
|
3549
3660
|
const parsed = SavePatchResponse.safeParse(await res.json());
|
3550
3661
|
if (parsed.success) {
|
@@ -3563,7 +3674,7 @@ class ValOpsHttp extends ValOps {
|
|
3563
3674
|
message: "Conflict: " + (await res.text())
|
3564
3675
|
});
|
3565
3676
|
}
|
3566
|
-
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")) {
|
3567
3678
|
const json = await res.json();
|
3568
3679
|
return fp.result.err({
|
3569
3680
|
errorType: "other",
|
@@ -3582,7 +3693,45 @@ class ValOpsHttp extends ValOps {
|
|
3582
3693
|
});
|
3583
3694
|
}
|
3584
3695
|
async saveBase64EncodedBinaryFileFromPatch(filePath, parentRef, patchId, data, type, metadata) {
|
3585
|
-
|
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
|
+
});
|
3586
3735
|
}
|
3587
3736
|
async getHttpFiles(files) {
|
3588
3737
|
const params = new URLSearchParams();
|
@@ -3593,7 +3742,7 @@ class ValOpsHttp extends ValOps {
|
|
3593
3742
|
params.set("body_sha",
|
3594
3743
|
// We use this for cache invalidation
|
3595
3744
|
core.Internal.getSHA256Hash(textEncoder.encode(stringifiedFiles)));
|
3596
|
-
return fetch(`${this.
|
3745
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/files?${params}`, {
|
3597
3746
|
method: "PUT",
|
3598
3747
|
// Yes, PUT is weird. Weirder to have a body in a GET request.
|
3599
3748
|
headers: {
|
@@ -3686,7 +3835,7 @@ class ValOpsHttp extends ValOps {
|
|
3686
3835
|
const params = new URLSearchParams();
|
3687
3836
|
params.set("file_path", filePath);
|
3688
3837
|
try {
|
3689
|
-
const metadataRes = await fetch(`${this.
|
3838
|
+
const metadataRes = await fetch(`${this.contentUrl}/v1/${this.project}/patches/${patchId}/files?${params}`, {
|
3690
3839
|
headers: {
|
3691
3840
|
...this.authHeaders,
|
3692
3841
|
"Content-Type": "application/json"
|
@@ -3740,7 +3889,7 @@ class ValOpsHttp extends ValOps {
|
|
3740
3889
|
};
|
3741
3890
|
}
|
3742
3891
|
async deletePatches(patchIds) {
|
3743
|
-
return fetch(`${this.
|
3892
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3744
3893
|
method: "DELETE",
|
3745
3894
|
headers: {
|
3746
3895
|
...this.authHeaders,
|
@@ -3786,11 +3935,44 @@ class ValOpsHttp extends ValOps {
|
|
3786
3935
|
};
|
3787
3936
|
});
|
3788
3937
|
}
|
3789
|
-
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) {
|
3790
3972
|
try {
|
3791
|
-
var _res$headers$
|
3973
|
+
var _res$headers$get4;
|
3792
3974
|
const existingBranch = this.branch;
|
3793
|
-
const res = await fetch(`${this.
|
3975
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit`, {
|
3794
3976
|
method: "POST",
|
3795
3977
|
headers: {
|
3796
3978
|
...this.authHeaders,
|
@@ -3802,6 +3984,7 @@ class ValOpsHttp extends ValOps {
|
|
3802
3984
|
appliedPatches: prepared.appliedPatches,
|
3803
3985
|
commit: this.commitSha,
|
3804
3986
|
root: this.root,
|
3987
|
+
filesDirectory,
|
3805
3988
|
baseSha: await this.getBaseSha(),
|
3806
3989
|
committer,
|
3807
3990
|
message,
|
@@ -3824,7 +4007,7 @@ class ValOpsHttp extends ValOps {
|
|
3824
4007
|
}
|
3825
4008
|
};
|
3826
4009
|
}
|
3827
|
-
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")) {
|
3828
4011
|
const json = await res.json();
|
3829
4012
|
if (json.isNotFastForward) {
|
3830
4013
|
return {
|
@@ -3856,8 +4039,8 @@ class ValOpsHttp extends ValOps {
|
|
3856
4039
|
|
3857
4040
|
// #region profiles
|
3858
4041
|
async getProfiles() {
|
3859
|
-
var _res$headers$
|
3860
|
-
const res = await fetch(`${this.
|
4042
|
+
var _res$headers$get5;
|
4043
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/profiles`, {
|
3861
4044
|
headers: {
|
3862
4045
|
...this.authHeaders,
|
3863
4046
|
"Content-Type": "application/json"
|
@@ -3871,7 +4054,7 @@ class ValOpsHttp extends ValOps {
|
|
3871
4054
|
}
|
3872
4055
|
return parsed.data.profiles;
|
3873
4056
|
}
|
3874
|
-
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")) {
|
3875
4058
|
const json = await res.json();
|
3876
4059
|
throw Error(`Could not get profiles (status: ${res.status}): ${"message" in json ? json.message : "Unknown error"}`);
|
3877
4060
|
}
|
@@ -3909,6 +4092,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
3909
4092
|
url.searchParams.set("state", token);
|
3910
4093
|
return url.toString();
|
3911
4094
|
};
|
4095
|
+
const commit = options.mode === "http" ? options.commit : undefined;
|
3912
4096
|
const getAppErrorUrl = error => {
|
3913
4097
|
if (!options.project) {
|
3914
4098
|
throw new Error("Project is not set");
|
@@ -4371,6 +4555,22 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4371
4555
|
...req.body,
|
4372
4556
|
profileId: "id" in auth ? auth.id : undefined
|
4373
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
|
+
}
|
4374
4574
|
if (currentStat.type === "error") {
|
4375
4575
|
return {
|
4376
4576
|
status: 500,
|
@@ -4381,6 +4581,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4381
4581
|
status: 200,
|
4382
4582
|
json: {
|
4383
4583
|
...currentStat,
|
4584
|
+
mode: serverOps instanceof ValOpsFS ? "fs" : serverOps instanceof ValOpsHttp ? "http" : "unknown",
|
4384
4585
|
config: options.config
|
4385
4586
|
}
|
4386
4587
|
};
|
@@ -4408,7 +4609,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4408
4609
|
};
|
4409
4610
|
}
|
4410
4611
|
const patches = req.body.patches;
|
4411
|
-
|
4612
|
+
let parentRef = req.body.parentRef;
|
4412
4613
|
const authorId = "id" in auth ? auth.id : null;
|
4413
4614
|
const newPatchIds = [];
|
4414
4615
|
for (const patch of patches) {
|
@@ -4439,6 +4640,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4439
4640
|
};
|
4440
4641
|
}
|
4441
4642
|
} else {
|
4643
|
+
parentRef = {
|
4644
|
+
type: "patch",
|
4645
|
+
patchId: createPatchRes.value.patchId
|
4646
|
+
};
|
4442
4647
|
newPatchIds.push(createPatchRes.value.patchId);
|
4443
4648
|
}
|
4444
4649
|
}
|
@@ -4446,10 +4651,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4446
4651
|
status: 200,
|
4447
4652
|
json: {
|
4448
4653
|
newPatchIds,
|
4449
|
-
parentRef
|
4450
|
-
type: "patch",
|
4451
|
-
patchId: newPatchIds[newPatchIds.length - 1]
|
4452
|
-
}
|
4654
|
+
parentRef
|
4453
4655
|
}
|
4454
4656
|
};
|
4455
4657
|
},
|
@@ -4474,13 +4676,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4474
4676
|
}
|
4475
4677
|
};
|
4476
4678
|
}
|
4477
|
-
const
|
4478
|
-
const authors = query.author;
|
4679
|
+
const excludePatchOps = query.exclude_patch_ops === true;
|
4479
4680
|
const fetchedPatchesRes = await serverOps.fetchPatches({
|
4480
|
-
authors,
|
4481
4681
|
patchIds: query.patch_id,
|
4482
|
-
|
4483
|
-
moduleFilePaths: query.module_file_path
|
4682
|
+
excludePatchOps: excludePatchOps
|
4484
4683
|
});
|
4485
4684
|
if (fetchedPatchesRes.error) {
|
4486
4685
|
// Error is singular
|
@@ -4661,8 +4860,17 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4661
4860
|
}
|
4662
4861
|
const patchOps = await serverOps.fetchPatches({
|
4663
4862
|
patchIds: undefined,
|
4664
|
-
|
4863
|
+
excludePatchOps: false
|
4665
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
|
+
}
|
4666
4874
|
const patchAnalysis = serverOps.analyzePatches(patchOps.patches);
|
4667
4875
|
let sourcesRes = await serverOps.getSources();
|
4668
4876
|
const onlyPatchedTreeModules = await serverOps.getSources({
|
@@ -4741,17 +4949,16 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4741
4949
|
},
|
4742
4950
|
"/profiles": {
|
4743
4951
|
GET: async req => {
|
4744
|
-
|
4745
|
-
|
4746
|
-
|
4747
|
-
|
4748
|
-
|
4749
|
-
|
4750
|
-
|
4751
|
-
|
4752
|
-
|
4753
|
-
|
4754
|
-
|
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
|
+
}
|
4755
4962
|
const profiles = await serverOps.getProfiles();
|
4756
4963
|
return {
|
4757
4964
|
status: 200,
|
@@ -4761,6 +4968,49 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4761
4968
|
};
|
4762
4969
|
}
|
4763
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
|
+
},
|
4764
5014
|
"/save": {
|
4765
5015
|
POST: async req => {
|
4766
5016
|
const cookies = req.cookies;
|
@@ -4793,9 +5043,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4793
5043
|
} = bodyRes.data;
|
4794
5044
|
const patches = await serverOps.fetchPatches({
|
4795
5045
|
patchIds,
|
4796
|
-
|
5046
|
+
excludePatchOps: false
|
4797
5047
|
});
|
4798
|
-
const analysis = serverOps.analyzePatches(patches.patches);
|
5048
|
+
const analysis = serverOps.analyzePatches(patches.patches, patches.commits, commit);
|
4799
5049
|
const preparedCommit = await serverOps.prepare({
|
4800
5050
|
...analysis,
|
4801
5051
|
...patches
|
@@ -4827,7 +5077,24 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4827
5077
|
};
|
4828
5078
|
} else if (serverOps instanceof ValOpsHttp) {
|
4829
5079
|
if (auth.error === undefined && auth.id) {
|
4830
|
-
|
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");
|
4831
5098
|
if (commitRes.error) {
|
4832
5099
|
console.error("Failed to commit", commitRes.error);
|
4833
5100
|
if ("isNotFastForward" in commitRes && commitRes.isNotFastForward) {
|