@valbuild/server 0.144.0 → 0.144.1
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/CHANGELOG.md +6 -0
- package/dist/declarations/src/ValOps.d.ts +10 -1
- package/dist/declarations/src/index.d.ts +1 -1
- package/dist/declarations/src/proposal.d.ts +28 -0
- package/dist/valbuild-server.cjs.dev.js +150 -8
- package/dist/valbuild-server.cjs.prod.js +150 -8
- package/dist/valbuild-server.esm.js +150 -9
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @valbuild/server
|
|
2
2
|
|
|
3
|
+
## 0.144.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#824](https://github.com/valbuild/val/pull/824) [`a641bb0`](https://github.com/valbuild/val/commit/a641bb0286756339252c53e9230d766c23fcccc6) Thanks [@freekh](https://github.com/freekh)! - `.jsonValues()` entries saved in a proposal now show at the proposal's address. Before, the page kept showing the entry as it was when the site was last built, and the Studio there showed every entry of a saved `.jsonValues()` module as empty.
|
|
8
|
+
|
|
3
9
|
## 0.144.0
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -51,6 +51,13 @@ export type ValOpsOptions = {
|
|
|
51
51
|
* the next save's prepare -- starts from it, and the SHAs describe it.
|
|
52
52
|
*/
|
|
53
53
|
snapshotSources?: Sources;
|
|
54
|
+
/**
|
|
55
|
+
* The `.jsonValues()` entries the same snapshot saved, by module and key:
|
|
56
|
+
* their content is in their own files, not in {@link snapshotSources}, which
|
|
57
|
+
* holds markers. The baseline those entries are read from, as a save in
|
|
58
|
+
* this instance would leave them (`proposalJsonEntries` in `./proposal`).
|
|
59
|
+
*/
|
|
60
|
+
snapshotJsonEntries?: Map<ModuleFilePath, Map<string, JSONValue>>;
|
|
54
61
|
};
|
|
55
62
|
export declare abstract class ValOps {
|
|
56
63
|
private readonly valModules;
|
|
@@ -101,7 +108,9 @@ export declare abstract class ValOps {
|
|
|
101
108
|
* unlike a module source there is nothing to re-extract, because the memo was
|
|
102
109
|
* never holding the content in the first place.
|
|
103
110
|
*
|
|
104
|
-
* `
|
|
111
|
+
* `deleted` for an entry the commit deleted: tagged, not `null`, because an
|
|
112
|
+
* entry's content may itself be JSON `null` (a nullable item), and a saved
|
|
113
|
+
* `null` read back as "deleted" would report the entry missing.
|
|
105
114
|
*
|
|
106
115
|
* Never cleared: it describes what is on disk. A host rebuild makes a new
|
|
107
116
|
* instance, which is the right reset. Bounded by the project's entry count,
|
|
@@ -2,7 +2,7 @@ export { createService, Service } from "./Service.js";
|
|
|
2
2
|
export { defineExternal, ok, err, isExternalResult, EXTERNAL_RESULT, } from "./externalRecords.js";
|
|
3
3
|
export type { AdapterFor, BoundExternalRecord, ExternalAuthor, ExternalBuilder, ExternalCtx, ExternalDefinition, ExternalFile, ExternalIssue, ExternalKeyPage, ExternalRecords, ExternalResult, ExternalSearchHit, ExternalSearchPage, ExternalSort, ItemOfModule, ReadonlyRecordHasNoWrites, Returns, } from "./externalRecords.js";
|
|
4
4
|
export { createValApiRouter, createValServer, safeReadGit } from "./ValRouter.js";
|
|
5
|
-
export { proposalFromEnv, proposalSnapshot } from "./proposal.js";
|
|
5
|
+
export { proposalFromEnv, proposalSnapshot, proposalSnapshotForReaders, } from "./proposal.js";
|
|
6
6
|
export type { ValProposal } from "./proposal.js";
|
|
7
7
|
export { initHandlerOptions, createValOps } from "./valServerConfig.js";
|
|
8
8
|
export { resolveRemoteFileAuth } from "./valServerConfig.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Json, ModuleFilePath } from "@valbuild/core";
|
|
2
|
+
import type { JSONValue } from "@valbuild/core/patch";
|
|
2
3
|
/**
|
|
3
4
|
* A proposal this server runs at the address of: an editor-managed branch of
|
|
4
5
|
* the project's content, served from its own copy of the content the
|
|
@@ -70,3 +71,30 @@ export declare function proposalFromEnv(env: {
|
|
|
70
71
|
* what the snapshot holds.
|
|
71
72
|
*/
|
|
72
73
|
export declare function proposalSnapshot(proposal: Pick<ValProposal, "modules">): Record<ModuleFilePath, Json>;
|
|
74
|
+
/**
|
|
75
|
+
* The `.jsonValues()` entries the proposal saved, by module and key.
|
|
76
|
+
*
|
|
77
|
+
* An entry's content is not in its module's Source -- that holds a marker per
|
|
78
|
+
* entry -- but in the entry's own `*.val.json`, and a save writes that file:
|
|
79
|
+
* it reaches the proposal's address as saved TEXT ({@link ValProposal.files}),
|
|
80
|
+
* not as Source. So the snapshot alone shows the build's entries. This is the
|
|
81
|
+
* other half: each saved `*.val.json`, read as the entry its module names.
|
|
82
|
+
*
|
|
83
|
+
* Which entry a file is comes from the module's `.val.ts`, whose
|
|
84
|
+
* `c.json(() => import("..."))` thunks name the files -- the saved text if
|
|
85
|
+
* the save rewrote it, else the build's own (`projectSource`). An entry whose
|
|
86
|
+
* module cannot be read that way is left to the build, as before: this adds
|
|
87
|
+
* what it can find and never fails the address.
|
|
88
|
+
*/
|
|
89
|
+
export declare function proposalJsonEntries(proposal: Pick<ValProposal, "modules" | "files">, projectSource?: Record<string, string>): Map<ModuleFilePath, Map<string, JSONValue>>;
|
|
90
|
+
/**
|
|
91
|
+
* The snapshot as a page reads it: {@link proposalSnapshot}, with each saved
|
|
92
|
+
* `.jsonValues()` entry's content in place of its marker -- the shape a draft
|
|
93
|
+
* already has, where the entries it edits hold content and the rest are
|
|
94
|
+
* markers the readers resolve from the build. See {@link proposalJsonEntries}.
|
|
95
|
+
*
|
|
96
|
+
* For the readers only. Val's own server keeps the markers
|
|
97
|
+
* ({@link proposalSnapshot}): its patching works on them, and it takes the
|
|
98
|
+
* saved entries separately.
|
|
99
|
+
*/
|
|
100
|
+
export declare function proposalSnapshotForReaders(proposal: Pick<ValProposal, "modules" | "files">, projectSource?: Record<string, string>): Record<ModuleFilePath, Json>;
|
|
@@ -3593,6 +3593,12 @@ function findNestedJsonValuesModuleErrors(schemas) {
|
|
|
3593
3593
|
}
|
|
3594
3594
|
return errors;
|
|
3595
3595
|
}
|
|
3596
|
+
|
|
3597
|
+
/**
|
|
3598
|
+
* What a save told this instance a `.jsonValues()` entry holds: its content --
|
|
3599
|
+
* JSON `null` included -- or that it was deleted. See `adoptedJsonEntries`.
|
|
3600
|
+
*/
|
|
3601
|
+
|
|
3596
3602
|
// #region ValOps
|
|
3597
3603
|
class ValOps {
|
|
3598
3604
|
/** Sources from val modules, immutable (without patches or anything) */
|
|
@@ -3641,7 +3647,9 @@ class ValOps {
|
|
|
3641
3647
|
* unlike a module source there is nothing to re-extract, because the memo was
|
|
3642
3648
|
* never holding the content in the first place.
|
|
3643
3649
|
*
|
|
3644
|
-
* `
|
|
3650
|
+
* `deleted` for an entry the commit deleted: tagged, not `null`, because an
|
|
3651
|
+
* entry's content may itself be JSON `null` (a nullable item), and a saved
|
|
3652
|
+
* `null` read back as "deleted" would report the entry missing.
|
|
3645
3653
|
*
|
|
3646
3654
|
* Never cleared: it describes what is on disk. A host rebuild makes a new
|
|
3647
3655
|
* instance, which is the right reset. Bounded by the project's entry count,
|
|
@@ -3660,6 +3668,16 @@ class ValOps {
|
|
|
3660
3668
|
this.modulesErrors = null;
|
|
3661
3669
|
this.shaEntries = null;
|
|
3662
3670
|
this.shaModuleErrors = null;
|
|
3671
|
+
for (const [moduleFilePath, entries] of (options === null || options === void 0 ? void 0 : options.snapshotJsonEntries) ?? []) {
|
|
3672
|
+
const adopted = new Map();
|
|
3673
|
+
for (const [entryKey, content] of entries) {
|
|
3674
|
+
adopted.set(entryKey, {
|
|
3675
|
+
kind: "content",
|
|
3676
|
+
content
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3679
|
+
this.adoptedJsonEntries.set(moduleFilePath, adopted);
|
|
3680
|
+
}
|
|
3663
3681
|
}
|
|
3664
3682
|
|
|
3665
3683
|
// #region stat
|
|
@@ -3801,7 +3819,13 @@ class ValOps {
|
|
|
3801
3819
|
}
|
|
3802
3820
|
const adopted = this.adoptedJsonEntries.get(moduleFilePath) ?? new Map();
|
|
3803
3821
|
for (const [entryKey, content] of Object.entries(entries)) {
|
|
3804
|
-
|
|
3822
|
+
// A commit's `null` is a deleted entry: see `patchedJsonEntries`.
|
|
3823
|
+
adopted.set(entryKey, content === null ? {
|
|
3824
|
+
kind: "deleted"
|
|
3825
|
+
} : {
|
|
3826
|
+
kind: "content",
|
|
3827
|
+
content
|
|
3828
|
+
});
|
|
3805
3829
|
}
|
|
3806
3830
|
this.adoptedJsonEntries.set(moduleFilePath, adopted);
|
|
3807
3831
|
}
|
|
@@ -4035,6 +4059,7 @@ class ValOps {
|
|
|
4035
4059
|
}
|
|
4036
4060
|
}
|
|
4037
4061
|
const loaded = await Promise.all([...requestedKeys, ...sourceKeys].map(async entryKey => {
|
|
4062
|
+
var _this$adoptedJsonEntr, _this$siteSourcesBefo;
|
|
4038
4063
|
const marker = record[entryKey];
|
|
4039
4064
|
if (marker !== undefined && !core.Internal.isJson(marker)) {
|
|
4040
4065
|
// Not a jsonValues entry — return the inlined value as-is (defensive).
|
|
@@ -4069,15 +4094,20 @@ class ValOps {
|
|
|
4069
4094
|
* The BASELINE only. Pending patches replay over it below exactly as
|
|
4070
4095
|
* they do over the thunk's answer.
|
|
4071
4096
|
*/
|
|
4072
|
-
const adopted = this.adoptedJsonEntries.get(moduleFilePath);
|
|
4073
|
-
if (adopted !== undefined
|
|
4074
|
-
const content = adopted.get(entryKey);
|
|
4097
|
+
const adopted = (_this$adoptedJsonEntr = this.adoptedJsonEntries.get(moduleFilePath)) === null || _this$adoptedJsonEntr === void 0 ? void 0 : _this$adoptedJsonEntr.get(entryKey);
|
|
4098
|
+
if (adopted !== undefined) {
|
|
4075
4099
|
return {
|
|
4076
4100
|
entryKey,
|
|
4077
|
-
baseContent:
|
|
4101
|
+
baseContent: adopted.kind === "deleted" ? undefined : adopted.content
|
|
4078
4102
|
};
|
|
4079
4103
|
}
|
|
4080
|
-
|
|
4104
|
+
/*
|
|
4105
|
+
* A snapshot's marker came as JSON, with no import behind it: the
|
|
4106
|
+
* entry the proposal did not save is the build's, behind the marker
|
|
4107
|
+
* the module evaluated to.
|
|
4108
|
+
*/
|
|
4109
|
+
const siteMarker = (_this$siteSourcesBefo = this.siteSourcesBeforeSnapshot) === null || _this$siteSourcesBefo === void 0 || (_this$siteSourcesBefo = _this$siteSourcesBefo[moduleFilePath]) === null || _this$siteSourcesBefo === void 0 ? void 0 : _this$siteSourcesBefo[entryKey];
|
|
4110
|
+
const thunk = core.Internal.getJsonImport(marker) ?? (core.Internal.isJson(siteMarker) ? core.Internal.getJsonImport(siteMarker) : undefined);
|
|
4081
4111
|
if (!thunk) {
|
|
4082
4112
|
return {
|
|
4083
4113
|
entryKey,
|
|
@@ -8988,6 +9018,116 @@ function proposalSnapshot(proposal) {
|
|
|
8988
9018
|
}
|
|
8989
9019
|
return snapshot;
|
|
8990
9020
|
}
|
|
9021
|
+
|
|
9022
|
+
/**
|
|
9023
|
+
* The `.jsonValues()` entries the proposal saved, by module and key.
|
|
9024
|
+
*
|
|
9025
|
+
* An entry's content is not in its module's Source -- that holds a marker per
|
|
9026
|
+
* entry -- but in the entry's own `*.val.json`, and a save writes that file:
|
|
9027
|
+
* it reaches the proposal's address as saved TEXT ({@link ValProposal.files}),
|
|
9028
|
+
* not as Source. So the snapshot alone shows the build's entries. This is the
|
|
9029
|
+
* other half: each saved `*.val.json`, read as the entry its module names.
|
|
9030
|
+
*
|
|
9031
|
+
* Which entry a file is comes from the module's `.val.ts`, whose
|
|
9032
|
+
* `c.json(() => import("..."))` thunks name the files -- the saved text if
|
|
9033
|
+
* the save rewrote it, else the build's own (`projectSource`). An entry whose
|
|
9034
|
+
* module cannot be read that way is left to the build, as before: this adds
|
|
9035
|
+
* what it can find and never fails the address.
|
|
9036
|
+
*/
|
|
9037
|
+
function proposalJsonEntries(proposal, projectSource) {
|
|
9038
|
+
const found = new Map();
|
|
9039
|
+
const savedJson = Object.keys(proposal.files).filter(path => path.endsWith(".val.json"));
|
|
9040
|
+
if (savedJson.length === 0) return found;
|
|
9041
|
+
const savedJsonPaths = new Set(savedJson);
|
|
9042
|
+
for (const [moduleFilePath, source] of Object.entries(proposal.modules)) {
|
|
9043
|
+
if (!holdsJsonMarkers(source)) continue;
|
|
9044
|
+
const relative = moduleFilePath.replace(/^\//, "");
|
|
9045
|
+
const text = proposal.files[relative] ?? (projectSource === null || projectSource === void 0 ? void 0 : projectSource[relative]);
|
|
9046
|
+
if (text === undefined) continue;
|
|
9047
|
+
const entries = jsonEntryPaths(relative, text);
|
|
9048
|
+
if (entries === null) continue;
|
|
9049
|
+
const byKey = new Map();
|
|
9050
|
+
for (const [key, importPath] of entries) {
|
|
9051
|
+
const jsonPath = resolveExistingJsonPath(moduleFilePath, importPath).replace(/^\//, "");
|
|
9052
|
+
if (!savedJsonPaths.has(jsonPath)) continue;
|
|
9053
|
+
const content = parseJson(proposal.files[jsonPath]);
|
|
9054
|
+
if (content !== undefined) byKey.set(key, content);
|
|
9055
|
+
}
|
|
9056
|
+
if (byKey.size > 0) found.set(moduleFilePath, byKey);
|
|
9057
|
+
}
|
|
9058
|
+
return found;
|
|
9059
|
+
}
|
|
9060
|
+
|
|
9061
|
+
/**
|
|
9062
|
+
* The snapshot as a page reads it: {@link proposalSnapshot}, with each saved
|
|
9063
|
+
* `.jsonValues()` entry's content in place of its marker -- the shape a draft
|
|
9064
|
+
* already has, where the entries it edits hold content and the rest are
|
|
9065
|
+
* markers the readers resolve from the build. See {@link proposalJsonEntries}.
|
|
9066
|
+
*
|
|
9067
|
+
* For the readers only. Val's own server keeps the markers
|
|
9068
|
+
* ({@link proposalSnapshot}): its patching works on them, and it takes the
|
|
9069
|
+
* saved entries separately.
|
|
9070
|
+
*/
|
|
9071
|
+
function proposalSnapshotForReaders(proposal, projectSource) {
|
|
9072
|
+
const snapshot = proposalSnapshot(proposal);
|
|
9073
|
+
for (const [moduleFilePath, entries] of proposalJsonEntries(proposal, projectSource)) {
|
|
9074
|
+
const source = snapshot[moduleFilePath];
|
|
9075
|
+
if (!isObject$1(source)) continue;
|
|
9076
|
+
const filled = {};
|
|
9077
|
+
for (const [key, value] of Object.entries(source)) {
|
|
9078
|
+
if (isJsonValue(value)) filled[key] = value;
|
|
9079
|
+
}
|
|
9080
|
+
for (const [key, content] of entries) {
|
|
9081
|
+
// Own keys only: an entry may be named `toString`.
|
|
9082
|
+
if (Object.prototype.hasOwnProperty.call(filled, key)) {
|
|
9083
|
+
filled[key] = content;
|
|
9084
|
+
}
|
|
9085
|
+
}
|
|
9086
|
+
snapshot[moduleFilePath] = filled;
|
|
9087
|
+
}
|
|
9088
|
+
return snapshot;
|
|
9089
|
+
}
|
|
9090
|
+
|
|
9091
|
+
/** A record of `.jsonValues()` markers (`{ _type: "json" }`), at least one. */
|
|
9092
|
+
function holdsJsonMarkers(source) {
|
|
9093
|
+
return isObject$1(source) && Object.values(source).some(value => isObject$1(value) && value["_type"] === "json");
|
|
9094
|
+
}
|
|
9095
|
+
|
|
9096
|
+
/** Each entry key's import path, from a `.jsonValues()` module's text. */
|
|
9097
|
+
function jsonEntryPaths(fileName, text) {
|
|
9098
|
+
try {
|
|
9099
|
+
const analysis = analyzeValModule(ts__default["default"].createSourceFile(fileName, text, ts__default["default"].ScriptTarget.ES2015, true));
|
|
9100
|
+
if (fp.result.isErr(analysis)) return null;
|
|
9101
|
+
const paths = new Map();
|
|
9102
|
+
for (const [key, entry] of analyzeJsonValuesEntries(analysis.value.source)) {
|
|
9103
|
+
paths.set(key, entry.importPath);
|
|
9104
|
+
}
|
|
9105
|
+
return paths;
|
|
9106
|
+
} catch {
|
|
9107
|
+
// Not a module this can read: its entries stay the build's.
|
|
9108
|
+
return null;
|
|
9109
|
+
}
|
|
9110
|
+
}
|
|
9111
|
+
function parseJson(text) {
|
|
9112
|
+
if (text === undefined) return undefined;
|
|
9113
|
+
try {
|
|
9114
|
+
const value = JSON.parse(text);
|
|
9115
|
+
return isMutableJsonValue(value) ? value : undefined;
|
|
9116
|
+
} catch {
|
|
9117
|
+
return undefined;
|
|
9118
|
+
}
|
|
9119
|
+
}
|
|
9120
|
+
|
|
9121
|
+
/** {@link isJsonValue}, for the mutable JSON a server patches. */
|
|
9122
|
+
function isMutableJsonValue(value) {
|
|
9123
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
9124
|
+
return true;
|
|
9125
|
+
}
|
|
9126
|
+
if (Array.isArray(value)) {
|
|
9127
|
+
return value.every(isMutableJsonValue);
|
|
9128
|
+
}
|
|
9129
|
+
return isObject$1(value) && Object.values(value).every(isMutableJsonValue);
|
|
9130
|
+
}
|
|
8991
9131
|
function isObject$1(value) {
|
|
8992
9132
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8993
9133
|
}
|
|
@@ -9432,7 +9572,8 @@ class ValOpsHttp extends ValOps {
|
|
|
9432
9572
|
auth, valModules, options) {
|
|
9433
9573
|
super(valModules, options !== null && options !== void 0 && options.proposal ? {
|
|
9434
9574
|
...options,
|
|
9435
|
-
snapshotSources: proposalSnapshot(options.proposal)
|
|
9575
|
+
snapshotSources: proposalSnapshot(options.proposal),
|
|
9576
|
+
snapshotJsonEntries: proposalJsonEntries(options.proposal, options.projectSource)
|
|
9436
9577
|
} : options);
|
|
9437
9578
|
this.contentUrl = contentUrl;
|
|
9438
9579
|
this.project = project;
|
|
@@ -24024,6 +24165,7 @@ exports.persistPersonalAccessToken = persistPersonalAccessToken;
|
|
|
24024
24165
|
exports.planJsonValuesEntryExtraction = planJsonValuesEntryExtraction;
|
|
24025
24166
|
exports.proposalFromEnv = proposalFromEnv;
|
|
24026
24167
|
exports.proposalSnapshot = proposalSnapshot;
|
|
24168
|
+
exports.proposalSnapshotForReaders = proposalSnapshotForReaders;
|
|
24027
24169
|
exports.readCapturedReport = readCapturedReport;
|
|
24028
24170
|
exports.readPatchStore = readPatchStore;
|
|
24029
24171
|
exports.rebaseContentOp = rebaseContentOp;
|
|
@@ -3593,6 +3593,12 @@ function findNestedJsonValuesModuleErrors(schemas) {
|
|
|
3593
3593
|
}
|
|
3594
3594
|
return errors;
|
|
3595
3595
|
}
|
|
3596
|
+
|
|
3597
|
+
/**
|
|
3598
|
+
* What a save told this instance a `.jsonValues()` entry holds: its content --
|
|
3599
|
+
* JSON `null` included -- or that it was deleted. See `adoptedJsonEntries`.
|
|
3600
|
+
*/
|
|
3601
|
+
|
|
3596
3602
|
// #region ValOps
|
|
3597
3603
|
class ValOps {
|
|
3598
3604
|
/** Sources from val modules, immutable (without patches or anything) */
|
|
@@ -3641,7 +3647,9 @@ class ValOps {
|
|
|
3641
3647
|
* unlike a module source there is nothing to re-extract, because the memo was
|
|
3642
3648
|
* never holding the content in the first place.
|
|
3643
3649
|
*
|
|
3644
|
-
* `
|
|
3650
|
+
* `deleted` for an entry the commit deleted: tagged, not `null`, because an
|
|
3651
|
+
* entry's content may itself be JSON `null` (a nullable item), and a saved
|
|
3652
|
+
* `null` read back as "deleted" would report the entry missing.
|
|
3645
3653
|
*
|
|
3646
3654
|
* Never cleared: it describes what is on disk. A host rebuild makes a new
|
|
3647
3655
|
* instance, which is the right reset. Bounded by the project's entry count,
|
|
@@ -3660,6 +3668,16 @@ class ValOps {
|
|
|
3660
3668
|
this.modulesErrors = null;
|
|
3661
3669
|
this.shaEntries = null;
|
|
3662
3670
|
this.shaModuleErrors = null;
|
|
3671
|
+
for (const [moduleFilePath, entries] of (options === null || options === void 0 ? void 0 : options.snapshotJsonEntries) ?? []) {
|
|
3672
|
+
const adopted = new Map();
|
|
3673
|
+
for (const [entryKey, content] of entries) {
|
|
3674
|
+
adopted.set(entryKey, {
|
|
3675
|
+
kind: "content",
|
|
3676
|
+
content
|
|
3677
|
+
});
|
|
3678
|
+
}
|
|
3679
|
+
this.adoptedJsonEntries.set(moduleFilePath, adopted);
|
|
3680
|
+
}
|
|
3663
3681
|
}
|
|
3664
3682
|
|
|
3665
3683
|
// #region stat
|
|
@@ -3801,7 +3819,13 @@ class ValOps {
|
|
|
3801
3819
|
}
|
|
3802
3820
|
const adopted = this.adoptedJsonEntries.get(moduleFilePath) ?? new Map();
|
|
3803
3821
|
for (const [entryKey, content] of Object.entries(entries)) {
|
|
3804
|
-
|
|
3822
|
+
// A commit's `null` is a deleted entry: see `patchedJsonEntries`.
|
|
3823
|
+
adopted.set(entryKey, content === null ? {
|
|
3824
|
+
kind: "deleted"
|
|
3825
|
+
} : {
|
|
3826
|
+
kind: "content",
|
|
3827
|
+
content
|
|
3828
|
+
});
|
|
3805
3829
|
}
|
|
3806
3830
|
this.adoptedJsonEntries.set(moduleFilePath, adopted);
|
|
3807
3831
|
}
|
|
@@ -4035,6 +4059,7 @@ class ValOps {
|
|
|
4035
4059
|
}
|
|
4036
4060
|
}
|
|
4037
4061
|
const loaded = await Promise.all([...requestedKeys, ...sourceKeys].map(async entryKey => {
|
|
4062
|
+
var _this$adoptedJsonEntr, _this$siteSourcesBefo;
|
|
4038
4063
|
const marker = record[entryKey];
|
|
4039
4064
|
if (marker !== undefined && !core.Internal.isJson(marker)) {
|
|
4040
4065
|
// Not a jsonValues entry — return the inlined value as-is (defensive).
|
|
@@ -4069,15 +4094,20 @@ class ValOps {
|
|
|
4069
4094
|
* The BASELINE only. Pending patches replay over it below exactly as
|
|
4070
4095
|
* they do over the thunk's answer.
|
|
4071
4096
|
*/
|
|
4072
|
-
const adopted = this.adoptedJsonEntries.get(moduleFilePath);
|
|
4073
|
-
if (adopted !== undefined
|
|
4074
|
-
const content = adopted.get(entryKey);
|
|
4097
|
+
const adopted = (_this$adoptedJsonEntr = this.adoptedJsonEntries.get(moduleFilePath)) === null || _this$adoptedJsonEntr === void 0 ? void 0 : _this$adoptedJsonEntr.get(entryKey);
|
|
4098
|
+
if (adopted !== undefined) {
|
|
4075
4099
|
return {
|
|
4076
4100
|
entryKey,
|
|
4077
|
-
baseContent:
|
|
4101
|
+
baseContent: adopted.kind === "deleted" ? undefined : adopted.content
|
|
4078
4102
|
};
|
|
4079
4103
|
}
|
|
4080
|
-
|
|
4104
|
+
/*
|
|
4105
|
+
* A snapshot's marker came as JSON, with no import behind it: the
|
|
4106
|
+
* entry the proposal did not save is the build's, behind the marker
|
|
4107
|
+
* the module evaluated to.
|
|
4108
|
+
*/
|
|
4109
|
+
const siteMarker = (_this$siteSourcesBefo = this.siteSourcesBeforeSnapshot) === null || _this$siteSourcesBefo === void 0 || (_this$siteSourcesBefo = _this$siteSourcesBefo[moduleFilePath]) === null || _this$siteSourcesBefo === void 0 ? void 0 : _this$siteSourcesBefo[entryKey];
|
|
4110
|
+
const thunk = core.Internal.getJsonImport(marker) ?? (core.Internal.isJson(siteMarker) ? core.Internal.getJsonImport(siteMarker) : undefined);
|
|
4081
4111
|
if (!thunk) {
|
|
4082
4112
|
return {
|
|
4083
4113
|
entryKey,
|
|
@@ -8988,6 +9018,116 @@ function proposalSnapshot(proposal) {
|
|
|
8988
9018
|
}
|
|
8989
9019
|
return snapshot;
|
|
8990
9020
|
}
|
|
9021
|
+
|
|
9022
|
+
/**
|
|
9023
|
+
* The `.jsonValues()` entries the proposal saved, by module and key.
|
|
9024
|
+
*
|
|
9025
|
+
* An entry's content is not in its module's Source -- that holds a marker per
|
|
9026
|
+
* entry -- but in the entry's own `*.val.json`, and a save writes that file:
|
|
9027
|
+
* it reaches the proposal's address as saved TEXT ({@link ValProposal.files}),
|
|
9028
|
+
* not as Source. So the snapshot alone shows the build's entries. This is the
|
|
9029
|
+
* other half: each saved `*.val.json`, read as the entry its module names.
|
|
9030
|
+
*
|
|
9031
|
+
* Which entry a file is comes from the module's `.val.ts`, whose
|
|
9032
|
+
* `c.json(() => import("..."))` thunks name the files -- the saved text if
|
|
9033
|
+
* the save rewrote it, else the build's own (`projectSource`). An entry whose
|
|
9034
|
+
* module cannot be read that way is left to the build, as before: this adds
|
|
9035
|
+
* what it can find and never fails the address.
|
|
9036
|
+
*/
|
|
9037
|
+
function proposalJsonEntries(proposal, projectSource) {
|
|
9038
|
+
const found = new Map();
|
|
9039
|
+
const savedJson = Object.keys(proposal.files).filter(path => path.endsWith(".val.json"));
|
|
9040
|
+
if (savedJson.length === 0) return found;
|
|
9041
|
+
const savedJsonPaths = new Set(savedJson);
|
|
9042
|
+
for (const [moduleFilePath, source] of Object.entries(proposal.modules)) {
|
|
9043
|
+
if (!holdsJsonMarkers(source)) continue;
|
|
9044
|
+
const relative = moduleFilePath.replace(/^\//, "");
|
|
9045
|
+
const text = proposal.files[relative] ?? (projectSource === null || projectSource === void 0 ? void 0 : projectSource[relative]);
|
|
9046
|
+
if (text === undefined) continue;
|
|
9047
|
+
const entries = jsonEntryPaths(relative, text);
|
|
9048
|
+
if (entries === null) continue;
|
|
9049
|
+
const byKey = new Map();
|
|
9050
|
+
for (const [key, importPath] of entries) {
|
|
9051
|
+
const jsonPath = resolveExistingJsonPath(moduleFilePath, importPath).replace(/^\//, "");
|
|
9052
|
+
if (!savedJsonPaths.has(jsonPath)) continue;
|
|
9053
|
+
const content = parseJson(proposal.files[jsonPath]);
|
|
9054
|
+
if (content !== undefined) byKey.set(key, content);
|
|
9055
|
+
}
|
|
9056
|
+
if (byKey.size > 0) found.set(moduleFilePath, byKey);
|
|
9057
|
+
}
|
|
9058
|
+
return found;
|
|
9059
|
+
}
|
|
9060
|
+
|
|
9061
|
+
/**
|
|
9062
|
+
* The snapshot as a page reads it: {@link proposalSnapshot}, with each saved
|
|
9063
|
+
* `.jsonValues()` entry's content in place of its marker -- the shape a draft
|
|
9064
|
+
* already has, where the entries it edits hold content and the rest are
|
|
9065
|
+
* markers the readers resolve from the build. See {@link proposalJsonEntries}.
|
|
9066
|
+
*
|
|
9067
|
+
* For the readers only. Val's own server keeps the markers
|
|
9068
|
+
* ({@link proposalSnapshot}): its patching works on them, and it takes the
|
|
9069
|
+
* saved entries separately.
|
|
9070
|
+
*/
|
|
9071
|
+
function proposalSnapshotForReaders(proposal, projectSource) {
|
|
9072
|
+
const snapshot = proposalSnapshot(proposal);
|
|
9073
|
+
for (const [moduleFilePath, entries] of proposalJsonEntries(proposal, projectSource)) {
|
|
9074
|
+
const source = snapshot[moduleFilePath];
|
|
9075
|
+
if (!isObject$1(source)) continue;
|
|
9076
|
+
const filled = {};
|
|
9077
|
+
for (const [key, value] of Object.entries(source)) {
|
|
9078
|
+
if (isJsonValue(value)) filled[key] = value;
|
|
9079
|
+
}
|
|
9080
|
+
for (const [key, content] of entries) {
|
|
9081
|
+
// Own keys only: an entry may be named `toString`.
|
|
9082
|
+
if (Object.prototype.hasOwnProperty.call(filled, key)) {
|
|
9083
|
+
filled[key] = content;
|
|
9084
|
+
}
|
|
9085
|
+
}
|
|
9086
|
+
snapshot[moduleFilePath] = filled;
|
|
9087
|
+
}
|
|
9088
|
+
return snapshot;
|
|
9089
|
+
}
|
|
9090
|
+
|
|
9091
|
+
/** A record of `.jsonValues()` markers (`{ _type: "json" }`), at least one. */
|
|
9092
|
+
function holdsJsonMarkers(source) {
|
|
9093
|
+
return isObject$1(source) && Object.values(source).some(value => isObject$1(value) && value["_type"] === "json");
|
|
9094
|
+
}
|
|
9095
|
+
|
|
9096
|
+
/** Each entry key's import path, from a `.jsonValues()` module's text. */
|
|
9097
|
+
function jsonEntryPaths(fileName, text) {
|
|
9098
|
+
try {
|
|
9099
|
+
const analysis = analyzeValModule(ts__default["default"].createSourceFile(fileName, text, ts__default["default"].ScriptTarget.ES2015, true));
|
|
9100
|
+
if (fp.result.isErr(analysis)) return null;
|
|
9101
|
+
const paths = new Map();
|
|
9102
|
+
for (const [key, entry] of analyzeJsonValuesEntries(analysis.value.source)) {
|
|
9103
|
+
paths.set(key, entry.importPath);
|
|
9104
|
+
}
|
|
9105
|
+
return paths;
|
|
9106
|
+
} catch {
|
|
9107
|
+
// Not a module this can read: its entries stay the build's.
|
|
9108
|
+
return null;
|
|
9109
|
+
}
|
|
9110
|
+
}
|
|
9111
|
+
function parseJson(text) {
|
|
9112
|
+
if (text === undefined) return undefined;
|
|
9113
|
+
try {
|
|
9114
|
+
const value = JSON.parse(text);
|
|
9115
|
+
return isMutableJsonValue(value) ? value : undefined;
|
|
9116
|
+
} catch {
|
|
9117
|
+
return undefined;
|
|
9118
|
+
}
|
|
9119
|
+
}
|
|
9120
|
+
|
|
9121
|
+
/** {@link isJsonValue}, for the mutable JSON a server patches. */
|
|
9122
|
+
function isMutableJsonValue(value) {
|
|
9123
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
9124
|
+
return true;
|
|
9125
|
+
}
|
|
9126
|
+
if (Array.isArray(value)) {
|
|
9127
|
+
return value.every(isMutableJsonValue);
|
|
9128
|
+
}
|
|
9129
|
+
return isObject$1(value) && Object.values(value).every(isMutableJsonValue);
|
|
9130
|
+
}
|
|
8991
9131
|
function isObject$1(value) {
|
|
8992
9132
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8993
9133
|
}
|
|
@@ -9432,7 +9572,8 @@ class ValOpsHttp extends ValOps {
|
|
|
9432
9572
|
auth, valModules, options) {
|
|
9433
9573
|
super(valModules, options !== null && options !== void 0 && options.proposal ? {
|
|
9434
9574
|
...options,
|
|
9435
|
-
snapshotSources: proposalSnapshot(options.proposal)
|
|
9575
|
+
snapshotSources: proposalSnapshot(options.proposal),
|
|
9576
|
+
snapshotJsonEntries: proposalJsonEntries(options.proposal, options.projectSource)
|
|
9436
9577
|
} : options);
|
|
9437
9578
|
this.contentUrl = contentUrl;
|
|
9438
9579
|
this.project = project;
|
|
@@ -24024,6 +24165,7 @@ exports.persistPersonalAccessToken = persistPersonalAccessToken;
|
|
|
24024
24165
|
exports.planJsonValuesEntryExtraction = planJsonValuesEntryExtraction;
|
|
24025
24166
|
exports.proposalFromEnv = proposalFromEnv;
|
|
24026
24167
|
exports.proposalSnapshot = proposalSnapshot;
|
|
24168
|
+
exports.proposalSnapshotForReaders = proposalSnapshotForReaders;
|
|
24027
24169
|
exports.readCapturedReport = readCapturedReport;
|
|
24028
24170
|
exports.readPatchStore = readPatchStore;
|
|
24029
24171
|
exports.rebaseContentOp = rebaseContentOp;
|
|
@@ -3556,6 +3556,12 @@ function findNestedJsonValuesModuleErrors(schemas) {
|
|
|
3556
3556
|
}
|
|
3557
3557
|
return errors;
|
|
3558
3558
|
}
|
|
3559
|
+
|
|
3560
|
+
/**
|
|
3561
|
+
* What a save told this instance a `.jsonValues()` entry holds: its content --
|
|
3562
|
+
* JSON `null` included -- or that it was deleted. See `adoptedJsonEntries`.
|
|
3563
|
+
*/
|
|
3564
|
+
|
|
3559
3565
|
// #region ValOps
|
|
3560
3566
|
class ValOps {
|
|
3561
3567
|
/** Sources from val modules, immutable (without patches or anything) */
|
|
@@ -3604,7 +3610,9 @@ class ValOps {
|
|
|
3604
3610
|
* unlike a module source there is nothing to re-extract, because the memo was
|
|
3605
3611
|
* never holding the content in the first place.
|
|
3606
3612
|
*
|
|
3607
|
-
* `
|
|
3613
|
+
* `deleted` for an entry the commit deleted: tagged, not `null`, because an
|
|
3614
|
+
* entry's content may itself be JSON `null` (a nullable item), and a saved
|
|
3615
|
+
* `null` read back as "deleted" would report the entry missing.
|
|
3608
3616
|
*
|
|
3609
3617
|
* Never cleared: it describes what is on disk. A host rebuild makes a new
|
|
3610
3618
|
* instance, which is the right reset. Bounded by the project's entry count,
|
|
@@ -3623,6 +3631,16 @@ class ValOps {
|
|
|
3623
3631
|
this.modulesErrors = null;
|
|
3624
3632
|
this.shaEntries = null;
|
|
3625
3633
|
this.shaModuleErrors = null;
|
|
3634
|
+
for (const [moduleFilePath, entries] of (options === null || options === void 0 ? void 0 : options.snapshotJsonEntries) ?? []) {
|
|
3635
|
+
const adopted = new Map();
|
|
3636
|
+
for (const [entryKey, content] of entries) {
|
|
3637
|
+
adopted.set(entryKey, {
|
|
3638
|
+
kind: "content",
|
|
3639
|
+
content
|
|
3640
|
+
});
|
|
3641
|
+
}
|
|
3642
|
+
this.adoptedJsonEntries.set(moduleFilePath, adopted);
|
|
3643
|
+
}
|
|
3626
3644
|
}
|
|
3627
3645
|
|
|
3628
3646
|
// #region stat
|
|
@@ -3764,7 +3782,13 @@ class ValOps {
|
|
|
3764
3782
|
}
|
|
3765
3783
|
const adopted = this.adoptedJsonEntries.get(moduleFilePath) ?? new Map();
|
|
3766
3784
|
for (const [entryKey, content] of Object.entries(entries)) {
|
|
3767
|
-
|
|
3785
|
+
// A commit's `null` is a deleted entry: see `patchedJsonEntries`.
|
|
3786
|
+
adopted.set(entryKey, content === null ? {
|
|
3787
|
+
kind: "deleted"
|
|
3788
|
+
} : {
|
|
3789
|
+
kind: "content",
|
|
3790
|
+
content
|
|
3791
|
+
});
|
|
3768
3792
|
}
|
|
3769
3793
|
this.adoptedJsonEntries.set(moduleFilePath, adopted);
|
|
3770
3794
|
}
|
|
@@ -3998,6 +4022,7 @@ class ValOps {
|
|
|
3998
4022
|
}
|
|
3999
4023
|
}
|
|
4000
4024
|
const loaded = await Promise.all([...requestedKeys, ...sourceKeys].map(async entryKey => {
|
|
4025
|
+
var _this$adoptedJsonEntr, _this$siteSourcesBefo;
|
|
4001
4026
|
const marker = record[entryKey];
|
|
4002
4027
|
if (marker !== undefined && !Internal.isJson(marker)) {
|
|
4003
4028
|
// Not a jsonValues entry — return the inlined value as-is (defensive).
|
|
@@ -4032,15 +4057,20 @@ class ValOps {
|
|
|
4032
4057
|
* The BASELINE only. Pending patches replay over it below exactly as
|
|
4033
4058
|
* they do over the thunk's answer.
|
|
4034
4059
|
*/
|
|
4035
|
-
const adopted = this.adoptedJsonEntries.get(moduleFilePath);
|
|
4036
|
-
if (adopted !== undefined
|
|
4037
|
-
const content = adopted.get(entryKey);
|
|
4060
|
+
const adopted = (_this$adoptedJsonEntr = this.adoptedJsonEntries.get(moduleFilePath)) === null || _this$adoptedJsonEntr === void 0 ? void 0 : _this$adoptedJsonEntr.get(entryKey);
|
|
4061
|
+
if (adopted !== undefined) {
|
|
4038
4062
|
return {
|
|
4039
4063
|
entryKey,
|
|
4040
|
-
baseContent:
|
|
4064
|
+
baseContent: adopted.kind === "deleted" ? undefined : adopted.content
|
|
4041
4065
|
};
|
|
4042
4066
|
}
|
|
4043
|
-
|
|
4067
|
+
/*
|
|
4068
|
+
* A snapshot's marker came as JSON, with no import behind it: the
|
|
4069
|
+
* entry the proposal did not save is the build's, behind the marker
|
|
4070
|
+
* the module evaluated to.
|
|
4071
|
+
*/
|
|
4072
|
+
const siteMarker = (_this$siteSourcesBefo = this.siteSourcesBeforeSnapshot) === null || _this$siteSourcesBefo === void 0 || (_this$siteSourcesBefo = _this$siteSourcesBefo[moduleFilePath]) === null || _this$siteSourcesBefo === void 0 ? void 0 : _this$siteSourcesBefo[entryKey];
|
|
4073
|
+
const thunk = Internal.getJsonImport(marker) ?? (Internal.isJson(siteMarker) ? Internal.getJsonImport(siteMarker) : undefined);
|
|
4044
4074
|
if (!thunk) {
|
|
4045
4075
|
return {
|
|
4046
4076
|
entryKey,
|
|
@@ -8951,6 +8981,116 @@ function proposalSnapshot(proposal) {
|
|
|
8951
8981
|
}
|
|
8952
8982
|
return snapshot;
|
|
8953
8983
|
}
|
|
8984
|
+
|
|
8985
|
+
/**
|
|
8986
|
+
* The `.jsonValues()` entries the proposal saved, by module and key.
|
|
8987
|
+
*
|
|
8988
|
+
* An entry's content is not in its module's Source -- that holds a marker per
|
|
8989
|
+
* entry -- but in the entry's own `*.val.json`, and a save writes that file:
|
|
8990
|
+
* it reaches the proposal's address as saved TEXT ({@link ValProposal.files}),
|
|
8991
|
+
* not as Source. So the snapshot alone shows the build's entries. This is the
|
|
8992
|
+
* other half: each saved `*.val.json`, read as the entry its module names.
|
|
8993
|
+
*
|
|
8994
|
+
* Which entry a file is comes from the module's `.val.ts`, whose
|
|
8995
|
+
* `c.json(() => import("..."))` thunks name the files -- the saved text if
|
|
8996
|
+
* the save rewrote it, else the build's own (`projectSource`). An entry whose
|
|
8997
|
+
* module cannot be read that way is left to the build, as before: this adds
|
|
8998
|
+
* what it can find and never fails the address.
|
|
8999
|
+
*/
|
|
9000
|
+
function proposalJsonEntries(proposal, projectSource) {
|
|
9001
|
+
const found = new Map();
|
|
9002
|
+
const savedJson = Object.keys(proposal.files).filter(path => path.endsWith(".val.json"));
|
|
9003
|
+
if (savedJson.length === 0) return found;
|
|
9004
|
+
const savedJsonPaths = new Set(savedJson);
|
|
9005
|
+
for (const [moduleFilePath, source] of Object.entries(proposal.modules)) {
|
|
9006
|
+
if (!holdsJsonMarkers(source)) continue;
|
|
9007
|
+
const relative = moduleFilePath.replace(/^\//, "");
|
|
9008
|
+
const text = proposal.files[relative] ?? (projectSource === null || projectSource === void 0 ? void 0 : projectSource[relative]);
|
|
9009
|
+
if (text === undefined) continue;
|
|
9010
|
+
const entries = jsonEntryPaths(relative, text);
|
|
9011
|
+
if (entries === null) continue;
|
|
9012
|
+
const byKey = new Map();
|
|
9013
|
+
for (const [key, importPath] of entries) {
|
|
9014
|
+
const jsonPath = resolveExistingJsonPath(moduleFilePath, importPath).replace(/^\//, "");
|
|
9015
|
+
if (!savedJsonPaths.has(jsonPath)) continue;
|
|
9016
|
+
const content = parseJson(proposal.files[jsonPath]);
|
|
9017
|
+
if (content !== undefined) byKey.set(key, content);
|
|
9018
|
+
}
|
|
9019
|
+
if (byKey.size > 0) found.set(moduleFilePath, byKey);
|
|
9020
|
+
}
|
|
9021
|
+
return found;
|
|
9022
|
+
}
|
|
9023
|
+
|
|
9024
|
+
/**
|
|
9025
|
+
* The snapshot as a page reads it: {@link proposalSnapshot}, with each saved
|
|
9026
|
+
* `.jsonValues()` entry's content in place of its marker -- the shape a draft
|
|
9027
|
+
* already has, where the entries it edits hold content and the rest are
|
|
9028
|
+
* markers the readers resolve from the build. See {@link proposalJsonEntries}.
|
|
9029
|
+
*
|
|
9030
|
+
* For the readers only. Val's own server keeps the markers
|
|
9031
|
+
* ({@link proposalSnapshot}): its patching works on them, and it takes the
|
|
9032
|
+
* saved entries separately.
|
|
9033
|
+
*/
|
|
9034
|
+
function proposalSnapshotForReaders(proposal, projectSource) {
|
|
9035
|
+
const snapshot = proposalSnapshot(proposal);
|
|
9036
|
+
for (const [moduleFilePath, entries] of proposalJsonEntries(proposal, projectSource)) {
|
|
9037
|
+
const source = snapshot[moduleFilePath];
|
|
9038
|
+
if (!isObject$1(source)) continue;
|
|
9039
|
+
const filled = {};
|
|
9040
|
+
for (const [key, value] of Object.entries(source)) {
|
|
9041
|
+
if (isJsonValue(value)) filled[key] = value;
|
|
9042
|
+
}
|
|
9043
|
+
for (const [key, content] of entries) {
|
|
9044
|
+
// Own keys only: an entry may be named `toString`.
|
|
9045
|
+
if (Object.prototype.hasOwnProperty.call(filled, key)) {
|
|
9046
|
+
filled[key] = content;
|
|
9047
|
+
}
|
|
9048
|
+
}
|
|
9049
|
+
snapshot[moduleFilePath] = filled;
|
|
9050
|
+
}
|
|
9051
|
+
return snapshot;
|
|
9052
|
+
}
|
|
9053
|
+
|
|
9054
|
+
/** A record of `.jsonValues()` markers (`{ _type: "json" }`), at least one. */
|
|
9055
|
+
function holdsJsonMarkers(source) {
|
|
9056
|
+
return isObject$1(source) && Object.values(source).some(value => isObject$1(value) && value["_type"] === "json");
|
|
9057
|
+
}
|
|
9058
|
+
|
|
9059
|
+
/** Each entry key's import path, from a `.jsonValues()` module's text. */
|
|
9060
|
+
function jsonEntryPaths(fileName, text) {
|
|
9061
|
+
try {
|
|
9062
|
+
const analysis = analyzeValModule(ts.createSourceFile(fileName, text, ts.ScriptTarget.ES2015, true));
|
|
9063
|
+
if (result.isErr(analysis)) return null;
|
|
9064
|
+
const paths = new Map();
|
|
9065
|
+
for (const [key, entry] of analyzeJsonValuesEntries(analysis.value.source)) {
|
|
9066
|
+
paths.set(key, entry.importPath);
|
|
9067
|
+
}
|
|
9068
|
+
return paths;
|
|
9069
|
+
} catch {
|
|
9070
|
+
// Not a module this can read: its entries stay the build's.
|
|
9071
|
+
return null;
|
|
9072
|
+
}
|
|
9073
|
+
}
|
|
9074
|
+
function parseJson(text) {
|
|
9075
|
+
if (text === undefined) return undefined;
|
|
9076
|
+
try {
|
|
9077
|
+
const value = JSON.parse(text);
|
|
9078
|
+
return isMutableJsonValue(value) ? value : undefined;
|
|
9079
|
+
} catch {
|
|
9080
|
+
return undefined;
|
|
9081
|
+
}
|
|
9082
|
+
}
|
|
9083
|
+
|
|
9084
|
+
/** {@link isJsonValue}, for the mutable JSON a server patches. */
|
|
9085
|
+
function isMutableJsonValue(value) {
|
|
9086
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
9087
|
+
return true;
|
|
9088
|
+
}
|
|
9089
|
+
if (Array.isArray(value)) {
|
|
9090
|
+
return value.every(isMutableJsonValue);
|
|
9091
|
+
}
|
|
9092
|
+
return isObject$1(value) && Object.values(value).every(isMutableJsonValue);
|
|
9093
|
+
}
|
|
8954
9094
|
function isObject$1(value) {
|
|
8955
9095
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8956
9096
|
}
|
|
@@ -9395,7 +9535,8 @@ class ValOpsHttp extends ValOps {
|
|
|
9395
9535
|
auth, valModules, options) {
|
|
9396
9536
|
super(valModules, options !== null && options !== void 0 && options.proposal ? {
|
|
9397
9537
|
...options,
|
|
9398
|
-
snapshotSources: proposalSnapshot(options.proposal)
|
|
9538
|
+
snapshotSources: proposalSnapshot(options.proposal),
|
|
9539
|
+
snapshotJsonEntries: proposalJsonEntries(options.proposal, options.projectSource)
|
|
9399
9540
|
} : options);
|
|
9400
9541
|
this.contentUrl = contentUrl;
|
|
9401
9542
|
this.project = project;
|
|
@@ -23901,4 +24042,4 @@ function readCapturedReport(snapshotDir) {
|
|
|
23901
24042
|
return JSON.parse(fs.readFileSync(reportPath, "utf-8"));
|
|
23902
24043
|
}
|
|
23903
24044
|
|
|
23904
|
-
export { APP_MODE_REQUIRES_REMOTE_FILES, DEFAULT_LOGIN_EXPIRES_IN_SECONDS, DEFAULT_LOGIN_HOST, DEFAULT_LOGIN_POLL_INTERVAL_SECONDS, EXTERNAL_RESULT, InMemoryPatchStore, Service, ValFSHost, ValLoginError, ValModuleLoader, ValOpsFS, ValOpsHttp, ValOpsMemory, ValSourceFileHandler, analyzeValModule, awaitValLoginConfirmation, checkRemoteRef, classifyJsonValuesOp, compareWithCapturedReport, createDefaultValFSHost, createFixPatch, createJsonEntryPathMap, createModulePathMap, createPrettierFormatter, createService, createValApiRouter, createValModuleFileInspector, createValOps, createValServer, currentFixHandlers, decodeJwtWithoutVerifying, defineExternal, describePatchStoreProblems, downloadFileFromRemote, encodeJwt, err, evalValConfigFile, extractFileMetadata, extractImageMetadata, extractJsonValuesEntry, extractVideoMetadata, extractVideoMetadataFromFile, filesOfVideo, filesOfVideosetEntry, findAndEvalValConfigFile, findDefaultExport, findJsonEntryFilePath, fixHandlers, formatPatchSourceError, formatSyntaxErrorTree, getCachedRemoteFileDir, getCachedRemoteFilePath, getCompilerOptions, getExpire, getFileExt, getModulePathRange, getPersonalAccessTokenPath, getSettings, getValidationErrorFileRef, handleCheckAllFiles, handleExternalUpload, handleFileMetadata, handleJsonValuesExtractEntry, handleRemoteFileCheck, handleRemoteFileDownload, handleRemoteFileUpload, handleRemoteGalleryFileUpload, handleUniqueFolderCheck, handleVideosetCheckAllFiles, handleVideosetCheckRemote, handleVideosetMetadata, handleVideosetUploadRemote, initHandlerOptions, isExternalResult, loadValModules, ok, parsePersonalAccessTokenFile, patchSourceFile, persistPersonalAccessToken, planJsonValuesEntryExtraction, proposalFromEnv, proposalSnapshot, readCapturedReport, readPatchStore, rebaseContentOp, replaySnapshot, resolveRemoteFileAuth, safeReadGit, startValLogin, uploadRemoteFile, validateMetadata, verifyJwt, videosetEntryVideoSchema };
|
|
24045
|
+
export { APP_MODE_REQUIRES_REMOTE_FILES, DEFAULT_LOGIN_EXPIRES_IN_SECONDS, DEFAULT_LOGIN_HOST, DEFAULT_LOGIN_POLL_INTERVAL_SECONDS, EXTERNAL_RESULT, InMemoryPatchStore, Service, ValFSHost, ValLoginError, ValModuleLoader, ValOpsFS, ValOpsHttp, ValOpsMemory, ValSourceFileHandler, analyzeValModule, awaitValLoginConfirmation, checkRemoteRef, classifyJsonValuesOp, compareWithCapturedReport, createDefaultValFSHost, createFixPatch, createJsonEntryPathMap, createModulePathMap, createPrettierFormatter, createService, createValApiRouter, createValModuleFileInspector, createValOps, createValServer, currentFixHandlers, decodeJwtWithoutVerifying, defineExternal, describePatchStoreProblems, downloadFileFromRemote, encodeJwt, err, evalValConfigFile, extractFileMetadata, extractImageMetadata, extractJsonValuesEntry, extractVideoMetadata, extractVideoMetadataFromFile, filesOfVideo, filesOfVideosetEntry, findAndEvalValConfigFile, findDefaultExport, findJsonEntryFilePath, fixHandlers, formatPatchSourceError, formatSyntaxErrorTree, getCachedRemoteFileDir, getCachedRemoteFilePath, getCompilerOptions, getExpire, getFileExt, getModulePathRange, getPersonalAccessTokenPath, getSettings, getValidationErrorFileRef, handleCheckAllFiles, handleExternalUpload, handleFileMetadata, handleJsonValuesExtractEntry, handleRemoteFileCheck, handleRemoteFileDownload, handleRemoteFileUpload, handleRemoteGalleryFileUpload, handleUniqueFolderCheck, handleVideosetCheckAllFiles, handleVideosetCheckRemote, handleVideosetMetadata, handleVideosetUploadRemote, initHandlerOptions, isExternalResult, loadValModules, ok, parsePersonalAccessTokenFile, patchSourceFile, persistPersonalAccessToken, planJsonValuesEntryExtraction, proposalFromEnv, proposalSnapshot, proposalSnapshotForReaders, readCapturedReport, readPatchStore, rebaseContentOp, replaySnapshot, resolveRemoteFileAuth, safeReadGit, startValLogin, uploadRemoteFile, validateMetadata, verifyJwt, videosetEntryVideoSchema };
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"./package.json": "./package.json"
|
|
17
17
|
},
|
|
18
18
|
"types": "dist/valbuild-server.cjs.d.ts",
|
|
19
|
-
"version": "0.144.
|
|
19
|
+
"version": "0.144.1",
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@prettier/sync": "^0.6.1",
|
|
22
22
|
"@types/jest": "^30.0.0",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"typescript": "^6.0.3",
|
|
31
31
|
"zod": "^4.4.3",
|
|
32
32
|
"zod-validation-error": "^5.0.0",
|
|
33
|
-
"@valbuild/core": "0.144.0",
|
|
34
33
|
"@valbuild/shared": "0.144.0",
|
|
35
|
-
"@valbuild/ui": "0.144.0"
|
|
34
|
+
"@valbuild/ui": "0.144.0",
|
|
35
|
+
"@valbuild/core": "0.144.0"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|
|
38
38
|
"node": "^20.19.0 || >=22"
|