@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
@@ -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,
|
@@ -3046,7 +3051,8 @@ class ValOpsFS extends ValOps {
|
|
3046
3051
|
|
3047
3052
|
// #region profiles
|
3048
3053
|
async getProfiles() {
|
3049
|
-
|
3054
|
+
// We do not have profiles in FS mode
|
3055
|
+
return [];
|
3050
3056
|
}
|
3051
3057
|
|
3052
3058
|
// #region fs file path helpers
|
@@ -3167,7 +3173,7 @@ const textEncoder = new TextEncoder();
|
|
3167
3173
|
const PatchId = z.string().refine(s => !!s); // TODO: validate
|
3168
3174
|
const CommitSha = z.string().refine(s => !!s); // TODO: validate
|
3169
3175
|
z.string().refine(s => !!s); // TODO: validate
|
3170
|
-
|
3176
|
+
z.string().refine(s => !!s); // TODO: validate
|
3171
3177
|
const ModuleFilePath = z.string().refine(s => !!s); // TODO: validate
|
3172
3178
|
const Metadata = z.union([z.object({
|
3173
3179
|
mimeType: z.string(),
|
@@ -3181,20 +3187,28 @@ const MetadataRes = z.object({
|
|
3181
3187
|
metadata: Metadata,
|
3182
3188
|
type: z.union([z.literal("file"), z.literal("image")]).nullable()
|
3183
3189
|
});
|
3184
|
-
const
|
3185
|
-
|
3186
|
-
patchId: PatchId,
|
3187
|
-
authorId: AuthorId.nullable(),
|
3188
|
-
createdAt: z.string().datetime(),
|
3189
|
-
baseSha: z.string()
|
3190
|
+
const SummaryResponse = z.object({
|
3191
|
+
commitSummary: z.string().nullable()
|
3190
3192
|
});
|
3191
|
-
const
|
3192
|
-
patches: z.array(z.
|
3193
|
-
|
3194
|
-
|
3195
|
-
|
3196
|
-
|
3197
|
-
|
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()
|
3198
3212
|
})).optional()
|
3199
3213
|
});
|
3200
3214
|
const FilesResponse = z.object({
|
@@ -3231,7 +3245,7 @@ const DeletePatchesResponse = z.object({
|
|
3231
3245
|
patchId: PatchId
|
3232
3246
|
})).optional()
|
3233
3247
|
});
|
3234
|
-
z.object({
|
3248
|
+
const SavePatchFileResponse = z.object({
|
3235
3249
|
patchId: PatchId,
|
3236
3250
|
filePath: ModuleFilePath
|
3237
3251
|
});
|
@@ -3250,11 +3264,11 @@ const ProfilesResponse = z.object({
|
|
3250
3264
|
}))
|
3251
3265
|
});
|
3252
3266
|
class ValOpsHttp extends ValOps {
|
3253
|
-
constructor(
|
3267
|
+
constructor(contentUrl, project, commitSha,
|
3254
3268
|
// TODO: CommitSha
|
3255
3269
|
branch, apiKey, valModules, options) {
|
3256
3270
|
super(valModules, options);
|
3257
|
-
this.
|
3271
|
+
this.contentUrl = contentUrl;
|
3258
3272
|
this.project = project;
|
3259
3273
|
this.commitSha = commitSha;
|
3260
3274
|
this.branch = branch;
|
@@ -3266,6 +3280,70 @@ class ValOpsHttp extends ValOps {
|
|
3266
3280
|
async onInit() {
|
3267
3281
|
// TODO: unused for now. Implement or remove
|
3268
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
|
+
}
|
3269
3347
|
async getStat(params) {
|
3270
3348
|
if (!(params !== null && params !== void 0 && params.profileId)) {
|
3271
3349
|
return {
|
@@ -3278,11 +3356,23 @@ class ValOpsHttp extends ValOps {
|
|
3278
3356
|
const currentBaseSha = await this.getBaseSha();
|
3279
3357
|
const currentSchemaSha = await this.getSchemaSha();
|
3280
3358
|
const allPatchData = await this.fetchPatches({
|
3281
|
-
|
3282
|
-
|
3283
|
-
patchIds: undefined,
|
3284
|
-
moduleFilePaths: undefined
|
3359
|
+
excludePatchOps: true,
|
3360
|
+
patchIds: undefined
|
3285
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
|
+
}
|
3286
3376
|
// We think these errors will be picked up else where (?), so we only return an error here if there are no patches
|
3287
3377
|
if (allPatchData.patches.length === 0) {
|
3288
3378
|
let message;
|
@@ -3329,7 +3419,7 @@ class ValOpsHttp extends ValOps {
|
|
3329
3419
|
};
|
3330
3420
|
}
|
3331
3421
|
async getWebSocketNonce(profileId) {
|
3332
|
-
return fetch(`${this.
|
3422
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/websocket/nonces`, {
|
3333
3423
|
method: "POST",
|
3334
3424
|
body: JSON.stringify({
|
3335
3425
|
branch: this.branch,
|
@@ -3406,16 +3496,12 @@ class ValOpsHttp extends ValOps {
|
|
3406
3496
|
if (patchIds === undefined || patchIds.length === 0) {
|
3407
3497
|
return this.fetchPatchesInternal({
|
3408
3498
|
patchIds: patchIds,
|
3409
|
-
|
3410
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3411
|
-
omitPatch: filters.omitPatch
|
3499
|
+
excludePatchOps: filters.excludePatchOps
|
3412
3500
|
});
|
3413
3501
|
}
|
3414
3502
|
for (const res of await Promise.all(patchIdChunks.map(patchIdChunk => this.fetchPatchesInternal({
|
3415
3503
|
patchIds: patchIdChunk,
|
3416
|
-
|
3417
|
-
moduleFilePaths: filters.moduleFilePaths,
|
3418
|
-
omitPatch: filters.omitPatch
|
3504
|
+
excludePatchOps: filters.excludePatchOps
|
3419
3505
|
})))) {
|
3420
3506
|
if ("error" in res) {
|
3421
3507
|
return res;
|
@@ -3433,72 +3519,97 @@ class ValOpsHttp extends ValOps {
|
|
3433
3519
|
async fetchPatchesInternal(filters) {
|
3434
3520
|
const params = [];
|
3435
3521
|
params.push(["branch", this.branch]);
|
3522
|
+
params.push(["commit", this.commitSha]);
|
3436
3523
|
if (filters.patchIds) {
|
3437
3524
|
for (const patchId of filters.patchIds) {
|
3438
3525
|
params.push(["patch_id", patchId]);
|
3439
3526
|
}
|
3440
3527
|
}
|
3441
|
-
if (filters.
|
3442
|
-
|
3443
|
-
params.push(["author_id", author]);
|
3444
|
-
}
|
3445
|
-
}
|
3446
|
-
if (filters.omitPatch) {
|
3447
|
-
params.push(["omit_patch", "true"]);
|
3448
|
-
}
|
3449
|
-
if (filters.moduleFilePaths) {
|
3450
|
-
for (const moduleFilePath of filters.moduleFilePaths) {
|
3451
|
-
params.push(["module_file_path", moduleFilePath]);
|
3452
|
-
}
|
3528
|
+
if (filters.excludePatchOps) {
|
3529
|
+
params.push(["exclude_patch_ops", "true"]);
|
3453
3530
|
}
|
3454
3531
|
const searchParams = new URLSearchParams(params);
|
3455
|
-
|
3456
|
-
|
3457
|
-
|
3458
|
-
|
3459
|
-
}
|
3460
|
-
}).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
|
+
});
|
3461
3536
|
const patches = [];
|
3462
|
-
if (
|
3463
|
-
const json = await
|
3464
|
-
const parsed =
|
3537
|
+
if (patchesRes.ok) {
|
3538
|
+
const json = await patchesRes.json();
|
3539
|
+
const parsed = GetApplicablePatches.safeParse(json);
|
3465
3540
|
if (parsed.success) {
|
3466
3541
|
const errors = [];
|
3467
3542
|
const data = parsed.data;
|
3468
3543
|
for (const patchesRes of data.patches) {
|
3544
|
+
var _patchesRes$applied;
|
3469
3545
|
patches.push({
|
3470
3546
|
authorId: patchesRes.authorId,
|
3471
3547
|
createdAt: patchesRes.createdAt,
|
3472
|
-
appliedAt: null,
|
3473
3548
|
patchId: patchesRes.patchId,
|
3474
3549
|
path: patchesRes.path,
|
3475
3550
|
baseSha: patchesRes.baseSha,
|
3476
|
-
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
|
3477
3555
|
});
|
3478
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
|
+
}
|
3479
3570
|
return {
|
3571
|
+
commits,
|
3480
3572
|
patches,
|
3481
3573
|
errors
|
3482
3574
|
};
|
3483
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) {
|
3484
3586
|
return {
|
3485
3587
|
patches,
|
3486
3588
|
error: {
|
3487
|
-
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."
|
3488
3590
|
}
|
3489
3591
|
};
|
3490
3592
|
}
|
3491
3593
|
return {
|
3492
3594
|
patches,
|
3493
3595
|
error: {
|
3494
|
-
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."
|
3495
3597
|
}
|
3496
3598
|
};
|
3497
|
-
})
|
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
|
+
}
|
3498
3609
|
}
|
3499
3610
|
async saveSourceFilePatch(path, patch, parentRef, authorId) {
|
3500
3611
|
const baseSha = await this.getBaseSha();
|
3501
|
-
return fetch(`${this.
|
3612
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3502
3613
|
method: "POST",
|
3503
3614
|
headers: {
|
3504
3615
|
...this.authHeaders,
|
@@ -3515,7 +3626,7 @@ class ValOpsHttp extends ValOps {
|
|
3515
3626
|
coreVersion: Internal.VERSION.core
|
3516
3627
|
})
|
3517
3628
|
}).then(async res => {
|
3518
|
-
var _res$headers$
|
3629
|
+
var _res$headers$get2;
|
3519
3630
|
if (res.ok) {
|
3520
3631
|
const parsed = SavePatchResponse.safeParse(await res.json());
|
3521
3632
|
if (parsed.success) {
|
@@ -3534,7 +3645,7 @@ class ValOpsHttp extends ValOps {
|
|
3534
3645
|
message: "Conflict: " + (await res.text())
|
3535
3646
|
});
|
3536
3647
|
}
|
3537
|
-
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")) {
|
3538
3649
|
const json = await res.json();
|
3539
3650
|
return result.err({
|
3540
3651
|
errorType: "other",
|
@@ -3553,7 +3664,45 @@ class ValOpsHttp extends ValOps {
|
|
3553
3664
|
});
|
3554
3665
|
}
|
3555
3666
|
async saveBase64EncodedBinaryFileFromPatch(filePath, parentRef, patchId, data, type, metadata) {
|
3556
|
-
|
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
|
+
});
|
3557
3706
|
}
|
3558
3707
|
async getHttpFiles(files) {
|
3559
3708
|
const params = new URLSearchParams();
|
@@ -3564,7 +3713,7 @@ class ValOpsHttp extends ValOps {
|
|
3564
3713
|
params.set("body_sha",
|
3565
3714
|
// We use this for cache invalidation
|
3566
3715
|
Internal.getSHA256Hash(textEncoder.encode(stringifiedFiles)));
|
3567
|
-
return fetch(`${this.
|
3716
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/files?${params}`, {
|
3568
3717
|
method: "PUT",
|
3569
3718
|
// Yes, PUT is weird. Weirder to have a body in a GET request.
|
3570
3719
|
headers: {
|
@@ -3657,7 +3806,7 @@ class ValOpsHttp extends ValOps {
|
|
3657
3806
|
const params = new URLSearchParams();
|
3658
3807
|
params.set("file_path", filePath);
|
3659
3808
|
try {
|
3660
|
-
const metadataRes = await fetch(`${this.
|
3809
|
+
const metadataRes = await fetch(`${this.contentUrl}/v1/${this.project}/patches/${patchId}/files?${params}`, {
|
3661
3810
|
headers: {
|
3662
3811
|
...this.authHeaders,
|
3663
3812
|
"Content-Type": "application/json"
|
@@ -3711,7 +3860,7 @@ class ValOpsHttp extends ValOps {
|
|
3711
3860
|
};
|
3712
3861
|
}
|
3713
3862
|
async deletePatches(patchIds) {
|
3714
|
-
return fetch(`${this.
|
3863
|
+
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3715
3864
|
method: "DELETE",
|
3716
3865
|
headers: {
|
3717
3866
|
...this.authHeaders,
|
@@ -3757,11 +3906,44 @@ class ValOpsHttp extends ValOps {
|
|
3757
3906
|
};
|
3758
3907
|
});
|
3759
3908
|
}
|
3760
|
-
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) {
|
3761
3943
|
try {
|
3762
|
-
var _res$headers$
|
3944
|
+
var _res$headers$get4;
|
3763
3945
|
const existingBranch = this.branch;
|
3764
|
-
const res = await fetch(`${this.
|
3946
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/commit`, {
|
3765
3947
|
method: "POST",
|
3766
3948
|
headers: {
|
3767
3949
|
...this.authHeaders,
|
@@ -3773,6 +3955,7 @@ class ValOpsHttp extends ValOps {
|
|
3773
3955
|
appliedPatches: prepared.appliedPatches,
|
3774
3956
|
commit: this.commitSha,
|
3775
3957
|
root: this.root,
|
3958
|
+
filesDirectory,
|
3776
3959
|
baseSha: await this.getBaseSha(),
|
3777
3960
|
committer,
|
3778
3961
|
message,
|
@@ -3795,7 +3978,7 @@ class ValOpsHttp extends ValOps {
|
|
3795
3978
|
}
|
3796
3979
|
};
|
3797
3980
|
}
|
3798
|
-
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")) {
|
3799
3982
|
const json = await res.json();
|
3800
3983
|
if (json.isNotFastForward) {
|
3801
3984
|
return {
|
@@ -3827,8 +4010,8 @@ class ValOpsHttp extends ValOps {
|
|
3827
4010
|
|
3828
4011
|
// #region profiles
|
3829
4012
|
async getProfiles() {
|
3830
|
-
var _res$headers$
|
3831
|
-
const res = await fetch(`${this.
|
4013
|
+
var _res$headers$get5;
|
4014
|
+
const res = await fetch(`${this.contentUrl}/v1/${this.project}/profiles`, {
|
3832
4015
|
headers: {
|
3833
4016
|
...this.authHeaders,
|
3834
4017
|
"Content-Type": "application/json"
|
@@ -3842,7 +4025,7 @@ class ValOpsHttp extends ValOps {
|
|
3842
4025
|
}
|
3843
4026
|
return parsed.data.profiles;
|
3844
4027
|
}
|
3845
|
-
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")) {
|
3846
4029
|
const json = await res.json();
|
3847
4030
|
throw Error(`Could not get profiles (status: ${res.status}): ${"message" in json ? json.message : "Unknown error"}`);
|
3848
4031
|
}
|
@@ -3880,6 +4063,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
3880
4063
|
url.searchParams.set("state", token);
|
3881
4064
|
return url.toString();
|
3882
4065
|
};
|
4066
|
+
const commit = options.mode === "http" ? options.commit : undefined;
|
3883
4067
|
const getAppErrorUrl = error => {
|
3884
4068
|
if (!options.project) {
|
3885
4069
|
throw new Error("Project is not set");
|
@@ -4342,6 +4526,22 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4342
4526
|
...req.body,
|
4343
4527
|
profileId: "id" in auth ? auth.id : undefined
|
4344
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
|
+
}
|
4345
4545
|
if (currentStat.type === "error") {
|
4346
4546
|
return {
|
4347
4547
|
status: 500,
|
@@ -4352,6 +4552,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4352
4552
|
status: 200,
|
4353
4553
|
json: {
|
4354
4554
|
...currentStat,
|
4555
|
+
mode: serverOps instanceof ValOpsFS ? "fs" : serverOps instanceof ValOpsHttp ? "http" : "unknown",
|
4355
4556
|
config: options.config
|
4356
4557
|
}
|
4357
4558
|
};
|
@@ -4379,7 +4580,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4379
4580
|
};
|
4380
4581
|
}
|
4381
4582
|
const patches = req.body.patches;
|
4382
|
-
|
4583
|
+
let parentRef = req.body.parentRef;
|
4383
4584
|
const authorId = "id" in auth ? auth.id : null;
|
4384
4585
|
const newPatchIds = [];
|
4385
4586
|
for (const patch of patches) {
|
@@ -4410,6 +4611,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4410
4611
|
};
|
4411
4612
|
}
|
4412
4613
|
} else {
|
4614
|
+
parentRef = {
|
4615
|
+
type: "patch",
|
4616
|
+
patchId: createPatchRes.value.patchId
|
4617
|
+
};
|
4413
4618
|
newPatchIds.push(createPatchRes.value.patchId);
|
4414
4619
|
}
|
4415
4620
|
}
|
@@ -4417,10 +4622,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4417
4622
|
status: 200,
|
4418
4623
|
json: {
|
4419
4624
|
newPatchIds,
|
4420
|
-
parentRef
|
4421
|
-
type: "patch",
|
4422
|
-
patchId: newPatchIds[newPatchIds.length - 1]
|
4423
|
-
}
|
4625
|
+
parentRef
|
4424
4626
|
}
|
4425
4627
|
};
|
4426
4628
|
},
|
@@ -4445,13 +4647,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4445
4647
|
}
|
4446
4648
|
};
|
4447
4649
|
}
|
4448
|
-
const
|
4449
|
-
const authors = query.author;
|
4650
|
+
const excludePatchOps = query.exclude_patch_ops === true;
|
4450
4651
|
const fetchedPatchesRes = await serverOps.fetchPatches({
|
4451
|
-
authors,
|
4452
4652
|
patchIds: query.patch_id,
|
4453
|
-
|
4454
|
-
moduleFilePaths: query.module_file_path
|
4653
|
+
excludePatchOps: excludePatchOps
|
4455
4654
|
});
|
4456
4655
|
if (fetchedPatchesRes.error) {
|
4457
4656
|
// Error is singular
|
@@ -4632,8 +4831,17 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4632
4831
|
}
|
4633
4832
|
const patchOps = await serverOps.fetchPatches({
|
4634
4833
|
patchIds: undefined,
|
4635
|
-
|
4834
|
+
excludePatchOps: false
|
4636
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
|
+
}
|
4637
4845
|
const patchAnalysis = serverOps.analyzePatches(patchOps.patches);
|
4638
4846
|
let sourcesRes = await serverOps.getSources();
|
4639
4847
|
const onlyPatchedTreeModules = await serverOps.getSources({
|
@@ -4712,17 +4920,16 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4712
4920
|
},
|
4713
4921
|
"/profiles": {
|
4714
4922
|
GET: async req => {
|
4715
|
-
|
4716
|
-
|
4717
|
-
|
4718
|
-
|
4719
|
-
|
4720
|
-
|
4721
|
-
|
4722
|
-
|
4723
|
-
|
4724
|
-
|
4725
|
-
|
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
|
+
}
|
4726
4933
|
const profiles = await serverOps.getProfiles();
|
4727
4934
|
return {
|
4728
4935
|
status: 200,
|
@@ -4732,6 +4939,49 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4732
4939
|
};
|
4733
4940
|
}
|
4734
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
|
+
},
|
4735
4985
|
"/save": {
|
4736
4986
|
POST: async req => {
|
4737
4987
|
const cookies = req.cookies;
|
@@ -4764,9 +5014,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4764
5014
|
} = bodyRes.data;
|
4765
5015
|
const patches = await serverOps.fetchPatches({
|
4766
5016
|
patchIds,
|
4767
|
-
|
5017
|
+
excludePatchOps: false
|
4768
5018
|
});
|
4769
|
-
const analysis = serverOps.analyzePatches(patches.patches);
|
5019
|
+
const analysis = serverOps.analyzePatches(patches.patches, patches.commits, commit);
|
4770
5020
|
const preparedCommit = await serverOps.prepare({
|
4771
5021
|
...analysis,
|
4772
5022
|
...patches
|
@@ -4798,7 +5048,24 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4798
5048
|
};
|
4799
5049
|
} else if (serverOps instanceof ValOpsHttp) {
|
4800
5050
|
if (auth.error === undefined && auth.id) {
|
4801
|
-
|
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");
|
4802
5069
|
if (commitRes.error) {
|
4803
5070
|
console.error("Failed to commit", commitRes.error);
|
4804
5071
|
if ("isNotFastForward" in commitRes && commitRes.isNotFastForward) {
|