@valbuild/server 0.130.0 → 0.132.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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,102 @@
|
|
|
1
1
|
# @valbuild/server
|
|
2
2
|
|
|
3
|
+
## 0.132.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#689](https://github.com/valbuild/val/pull/689) [`72cc676`](https://github.com/valbuild/val/commit/72cc6765e92a6e72b5c09ddd9eed8efa7ce899f2) Thanks [@freekh](https://github.com/freekh)! - `VAL_ENV=app` selects `http` mode.
|
|
8
|
+
|
|
9
|
+
A host knows WHERE it is running; which Val mode that implies is Val's to
|
|
10
|
+
derive. `VAL_ENV=app` says "this is the Val app" — a project built in a browser
|
|
11
|
+
and served from a Worker isolate — and Val reads that as http mode: there is no
|
|
12
|
+
disk, so `fs` is never the right fall-through, and the content is Val's own,
|
|
13
|
+
read over HTTP at a commit like any other deployed app.
|
|
14
|
+
|
|
15
|
+
Unlike `VAL_MODE=memory`, this **selects** the mode rather than only refusing a
|
|
16
|
+
fall-through, because everything http mode needs is an environment variable. The
|
|
17
|
+
point is what happens when one is missing: inference reads an absent
|
|
18
|
+
`VAL_API_KEY` as "not a proxy" and resolves `fs` mode, which in an isolate fails
|
|
19
|
+
on `.val/patches.lock` — a path, two layers below the actual mistake. Now each
|
|
20
|
+
of `VAL_API_KEY`, `VAL_SECRET`, `VAL_PROJECT`, `VAL_GIT_COMMIT` and
|
|
21
|
+
`VAL_GIT_BRANCH` is named when it is the one that is not set, and the message
|
|
22
|
+
says which variable put the app in http mode.
|
|
23
|
+
|
|
24
|
+
An explicit `VAL_MODE` still wins, including when it is a typo that has to be
|
|
25
|
+
refused, and `http` is still not a value `VAL_MODE` accepts. A host that passes
|
|
26
|
+
`sourceFiles` still gets memory mode: that is checked before the environment is
|
|
27
|
+
consulted at all, so a build published by an older platform keeps working.
|
|
28
|
+
|
|
29
|
+
## 0.131.0
|
|
30
|
+
|
|
31
|
+
### Minor Changes
|
|
32
|
+
|
|
33
|
+
- [#686](https://github.com/valbuild/val/pull/686) [`0d5857b`](https://github.com/valbuild/val/commit/0d5857b731e11f7e6a011f79297df6485908c31f) Thanks [@freekh](https://github.com/freekh)! - Say `VAL_MODE=memory` where there is no disk, and get a sentence instead of an `EPERM`
|
|
34
|
+
|
|
35
|
+
Memory mode — the one for a host that holds the project's source itself — is
|
|
36
|
+
selected by passing `sourceFiles`, and it has to be: nothing in an environment
|
|
37
|
+
can supply a project's source, so a mode that an env var could switch on would
|
|
38
|
+
be a server with no content in it.
|
|
39
|
+
|
|
40
|
+
The cost was the failure when a host forgot. Val inferred `fs` mode, `fs` mode
|
|
41
|
+
went looking for a working tree, and in a Worker isolate the first thing to
|
|
42
|
+
touch the disk failed:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
patch-error /bundle/.val/patches.lock: EPERM
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
That names a path two layers below the decision that caused it, and nobody
|
|
49
|
+
reading it would guess "your server was configured for the wrong mode".
|
|
50
|
+
|
|
51
|
+
So an environment can now DECLARE that it has no disk:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
VAL_MODE=memory
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
It does not turn memory mode on. It says the host is supposed to be supplying
|
|
58
|
+
`sourceFiles`, so if none arrive, Val refuses at configuration time and says
|
|
59
|
+
where to pass them. `VAL_MODE=` counts as unset, the way a shell means it; any
|
|
60
|
+
other value is refused rather than ignored, since leaving you in `fs` mode is
|
|
61
|
+
the exact failure this is meant to catch.
|
|
62
|
+
|
|
63
|
+
**`initValContent` takes the same options, and this is the release that
|
|
64
|
+
noticed.** It builds a Val server of its own — these readers resolve content by
|
|
65
|
+
asking it, not by calling the API over HTTP — so configuring `initValServer`
|
|
66
|
+
alone left them inferring `fs` mode. On a host with no filesystem that is a
|
|
67
|
+
reader looking for a working tree that is not there; it went unnoticed because
|
|
68
|
+
published reads still worked.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const patchStore = new InMemoryPatchStore(); // now exported from this package
|
|
72
|
+
|
|
73
|
+
const { valApiHandler, draftMode } = initValServer(valModules, config, {
|
|
74
|
+
sourceFiles: FILES,
|
|
75
|
+
patchStore,
|
|
76
|
+
unsafelyAllowUnauthenticated: true,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const { fetchValStega } = initValContent(config, valModules, {
|
|
80
|
+
draftMode,
|
|
81
|
+
// The same three. Two patch stores are two sets of pending edits, and a
|
|
82
|
+
// reader that checks a session the host never issues answers itself 401 and
|
|
83
|
+
// falls back to published content — a draft render showing the live site.
|
|
84
|
+
sourceFiles: FILES,
|
|
85
|
+
patchStore,
|
|
86
|
+
unsafelyAllowUnauthenticated: true,
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
All three are optional. Left out, this reader gets its own store and its own
|
|
91
|
+
answer about authentication, which is right for published content.
|
|
92
|
+
|
|
93
|
+
`@valbuild/next` has no memory mode: its `initValServer` takes neither option,
|
|
94
|
+
so for a Next app `VAL_MODE=memory` names an environment Val cannot serve from,
|
|
95
|
+
and the error says so.
|
|
96
|
+
|
|
97
|
+
Nothing changes for an app that sets none of this: `http` when `VAL_API_KEY`
|
|
98
|
+
and `VAL_SECRET` are both present, `fs` otherwise, as before.
|
|
99
|
+
|
|
3
100
|
## 0.130.0
|
|
4
101
|
|
|
5
102
|
### Minor Changes
|
|
@@ -61,6 +61,11 @@ type ValServerOverrides = Partial<{
|
|
|
61
61
|
* and "proxy" this one cannot be inferred from the environment -- there is
|
|
62
62
|
* nothing to infer it FROM, and a mode that can be turned on without
|
|
63
63
|
* supplying the source would be a server with no content in it.
|
|
64
|
+
*
|
|
65
|
+
* An environment that has no disk can still say it EXPECTS this, by setting
|
|
66
|
+
* `VAL_MODE=memory`. That does not select the mode; it makes forgetting to
|
|
67
|
+
* pass the source an error here rather than an `EPERM` from `fs` mode two
|
|
68
|
+
* layers down.
|
|
64
69
|
*/
|
|
65
70
|
sourceFiles: Record<string, string>;
|
|
66
71
|
/**
|
|
@@ -10051,6 +10051,67 @@ function parsePersonalAccessTokenFile(content) {
|
|
|
10051
10051
|
|
|
10052
10052
|
const DEFAULT_VAL_BUILD_URL = "https://admin.val.build";
|
|
10053
10053
|
|
|
10054
|
+
/**
|
|
10055
|
+
* The value of `VAL_ENV` that means "this is the Val app".
|
|
10056
|
+
*
|
|
10057
|
+
* The Val app builds a project in a browser and runs it in a Worker isolate.
|
|
10058
|
+
* There is no disk there and there never will be, so `fs` mode is never the
|
|
10059
|
+
* right fall-through -- and the content is Val's own, reached over HTTP at a
|
|
10060
|
+
* commit, exactly as it is for any other deployed app. So this names `http`.
|
|
10061
|
+
*
|
|
10062
|
+
* What makes the app unusual is not where its content comes from but what
|
|
10063
|
+
* publishing means: the browser rebuilds the site and the new build is served
|
|
10064
|
+
* immediately, instead of a host noticing a commit and redeploying. That is a
|
|
10065
|
+
* difference in what happens AFTER the commit, and `publishOverride` is where
|
|
10066
|
+
* a host says so -- not a difference in where patches, files or sources live.
|
|
10067
|
+
*
|
|
10068
|
+
* A host says WHERE it runs, which is a fact it knows. Which Val mode that
|
|
10069
|
+
* implies is Val's to derive, and that is the whole reason this exists next to
|
|
10070
|
+
* `VAL_MODE` rather than the platform naming a mode itself: one is a
|
|
10071
|
+
* description of an environment, the other an assertion about Val's internals,
|
|
10072
|
+
* and only the first stays true when the internals move. They have already
|
|
10073
|
+
* moved once -- this meant `memory` while the app kept its own patch store --
|
|
10074
|
+
* and no platform had to be changed to follow.
|
|
10075
|
+
*/
|
|
10076
|
+
const VAL_APP_ENV = "app";
|
|
10077
|
+
|
|
10078
|
+
/** Which mode the environment SAYS this is, and which variable said so. */
|
|
10079
|
+
|
|
10080
|
+
/**
|
|
10081
|
+
* `null` is "the environment did not say", which is the normal case.
|
|
10082
|
+
*
|
|
10083
|
+
* The two variables differ in what can be DONE with an answer, and the
|
|
10084
|
+
* difference is whether the environment holds everything the mode needs.
|
|
10085
|
+
* `http` does -- an api key, a secret, a project, a commit and a branch are all
|
|
10086
|
+
* env vars -- so `VAL_ENV=app` SELECTS it, and the checks in
|
|
10087
|
+
* {@link initHandlerOptions} name whichever one is missing. `memory` does not:
|
|
10088
|
+
* it needs the host's own source files, which nothing in an environment can
|
|
10089
|
+
* supply, so `VAL_MODE=memory` can only ever turn a fall-through into an error.
|
|
10090
|
+
*/
|
|
10091
|
+
function namedMode() {
|
|
10092
|
+
const declared = process.env.VAL_MODE;
|
|
10093
|
+
/*
|
|
10094
|
+
* An empty value counts as unset, which is what `VAL_MODE=` in a shell or a
|
|
10095
|
+
* CI settings page means. An explicit `VAL_MODE` otherwise wins over
|
|
10096
|
+
* `VAL_ENV`: naming a mode outright says something more specific than naming
|
|
10097
|
+
* an environment does, including when what it names is wrong and has to be
|
|
10098
|
+
* refused.
|
|
10099
|
+
*/
|
|
10100
|
+
if (declared !== undefined && declared !== "") {
|
|
10101
|
+
return {
|
|
10102
|
+
mode: declared,
|
|
10103
|
+
from: "VAL_MODE"
|
|
10104
|
+
};
|
|
10105
|
+
}
|
|
10106
|
+
if (process.env.VAL_ENV === VAL_APP_ENV) {
|
|
10107
|
+
return {
|
|
10108
|
+
mode: "http",
|
|
10109
|
+
from: "VAL_ENV"
|
|
10110
|
+
};
|
|
10111
|
+
}
|
|
10112
|
+
return null;
|
|
10113
|
+
}
|
|
10114
|
+
|
|
10054
10115
|
/**
|
|
10055
10116
|
* Resolve options plus environment into a concrete {@link ValServerConfig}.
|
|
10056
10117
|
*
|
|
@@ -10103,9 +10164,53 @@ async function initHandlerOptions(route, opts, config) {
|
|
|
10103
10164
|
config
|
|
10104
10165
|
};
|
|
10105
10166
|
}
|
|
10167
|
+
/*
|
|
10168
|
+
* The environment saying 'memory' means the host MEANT to hold the source,
|
|
10169
|
+
* and did not. Either variable can say it: `VAL_MODE=memory` outright, or
|
|
10170
|
+
* `VAL_ENV=app`, which names an environment that has no disk.
|
|
10171
|
+
*
|
|
10172
|
+
* Neither can SELECT memory mode -- nothing in the environment can supply
|
|
10173
|
+
* `sourceFiles`, and a mode turned on without them is a server with no
|
|
10174
|
+
* content in it. What they do is turn the fall-through into an error.
|
|
10175
|
+
*
|
|
10176
|
+
* Without it, a host that forgot to pass its source got `fs` mode, and `fs`
|
|
10177
|
+
* mode in a Worker isolate reaches for a working tree that is not there: the
|
|
10178
|
+
* failure is an `EPERM` on `.val/patches.lock`, several layers below the
|
|
10179
|
+
* mistake, naming a path rather than the decision that led to it. Every
|
|
10180
|
+
* environment that runs Val without a disk can set this once and get a
|
|
10181
|
+
* sentence instead.
|
|
10182
|
+
*/
|
|
10183
|
+
const declared = namedMode();
|
|
10184
|
+
if ((declared === null || declared === void 0 ? void 0 : declared.mode) === "memory") {
|
|
10185
|
+
throw new Error("VAL_MODE is 'memory', but no `sourceFiles` were given here, so there " + "is no source to serve. Memory mode cannot be turned on by the " + "environment: it needs the project's own source, and only the host " + "that holds it can hand it over. On TanStack Start that is the " + "`sourceFiles` option, passed to `initValServer` AND to " + "`initValContent`, which has a Val server of its own and is " + "configured separately. @valbuild/next has no memory mode yet, so " + "for a Next app this variable is set on an environment Val cannot " + "serve from. Unset VAL_MODE to go back to the inferred mode instead " + "('http' when VAL_API_KEY and VAL_SECRET are both set, 'fs' " + "otherwise).");
|
|
10186
|
+
}
|
|
10187
|
+
/*
|
|
10188
|
+
* Every other value is refused rather than ignored: ignoring `VAL_MODE=memry`
|
|
10189
|
+
* would leave the app in `fs` mode, which is the exact failure this variable
|
|
10190
|
+
* exists to catch.
|
|
10191
|
+
*
|
|
10192
|
+
* `VAL_ENV` is excluded by name rather than by its value happening to pass:
|
|
10193
|
+
* it names 'http', which is selected below, and a reader who sees only
|
|
10194
|
+
* `declared !== null` here would reasonably conclude that 'http' is a
|
|
10195
|
+
* `VAL_MODE` value -- it is not, and the message below says so.
|
|
10196
|
+
*/
|
|
10197
|
+
if (declared !== null && declared.from === "VAL_MODE") {
|
|
10198
|
+
throw new Error(`VAL_MODE is '${declared.mode}', which is not a mode Val knows. The only ` + "value it accepts is 'memory', which asserts that the host supplies " + "`sourceFiles`. 'fs' and 'http' are inferred rather than named: " + "'http' when VAL_API_KEY and VAL_SECRET are both set, 'fs' otherwise.");
|
|
10199
|
+
}
|
|
10106
10200
|
const maybeApiKey = opts.apiKey || process.env.VAL_API_KEY;
|
|
10107
10201
|
const maybeValSecret = opts.valSecret || process.env.VAL_SECRET;
|
|
10108
|
-
|
|
10202
|
+
/*
|
|
10203
|
+
* The app's environment selects http mode, rather than leaving it to be
|
|
10204
|
+
* inferred from a credential being present.
|
|
10205
|
+
*
|
|
10206
|
+
* The difference shows when something is MISSING. Inference reads an absent
|
|
10207
|
+
* api key as "not a proxy" and falls through to `fs`, which in an isolate
|
|
10208
|
+
* reaches for a working tree that is not there -- an `EPERM` on
|
|
10209
|
+
* `.val/patches.lock`, several layers below the mistake. Selecting the mode
|
|
10210
|
+
* means the checks below run instead, and each one names what it wanted.
|
|
10211
|
+
*/
|
|
10212
|
+
const isAppEnv = (declared === null || declared === void 0 ? void 0 : declared.from) === "VAL_ENV";
|
|
10213
|
+
const isProxyMode = opts.mode === "proxy" || isAppEnv || opts.mode === undefined && (maybeApiKey || maybeValSecret);
|
|
10109
10214
|
const valEnableRedirectUrl = opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL;
|
|
10110
10215
|
const valDisableRedirectUrl = opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL;
|
|
10111
10216
|
const maybeValProject = opts.project || process.env.VAL_PROJECT;
|
|
@@ -10117,19 +10222,28 @@ async function initHandlerOptions(route, opts, config) {
|
|
|
10117
10222
|
});
|
|
10118
10223
|
if (isProxyMode) {
|
|
10119
10224
|
var _opts$versions, _opts$versions2;
|
|
10225
|
+
/*
|
|
10226
|
+
* Why this app is in http mode, in the message that says what is missing.
|
|
10227
|
+
*
|
|
10228
|
+
* "must be set in proxy mode" is a fine sentence for a developer who wrote
|
|
10229
|
+
* `mode: "proxy"` and a poor one for an app that never mentioned a mode:
|
|
10230
|
+
* there, the answer to "why am I in proxy mode?" is a variable set by the
|
|
10231
|
+
* platform, in a file the reader of this error is not looking at.
|
|
10232
|
+
*/
|
|
10233
|
+
const because = isAppEnv ? " (VAL_ENV is 'app', which is the Val app: its content is Val's own " + "and is read over HTTP at a commit, so http mode is the mode and " + "these are what it needs)" : "";
|
|
10120
10234
|
if (!maybeApiKey || !maybeValSecret) {
|
|
10121
|
-
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode");
|
|
10235
|
+
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode" + because);
|
|
10122
10236
|
}
|
|
10123
10237
|
const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
|
|
10124
10238
|
if (!maybeGitCommit) {
|
|
10125
|
-
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode");
|
|
10239
|
+
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode" + because);
|
|
10126
10240
|
}
|
|
10127
10241
|
const maybeGitBranch = opts.gitBranch || process.env.VAL_GIT_BRANCH;
|
|
10128
10242
|
if (!maybeGitBranch) {
|
|
10129
|
-
throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode");
|
|
10243
|
+
throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode" + because);
|
|
10130
10244
|
}
|
|
10131
10245
|
if (!maybeValProject) {
|
|
10132
|
-
throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set.");
|
|
10246
|
+
throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set." + because);
|
|
10133
10247
|
}
|
|
10134
10248
|
const coreVersion = (_opts$versions = opts.versions) === null || _opts$versions === void 0 ? void 0 : _opts$versions.core;
|
|
10135
10249
|
if (!coreVersion) {
|
|
@@ -10051,6 +10051,67 @@ function parsePersonalAccessTokenFile(content) {
|
|
|
10051
10051
|
|
|
10052
10052
|
const DEFAULT_VAL_BUILD_URL = "https://admin.val.build";
|
|
10053
10053
|
|
|
10054
|
+
/**
|
|
10055
|
+
* The value of `VAL_ENV` that means "this is the Val app".
|
|
10056
|
+
*
|
|
10057
|
+
* The Val app builds a project in a browser and runs it in a Worker isolate.
|
|
10058
|
+
* There is no disk there and there never will be, so `fs` mode is never the
|
|
10059
|
+
* right fall-through -- and the content is Val's own, reached over HTTP at a
|
|
10060
|
+
* commit, exactly as it is for any other deployed app. So this names `http`.
|
|
10061
|
+
*
|
|
10062
|
+
* What makes the app unusual is not where its content comes from but what
|
|
10063
|
+
* publishing means: the browser rebuilds the site and the new build is served
|
|
10064
|
+
* immediately, instead of a host noticing a commit and redeploying. That is a
|
|
10065
|
+
* difference in what happens AFTER the commit, and `publishOverride` is where
|
|
10066
|
+
* a host says so -- not a difference in where patches, files or sources live.
|
|
10067
|
+
*
|
|
10068
|
+
* A host says WHERE it runs, which is a fact it knows. Which Val mode that
|
|
10069
|
+
* implies is Val's to derive, and that is the whole reason this exists next to
|
|
10070
|
+
* `VAL_MODE` rather than the platform naming a mode itself: one is a
|
|
10071
|
+
* description of an environment, the other an assertion about Val's internals,
|
|
10072
|
+
* and only the first stays true when the internals move. They have already
|
|
10073
|
+
* moved once -- this meant `memory` while the app kept its own patch store --
|
|
10074
|
+
* and no platform had to be changed to follow.
|
|
10075
|
+
*/
|
|
10076
|
+
const VAL_APP_ENV = "app";
|
|
10077
|
+
|
|
10078
|
+
/** Which mode the environment SAYS this is, and which variable said so. */
|
|
10079
|
+
|
|
10080
|
+
/**
|
|
10081
|
+
* `null` is "the environment did not say", which is the normal case.
|
|
10082
|
+
*
|
|
10083
|
+
* The two variables differ in what can be DONE with an answer, and the
|
|
10084
|
+
* difference is whether the environment holds everything the mode needs.
|
|
10085
|
+
* `http` does -- an api key, a secret, a project, a commit and a branch are all
|
|
10086
|
+
* env vars -- so `VAL_ENV=app` SELECTS it, and the checks in
|
|
10087
|
+
* {@link initHandlerOptions} name whichever one is missing. `memory` does not:
|
|
10088
|
+
* it needs the host's own source files, which nothing in an environment can
|
|
10089
|
+
* supply, so `VAL_MODE=memory` can only ever turn a fall-through into an error.
|
|
10090
|
+
*/
|
|
10091
|
+
function namedMode() {
|
|
10092
|
+
const declared = process.env.VAL_MODE;
|
|
10093
|
+
/*
|
|
10094
|
+
* An empty value counts as unset, which is what `VAL_MODE=` in a shell or a
|
|
10095
|
+
* CI settings page means. An explicit `VAL_MODE` otherwise wins over
|
|
10096
|
+
* `VAL_ENV`: naming a mode outright says something more specific than naming
|
|
10097
|
+
* an environment does, including when what it names is wrong and has to be
|
|
10098
|
+
* refused.
|
|
10099
|
+
*/
|
|
10100
|
+
if (declared !== undefined && declared !== "") {
|
|
10101
|
+
return {
|
|
10102
|
+
mode: declared,
|
|
10103
|
+
from: "VAL_MODE"
|
|
10104
|
+
};
|
|
10105
|
+
}
|
|
10106
|
+
if (process.env.VAL_ENV === VAL_APP_ENV) {
|
|
10107
|
+
return {
|
|
10108
|
+
mode: "http",
|
|
10109
|
+
from: "VAL_ENV"
|
|
10110
|
+
};
|
|
10111
|
+
}
|
|
10112
|
+
return null;
|
|
10113
|
+
}
|
|
10114
|
+
|
|
10054
10115
|
/**
|
|
10055
10116
|
* Resolve options plus environment into a concrete {@link ValServerConfig}.
|
|
10056
10117
|
*
|
|
@@ -10103,9 +10164,53 @@ async function initHandlerOptions(route, opts, config) {
|
|
|
10103
10164
|
config
|
|
10104
10165
|
};
|
|
10105
10166
|
}
|
|
10167
|
+
/*
|
|
10168
|
+
* The environment saying 'memory' means the host MEANT to hold the source,
|
|
10169
|
+
* and did not. Either variable can say it: `VAL_MODE=memory` outright, or
|
|
10170
|
+
* `VAL_ENV=app`, which names an environment that has no disk.
|
|
10171
|
+
*
|
|
10172
|
+
* Neither can SELECT memory mode -- nothing in the environment can supply
|
|
10173
|
+
* `sourceFiles`, and a mode turned on without them is a server with no
|
|
10174
|
+
* content in it. What they do is turn the fall-through into an error.
|
|
10175
|
+
*
|
|
10176
|
+
* Without it, a host that forgot to pass its source got `fs` mode, and `fs`
|
|
10177
|
+
* mode in a Worker isolate reaches for a working tree that is not there: the
|
|
10178
|
+
* failure is an `EPERM` on `.val/patches.lock`, several layers below the
|
|
10179
|
+
* mistake, naming a path rather than the decision that led to it. Every
|
|
10180
|
+
* environment that runs Val without a disk can set this once and get a
|
|
10181
|
+
* sentence instead.
|
|
10182
|
+
*/
|
|
10183
|
+
const declared = namedMode();
|
|
10184
|
+
if ((declared === null || declared === void 0 ? void 0 : declared.mode) === "memory") {
|
|
10185
|
+
throw new Error("VAL_MODE is 'memory', but no `sourceFiles` were given here, so there " + "is no source to serve. Memory mode cannot be turned on by the " + "environment: it needs the project's own source, and only the host " + "that holds it can hand it over. On TanStack Start that is the " + "`sourceFiles` option, passed to `initValServer` AND to " + "`initValContent`, which has a Val server of its own and is " + "configured separately. @valbuild/next has no memory mode yet, so " + "for a Next app this variable is set on an environment Val cannot " + "serve from. Unset VAL_MODE to go back to the inferred mode instead " + "('http' when VAL_API_KEY and VAL_SECRET are both set, 'fs' " + "otherwise).");
|
|
10186
|
+
}
|
|
10187
|
+
/*
|
|
10188
|
+
* Every other value is refused rather than ignored: ignoring `VAL_MODE=memry`
|
|
10189
|
+
* would leave the app in `fs` mode, which is the exact failure this variable
|
|
10190
|
+
* exists to catch.
|
|
10191
|
+
*
|
|
10192
|
+
* `VAL_ENV` is excluded by name rather than by its value happening to pass:
|
|
10193
|
+
* it names 'http', which is selected below, and a reader who sees only
|
|
10194
|
+
* `declared !== null` here would reasonably conclude that 'http' is a
|
|
10195
|
+
* `VAL_MODE` value -- it is not, and the message below says so.
|
|
10196
|
+
*/
|
|
10197
|
+
if (declared !== null && declared.from === "VAL_MODE") {
|
|
10198
|
+
throw new Error(`VAL_MODE is '${declared.mode}', which is not a mode Val knows. The only ` + "value it accepts is 'memory', which asserts that the host supplies " + "`sourceFiles`. 'fs' and 'http' are inferred rather than named: " + "'http' when VAL_API_KEY and VAL_SECRET are both set, 'fs' otherwise.");
|
|
10199
|
+
}
|
|
10106
10200
|
const maybeApiKey = opts.apiKey || process.env.VAL_API_KEY;
|
|
10107
10201
|
const maybeValSecret = opts.valSecret || process.env.VAL_SECRET;
|
|
10108
|
-
|
|
10202
|
+
/*
|
|
10203
|
+
* The app's environment selects http mode, rather than leaving it to be
|
|
10204
|
+
* inferred from a credential being present.
|
|
10205
|
+
*
|
|
10206
|
+
* The difference shows when something is MISSING. Inference reads an absent
|
|
10207
|
+
* api key as "not a proxy" and falls through to `fs`, which in an isolate
|
|
10208
|
+
* reaches for a working tree that is not there -- an `EPERM` on
|
|
10209
|
+
* `.val/patches.lock`, several layers below the mistake. Selecting the mode
|
|
10210
|
+
* means the checks below run instead, and each one names what it wanted.
|
|
10211
|
+
*/
|
|
10212
|
+
const isAppEnv = (declared === null || declared === void 0 ? void 0 : declared.from) === "VAL_ENV";
|
|
10213
|
+
const isProxyMode = opts.mode === "proxy" || isAppEnv || opts.mode === undefined && (maybeApiKey || maybeValSecret);
|
|
10109
10214
|
const valEnableRedirectUrl = opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL;
|
|
10110
10215
|
const valDisableRedirectUrl = opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL;
|
|
10111
10216
|
const maybeValProject = opts.project || process.env.VAL_PROJECT;
|
|
@@ -10117,19 +10222,28 @@ async function initHandlerOptions(route, opts, config) {
|
|
|
10117
10222
|
});
|
|
10118
10223
|
if (isProxyMode) {
|
|
10119
10224
|
var _opts$versions, _opts$versions2;
|
|
10225
|
+
/*
|
|
10226
|
+
* Why this app is in http mode, in the message that says what is missing.
|
|
10227
|
+
*
|
|
10228
|
+
* "must be set in proxy mode" is a fine sentence for a developer who wrote
|
|
10229
|
+
* `mode: "proxy"` and a poor one for an app that never mentioned a mode:
|
|
10230
|
+
* there, the answer to "why am I in proxy mode?" is a variable set by the
|
|
10231
|
+
* platform, in a file the reader of this error is not looking at.
|
|
10232
|
+
*/
|
|
10233
|
+
const because = isAppEnv ? " (VAL_ENV is 'app', which is the Val app: its content is Val's own " + "and is read over HTTP at a commit, so http mode is the mode and " + "these are what it needs)" : "";
|
|
10120
10234
|
if (!maybeApiKey || !maybeValSecret) {
|
|
10121
|
-
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode");
|
|
10235
|
+
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode" + because);
|
|
10122
10236
|
}
|
|
10123
10237
|
const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
|
|
10124
10238
|
if (!maybeGitCommit) {
|
|
10125
|
-
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode");
|
|
10239
|
+
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode" + because);
|
|
10126
10240
|
}
|
|
10127
10241
|
const maybeGitBranch = opts.gitBranch || process.env.VAL_GIT_BRANCH;
|
|
10128
10242
|
if (!maybeGitBranch) {
|
|
10129
|
-
throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode");
|
|
10243
|
+
throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode" + because);
|
|
10130
10244
|
}
|
|
10131
10245
|
if (!maybeValProject) {
|
|
10132
|
-
throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set.");
|
|
10246
|
+
throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set." + because);
|
|
10133
10247
|
}
|
|
10134
10248
|
const coreVersion = (_opts$versions = opts.versions) === null || _opts$versions === void 0 ? void 0 : _opts$versions.core;
|
|
10135
10249
|
if (!coreVersion) {
|
|
@@ -10017,6 +10017,67 @@ function parsePersonalAccessTokenFile(content) {
|
|
|
10017
10017
|
|
|
10018
10018
|
const DEFAULT_VAL_BUILD_URL = "https://admin.val.build";
|
|
10019
10019
|
|
|
10020
|
+
/**
|
|
10021
|
+
* The value of `VAL_ENV` that means "this is the Val app".
|
|
10022
|
+
*
|
|
10023
|
+
* The Val app builds a project in a browser and runs it in a Worker isolate.
|
|
10024
|
+
* There is no disk there and there never will be, so `fs` mode is never the
|
|
10025
|
+
* right fall-through -- and the content is Val's own, reached over HTTP at a
|
|
10026
|
+
* commit, exactly as it is for any other deployed app. So this names `http`.
|
|
10027
|
+
*
|
|
10028
|
+
* What makes the app unusual is not where its content comes from but what
|
|
10029
|
+
* publishing means: the browser rebuilds the site and the new build is served
|
|
10030
|
+
* immediately, instead of a host noticing a commit and redeploying. That is a
|
|
10031
|
+
* difference in what happens AFTER the commit, and `publishOverride` is where
|
|
10032
|
+
* a host says so -- not a difference in where patches, files or sources live.
|
|
10033
|
+
*
|
|
10034
|
+
* A host says WHERE it runs, which is a fact it knows. Which Val mode that
|
|
10035
|
+
* implies is Val's to derive, and that is the whole reason this exists next to
|
|
10036
|
+
* `VAL_MODE` rather than the platform naming a mode itself: one is a
|
|
10037
|
+
* description of an environment, the other an assertion about Val's internals,
|
|
10038
|
+
* and only the first stays true when the internals move. They have already
|
|
10039
|
+
* moved once -- this meant `memory` while the app kept its own patch store --
|
|
10040
|
+
* and no platform had to be changed to follow.
|
|
10041
|
+
*/
|
|
10042
|
+
const VAL_APP_ENV = "app";
|
|
10043
|
+
|
|
10044
|
+
/** Which mode the environment SAYS this is, and which variable said so. */
|
|
10045
|
+
|
|
10046
|
+
/**
|
|
10047
|
+
* `null` is "the environment did not say", which is the normal case.
|
|
10048
|
+
*
|
|
10049
|
+
* The two variables differ in what can be DONE with an answer, and the
|
|
10050
|
+
* difference is whether the environment holds everything the mode needs.
|
|
10051
|
+
* `http` does -- an api key, a secret, a project, a commit and a branch are all
|
|
10052
|
+
* env vars -- so `VAL_ENV=app` SELECTS it, and the checks in
|
|
10053
|
+
* {@link initHandlerOptions} name whichever one is missing. `memory` does not:
|
|
10054
|
+
* it needs the host's own source files, which nothing in an environment can
|
|
10055
|
+
* supply, so `VAL_MODE=memory` can only ever turn a fall-through into an error.
|
|
10056
|
+
*/
|
|
10057
|
+
function namedMode() {
|
|
10058
|
+
const declared = process.env.VAL_MODE;
|
|
10059
|
+
/*
|
|
10060
|
+
* An empty value counts as unset, which is what `VAL_MODE=` in a shell or a
|
|
10061
|
+
* CI settings page means. An explicit `VAL_MODE` otherwise wins over
|
|
10062
|
+
* `VAL_ENV`: naming a mode outright says something more specific than naming
|
|
10063
|
+
* an environment does, including when what it names is wrong and has to be
|
|
10064
|
+
* refused.
|
|
10065
|
+
*/
|
|
10066
|
+
if (declared !== undefined && declared !== "") {
|
|
10067
|
+
return {
|
|
10068
|
+
mode: declared,
|
|
10069
|
+
from: "VAL_MODE"
|
|
10070
|
+
};
|
|
10071
|
+
}
|
|
10072
|
+
if (process.env.VAL_ENV === VAL_APP_ENV) {
|
|
10073
|
+
return {
|
|
10074
|
+
mode: "http",
|
|
10075
|
+
from: "VAL_ENV"
|
|
10076
|
+
};
|
|
10077
|
+
}
|
|
10078
|
+
return null;
|
|
10079
|
+
}
|
|
10080
|
+
|
|
10020
10081
|
/**
|
|
10021
10082
|
* Resolve options plus environment into a concrete {@link ValServerConfig}.
|
|
10022
10083
|
*
|
|
@@ -10069,9 +10130,53 @@ async function initHandlerOptions(route, opts, config) {
|
|
|
10069
10130
|
config
|
|
10070
10131
|
};
|
|
10071
10132
|
}
|
|
10133
|
+
/*
|
|
10134
|
+
* The environment saying 'memory' means the host MEANT to hold the source,
|
|
10135
|
+
* and did not. Either variable can say it: `VAL_MODE=memory` outright, or
|
|
10136
|
+
* `VAL_ENV=app`, which names an environment that has no disk.
|
|
10137
|
+
*
|
|
10138
|
+
* Neither can SELECT memory mode -- nothing in the environment can supply
|
|
10139
|
+
* `sourceFiles`, and a mode turned on without them is a server with no
|
|
10140
|
+
* content in it. What they do is turn the fall-through into an error.
|
|
10141
|
+
*
|
|
10142
|
+
* Without it, a host that forgot to pass its source got `fs` mode, and `fs`
|
|
10143
|
+
* mode in a Worker isolate reaches for a working tree that is not there: the
|
|
10144
|
+
* failure is an `EPERM` on `.val/patches.lock`, several layers below the
|
|
10145
|
+
* mistake, naming a path rather than the decision that led to it. Every
|
|
10146
|
+
* environment that runs Val without a disk can set this once and get a
|
|
10147
|
+
* sentence instead.
|
|
10148
|
+
*/
|
|
10149
|
+
const declared = namedMode();
|
|
10150
|
+
if ((declared === null || declared === void 0 ? void 0 : declared.mode) === "memory") {
|
|
10151
|
+
throw new Error("VAL_MODE is 'memory', but no `sourceFiles` were given here, so there " + "is no source to serve. Memory mode cannot be turned on by the " + "environment: it needs the project's own source, and only the host " + "that holds it can hand it over. On TanStack Start that is the " + "`sourceFiles` option, passed to `initValServer` AND to " + "`initValContent`, which has a Val server of its own and is " + "configured separately. @valbuild/next has no memory mode yet, so " + "for a Next app this variable is set on an environment Val cannot " + "serve from. Unset VAL_MODE to go back to the inferred mode instead " + "('http' when VAL_API_KEY and VAL_SECRET are both set, 'fs' " + "otherwise).");
|
|
10152
|
+
}
|
|
10153
|
+
/*
|
|
10154
|
+
* Every other value is refused rather than ignored: ignoring `VAL_MODE=memry`
|
|
10155
|
+
* would leave the app in `fs` mode, which is the exact failure this variable
|
|
10156
|
+
* exists to catch.
|
|
10157
|
+
*
|
|
10158
|
+
* `VAL_ENV` is excluded by name rather than by its value happening to pass:
|
|
10159
|
+
* it names 'http', which is selected below, and a reader who sees only
|
|
10160
|
+
* `declared !== null` here would reasonably conclude that 'http' is a
|
|
10161
|
+
* `VAL_MODE` value -- it is not, and the message below says so.
|
|
10162
|
+
*/
|
|
10163
|
+
if (declared !== null && declared.from === "VAL_MODE") {
|
|
10164
|
+
throw new Error(`VAL_MODE is '${declared.mode}', which is not a mode Val knows. The only ` + "value it accepts is 'memory', which asserts that the host supplies " + "`sourceFiles`. 'fs' and 'http' are inferred rather than named: " + "'http' when VAL_API_KEY and VAL_SECRET are both set, 'fs' otherwise.");
|
|
10165
|
+
}
|
|
10072
10166
|
const maybeApiKey = opts.apiKey || process.env.VAL_API_KEY;
|
|
10073
10167
|
const maybeValSecret = opts.valSecret || process.env.VAL_SECRET;
|
|
10074
|
-
|
|
10168
|
+
/*
|
|
10169
|
+
* The app's environment selects http mode, rather than leaving it to be
|
|
10170
|
+
* inferred from a credential being present.
|
|
10171
|
+
*
|
|
10172
|
+
* The difference shows when something is MISSING. Inference reads an absent
|
|
10173
|
+
* api key as "not a proxy" and falls through to `fs`, which in an isolate
|
|
10174
|
+
* reaches for a working tree that is not there -- an `EPERM` on
|
|
10175
|
+
* `.val/patches.lock`, several layers below the mistake. Selecting the mode
|
|
10176
|
+
* means the checks below run instead, and each one names what it wanted.
|
|
10177
|
+
*/
|
|
10178
|
+
const isAppEnv = (declared === null || declared === void 0 ? void 0 : declared.from) === "VAL_ENV";
|
|
10179
|
+
const isProxyMode = opts.mode === "proxy" || isAppEnv || opts.mode === undefined && (maybeApiKey || maybeValSecret);
|
|
10075
10180
|
const valEnableRedirectUrl = opts.valEnableRedirectUrl || process.env.VAL_ENABLE_REDIRECT_URL;
|
|
10076
10181
|
const valDisableRedirectUrl = opts.valDisableRedirectUrl || process.env.VAL_DISABLE_REDIRECT_URL;
|
|
10077
10182
|
const maybeValProject = opts.project || process.env.VAL_PROJECT;
|
|
@@ -10083,19 +10188,28 @@ async function initHandlerOptions(route, opts, config) {
|
|
|
10083
10188
|
});
|
|
10084
10189
|
if (isProxyMode) {
|
|
10085
10190
|
var _opts$versions, _opts$versions2;
|
|
10191
|
+
/*
|
|
10192
|
+
* Why this app is in http mode, in the message that says what is missing.
|
|
10193
|
+
*
|
|
10194
|
+
* "must be set in proxy mode" is a fine sentence for a developer who wrote
|
|
10195
|
+
* `mode: "proxy"` and a poor one for an app that never mentioned a mode:
|
|
10196
|
+
* there, the answer to "why am I in proxy mode?" is a variable set by the
|
|
10197
|
+
* platform, in a file the reader of this error is not looking at.
|
|
10198
|
+
*/
|
|
10199
|
+
const because = isAppEnv ? " (VAL_ENV is 'app', which is the Val app: its content is Val's own " + "and is read over HTTP at a commit, so http mode is the mode and " + "these are what it needs)" : "";
|
|
10086
10200
|
if (!maybeApiKey || !maybeValSecret) {
|
|
10087
|
-
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode");
|
|
10201
|
+
throw new Error("VAL_API_KEY and VAL_SECRET env vars must both be set in proxy mode" + because);
|
|
10088
10202
|
}
|
|
10089
10203
|
const maybeGitCommit = opts.gitCommit || process.env.VAL_GIT_COMMIT;
|
|
10090
10204
|
if (!maybeGitCommit) {
|
|
10091
|
-
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode");
|
|
10205
|
+
throw new Error("VAL_GIT_COMMIT env var must be set in proxy mode" + because);
|
|
10092
10206
|
}
|
|
10093
10207
|
const maybeGitBranch = opts.gitBranch || process.env.VAL_GIT_BRANCH;
|
|
10094
10208
|
if (!maybeGitBranch) {
|
|
10095
|
-
throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode");
|
|
10209
|
+
throw new Error("VAL_GIT_BRANCH env var must be set in proxy mode" + because);
|
|
10096
10210
|
}
|
|
10097
10211
|
if (!maybeValProject) {
|
|
10098
|
-
throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set.");
|
|
10212
|
+
throw new Error("Proxy mode does not work unless the 'project' option in val.config is defined or the VAL_PROJECT env var is set." + because);
|
|
10099
10213
|
}
|
|
10100
10214
|
const coreVersion = (_opts$versions = opts.versions) === null || _opts$versions === void 0 ? void 0 : _opts$versions.core;
|
|
10101
10215
|
if (!coreVersion) {
|
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.
|
|
19
|
+
"version": "0.132.0",
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@prettier/sync": "^0.6.1",
|
|
22
22
|
"@types/jest": "^30.0.0"
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"typescript": "^6.0.3",
|
|
30
30
|
"zod": "^4.4.3",
|
|
31
31
|
"zod-validation-error": "^5.0.0",
|
|
32
|
-
"@valbuild/shared": "0.130.0",
|
|
33
32
|
"@valbuild/core": "0.130.0",
|
|
34
|
-
"@valbuild/ui": "0.130.0"
|
|
33
|
+
"@valbuild/ui": "0.130.0",
|
|
34
|
+
"@valbuild/shared": "0.130.0"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": "^20.19.0 || >=22"
|