@valbuild/server 0.73.2 → 0.75.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 +287 -75
- package/dist/valbuild-server.cjs.prod.js +287 -75
- package/dist/valbuild-server.esm.js +288 -76
- package/package.json +4 -4
@@ -1,7 +1,7 @@
|
|
1
1
|
import { newQuickJSWASMModule } from 'quickjs-emscripten';
|
2
2
|
import ts from 'typescript';
|
3
3
|
import { result, pipe } from '@valbuild/core/fp';
|
4
|
-
import { FILE_REF_PROP, FILE_REF_SUBTYPE_TAG, VAL_EXTENSION, derefPatch, Internal, Schema, ImageSchema, RichTextSchema, FileSchema } from '@valbuild/core';
|
4
|
+
import { FILE_REF_PROP, FILE_REF_SUBTYPE_TAG, VAL_EXTENSION, derefPatch, Internal, Schema, ImageSchema, RichTextSchema, FileSchema, DEFAULT_CONTENT_HOST } from '@valbuild/core';
|
5
5
|
import { deepEqual, isNotRoot, PatchError, parseAndValidateArrayIndex, applyPatch, JSONOps, deepClone, sourceToPatchPath } from '@valbuild/core/patch';
|
6
6
|
import * as fsPath from 'path';
|
7
7
|
import fsPath__default from 'path';
|
@@ -1454,7 +1454,11 @@ const tsOps = new TSOps(document => {
|
|
1454
1454
|
class ValOps {
|
1455
1455
|
/** Sources from val modules, immutable (without patches or anything) */
|
1456
1456
|
|
1457
|
-
/** The sha256 / hash of sources +
|
1457
|
+
/** The sha256 / hash of all sources + all schemas + config */
|
1458
|
+
|
1459
|
+
/** The sha256 / hash of all sources */
|
1460
|
+
|
1461
|
+
/** The sha256 / hash of config */
|
1458
1462
|
|
1459
1463
|
/** Schema from val modules, immutable */
|
1460
1464
|
|
@@ -1467,6 +1471,8 @@ class ValOps {
|
|
1467
1471
|
this.baseSha = null;
|
1468
1472
|
this.schemas = null;
|
1469
1473
|
this.schemaSha = null;
|
1474
|
+
this.sourcesSha = null;
|
1475
|
+
this.configSha = null;
|
1470
1476
|
this.modulesErrors = null;
|
1471
1477
|
}
|
1472
1478
|
hash(input) {
|
@@ -1524,7 +1530,7 @@ class ValOps {
|
|
1524
1530
|
|
1525
1531
|
// #region initTree
|
1526
1532
|
async initSources() {
|
1527
|
-
if (this.baseSha === null || this.schemaSha === null || this.sources === null || this.schemas === null || this.modulesErrors === null) {
|
1533
|
+
if (this.baseSha === null || this.sourcesSha === null || this.configSha === null || this.schemaSha === null || this.sources === null || this.schemas === null || this.modulesErrors === null) {
|
1528
1534
|
const currentModulesErrors = [];
|
1529
1535
|
const addModuleError = (message, index, path) => {
|
1530
1536
|
currentModulesErrors[index] = {
|
@@ -1534,8 +1540,10 @@ class ValOps {
|
|
1534
1540
|
};
|
1535
1541
|
const currentSources = {};
|
1536
1542
|
const currentSchemas = {};
|
1537
|
-
|
1538
|
-
let
|
1543
|
+
const configSha = this.hash(JSON.stringify(this.valModules.config));
|
1544
|
+
let sourcesSha = "";
|
1545
|
+
let baseSha = configSha;
|
1546
|
+
let schemaSha = configSha;
|
1539
1547
|
for (let moduleIdx = 0; moduleIdx < this.valModules.modules.length; moduleIdx++) {
|
1540
1548
|
const module = this.valModules.modules[moduleIdx];
|
1541
1549
|
if (!module.def) {
|
@@ -1590,6 +1598,10 @@ class ValOps {
|
|
1590
1598
|
currentSources[pathM] = source;
|
1591
1599
|
currentSchemas[pathM] = schema;
|
1592
1600
|
// make sure the checks above is enough that this does not fail - even if val modules are not set up correctly
|
1601
|
+
sourcesSha = this.hash(sourcesSha + JSON.stringify({
|
1602
|
+
path,
|
1603
|
+
source
|
1604
|
+
}));
|
1593
1605
|
baseSha = this.hash(baseSha + JSON.stringify({
|
1594
1606
|
path,
|
1595
1607
|
schema: serializedSchema,
|
@@ -1603,11 +1615,15 @@ class ValOps {
|
|
1603
1615
|
this.schemas = currentSchemas;
|
1604
1616
|
this.baseSha = baseSha;
|
1605
1617
|
this.schemaSha = schemaSha;
|
1618
|
+
this.sourcesSha = sourcesSha;
|
1619
|
+
this.configSha = configSha;
|
1606
1620
|
this.modulesErrors = currentModulesErrors;
|
1607
1621
|
}
|
1608
1622
|
return {
|
1609
1623
|
baseSha: this.baseSha,
|
1610
1624
|
schemaSha: this.schemaSha,
|
1625
|
+
sourcesSha: this.sourcesSha,
|
1626
|
+
configSha: this.configSha,
|
1611
1627
|
sources: this.sources,
|
1612
1628
|
schemas: this.schemas,
|
1613
1629
|
moduleErrors: this.modulesErrors
|
@@ -1632,6 +1648,12 @@ class ValOps {
|
|
1632
1648
|
async getBaseSha() {
|
1633
1649
|
return this.initSources().then(result => result.baseSha);
|
1634
1650
|
}
|
1651
|
+
async getConfigSha() {
|
1652
|
+
return this.initSources().then(result => result.configSha);
|
1653
|
+
}
|
1654
|
+
async getSourcesSha() {
|
1655
|
+
return this.initSources().then(result => result.sourcesSha);
|
1656
|
+
}
|
1635
1657
|
async getSchemaSha() {
|
1636
1658
|
return this.initSources().then(result => result.schemaSha);
|
1637
1659
|
}
|
@@ -2191,7 +2213,7 @@ class ValOps {
|
|
2191
2213
|
}
|
2192
2214
|
|
2193
2215
|
// #region createPatch
|
2194
|
-
async createPatch(path, patch, parentRef, authorId) {
|
2216
|
+
async createPatch(path, patch, patchId, parentRef, authorId) {
|
2195
2217
|
const initTree = await this.initSources();
|
2196
2218
|
const schemas = initTree.schemas;
|
2197
2219
|
const moduleErrors = initTree.moduleErrors;
|
@@ -2280,7 +2302,7 @@ class ValOps {
|
|
2280
2302
|
}
|
2281
2303
|
}
|
2282
2304
|
}
|
2283
|
-
const saveRes = await this.saveSourceFilePatch(path, patch, parentRef, authorId);
|
2305
|
+
const saveRes = await this.saveSourceFilePatch(path, patch, patchId, parentRef, authorId);
|
2284
2306
|
if (result.isErr(saveRes)) {
|
2285
2307
|
console.error(`Could not save source patch at path: '${path}'. Error: ${saveRes.error.errorType === "other" ? saveRes.error.message : saveRes.error.errorType}`);
|
2286
2308
|
if (saveRes.error.errorType === "patch-head-conflict") {
|
@@ -2293,7 +2315,6 @@ class ValOps {
|
|
2293
2315
|
error: saveRes.error
|
2294
2316
|
});
|
2295
2317
|
}
|
2296
|
-
const patchId = saveRes.value.patchId;
|
2297
2318
|
const saveFileRes = await Promise.all(Object.entries(files).map(async ([filePath, data]) => {
|
2298
2319
|
if (data.error) {
|
2299
2320
|
return {
|
@@ -2603,6 +2624,7 @@ class ValOpsFS extends ValOps {
|
|
2603
2624
|
var _this$options, _this$options2;
|
2604
2625
|
const currentBaseSha = await this.getBaseSha();
|
2605
2626
|
const currentSchemaSha = await this.getSchemaSha();
|
2627
|
+
const currentSourcesSha = await this.getSourcesSha();
|
2606
2628
|
const moduleFilePaths = Object.keys(await this.getSchemas());
|
2607
2629
|
const patchData = await this.readPatches();
|
2608
2630
|
const patches = [];
|
@@ -2613,12 +2635,15 @@ class ValOpsFS extends ValOps {
|
|
2613
2635
|
patches.push(patchId);
|
2614
2636
|
}
|
2615
2637
|
// something changed: return immediately
|
2616
|
-
const didChange = !params || currentBaseSha !== params.baseSha ||
|
2638
|
+
const didChange = !params || currentBaseSha !== params.baseSha ||
|
2639
|
+
// base sha covers both sources sha and schema sha, so we could remove checks for schema sha and sources sha
|
2640
|
+
currentSourcesSha !== params.sourcesSha || currentSchemaSha !== params.schemaSha || patches.length !== params.patches.length || patches.some((p, i) => p !== params.patches[i]);
|
2617
2641
|
if (didChange) {
|
2618
2642
|
return {
|
2619
2643
|
type: "did-change",
|
2620
2644
|
baseSha: currentBaseSha,
|
2621
2645
|
schemaSha: currentSchemaSha,
|
2646
|
+
sourcesSha: currentSourcesSha,
|
2622
2647
|
patches
|
2623
2648
|
};
|
2624
2649
|
}
|
@@ -2732,6 +2757,7 @@ class ValOpsFS extends ValOps {
|
|
2732
2757
|
type,
|
2733
2758
|
baseSha: currentBaseSha,
|
2734
2759
|
schemaSha: currentSchemaSha,
|
2760
|
+
sourcesSha: currentSourcesSha,
|
2735
2761
|
patches
|
2736
2762
|
};
|
2737
2763
|
} catch (err) {
|
@@ -2806,6 +2832,11 @@ class ValOpsFS extends ValOps {
|
|
2806
2832
|
};
|
2807
2833
|
}
|
2808
2834
|
return patchData;
|
2835
|
+
}).filter(patchData => {
|
2836
|
+
if (filters.patchIds && filters.patchIds.length > 0) {
|
2837
|
+
return filters.patchIds.includes(patchData.patchId);
|
2838
|
+
}
|
2839
|
+
return true;
|
2809
2840
|
});
|
2810
2841
|
return {
|
2811
2842
|
patches: sortedPatches,
|
@@ -2942,11 +2973,10 @@ class ValOpsFS extends ValOps {
|
|
2942
2973
|
};
|
2943
2974
|
}
|
2944
2975
|
}
|
2945
|
-
async saveSourceFilePatch(path, patch, parentRef, authorId) {
|
2976
|
+
async saveSourceFilePatch(path, patch, patchId, parentRef, authorId) {
|
2946
2977
|
const patchDir = this.getParentPatchIdFromParentRef(parentRef);
|
2947
2978
|
try {
|
2948
2979
|
const baseSha = await this.getBaseSha();
|
2949
|
-
const patchId = crypto.randomUUID();
|
2950
2980
|
const data = {
|
2951
2981
|
patch,
|
2952
2982
|
patchId,
|
@@ -2957,6 +2987,13 @@ class ValOpsFS extends ValOps {
|
|
2957
2987
|
coreVersion: Internal.VERSION.core,
|
2958
2988
|
createdAt: new Date().toISOString()
|
2959
2989
|
};
|
2990
|
+
const headParentPatchId = "head";
|
2991
|
+
if (patchDir !== headParentPatchId && !this.host.fileExists(this.getPatchFilePath(headParentPatchId))) {
|
2992
|
+
console.error("Val: out-of-band patch detected.", this.getPatchFilePath(headParentPatchId));
|
2993
|
+
return result.err({
|
2994
|
+
errorType: "patch-head-conflict"
|
2995
|
+
});
|
2996
|
+
}
|
2960
2997
|
const writeRes = this.host.tryWriteUf8File(this.getPatchFilePath(patchDir), JSON.stringify(data));
|
2961
2998
|
if (writeRes.type === "error") {
|
2962
2999
|
return writeRes.errorType === "dir-already-exists" ? result.err({
|
@@ -3128,6 +3165,28 @@ class ValOpsFS extends ValOps {
|
|
3128
3165
|
deleted
|
3129
3166
|
};
|
3130
3167
|
}
|
3168
|
+
async deleteAllPatches() {
|
3169
|
+
const patchesCacheDir = this.getPatchesDir();
|
3170
|
+
const tmpDir = fsPath__default.join(this.rootDir, ValOpsFS.VAL_DIR, "patches-deleted-" + crypto.randomUUID());
|
3171
|
+
try {
|
3172
|
+
this.host.moveDir(patchesCacheDir, tmpDir);
|
3173
|
+
this.host.deleteDir(tmpDir);
|
3174
|
+
return {};
|
3175
|
+
} catch (err) {
|
3176
|
+
if (err instanceof Error) {
|
3177
|
+
return {
|
3178
|
+
error: {
|
3179
|
+
message: `Got an error while deleting patches: ${err.message}`
|
3180
|
+
}
|
3181
|
+
};
|
3182
|
+
}
|
3183
|
+
return {
|
3184
|
+
error: {
|
3185
|
+
message: "Got an unexpected error while deleting patches"
|
3186
|
+
}
|
3187
|
+
};
|
3188
|
+
}
|
3189
|
+
}
|
3131
3190
|
updateOrderedPatches(updates, patchDirMap, deletePatchIds) {
|
3132
3191
|
for (const patchId of deletePatchIds) {
|
3133
3192
|
const patchDir = patchDirMap[patchId];
|
@@ -3170,7 +3229,7 @@ class ValOpsFS extends ValOps {
|
|
3170
3229
|
}
|
3171
3230
|
}
|
3172
3231
|
}
|
3173
|
-
async saveOrUploadFiles(preparedCommit,
|
3232
|
+
async saveOrUploadFiles(preparedCommit, mode, auth) {
|
3174
3233
|
const updatedFiles = [];
|
3175
3234
|
const uploadedRemoteRefs = [];
|
3176
3235
|
const errors = {};
|
@@ -3188,42 +3247,50 @@ class ValOpsFS extends ValOps {
|
|
3188
3247
|
}]) => [ref, {
|
3189
3248
|
patchId
|
3190
3249
|
}]);
|
3191
|
-
|
3192
|
-
|
3193
|
-
|
3194
|
-
|
3195
|
-
const splitRemoteRefRes = Internal.remote.splitRemoteRef(ref);
|
3196
|
-
if (splitRemoteRefRes.status === "error") {
|
3197
|
-
errors[ref] = {
|
3198
|
-
message: "Failed to split remote ref: " + ref
|
3250
|
+
if (mode === "upload-remote") {
|
3251
|
+
if (!auth) {
|
3252
|
+
errors["auth"] = {
|
3253
|
+
message: "No auth provided"
|
3199
3254
|
};
|
3200
|
-
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3204
|
-
errors[ref] = {
|
3205
|
-
message: "Failed to get binary file from patch. Ref: " + ref + ". PatchId: " + patchId
|
3206
|
-
};
|
3207
|
-
continue;
|
3208
|
-
}
|
3209
|
-
if (testMode === "test-skip-remote") {
|
3210
|
-
console.log("Skip remote flag enabled. Skipping file upload", ref);
|
3211
|
-
continue;
|
3212
|
-
}
|
3213
|
-
if (!((_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.config.project)) {
|
3214
|
-
errors[ref] = {
|
3215
|
-
message: "No project found in config"
|
3255
|
+
return {
|
3256
|
+
updatedFiles,
|
3257
|
+
uploadedRemoteRefs,
|
3258
|
+
errors
|
3216
3259
|
};
|
3217
|
-
continue;
|
3218
3260
|
}
|
3219
|
-
|
3220
|
-
|
3221
|
-
|
3222
|
-
|
3223
|
-
|
3261
|
+
for (const [ref, {
|
3262
|
+
patchId
|
3263
|
+
}] of remoteFileDescriptors) {
|
3264
|
+
var _this$options4;
|
3265
|
+
const splitRemoteRefRes = Internal.remote.splitRemoteRef(ref);
|
3266
|
+
if (splitRemoteRefRes.status === "error") {
|
3267
|
+
errors[ref] = {
|
3268
|
+
message: "Failed to split remote ref: " + ref
|
3269
|
+
};
|
3270
|
+
continue;
|
3271
|
+
}
|
3272
|
+
const fileBuffer = await this.getBase64EncodedBinaryFileFromPatch(splitRemoteRefRes.filePath, patchId);
|
3273
|
+
if (!fileBuffer) {
|
3274
|
+
errors[ref] = {
|
3275
|
+
message: "Failed to get binary file from patch. Ref: " + ref + ". PatchId: " + patchId
|
3276
|
+
};
|
3277
|
+
continue;
|
3278
|
+
}
|
3279
|
+
if (!((_this$options4 = this.options) !== null && _this$options4 !== void 0 && _this$options4.config.project)) {
|
3280
|
+
errors[ref] = {
|
3281
|
+
message: "No project found in config"
|
3282
|
+
};
|
3283
|
+
continue;
|
3284
|
+
}
|
3285
|
+
console.log("Uploading remote file", ref);
|
3286
|
+
const res = await uploadRemoteFile(this.contentUrl, this.options.config.project, splitRemoteRefRes.bucket, splitRemoteRefRes.fileHash, getFileExt(splitRemoteRefRes.filePath), fileBuffer, auth);
|
3287
|
+
if (!res.success) {
|
3288
|
+
console.error("Failed to upload remote file", ref, res.error);
|
3289
|
+
throw new Error(`Failed to upload remote file: ${ref}. ${res.error}`);
|
3290
|
+
}
|
3291
|
+
console.log("Completed remote file", ref);
|
3292
|
+
uploadedRemoteRefs.push(ref);
|
3224
3293
|
}
|
3225
|
-
console.log("Completed remote file", ref);
|
3226
|
-
uploadedRemoteRefs.push(ref);
|
3227
3294
|
}
|
3228
3295
|
const patchIdToPatchDirMapRes = await this.getParentPatchIdFromPatchIdMap();
|
3229
3296
|
if (result.isErr(patchIdToPatchDirMapRes)) {
|
@@ -3522,9 +3589,17 @@ const GetApplicablePatches = z.object({
|
|
3522
3589
|
commitSha: z.string(),
|
3523
3590
|
clientCommitSha: z.string(),
|
3524
3591
|
parentCommitSha: z.string(),
|
3592
|
+
commitMessage: z.string().nullable(),
|
3525
3593
|
branch: z.string(),
|
3526
3594
|
creator: z.string(),
|
3527
3595
|
createdAt: z.string()
|
3596
|
+
})).optional(),
|
3597
|
+
deployments: z.array(z.object({
|
3598
|
+
deploymentId: z.string(),
|
3599
|
+
commitSha: z.string(),
|
3600
|
+
deploymentState: z.string(),
|
3601
|
+
createdAt: z.string(),
|
3602
|
+
updatedAt: z.string()
|
3528
3603
|
})).optional()
|
3529
3604
|
});
|
3530
3605
|
const FilesResponse = z.object({
|
@@ -3576,6 +3651,8 @@ const ProfilesResponse = z.object({
|
|
3576
3651
|
profiles: z.array(z.object({
|
3577
3652
|
profileId: z.string(),
|
3578
3653
|
fullName: z.string(),
|
3654
|
+
email: z.string().optional(),
|
3655
|
+
// TODO: make this required once this can be guaranteed
|
3579
3656
|
avatar: z.object({
|
3580
3657
|
url: z.string()
|
3581
3658
|
}).nullable()
|
@@ -3673,6 +3750,7 @@ class ValOpsHttp extends ValOps {
|
|
3673
3750
|
}
|
3674
3751
|
const currentBaseSha = await this.getBaseSha();
|
3675
3752
|
const currentSchemaSha = await this.getSchemaSha();
|
3753
|
+
const currentSourcesSha = await this.getSourcesSha();
|
3676
3754
|
const allPatchData = await this.fetchPatches({
|
3677
3755
|
excludePatchOps: true,
|
3678
3756
|
patchIds: undefined
|
@@ -3732,6 +3810,9 @@ class ValOpsHttp extends ValOps {
|
|
3732
3810
|
nonce,
|
3733
3811
|
baseSha: currentBaseSha,
|
3734
3812
|
schemaSha: currentSchemaSha,
|
3813
|
+
sourcesSha: currentSourcesSha,
|
3814
|
+
commits: allPatchData.commits || [],
|
3815
|
+
deployments: allPatchData.deployments || [],
|
3735
3816
|
patches,
|
3736
3817
|
commitSha: this.commitSha
|
3737
3818
|
};
|
@@ -3741,7 +3822,8 @@ class ValOpsHttp extends ValOps {
|
|
3741
3822
|
method: "POST",
|
3742
3823
|
body: JSON.stringify({
|
3743
3824
|
branch: this.branch,
|
3744
|
-
profileId
|
3825
|
+
profileId,
|
3826
|
+
commitSha: this.commitSha
|
3745
3827
|
}),
|
3746
3828
|
headers: {
|
3747
3829
|
...this.authHeaders,
|
@@ -3881,12 +3963,26 @@ class ValOpsHttp extends ValOps {
|
|
3881
3963
|
parentCommitSha: commit.parentCommitSha,
|
3882
3964
|
branch: commit.branch,
|
3883
3965
|
creator: commit.creator,
|
3884
|
-
createdAt: commit.createdAt
|
3966
|
+
createdAt: commit.createdAt,
|
3967
|
+
commitMessage: commit.commitMessage
|
3968
|
+
});
|
3969
|
+
}
|
3970
|
+
}
|
3971
|
+
const deployments = [];
|
3972
|
+
if (data.deployments) {
|
3973
|
+
for (const deployment of data.deployments) {
|
3974
|
+
deployments.push({
|
3975
|
+
commitSha: deployment.commitSha,
|
3976
|
+
deploymentId: deployment.deploymentId,
|
3977
|
+
deploymentState: deployment.deploymentState,
|
3978
|
+
createdAt: deployment.createdAt,
|
3979
|
+
updatedAt: deployment.updatedAt
|
3885
3980
|
});
|
3886
3981
|
}
|
3887
3982
|
}
|
3888
3983
|
return {
|
3889
3984
|
commits,
|
3985
|
+
deployments,
|
3890
3986
|
patches,
|
3891
3987
|
errors
|
3892
3988
|
};
|
@@ -3925,7 +4021,7 @@ class ValOpsHttp extends ValOps {
|
|
3925
4021
|
};
|
3926
4022
|
}
|
3927
4023
|
}
|
3928
|
-
async saveSourceFilePatch(path, patch, parentRef, authorId) {
|
4024
|
+
async saveSourceFilePatch(path, patch, patchId, parentRef, authorId) {
|
3929
4025
|
const baseSha = await this.getBaseSha();
|
3930
4026
|
return fetch(`${this.contentUrl}/v1/${this.project}/patches`, {
|
3931
4027
|
method: "POST",
|
@@ -3937,6 +4033,7 @@ class ValOpsHttp extends ValOps {
|
|
3937
4033
|
path,
|
3938
4034
|
patch,
|
3939
4035
|
authorId,
|
4036
|
+
patchId,
|
3940
4037
|
parentPatchId: parentRef.type === "patch" ? parentRef.patchId : null,
|
3941
4038
|
baseSha,
|
3942
4039
|
commit: this.commitSha,
|
@@ -4382,7 +4479,7 @@ class ValOpsHttp extends ValOps {
|
|
4382
4479
|
}
|
4383
4480
|
}
|
4384
4481
|
|
4385
|
-
const host = process.env.VAL_CONTENT_URL ||
|
4482
|
+
const host = process.env.VAL_CONTENT_URL || DEFAULT_CONTENT_HOST;
|
4386
4483
|
const SettingsSchema = z.object({
|
4387
4484
|
publicProjectId: z.string(),
|
4388
4485
|
remoteFileBuckets: z.array(z.object({
|
@@ -4485,6 +4582,51 @@ function parsePersonalAccessTokenFile(content) {
|
|
4485
4582
|
}
|
4486
4583
|
}
|
4487
4584
|
|
4585
|
+
/**
|
4586
|
+
* Iterates through all schemas and find if there is 1 or more remote files in them
|
4587
|
+
*/
|
4588
|
+
function hasRemoteFileSchema(schema) {
|
4589
|
+
if (schema.type === "file" || schema.type === "image") {
|
4590
|
+
return !!schema.remote;
|
4591
|
+
} else if (schema.type === "richtext") {
|
4592
|
+
var _schema$options;
|
4593
|
+
if (typeof ((_schema$options = schema.options) === null || _schema$options === void 0 || (_schema$options = _schema$options.inline) === null || _schema$options === void 0 ? void 0 : _schema$options.img) === "object") {
|
4594
|
+
return hasRemoteFileSchema(schema.options.inline.img);
|
4595
|
+
}
|
4596
|
+
return false;
|
4597
|
+
} else if (schema.type === "array" || schema.type === "record") {
|
4598
|
+
return hasRemoteFileSchema(schema.item);
|
4599
|
+
} else if (schema.type === "object") {
|
4600
|
+
for (const key in schema.items) {
|
4601
|
+
const hasRemoteFile = hasRemoteFileSchema(schema.items[key]);
|
4602
|
+
if (hasRemoteFile) {
|
4603
|
+
return true;
|
4604
|
+
}
|
4605
|
+
}
|
4606
|
+
return false;
|
4607
|
+
} else if (schema.type === "union") {
|
4608
|
+
const unionStringSchema = typeof schema.key === "object" && schema.key.type === "literal" ? schema : undefined;
|
4609
|
+
const unionObjectSchema = typeof schema.key === "string" ? schema : undefined;
|
4610
|
+
if (unionStringSchema) {
|
4611
|
+
return false;
|
4612
|
+
}
|
4613
|
+
if (unionObjectSchema) {
|
4614
|
+
for (const key in unionObjectSchema.items) {
|
4615
|
+
const hasRemoteFile = hasRemoteFileSchema(unionObjectSchema.items[key]);
|
4616
|
+
if (hasRemoteFile) {
|
4617
|
+
return true;
|
4618
|
+
}
|
4619
|
+
}
|
4620
|
+
}
|
4621
|
+
return false;
|
4622
|
+
} else if (schema.type === "boolean" || schema.type === "number" || schema.type === "string" || schema.type === "literal" || schema.type === "date" || schema.type === "keyOf") {
|
4623
|
+
return false;
|
4624
|
+
} else {
|
4625
|
+
const exhaustiveCheck = schema;
|
4626
|
+
throw new Error(`Unexpected schema: ${JSON.stringify(exhaustiveCheck)}`);
|
4627
|
+
}
|
4628
|
+
}
|
4629
|
+
|
4488
4630
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
4489
4631
|
const ValServer = (valModules, options, callbacks) => {
|
4490
4632
|
let serverOps;
|
@@ -4655,7 +4797,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
4655
4797
|
apiKey: options.apiKey
|
4656
4798
|
};
|
4657
4799
|
} else if (serverOps instanceof ValOpsFS) {
|
4658
|
-
const projectRootDir = options.config.root;
|
4800
|
+
const projectRootDir = options.config.root || ".";
|
4659
4801
|
if (!projectRootDir) {
|
4660
4802
|
return {
|
4661
4803
|
status: 400,
|
@@ -5009,15 +5151,59 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5009
5151
|
}
|
5010
5152
|
},
|
5011
5153
|
"/logout": {
|
5012
|
-
GET: async
|
5154
|
+
GET: async req => {
|
5155
|
+
const query = req.query;
|
5156
|
+
const redirectTo = query.redirect_to;
|
5157
|
+
if (redirectTo) {
|
5158
|
+
return {
|
5159
|
+
status: 302,
|
5160
|
+
redirectTo: redirectTo,
|
5161
|
+
cookies: {
|
5162
|
+
[VAL_SESSION_COOKIE]: {
|
5163
|
+
value: "empty",
|
5164
|
+
options: {
|
5165
|
+
httpOnly: true,
|
5166
|
+
sameSite: "strict",
|
5167
|
+
path: "/",
|
5168
|
+
secure: true,
|
5169
|
+
expires: new Date(0)
|
5170
|
+
}
|
5171
|
+
},
|
5172
|
+
[VAL_STATE_COOKIE]: {
|
5173
|
+
value: "empty",
|
5174
|
+
options: {
|
5175
|
+
httpOnly: true,
|
5176
|
+
sameSite: "strict",
|
5177
|
+
path: "/",
|
5178
|
+
secure: true,
|
5179
|
+
expires: new Date(0)
|
5180
|
+
}
|
5181
|
+
}
|
5182
|
+
}
|
5183
|
+
};
|
5184
|
+
}
|
5013
5185
|
return {
|
5014
5186
|
status: 200,
|
5015
5187
|
cookies: {
|
5016
5188
|
[VAL_SESSION_COOKIE]: {
|
5017
|
-
value:
|
5189
|
+
value: "empty",
|
5190
|
+
options: {
|
5191
|
+
httpOnly: true,
|
5192
|
+
sameSite: "strict",
|
5193
|
+
path: "/",
|
5194
|
+
secure: true,
|
5195
|
+
expires: new Date(0)
|
5196
|
+
}
|
5018
5197
|
},
|
5019
5198
|
[VAL_STATE_COOKIE]: {
|
5020
|
-
value:
|
5199
|
+
value: "empty",
|
5200
|
+
options: {
|
5201
|
+
httpOnly: true,
|
5202
|
+
sameSite: "strict",
|
5203
|
+
path: "/",
|
5204
|
+
secure: true,
|
5205
|
+
expires: new Date(0)
|
5206
|
+
}
|
5021
5207
|
}
|
5022
5208
|
}
|
5023
5209
|
};
|
@@ -5101,9 +5287,10 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5101
5287
|
}
|
5102
5288
|
};
|
5103
5289
|
}
|
5290
|
+
const profileId = "id" in auth ? auth.id : undefined;
|
5104
5291
|
const currentStat = await serverOps.getStat({
|
5105
5292
|
...req.body,
|
5106
|
-
profileId
|
5293
|
+
profileId
|
5107
5294
|
});
|
5108
5295
|
if (currentStat.type === "error" && currentStat.networkError) {
|
5109
5296
|
return {
|
@@ -5127,11 +5314,21 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5127
5314
|
json: currentStat.error
|
5128
5315
|
};
|
5129
5316
|
}
|
5317
|
+
const mode = serverOps instanceof ValOpsFS ? "fs" : serverOps instanceof ValOpsHttp ? "http" : "unknown";
|
5318
|
+
if (mode === "unknown") {
|
5319
|
+
return {
|
5320
|
+
status: 500,
|
5321
|
+
json: {
|
5322
|
+
message: "Server mode is neither fs nor http - this is an internal Val bug"
|
5323
|
+
}
|
5324
|
+
};
|
5325
|
+
}
|
5130
5326
|
return {
|
5131
5327
|
status: 200,
|
5132
5328
|
json: {
|
5133
5329
|
...currentStat,
|
5134
|
-
|
5330
|
+
profileId: profileId ?? null,
|
5331
|
+
mode,
|
5135
5332
|
config: options.config
|
5136
5333
|
}
|
5137
5334
|
};
|
@@ -5163,7 +5360,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5163
5360
|
const authorId = "id" in auth ? auth.id : null;
|
5164
5361
|
const newPatchIds = [];
|
5165
5362
|
for (const patch of patches) {
|
5166
|
-
const createPatchRes = await serverOps.createPatch(patch.path, patch.patch, parentRef, authorId);
|
5363
|
+
const createPatchRes = await serverOps.createPatch(patch.path, patch.patch, patch.patchId, parentRef, authorId);
|
5167
5364
|
if (result.isErr(createPatchRes)) {
|
5168
5365
|
if (createPatchRes.error.errorType === "patch-head-conflict") {
|
5169
5366
|
return {
|
@@ -5397,6 +5594,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5397
5594
|
}
|
5398
5595
|
};
|
5399
5596
|
}
|
5597
|
+
const sourcesSha = await serverOps.getSourcesSha();
|
5400
5598
|
const moduleErrors = await serverOps.getModuleErrors();
|
5401
5599
|
if ((moduleErrors === null || moduleErrors === void 0 ? void 0 : moduleErrors.length) > 0) {
|
5402
5600
|
console.error("Val: Module errors", moduleErrors);
|
@@ -5457,7 +5655,9 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5457
5655
|
const modules = {};
|
5458
5656
|
for (const [moduleFilePathS, module] of Object.entries(sourcesRes.sources)) {
|
5459
5657
|
const moduleFilePath = moduleFilePathS;
|
5460
|
-
|
5658
|
+
// TODO: currently sourcesRes contains ALL MODULES.
|
5659
|
+
// We should only evaluate exactly what we need
|
5660
|
+
if (!req.path || moduleFilePath.startsWith(req.path)) {
|
5461
5661
|
var _patchAnalysis$patche, _sourcesValidation$er;
|
5462
5662
|
const skippedPatches = [];
|
5463
5663
|
const patchErrors = {};
|
@@ -5494,6 +5694,7 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5494
5694
|
status: 200,
|
5495
5695
|
json: {
|
5496
5696
|
schemaSha,
|
5697
|
+
sourcesSha,
|
5497
5698
|
modules
|
5498
5699
|
}
|
5499
5700
|
};
|
@@ -5622,33 +5823,33 @@ const ValServer = (valModules, options, callbacks) => {
|
|
5622
5823
|
};
|
5623
5824
|
}
|
5624
5825
|
if (serverOps instanceof ValOpsFS) {
|
5625
|
-
|
5626
|
-
|
5826
|
+
var _remoteFileAuthRes;
|
5827
|
+
const isRemoteRequired = getIsRemoteRequired(await serverOps.getSchemas());
|
5828
|
+
let mode;
|
5829
|
+
let remoteFileAuthRes;
|
5830
|
+
if (isRemoteRequired) {
|
5831
|
+
mode = "upload-remote";
|
5832
|
+
remoteFileAuthRes = await getRemoteFileAuth();
|
5833
|
+
} else {
|
5834
|
+
mode = "skip-remote";
|
5835
|
+
}
|
5836
|
+
if (remoteFileAuthRes && remoteFileAuthRes.status !== 200) {
|
5627
5837
|
return remoteFileAuthRes;
|
5628
5838
|
}
|
5629
|
-
const remoteFileAuth = remoteFileAuthRes.json.remoteFileAuth;
|
5630
|
-
await serverOps.
|
5631
|
-
await serverOps.
|
5839
|
+
const remoteFileAuth = (_remoteFileAuthRes = remoteFileAuthRes) === null || _remoteFileAuthRes === void 0 || (_remoteFileAuthRes = _remoteFileAuthRes.json) === null || _remoteFileAuthRes === void 0 ? void 0 : _remoteFileAuthRes.remoteFileAuth;
|
5840
|
+
const deleteRes = await serverOps.deleteAllPatches();
|
5841
|
+
await serverOps.saveOrUploadFiles(preparedCommit, mode, remoteFileAuth);
|
5842
|
+
if (deleteRes.error) {
|
5843
|
+
console.error(`Val got an error while cleaning up patches after publish: ${deleteRes.error.message}`);
|
5844
|
+
}
|
5632
5845
|
return {
|
5633
5846
|
status: 200,
|
5634
5847
|
json: {} // TODO:
|
5635
5848
|
};
|
5636
5849
|
} else if (serverOps instanceof ValOpsHttp) {
|
5637
5850
|
if (auth.error === undefined && auth.id) {
|
5638
|
-
var _options$config$
|
5639
|
-
|
5640
|
-
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)) {
|
5641
|
-
const res = await serverOps.getCommitMessage(preparedCommit);
|
5642
|
-
if (res.error) {
|
5643
|
-
// ignore
|
5644
|
-
console.error("Failed to get commit message", res.error.message);
|
5645
|
-
} else {
|
5646
|
-
message = res.commitSummary;
|
5647
|
-
}
|
5648
|
-
}
|
5649
|
-
console.log({
|
5650
|
-
message
|
5651
|
-
});
|
5851
|
+
var _options$config$files;
|
5852
|
+
const message = body.message || "Val CMS update (" + Object.keys(analysis.patchesByModule).length + " files changed)";
|
5652
5853
|
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");
|
5653
5854
|
if (commitRes.error) {
|
5654
5855
|
console.error("Failed to commit", commitRes.error);
|
@@ -6041,6 +6242,17 @@ function guessMimeTypeFromPath(filePath) {
|
|
6041
6242
|
}
|
6042
6243
|
return null;
|
6043
6244
|
}
|
6245
|
+
function getIsRemoteRequired(schemas) {
|
6246
|
+
for (const moduleFilePathS in schemas) {
|
6247
|
+
const moduleFilePath = moduleFilePathS;
|
6248
|
+
const schema = schemas[moduleFilePath].serialize();
|
6249
|
+
const isRemoteRequired = hasRemoteFileSchema(schema);
|
6250
|
+
if (isRemoteRequired) {
|
6251
|
+
return true;
|
6252
|
+
}
|
6253
|
+
}
|
6254
|
+
return false;
|
6255
|
+
}
|
6044
6256
|
|
6045
6257
|
async function createValServer(valModules, route, opts, config, callbacks, formatter) {
|
6046
6258
|
const valServerConfig = await initHandlerOptions(route, opts, config);
|
@@ -6057,7 +6269,7 @@ async function initHandlerOptions(route, opts, config) {
|
|
6057
6269
|
const valDisableRedirectUrl = opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL;
|
6058
6270
|
const maybeValProject = opts.project || process.env.VAL_PROJECT;
|
6059
6271
|
const valBuildUrl = opts.valBuildUrl || process.env.VAL_BUILD_URL || "https://app.val.build";
|
6060
|
-
const valContentUrl = opts.valContentUrl || process.env.VAL_CONTENT_URL ||
|
6272
|
+
const valContentUrl = opts.valContentUrl || process.env.VAL_CONTENT_URL || DEFAULT_CONTENT_HOST;
|
6061
6273
|
if (isProxyMode) {
|
6062
6274
|
var _opts$versions, _opts$versions2;
|
6063
6275
|
if (!maybeApiKey || !maybeValSecret) {
|