@uniflowed/config 0.0.0-alpha.4 → 0.0.0-alpha.41
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/index.js +11 -0
- package/internal/schema.js +805 -23
- package/package.json +3 -2
package/index.js
CHANGED
|
@@ -3,9 +3,20 @@
|
|
|
3
3
|
// `@uniflowed/config`.
|
|
4
4
|
|
|
5
5
|
export type {
|
|
6
|
+
BuilderSpec,
|
|
6
7
|
CapabilityJsHost,
|
|
8
|
+
CoverageThresholds,
|
|
9
|
+
DeployAdapter,
|
|
10
|
+
PackageManagerPreference,
|
|
11
|
+
PackageManagerSpec,
|
|
12
|
+
Permissions,
|
|
13
|
+
PluginEntry,
|
|
7
14
|
RuleLevel,
|
|
15
|
+
RuntimeEngine,
|
|
16
|
+
RuntimeSpec,
|
|
17
|
+
SizeBudget,
|
|
8
18
|
TaskDefinition,
|
|
19
|
+
TestRunnerSpec,
|
|
9
20
|
UniflowedConfig,
|
|
10
21
|
} from "./internal/schema.js";
|
|
11
22
|
|
package/internal/schema.js
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Owns the Flow shape of `uf.config.js`; `index.js` keeps the public package
|
|
4
4
|
// entry point thin.
|
|
5
|
+
//
|
|
6
|
+
// # Every key uf reads, and nothing else
|
|
7
|
+
//
|
|
8
|
+
// The guide says a config file "is type-checked as Flow code", which is the
|
|
9
|
+
// whole reason to write one in Flow. That makes an undeclared key worse than a
|
|
10
|
+
// missing feature: `lint.files`, `lint.ignore` and `app.router.enabled` were
|
|
11
|
+
// documented in the configuration reference, accepted by the runtime, and
|
|
12
|
+
// absent from this type — so a project following the reference had to choose
|
|
13
|
+
// between the documented key and a config that checks
|
|
14
|
+
// (ubugeeei-prod/uf#481). They were not the only three.
|
|
15
|
+
//
|
|
16
|
+
// So the key *names* below are no longer a person's job to keep in step with
|
|
17
|
+
// the loader. `crates/uf_config`'s `the_flow_schema_declares_every_key_uf_reads`
|
|
18
|
+
// parses this file with uf's own Flow parser and compares the paths it declares
|
|
19
|
+
// against the paths `uf_config::UniflowedConfig` serializes — in both
|
|
20
|
+
// directions, because a key declared here and read by nothing is an option that
|
|
21
|
+
// silently does nothing, which is the same defect wearing the other face.
|
|
22
|
+
//
|
|
23
|
+
// The value *types* are still this file's own judgement, and deliberately so.
|
|
24
|
+
// A test over names cannot say whether `"biome" | "prettier" | "none"` is the
|
|
25
|
+
// right set, and several keys below are narrower than what the loader will
|
|
26
|
+
// parse — `orm.module` is `"@uniflowed/orm"` because there is one
|
|
27
|
+
// implementation, where the loader takes any string. Where this package means
|
|
28
|
+
// to be more opinionated than the parser, that is what these say.
|
|
29
|
+
//
|
|
30
|
+
// # What an editor shows
|
|
31
|
+
//
|
|
32
|
+
// `uf lsp` completes and explains `uf.config.js` from this file, compiled into
|
|
33
|
+
// the binary. A key's completion shows the comment directly above the key and
|
|
34
|
+
// the type as it is written here, and the members of a literal union are the
|
|
35
|
+
// values it offers — so a comment above a key is written for somebody typing
|
|
36
|
+
// that key. Either kind of comment counts above a key; above a type alias only
|
|
37
|
+
// a `/** */` block does, because the `//` notes on the aliases are this file's
|
|
38
|
+
// history rather than the key's meaning. `crates/uf_config/src/schema.rs` is
|
|
39
|
+
// the reader, and says exactly what it takes.
|
|
5
40
|
|
|
6
41
|
export type RuleLevel = "off" | "warn" | "error" | 0 | 1 | 2 | boolean;
|
|
7
42
|
|
|
@@ -12,12 +47,317 @@ export type TaskDefinition =
|
|
|
12
47
|
readonly cwd?: string,
|
|
13
48
|
readonly dependsOn?: $ReadOnlyArray<string>,
|
|
14
49
|
readonly env?: { readonly [string]: string },
|
|
50
|
+
// Everything the task reads, as paths or globs from the project root; a
|
|
51
|
+
// pattern beginning `!` excludes. This is the whole of the cache key, so
|
|
52
|
+
// a task that lists nothing is never cached and always runs.
|
|
53
|
+
readonly inputs?: $ReadOnlyArray<string>,
|
|
54
|
+
// Everything it writes. Checked rather than restored: a replayed result
|
|
55
|
+
// has to still have its files on disk, unchanged.
|
|
56
|
+
readonly outputs?: $ReadOnlyArray<string>,
|
|
57
|
+
// `false` keeps a task with declared inputs out of the cache.
|
|
58
|
+
readonly cache?: boolean,
|
|
15
59
|
};
|
|
16
60
|
|
|
17
61
|
export type CapabilityJsHost = "node" | "deno" | "bun";
|
|
18
62
|
|
|
63
|
+
/**
|
|
64
|
+
* The package manager uf drives, overriding what it infers from the project.
|
|
65
|
+
*
|
|
66
|
+
* `"auto"` reads the project itself: an explicit `"packageManager"` field, then
|
|
67
|
+
* a lockfile, then the nearest workspace root, then uf's own resolver.
|
|
68
|
+
*/
|
|
69
|
+
// The eight below are the *names a project may pin*, not commands this module
|
|
70
|
+
// runs: `@uniflowed/config` declares a type and executes nothing at all.
|
|
71
|
+
// `uniflowed/no-npm-script-invocation` is a line scanner, and a string whose
|
|
72
|
+
// entire contents is `pnpm` reads exactly like the `spawn("pnpm", […])` the
|
|
73
|
+
// rule exists to catch — `crates/uf_lint/src/scan/search.rs` says so in its own
|
|
74
|
+
// documentation and calls what is left "rare and suppressible". This is that
|
|
75
|
+
// residue, and there is no spelling of these values that is not one of them.
|
|
76
|
+
// uf-lint-disable uniflowed/no-npm-script-invocation
|
|
77
|
+
export type PackageManagerPreference =
|
|
78
|
+
| "auto"
|
|
79
|
+
| "uf"
|
|
80
|
+
| "npm"
|
|
81
|
+
| "pnpm"
|
|
82
|
+
| "yarn"
|
|
83
|
+
| "yarn-classic"
|
|
84
|
+
| "yarn-berry"
|
|
85
|
+
| "bun";
|
|
86
|
+
// uf-lint-enable uniflowed/no-npm-script-invocation
|
|
87
|
+
|
|
88
|
+
// The runtimes a project may say it is written for, which are the runtimes uf
|
|
89
|
+
// has a host for. It read `"uf" | ... | "edge" | "serverless" | "container"`,
|
|
90
|
+
// and those four are rows `uf_runtime::HOSTS` grades planned with no Flow
|
|
91
|
+
// loader — so a project that named one could not import its own first file
|
|
92
|
+
// there, and every command went on running on Node anyway. uf refuses them at
|
|
93
|
+
// the key that named them now; this type is where a reader finds that out
|
|
94
|
+
// before `uf check` does. See docs/hosts.md and ubugeeei-prod/uf#246.
|
|
95
|
+
//
|
|
96
|
+
// A deployment target is `DeployAdapter`, on `app.runtime.deploy`, and is a
|
|
97
|
+
// different question with a longer list.
|
|
98
|
+
export type RuntimeEngine = "node" | "deno" | "bun";
|
|
99
|
+
|
|
100
|
+
export type DeployAdapter =
|
|
101
|
+
| "node"
|
|
102
|
+
| "bun"
|
|
103
|
+
| "deno"
|
|
104
|
+
| "edge"
|
|
105
|
+
| "serverless"
|
|
106
|
+
| "static"
|
|
107
|
+
| "container";
|
|
108
|
+
|
|
109
|
+
// # Tools, declared where they are used
|
|
110
|
+
//
|
|
111
|
+
// The four aliases below are strings to Flow and a grammar to uf, which reads
|
|
112
|
+
// every one of them where the config is read and refuses what it cannot run —
|
|
113
|
+
// naming the key, what was written, and what to write instead. They are
|
|
114
|
+
// aliases rather than bare `string` so the grammar has one place to be written
|
|
115
|
+
// down, and so an editor can find a tool-spec key by its type — which is what
|
|
116
|
+
// completion in `uf.config.js` keys on (ubugeeei-prod/uf#941). Rename one and
|
|
117
|
+
// that stops working without a type error anywhere.
|
|
118
|
+
//
|
|
119
|
+
// A spec is `name[@version]`, and what follows the `@` is one of three things:
|
|
120
|
+
//
|
|
121
|
+
// * nothing — `"node"` — the `node` on `PATH`, which is what every project
|
|
122
|
+
// got before it could say anything else;
|
|
123
|
+
// * a numeric prefix — `"node@26"`, `"bun@1.4"` — the newest release that
|
|
124
|
+
// starts with it, resolved once against the publisher's index and locked in
|
|
125
|
+
// `uf.lock`, so every machine runs the same release until somebody moves it;
|
|
126
|
+
// * a full version — `"pnpm@12.0.0"` — exactly that release.
|
|
127
|
+
//
|
|
128
|
+
// A range — `"node@^26"`, `"node@>=24"`, `"node@24.x"` — is refused: a range is
|
|
129
|
+
// not an environment, because it can resolve to a different release tomorrow.
|
|
130
|
+
// So is a tag such as `"node@lts"`, for the same reason. ubugeeei-prod/uf#940.
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* A JavaScript runtime, and optionally which release of it: `"node"`,
|
|
134
|
+
* `"node@26"`, `"bun@1.3.5"`.
|
|
135
|
+
*
|
|
136
|
+
* The names are `node`, `bun` and `deno`. No version is the one on `PATH`; a
|
|
137
|
+
* prefix is the newest release that starts with it, locked in `uf.lock`; a full
|
|
138
|
+
* version is exactly that release. A range or a tag is refused.
|
|
139
|
+
*
|
|
140
|
+
* The type of `runtime`, `build.runtime` and `test.runtime`.
|
|
141
|
+
*/
|
|
142
|
+
export type RuntimeSpec = string;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* A package manager, and optionally which release of it: `"pnpm"`,
|
|
146
|
+
* `"pnpm@10"`, `"pnpm@12.0.0"`.
|
|
147
|
+
*
|
|
148
|
+
* The names are `npm`, `pnpm`, `yarn` and `bun`. Yarn's edition is its major
|
|
149
|
+
* version — `"yarn@1"` is Classic. No version is the one on `PATH`; a prefix is
|
|
150
|
+
* the newest release that starts with it, locked in `uf.lock`; a full version
|
|
151
|
+
* is exactly that release. A range or a tag is refused.
|
|
152
|
+
*
|
|
153
|
+
* The type of `packageManager`.
|
|
154
|
+
*/
|
|
155
|
+
export type PackageManagerSpec = string;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* What runs the test suite: `"uf"` or `"bun[@version]"`.
|
|
159
|
+
*
|
|
160
|
+
* `"uf"` is the runner built into uf, and the default; it takes no version,
|
|
161
|
+
* because it is the binary that is running. `"bun"` is `bun test`, on the Bun
|
|
162
|
+
* it names — so it also decides the test runtime when `test.runtime` is
|
|
163
|
+
* absent, and a `test.runtime` naming anything else is an error. The version
|
|
164
|
+
* follows the same grammar as a runtime's. Under a Bun runner `uf test` hands
|
|
165
|
+
* the files its discovery found to `bun test`, with uf's Flow preload, and
|
|
166
|
+
* `@uniflowed/test` resolves to `bun:test`; what Bun has no equivalent for
|
|
167
|
+
* raises `UnsupportedError` by name. See guide/testing, "Choosing a runner".
|
|
168
|
+
*
|
|
169
|
+
* The type of `test.runner`.
|
|
170
|
+
*/
|
|
171
|
+
export type TestRunnerSpec = string;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Which builder `uf dev`, `uf build`, `uf preview` and `uf start` drive:
|
|
175
|
+
* `"vite"`, or a module specifier.
|
|
176
|
+
*
|
|
177
|
+
* `"vite"` is `@uniflowed/vite`, the builder uf ships and the default. Any other
|
|
178
|
+
* string is a module specifier — a package found up `node_modules`, or a path
|
|
179
|
+
* starting with `.` or `/` that must stay inside the project — whose driver
|
|
180
|
+
* satisfies the contract in docs/architecture.md.
|
|
181
|
+
*
|
|
182
|
+
* The type of `build.builder`.
|
|
183
|
+
*/
|
|
184
|
+
export type BuilderSpec = string;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* One entry of `plugins: [...]`.
|
|
188
|
+
*
|
|
189
|
+
* A bare name takes the default band and applies to every pipeline; the long
|
|
190
|
+
* form says otherwise. Declaration order decides within a band, so the
|
|
191
|
+
* resolved pipeline is a function of this file alone.
|
|
192
|
+
*/
|
|
193
|
+
export type PluginEntry =
|
|
194
|
+
| string
|
|
195
|
+
| {
|
|
196
|
+
readonly name: string,
|
|
197
|
+
readonly order?: "pre" | "normal" | "post",
|
|
198
|
+
readonly apply?: "build" | "serve" | "always",
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// # `app.router`'s three lists
|
|
202
|
+
//
|
|
203
|
+
// Next.js's `redirects`, `rewrites` and `headers`, written as data rather than
|
|
204
|
+
// as async functions, because this file is read without being run. A `source`
|
|
205
|
+
// is a path in the route table's own grammar — a literal segment, `:name` for
|
|
206
|
+
// one segment, and a trailing `:name*` for the rest — and each rule is an exact
|
|
207
|
+
// object, so a misspelled field is an error here and where `uf` reads the file.
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* One redirect: a request for `source` is answered with a redirect to
|
|
211
|
+
* `destination`, before anything else answers — a file included.
|
|
212
|
+
*
|
|
213
|
+
* `destination` is a path of this application or an absolute `http(s)` URL,
|
|
214
|
+
* and may use the `:name` and `:name*` segments `source` declared. The
|
|
215
|
+
* request's query is passed through. `permanent: true` is a `308`, `false` a
|
|
216
|
+
* `307`; both keep the method.
|
|
217
|
+
*/
|
|
218
|
+
export type RouteRedirect = {
|
|
219
|
+
readonly source: string,
|
|
220
|
+
readonly destination: string,
|
|
221
|
+
readonly permanent: boolean,
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* One rewrite: a request for `source` is answered by the route at
|
|
226
|
+
* `destination`, and the address bar keeps `source`.
|
|
227
|
+
*
|
|
228
|
+
* `destination` is a path of this application — never another origin, which
|
|
229
|
+
* is a route handler that fetches — and may use `source`'s segments. Applied
|
|
230
|
+
* after the build's own files and before middleware, so the middleware that
|
|
231
|
+
* runs is the destination's.
|
|
232
|
+
*/
|
|
233
|
+
export type RouteRewrite = {
|
|
234
|
+
readonly source: string,
|
|
235
|
+
readonly destination: string,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Response headers for every request whose path matches `source`, files
|
|
240
|
+
* included. Every matching rule applies, in order, and a later one setting the
|
|
241
|
+
* same name wins — over the response's own header of that name, too.
|
|
242
|
+
*/
|
|
243
|
+
export type RouteHeaders = {
|
|
244
|
+
readonly source: string,
|
|
245
|
+
readonly headers: { readonly [name: string]: string },
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Which spelling of a path is the page.
|
|
250
|
+
*
|
|
251
|
+
* `"never"` answers `/about/` with a `308` to `/about` and writes the page as
|
|
252
|
+
* `about.html`; `"always"` answers `/about` with a `308` to `/about/` and
|
|
253
|
+
* writes `about/index.html`; `"ignore"`, the default, answers both and writes
|
|
254
|
+
* `about/index.html`. `next.config.js`'s `trailingSlash: false`, `true` and
|
|
255
|
+
* `skipTrailingSlashRedirect: true`.
|
|
256
|
+
*/
|
|
257
|
+
export type RouterTrailingSlash = "never" | "always" | "ignore";
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* A ceiling `uf build` fails over, and what it is measured on.
|
|
261
|
+
*
|
|
262
|
+
* `max` accepts a byte count or a size a person would write — `"180kb"` —
|
|
263
|
+
* because a budget is written by hand and read back by a report.
|
|
264
|
+
*/
|
|
265
|
+
export type SizeBudget = {
|
|
266
|
+
readonly max: number | string,
|
|
267
|
+
readonly metric?: "raw" | "gzip" | "brotli",
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* What the project's own code may reach.
|
|
272
|
+
*
|
|
273
|
+
* Absent from `uf.config.js` means no permission model: the toolchain starts
|
|
274
|
+
* its host the way it always has. Present means **deny by default** — the
|
|
275
|
+
* project's code gets what is listed and nothing else — and `permissions: {}`
|
|
276
|
+
* is a legitimate thing to write, meaning "nothing beyond what uf itself needs
|
|
277
|
+
* to load and transform the project". There is deliberately no way to spell
|
|
278
|
+
* "everything"; a project that wants everything does not declare a set.
|
|
279
|
+
*
|
|
280
|
+
* Every field is a list of literal strings, because `uf.config.js` is read as
|
|
281
|
+
* text and parsed as JSON5 rather than executed: a computed path or a
|
|
282
|
+
* `process.env` read here would not parse.
|
|
283
|
+
*
|
|
284
|
+
* The set is uf's, not a runtime's. Node.js enforces `read` and `write`, Deno
|
|
285
|
+
* enforces all five, and Bun has no permission model at all — a host that
|
|
286
|
+
* cannot enforce what is declared **refuses the run** rather than applying part
|
|
287
|
+
* of it. `docs/hosts.md` is the table.
|
|
288
|
+
*
|
|
289
|
+
* The declared paths are *added to* the ones uf needs to run the project, so
|
|
290
|
+
* what a set denies is the rest of the machine — `~/.ssh`, the network, the
|
|
291
|
+
* environment — and not the project's own files.
|
|
292
|
+
*/
|
|
293
|
+
export type Permissions = {
|
|
294
|
+
readonly read?: $ReadOnlyArray<string>,
|
|
295
|
+
readonly write?: $ReadOnlyArray<string>,
|
|
296
|
+
readonly net?: $ReadOnlyArray<string>,
|
|
297
|
+
readonly env?: $ReadOnlyArray<string>,
|
|
298
|
+
readonly run?: $ReadOnlyArray<string>,
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Percentages a coverage gate requires, as whole numbers between 0 and 100.
|
|
303
|
+
*
|
|
304
|
+
* A metric nobody names is not checked, which is not the same as requiring
|
|
305
|
+
* zero: `{ lines: 0 }` says "every line, and I mean it" in a way that reads
|
|
306
|
+
* wrong, so the absent case is the one that means nothing is required.
|
|
307
|
+
*/
|
|
308
|
+
export type CoverageThresholds = {
|
|
309
|
+
readonly lines?: number,
|
|
310
|
+
readonly functions?: number,
|
|
311
|
+
readonly branches?: number,
|
|
312
|
+
};
|
|
313
|
+
|
|
19
314
|
export type UniflowedConfig = {
|
|
315
|
+
/**
|
|
316
|
+
* The runtime accessibility audit: `expect(el).toHaveNoAxeViolations()` in a
|
|
317
|
+
* test, and the page `uf dev` is serving.
|
|
318
|
+
*
|
|
319
|
+
* One block for both on purpose. A rule a project has decided cannot be
|
|
320
|
+
* judged here — `color-contrast` against a DOM with no layout is the
|
|
321
|
+
* standing example — has to be the same rule in CI and in the loop somebody
|
|
322
|
+
* is working in, or the audit that finds a violation while the component is
|
|
323
|
+
* being written disagrees with the one that blocks the pull request.
|
|
324
|
+
*
|
|
325
|
+
* Inert without axe-core, which uf does not install: add it and both halves
|
|
326
|
+
* start working.
|
|
327
|
+
*
|
|
328
|
+
* Not the same thing as `lint.rules`' `a11y/*`, which read JSX that was
|
|
329
|
+
* never rendered.
|
|
330
|
+
*/
|
|
331
|
+
readonly accessibility?: {
|
|
332
|
+
readonly devAudit?: boolean,
|
|
333
|
+
readonly axe?: {
|
|
334
|
+
// Run only rules carrying one of these axe tags; every rule when absent.
|
|
335
|
+
readonly tags?: $ReadOnlyArray<string>,
|
|
336
|
+
readonly disabledRules?: $ReadOnlyArray<string>,
|
|
337
|
+
readonly minImpact?: "minor" | "moderate" | "serious" | "critical",
|
|
338
|
+
},
|
|
339
|
+
},
|
|
20
340
|
readonly app?: {
|
|
341
|
+
// Whether a component with no directive is rendered on the server or
|
|
342
|
+
// shipped to the browser.
|
|
343
|
+
readonly componentDefault?: "server" | "client",
|
|
344
|
+
readonly framework?: "uniflowed" | "react" | "react-native",
|
|
345
|
+
readonly react?: {
|
|
346
|
+
// React 19's Strict Mode, on by default in `uf dev`: it double-invokes
|
|
347
|
+
// render and effects so an impurity shows up in development rather
|
|
348
|
+
// than in production. Off has to be a choice a project makes.
|
|
349
|
+
readonly strictMode?: boolean,
|
|
350
|
+
readonly version?: string,
|
|
351
|
+
readonly asyncReact?: boolean,
|
|
352
|
+
readonly suspense?: boolean,
|
|
353
|
+
readonly useHook?: boolean,
|
|
354
|
+
},
|
|
355
|
+
// Whether the project builds React Server Components at all, and whether
|
|
356
|
+
// a `"use server"` export is wired to an endpoint.
|
|
357
|
+
readonly rsc?: boolean,
|
|
358
|
+
readonly serverActions?: boolean,
|
|
359
|
+
// The runtimes the build must satisfy.
|
|
360
|
+
readonly targets?: $ReadOnlyArray<"web" | "react-native" | "server" | "hermes">,
|
|
21
361
|
readonly orm?: {
|
|
22
362
|
readonly enabled?: boolean,
|
|
23
363
|
readonly module?: "@uniflowed/orm",
|
|
@@ -26,11 +366,18 @@ export type UniflowedConfig = {
|
|
|
26
366
|
readonly preparedByDefault?: true,
|
|
27
367
|
},
|
|
28
368
|
readonly builtins?: {
|
|
369
|
+
readonly data?: "uniflowed-query",
|
|
370
|
+
readonly effect?: "uniflowed-effect",
|
|
29
371
|
readonly fetch?: {
|
|
30
372
|
readonly module?: "@uniflowed/fetch",
|
|
31
373
|
readonly overrideGlobalFetch?: false,
|
|
32
374
|
},
|
|
33
375
|
readonly cell?: boolean,
|
|
376
|
+
readonly frameworkLints?: boolean,
|
|
377
|
+
readonly nativeTestRunner?: boolean,
|
|
378
|
+
readonly reactTestingLibrary?: boolean,
|
|
379
|
+
readonly relay?: boolean,
|
|
380
|
+
readonly style?: "style-x",
|
|
34
381
|
readonly reactCompiler?: {
|
|
35
382
|
readonly enabled?: boolean,
|
|
36
383
|
readonly implementation?: "official-rust",
|
|
@@ -53,9 +400,59 @@ export type UniflowedConfig = {
|
|
|
53
400
|
readonly extensions?: $ReadOnlyArray<".mdx">,
|
|
54
401
|
readonly jsxImportSource?: "@uniflowed/jsx-runtime",
|
|
55
402
|
readonly pipelinePlugin?: "built-in",
|
|
403
|
+
// Colours are computed during the build and written into the HTML,
|
|
404
|
+
// so nothing ships to the browser to do it. Both themes are emitted
|
|
405
|
+
// together as CSS variables, because a build cannot know which the
|
|
406
|
+
// reader prefers.
|
|
407
|
+
readonly highlight?: {
|
|
408
|
+
readonly enabled?: boolean,
|
|
409
|
+
readonly themes?: {
|
|
410
|
+
readonly light?: string,
|
|
411
|
+
readonly dark?: string,
|
|
412
|
+
},
|
|
413
|
+
// Grammars beyond the ones a uf project uses by default.
|
|
414
|
+
readonly langs?: $ReadOnlyArray<string>,
|
|
415
|
+
},
|
|
56
416
|
},
|
|
57
417
|
readonly cache?: "opt-in",
|
|
58
418
|
},
|
|
419
|
+
readonly images?: {
|
|
420
|
+
readonly enabled?: boolean,
|
|
421
|
+
// The widths a layout asks for. uf emits one variant per width that is
|
|
422
|
+
// not wider than the source, plus one at the source's own width.
|
|
423
|
+
readonly widths?: $ReadOnlyArray<number>,
|
|
424
|
+
readonly quality?: number,
|
|
425
|
+
readonly placeholder?: boolean,
|
|
426
|
+
},
|
|
427
|
+
readonly fonts?: {
|
|
428
|
+
readonly enabled?: boolean,
|
|
429
|
+
readonly display?: string,
|
|
430
|
+
// The local face uf scales into a metric-matched fallback. One of the
|
|
431
|
+
// faces `uf_assets::font::LOCAL_FACES` knows the metrics of, because
|
|
432
|
+
// the scaling is a ratio against real numbers rather than a guess.
|
|
433
|
+
readonly fallback?: string,
|
|
434
|
+
// How an imported family is cut down. `"none"` is the default and the
|
|
435
|
+
// argued position: subsetting is lossy, and a build cannot see the
|
|
436
|
+
// text a server will render or a user will type. `"ranges"` splits the
|
|
437
|
+
// font's own coverage into script buckets with exact `unicode-range`
|
|
438
|
+
// values and loses nothing.
|
|
439
|
+
readonly subset?: "none" | "ranges",
|
|
440
|
+
// Whether `Font` preloads the primary face. Exactly one file is ever
|
|
441
|
+
// preloaded, however many buckets a split produced.
|
|
442
|
+
readonly preload?: boolean,
|
|
443
|
+
},
|
|
444
|
+
readonly icons?: {
|
|
445
|
+
readonly enabled?: boolean,
|
|
446
|
+
// Where `uf:icon/<name>` looks for `<name>.svg`, from the project
|
|
447
|
+
// root. A directory rather than a claim on `.svg`, which stays Vite's.
|
|
448
|
+
readonly dir?: string,
|
|
449
|
+
},
|
|
450
|
+
readonly og?: {
|
|
451
|
+
readonly enabled?: boolean,
|
|
452
|
+
// The typeface every `*.og.json` is drawn with unless it names its
|
|
453
|
+
// own. uf embeds none, so a project that draws cards points at one.
|
|
454
|
+
readonly font?: string | null,
|
|
455
|
+
},
|
|
59
456
|
readonly motion?: {
|
|
60
457
|
readonly module?: "@uniflowed/motion",
|
|
61
458
|
readonly engine?: "uf-native",
|
|
@@ -89,10 +486,8 @@ export type UniflowedConfig = {
|
|
|
89
486
|
},
|
|
90
487
|
},
|
|
91
488
|
readonly runtime?: {
|
|
92
|
-
readonly default?:
|
|
93
|
-
readonly compatibility?: $ReadOnlyArray<
|
|
94
|
-
"node" | "bun" | "deno" | "edge" | "serverless" | "container",
|
|
95
|
-
>,
|
|
489
|
+
readonly default?: RuntimeEngine,
|
|
490
|
+
readonly compatibility?: $ReadOnlyArray<RuntimeEngine>,
|
|
96
491
|
readonly capabilityJsHost?: {
|
|
97
492
|
readonly default?: CapabilityJsHost,
|
|
98
493
|
readonly hosts?: $ReadOnlyArray<CapabilityJsHost>,
|
|
@@ -100,36 +495,199 @@ export type UniflowedConfig = {
|
|
|
100
495
|
},
|
|
101
496
|
readonly deploy?: {
|
|
102
497
|
readonly enabled?: boolean,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
498
|
+
// The target `uf build` writes an artefact for when none is named on
|
|
499
|
+
// the command line; `--adapter` beats it.
|
|
500
|
+
readonly adapter?: DeployAdapter,
|
|
501
|
+
readonly adapters?: $ReadOnlyArray<DeployAdapter>,
|
|
106
502
|
},
|
|
107
503
|
},
|
|
108
504
|
readonly router?: {
|
|
505
|
+
// `false` says this project is not a uf application, and is the only way
|
|
506
|
+
// to say it: a library has no routes to scan for.
|
|
507
|
+
readonly enabled?: boolean,
|
|
109
508
|
readonly entry?: string,
|
|
110
509
|
readonly root?: string,
|
|
111
510
|
readonly manifest?: string,
|
|
511
|
+
readonly convention?: "file-system",
|
|
512
|
+
// Turning the file-system router off is what makes a project a
|
|
513
|
+
// **library** rather than an application, and `uf build` reads it: see
|
|
514
|
+
// `build.lib` below and docs/app/reference/config.
|
|
515
|
+
readonly enabled?: boolean,
|
|
516
|
+
/**
|
|
517
|
+
* Redirects answered before anything else, in order; the first whose
|
|
518
|
+
* `source` matches wins. `next.config.js`'s `redirects()`. See
|
|
519
|
+
* `RouteRedirect` and docs/app/guide/routing.
|
|
520
|
+
*/
|
|
521
|
+
readonly redirects?: $ReadOnlyArray<RouteRedirect>,
|
|
522
|
+
/**
|
|
523
|
+
* Routes served at another path, in order; the first whose `source`
|
|
524
|
+
* matches wins. `next.config.js`'s `rewrites()`, without proxying. See
|
|
525
|
+
* `RouteRewrite` and docs/app/guide/routing.
|
|
526
|
+
*/
|
|
527
|
+
readonly rewrites?: $ReadOnlyArray<RouteRewrite>,
|
|
528
|
+
/**
|
|
529
|
+
* Response headers by path; every matching rule applies.
|
|
530
|
+
* `next.config.js`'s `headers()`. See `RouteHeaders` and
|
|
531
|
+
* docs/app/guide/routing.
|
|
532
|
+
*/
|
|
533
|
+
readonly headers?: $ReadOnlyArray<RouteHeaders>,
|
|
534
|
+
/**
|
|
535
|
+
* The path the whole application is served under — `"/docs"` — with no
|
|
536
|
+
* trailing slash. Every link, redirect, asset URL, payload URL and
|
|
537
|
+
* sitemap entry carries it, and a request outside it is a `404`. The
|
|
538
|
+
* sources of the three lists above are written without it.
|
|
539
|
+
* `next.config.js`'s `basePath`.
|
|
540
|
+
*/
|
|
541
|
+
readonly basePath?: string,
|
|
542
|
+
/**
|
|
543
|
+
* Which spelling of a path is the page; see `RouterTrailingSlash`.
|
|
544
|
+
* `"ignore"` when absent.
|
|
545
|
+
*/
|
|
546
|
+
readonly trailingSlash?: RouterTrailingSlash,
|
|
547
|
+
/** HTTPS links explicitly claimed by the iOS and Android applications. */
|
|
548
|
+
readonly nativeLinks?: {|
|
|
549
|
+
readonly origins: $ReadOnlyArray<string>,
|
|
550
|
+
readonly routes: $ReadOnlyArray<string>,
|
|
551
|
+
readonly iosAppIds: $ReadOnlyArray<string>,
|
|
552
|
+
readonly androidPackage: string,
|
|
553
|
+
readonly androidSha256: $ReadOnlyArray<string>,
|
|
554
|
+
|},
|
|
112
555
|
},
|
|
113
556
|
readonly rendering?: {
|
|
114
|
-
|
|
557
|
+
// `"csr"` is the one value that cannot share the list: it renders every
|
|
558
|
+
// route in the browser from one shell, where the others write a document
|
|
559
|
+
// per route, so there is no per-route choice left for the list to hold.
|
|
560
|
+
// `["csr"]` is a single-page application; see docs/app/guide/rendering.
|
|
561
|
+
readonly modes?: $ReadOnlyArray<"ppr" | "ssr" | "ssg" | "isr" | "csr">,
|
|
562
|
+
// What the browser does when a visitor follows a link, which is a
|
|
563
|
+
// different question from `modes` rather than a fifth value in it:
|
|
564
|
+
// `modes` says where a document comes from, per route, and this says
|
|
565
|
+
// what happens once the browser has one. `"document"` is a full document
|
|
566
|
+
// request — the client router is not installed and `Link` renders an
|
|
567
|
+
// ordinary anchor. See docs/app/guide/routing/navigation.
|
|
568
|
+
readonly navigation?: "client" | "document",
|
|
569
|
+
// How long, in whole seconds, the client router shows a route it already
|
|
570
|
+
// fetched or prefetched without asking the server again: a click on a
|
|
571
|
+
// prefetched link, a second visit and the back button all read it. `0`,
|
|
572
|
+
// the default, keeps nothing. `router.refresh()` and every server action
|
|
573
|
+
// clear it. See docs/app/guide/routing and docs/app/guide/cache.
|
|
574
|
+
readonly staleTime?: number,
|
|
115
575
|
readonly cache?: {
|
|
116
576
|
readonly actions?: boolean,
|
|
117
577
|
readonly data?: boolean,
|
|
118
578
|
readonly fetch?: boolean,
|
|
119
579
|
readonly route?: boolean,
|
|
580
|
+
// Where cache entries live, and the only thing here that is a *name*
|
|
581
|
+
// rather than a switch: `"memory"` (the default) is one process,
|
|
582
|
+
// `"filesystem"` is uf's built-in durable provider, and anything else
|
|
583
|
+
// is a module specifier exporting `createCacheProvider` — the same
|
|
584
|
+
// shape `builder.module` has, and for the same red line. Turning this
|
|
585
|
+
// on caches nothing new: a route still has to state a lifetime.
|
|
586
|
+
readonly store?: string,
|
|
587
|
+
// Where `"filesystem"` keeps them. Defaults to `.uf/cache/route` under
|
|
588
|
+
// the project. A deployment that has one writable directory — `/tmp` on
|
|
589
|
+
// a Lambda, a mounted volume in a container — names it here.
|
|
590
|
+
readonly storeDir?: string,
|
|
120
591
|
},
|
|
121
592
|
},
|
|
122
593
|
},
|
|
123
594
|
readonly build?: {
|
|
595
|
+
// Size ceilings that fail the build. Unset by default: failing a build
|
|
596
|
+
// nobody asked uf to police is worse than reporting the size.
|
|
597
|
+
readonly budgets?: {
|
|
598
|
+
readonly total?: SizeBudget,
|
|
599
|
+
readonly initialJs?: SizeBudget,
|
|
600
|
+
readonly perRoute?: SizeBudget,
|
|
601
|
+
readonly perAsset?: SizeBudget,
|
|
602
|
+
},
|
|
124
603
|
readonly entries?: $ReadOnlyArray<string>,
|
|
604
|
+
// Commands to run around the build, in the same shape as `tasks`.
|
|
605
|
+
readonly hooks?: { readonly [string]: TaskDefinition },
|
|
125
606
|
readonly outDir?: string,
|
|
607
|
+
// Prerender every route and leave no server bundle behind. Read together
|
|
608
|
+
// with `app.rendering.modes`; see docs/app/reference/config.
|
|
126
609
|
readonly staticBuild?: boolean,
|
|
127
610
|
readonly sourcemap?: boolean,
|
|
611
|
+
/**
|
|
612
|
+
* What a **library** build writes, for a project whose
|
|
613
|
+
* `app.router.enabled` is false.
|
|
614
|
+
*
|
|
615
|
+
* Never the switch. `app.router.enabled` decides which of the two builds
|
|
616
|
+
* `uf build` runs, and declaring this key in a project whose router is on
|
|
617
|
+
* is refused where the config is read rather than resolved by precedence.
|
|
618
|
+
* Every field has a default that builds what `uf new --lib` scaffolds, so
|
|
619
|
+
* a library ordinarily writes none of this.
|
|
620
|
+
*
|
|
621
|
+
* `"umd"` and `"iife"` are deliberately absent from `formats`: each needs
|
|
622
|
+
* a global name per entry, and what a Flow library's global should be is
|
|
623
|
+
* not a decision uf has made.
|
|
624
|
+
*/
|
|
625
|
+
readonly lib?: {
|
|
626
|
+
// The modules to build, relative to the project root. Each names its own
|
|
627
|
+
// output by its path — `internal/parse.js` is written to
|
|
628
|
+
// `dist/internal/parse.js` — so two entries cannot collide.
|
|
629
|
+
readonly entries?: $ReadOnlyArray<string>,
|
|
630
|
+
readonly formats?: $ReadOnlyArray<"es" | "cjs">,
|
|
631
|
+
// Package names to leave as imports *beyond* the ones the manifest
|
|
632
|
+
// declares. A library build already externalises `dependencies`,
|
|
633
|
+
// `peerDependencies`, `optionalDependencies` and the host's built-in
|
|
634
|
+
// modules; this is for what a manifest cannot say.
|
|
635
|
+
readonly external?: $ReadOnlyArray<string>,
|
|
636
|
+
/**
|
|
637
|
+
* Write a TypeScript declaration file beside each entry. On by
|
|
638
|
+
* default.
|
|
639
|
+
*
|
|
640
|
+
* Most people who install a Flow library write TypeScript, and to them
|
|
641
|
+
* a package with no `.d.ts` is `any`. Every Flow construct that has no
|
|
642
|
+
* TypeScript meaning is named in the build report rather than silently
|
|
643
|
+
* widened, so turning this off is for a library that would rather ship
|
|
644
|
+
* no declarations than ones with gaps in them — not for one that wants
|
|
645
|
+
* to stop hearing about the gaps.
|
|
646
|
+
*/
|
|
647
|
+
readonly declarations?: boolean,
|
|
648
|
+
},
|
|
649
|
+
/**
|
|
650
|
+
* What `uf dev`, `uf build` and `uf preview` run on, when it is not the
|
|
651
|
+
* top-level `runtime`: `"node@26"`.
|
|
652
|
+
*
|
|
653
|
+
* Read before `runtime`, so a project that builds on Node and tests on Bun
|
|
654
|
+
* can say so. See `RuntimeSpec` for the grammar.
|
|
655
|
+
*/
|
|
656
|
+
readonly runtime?: RuntimeSpec,
|
|
657
|
+
/**
|
|
658
|
+
* Which builder `uf dev`, `uf build`, `uf preview` and `uf start` drive:
|
|
659
|
+
* `"vite"`, or a module specifier.
|
|
660
|
+
*
|
|
661
|
+
* Vite is the default, not a dependency: any module satisfying the
|
|
662
|
+
* contract in docs/architecture.md can be named here. See `BuilderSpec`.
|
|
663
|
+
*/
|
|
664
|
+
readonly builder?: BuilderSpec,
|
|
665
|
+
},
|
|
666
|
+
readonly builder?: {
|
|
667
|
+
/**
|
|
668
|
+
* The old spelling of `build.builder`.
|
|
669
|
+
*
|
|
670
|
+
* **Deprecated**, and read only when `build.builder` is absent; the two
|
|
671
|
+
* naming different builders is an error. `"@uniflowed/vite"` here is
|
|
672
|
+
* `builder: "vite"` there, and any other specifier moves as it is.
|
|
673
|
+
*/
|
|
674
|
+
readonly module?: string,
|
|
128
675
|
},
|
|
129
676
|
readonly dev?: {
|
|
130
677
|
readonly host?: string,
|
|
131
678
|
readonly port?: number,
|
|
132
679
|
readonly strictPort?: boolean,
|
|
680
|
+
// Which files the dev server may serve. `deny` is evaluated on the
|
|
681
|
+
// canonical path and beats `allow`; see docs/security.md.
|
|
682
|
+
readonly fs?: {
|
|
683
|
+
readonly allow?: $ReadOnlyArray<string>,
|
|
684
|
+
readonly deny?: $ReadOnlyArray<string>,
|
|
685
|
+
},
|
|
686
|
+
// `--host` refuses to bind a routable address while this is empty: a dev
|
|
687
|
+
// server reachable from the network with no host allow-list is a file
|
|
688
|
+
// server for your source tree.
|
|
689
|
+
readonly allowedHosts?: $ReadOnlyArray<string>,
|
|
690
|
+
readonly allowedOrigins?: $ReadOnlyArray<string>,
|
|
133
691
|
},
|
|
134
692
|
readonly docs?: {
|
|
135
693
|
readonly enabled?: boolean,
|
|
@@ -139,13 +697,27 @@ export type UniflowedConfig = {
|
|
|
139
697
|
readonly staticBuild?: boolean,
|
|
140
698
|
readonly deploy?: "void",
|
|
141
699
|
},
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
700
|
+
/**
|
|
701
|
+
* The `.env` cascade and the mode it is read for.
|
|
702
|
+
*
|
|
703
|
+
* `active` empty means the command decides — `development` for `uf dev`,
|
|
704
|
+
* `production` for a build, `test` for `uf test`. `files` empty selects the
|
|
705
|
+
* conventional cascade rather than no files at all.
|
|
706
|
+
*/
|
|
707
|
+
readonly env?: {
|
|
708
|
+
readonly active?: string,
|
|
709
|
+
readonly files?: $ReadOnlyArray<string>,
|
|
710
|
+
/**
|
|
711
|
+
* Runtimes and package managers by exact version — `{ node: "24.14.0" }`.
|
|
712
|
+
*
|
|
713
|
+
* **Deprecated.** It says which tools a project has and not what each is
|
|
714
|
+
* for, so a project that builds on Node and tests on Bun could not write
|
|
715
|
+
* that down. Declare each tool where it is used instead — `runtime`,
|
|
716
|
+
* `build.runtime`, `test.runtime` and `packageManager` — as
|
|
717
|
+
* `name@version`. It keeps working for `uf env install` and `uf env exec`,
|
|
718
|
+
* and a pin here that disagrees with one of those keys is an error.
|
|
719
|
+
*/
|
|
720
|
+
readonly toolchain?: { readonly [string]: string },
|
|
149
721
|
},
|
|
150
722
|
readonly fmt?: {
|
|
151
723
|
readonly indentWidth?: number,
|
|
@@ -156,11 +728,58 @@ export type UniflowedConfig = {
|
|
|
156
728
|
readonly printer?: "uf-rust",
|
|
157
729
|
},
|
|
158
730
|
readonly nonFlow?: {
|
|
159
|
-
readonly formatter?: "biome",
|
|
731
|
+
readonly formatter?: "biome" | "prettier" | "none",
|
|
732
|
+
/**
|
|
733
|
+
* Extra arguments, passed to that formatter verbatim.
|
|
734
|
+
*
|
|
735
|
+
* Strings rather than a shape, so that reaching one of biome's or
|
|
736
|
+
* prettier's own options never waits for a uf release — a Tailwind 4
|
|
737
|
+
* project writes `["--css-parse-tailwind-directives=true"]` and needs no
|
|
738
|
+
* second configuration file. An argument that would turn `uf fmt
|
|
739
|
+
* --check` into a write is refused where the config is read.
|
|
740
|
+
*/
|
|
741
|
+
readonly arguments?: $ReadOnlyArray<string>,
|
|
160
742
|
},
|
|
161
743
|
readonly quotes?: "single" | "double",
|
|
162
744
|
readonly semicolons?: boolean,
|
|
163
745
|
},
|
|
746
|
+
/**
|
|
747
|
+
* Paths no command walks into.
|
|
748
|
+
*
|
|
749
|
+
* Top level because every command that walks the project reads it: `uf fmt`,
|
|
750
|
+
* `uf lint`, `uf check`, `uf test` and `uf doc`. A bare name — `dist` — names
|
|
751
|
+
* a kind of directory and matches at any depth; a path — `src/generated` —
|
|
752
|
+
* names one place. `.uf` and `.git` are uf's and git's and are not a
|
|
753
|
+
* project's to opt back into.
|
|
754
|
+
*
|
|
755
|
+
* Absent takes uf's own list, `["node_modules", "dist", "target"]`. An empty
|
|
756
|
+
* list is a different instruction: it is a project that has looked at that
|
|
757
|
+
* list and wants none of it.
|
|
758
|
+
*/
|
|
759
|
+
readonly ignore?: $ReadOnlyArray<string>,
|
|
760
|
+
readonly lint?: {
|
|
761
|
+
readonly engine?: "rust",
|
|
762
|
+
// Globs to lint.
|
|
763
|
+
readonly files?: $ReadOnlyArray<string>,
|
|
764
|
+
/**
|
|
765
|
+
* The old spelling of the top-level `ignore`.
|
|
766
|
+
*
|
|
767
|
+
* **Deprecated**, and read only when `ignore` is absent. It was never
|
|
768
|
+
* `uf lint`'s alone: `uf fmt`, `uf check`, `uf test` and `uf doc` walk the
|
|
769
|
+
* project through the same code and have always obeyed it, so the key was
|
|
770
|
+
* named after one of the five commands that read it. It keeps working for
|
|
771
|
+
* as long as alpha lasts, and every one of those commands says so once.
|
|
772
|
+
* See ubugeeei-prod/uf#575.
|
|
773
|
+
*/
|
|
774
|
+
readonly ignore?: $ReadOnlyArray<string>,
|
|
775
|
+
readonly flow?: {
|
|
776
|
+
readonly builtins?: "mixed",
|
|
777
|
+
readonly parser?: "official-flow-rust",
|
|
778
|
+
},
|
|
779
|
+
// Changes to uf's rule table, not the whole of it: a rule you did not
|
|
780
|
+
// mention keeps the level uf ships. Say `"off"` to switch one off.
|
|
781
|
+
readonly rules?: { readonly [string]: RuleLevel },
|
|
782
|
+
},
|
|
164
783
|
readonly package?: {
|
|
165
784
|
readonly generator?: "napi-rs",
|
|
166
785
|
readonly targets?: $ReadOnlyArray<
|
|
@@ -168,12 +787,73 @@ export type UniflowedConfig = {
|
|
|
168
787
|
>,
|
|
169
788
|
readonly typescriptDeclarationsToFlow?: true,
|
|
170
789
|
},
|
|
790
|
+
/**
|
|
791
|
+
* The package manager `uf install`, `uf add`, `uf update` and the rest drive,
|
|
792
|
+
* and optionally which release of it: `"pnpm@12.0.0"`.
|
|
793
|
+
*
|
|
794
|
+
* Read before `pm.packageManager` — its deprecated spelling — and before
|
|
795
|
+
* `package.json#packageManager` and the lockfile. See `PackageManagerSpec`.
|
|
796
|
+
*/
|
|
797
|
+
readonly packageManager?: PackageManagerSpec,
|
|
798
|
+
readonly permissions?: Permissions,
|
|
799
|
+
// Plugins the project adds, appended to uf's own and resolved in the order
|
|
800
|
+
// they are written. A name that names a file is code to run, so `uf_plugin`
|
|
801
|
+
// refuses any that reaches outside the project root.
|
|
802
|
+
readonly plugins?: $ReadOnlyArray<PluginEntry>,
|
|
171
803
|
readonly pm?: {
|
|
172
804
|
readonly module?: "@uniflowed/pm",
|
|
173
805
|
readonly resolver?: "uf-native",
|
|
174
806
|
readonly lockfile?: "uf.lock",
|
|
175
807
|
readonly storeDir?: string,
|
|
176
808
|
readonly allowLifecycleScripts?: false,
|
|
809
|
+
/**
|
|
810
|
+
* The package manager uf drives, in the spelling that came before the
|
|
811
|
+
* top-level `packageManager`.
|
|
812
|
+
*
|
|
813
|
+
* **Deprecated** for the managers `packageManager` can name — write
|
|
814
|
+
* `packageManager: "pnpm"` rather than `pm: { packageManager: "pnpm" }`,
|
|
815
|
+
* and `"yarn@1"` for `"yarn-classic"` — and read only when that key is
|
|
816
|
+
* absent. The two naming different managers is an error. `"uf"`, uf's own
|
|
817
|
+
* resolver, has no other spelling and is not deprecated.
|
|
818
|
+
*/
|
|
819
|
+
readonly packageManager?: PackageManagerPreference,
|
|
820
|
+
/**
|
|
821
|
+
* The registry uf *reads* from: packuments, provenance attestations, and
|
|
822
|
+
* the versions `uf update` reports against.
|
|
823
|
+
*
|
|
824
|
+
* Unset means `publish.registry`, which is where this lived until it
|
|
825
|
+
* turned out to be answering two questions with one value. A project that
|
|
826
|
+
* publishes to a company registry and installs through a read-through
|
|
827
|
+
* mirror sets both; one that has only ever set `publish.registry` keeps
|
|
828
|
+
* working and is told, once, which key to move to.
|
|
829
|
+
*/
|
|
830
|
+
readonly registry?: string,
|
|
831
|
+
/**
|
|
832
|
+
* Which registry answers for which scope: `{ "@company": "https://…" }`.
|
|
833
|
+
*
|
|
834
|
+
* A scope named here resolves from that registry **and nowhere else**.
|
|
835
|
+
* There is no fallback to the public registry, deliberately: publishing
|
|
836
|
+
* `@company/internal-thing` to npmjs and waiting for a resolver to fall
|
|
837
|
+
* back to it is the dependency-confusion attack, so the fallback is the
|
|
838
|
+
* vulnerability rather than a recovery from it. A name the bound registry
|
|
839
|
+
* does not have is an error that names the scope and the registry.
|
|
840
|
+
*
|
|
841
|
+
* uf refuses an install whose lockfile resolves a bound scope from
|
|
842
|
+
* somewhere else. It does not rewrite the project's `.npmrc`: the manager
|
|
843
|
+
* that resolves is the manager that has to be told, in its own
|
|
844
|
+
* configuration.
|
|
845
|
+
*/
|
|
846
|
+
readonly scopes?: { readonly [scope: string]: string },
|
|
847
|
+
/**
|
|
848
|
+
* How hard `uf install` looks at npm provenance attestations.
|
|
849
|
+
*
|
|
850
|
+
* `"report"`, the default, reads the attestation of every package the
|
|
851
|
+
* install brought in or moved: an attestation that is not about the
|
|
852
|
+
* tarball being installed stops the install, and a package with none is a
|
|
853
|
+
* line in the summary. `"off"` reads none, for a machine with no route to
|
|
854
|
+
* a registry.
|
|
855
|
+
*/
|
|
856
|
+
readonly provenance?: "report" | "off",
|
|
177
857
|
},
|
|
178
858
|
readonly rm?: {
|
|
179
859
|
readonly module?: "@uniflowed/rm",
|
|
@@ -184,6 +864,17 @@ export type UniflowedConfig = {
|
|
|
184
864
|
readonly apply?: "config-and-host",
|
|
185
865
|
readonly doctor?: boolean,
|
|
186
866
|
},
|
|
867
|
+
/**
|
|
868
|
+
* The runtime every command runs on unless a section names its own, and
|
|
869
|
+
* optionally which release of it: `"node@26"`.
|
|
870
|
+
*
|
|
871
|
+
* `uf start`, `uf run` and `uf exec` read it directly. `uf dev`, `uf build`
|
|
872
|
+
* and `uf preview` read `build.runtime` first; `uf test` reads `test.runtime`
|
|
873
|
+
* and the runtime its runner brings first. Absent, a command starts
|
|
874
|
+
* `app.runtime.capabilityJsHost` from `PATH`, as it always has. See
|
|
875
|
+
* `RuntimeSpec`.
|
|
876
|
+
*/
|
|
877
|
+
readonly runtime?: RuntimeSpec,
|
|
187
878
|
readonly server?: {
|
|
188
879
|
readonly engine?: "native-rust",
|
|
189
880
|
readonly native?: {
|
|
@@ -194,6 +885,19 @@ export type UniflowedConfig = {
|
|
|
194
885
|
>,
|
|
195
886
|
},
|
|
196
887
|
},
|
|
888
|
+
// Where the built site is served from, and what `uf build` may therefore
|
|
889
|
+
// write for a crawler. `url` is the switch: without it no `sitemap.xml` and
|
|
890
|
+
// no `robots.txt` are written at all, because a build cannot guess the host
|
|
891
|
+
// it will be deployed to and a wrong `<loc>` is worse than a missing one.
|
|
892
|
+
readonly site?: {
|
|
893
|
+
readonly url?: string,
|
|
894
|
+
readonly sitemap?: boolean,
|
|
895
|
+
readonly robots?: {
|
|
896
|
+
readonly enabled?: boolean,
|
|
897
|
+
readonly allow?: $ReadOnlyArray<string>,
|
|
898
|
+
readonly disallow?: $ReadOnlyArray<string>,
|
|
899
|
+
},
|
|
900
|
+
},
|
|
197
901
|
readonly std?: {
|
|
198
902
|
readonly module?: "@uniflowed/std",
|
|
199
903
|
readonly wintertcAligned?: true,
|
|
@@ -282,16 +986,94 @@ export type UniflowedConfig = {
|
|
|
282
986
|
},
|
|
283
987
|
readonly test?: {
|
|
284
988
|
readonly module?: "@uniflowed/test",
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
989
|
+
/**
|
|
990
|
+
* What `uf test` runs on, when it is neither the runtime the runner brings
|
|
991
|
+
* nor the top-level `runtime`: `"node@26"`.
|
|
992
|
+
*
|
|
993
|
+
* A runner that brings its own — `runner: "bun@1.4"` — decides this when it
|
|
994
|
+
* is absent, and a `runtime` here naming anything else is an error. See
|
|
995
|
+
* `RuntimeSpec`.
|
|
996
|
+
*/
|
|
997
|
+
readonly runtime?: RuntimeSpec,
|
|
998
|
+
/**
|
|
999
|
+
* Which application host `uf test` targets.
|
|
1000
|
+
*
|
|
1001
|
+
* `"auto"` follows `app.framework`: React Native projects target
|
|
1002
|
+
* `"react-native"`, and every other project targets `"web"`. Write
|
|
1003
|
+
* `"web"` in a React Native project only for tests that intentionally
|
|
1004
|
+
* target a document.
|
|
1005
|
+
*/
|
|
1006
|
+
readonly target?: "auto" | "web" | "react-native",
|
|
1007
|
+
/**
|
|
1008
|
+
* What runs the suite: `"uf"`, the default, or `"bun[@version]"`. See
|
|
1009
|
+
* `TestRunnerSpec`.
|
|
1010
|
+
*
|
|
1011
|
+
* The object is the old description of uf's own runner, field by field,
|
|
1012
|
+
* and is **deprecated**: it still parses, and `applicationTarget` in it is
|
|
1013
|
+
* still read when `target` is absent.
|
|
1014
|
+
*/
|
|
1015
|
+
readonly runner?:
|
|
1016
|
+
| TestRunnerSpec
|
|
1017
|
+
| {
|
|
1018
|
+
readonly applicationTarget?: "auto" | "web" | "react-native",
|
|
1019
|
+
readonly runtime?: "vite-task" | "capability-js-host" | "uf-self-hosted",
|
|
1020
|
+
readonly jsHosts?: $ReadOnlyArray<CapabilityJsHost>,
|
|
1021
|
+
readonly scheduler?: "vite-task-cache" | "native-work-stealing",
|
|
1022
|
+
readonly performanceTarget?: "vite-task" | "faster-than-bun",
|
|
1023
|
+
readonly officialFlowParser?: true,
|
|
1024
|
+
},
|
|
292
1025
|
readonly reactTestingLibraryNative?: true,
|
|
1026
|
+
/**
|
|
1027
|
+
* What `uf test --coverage` measures, writes and fails on.
|
|
1028
|
+
*
|
|
1029
|
+
* The thresholds live here rather than on the command line because a
|
|
1030
|
+
* coverage gate is a property of the project: the number CI fails on has to
|
|
1031
|
+
* be the number a laptop fails on. They are checked whenever coverage was
|
|
1032
|
+
* collected, so `enabled: false` plus `--coverage` still gates.
|
|
1033
|
+
*/
|
|
1034
|
+
readonly coverage?: {
|
|
1035
|
+
readonly enabled?: boolean,
|
|
1036
|
+
readonly directory?: string,
|
|
1037
|
+
readonly reporters?: $ReadOnlyArray<"text" | "lcov" | "cobertura">,
|
|
1038
|
+
readonly include?: $ReadOnlyArray<string>,
|
|
1039
|
+
readonly exclude?: $ReadOnlyArray<string>,
|
|
1040
|
+
readonly thresholds?: CoverageThresholds,
|
|
1041
|
+
readonly perFileThresholds?: CoverageThresholds,
|
|
1042
|
+
},
|
|
293
1043
|
},
|
|
294
1044
|
readonly tasks?: { readonly [string]: TaskDefinition },
|
|
1045
|
+
/**
|
|
1046
|
+
* Tasks `uf prepare` runs before a commit, keyed by a glob over the staged
|
|
1047
|
+
* files.
|
|
1048
|
+
*
|
|
1049
|
+
* A glob with no `/` matches a file's name wherever it is; one with a `/`
|
|
1050
|
+
* matches its path from the project root. Each task named runs once, with
|
|
1051
|
+
* every staged file its glob matches appended to its command, over what is
|
|
1052
|
+
* staged rather than what is on disk. A fix to a fully staged file is staged
|
|
1053
|
+
* with it; a fix to a half-staged one is not kept, and stops the commit.
|
|
1054
|
+
*/
|
|
1055
|
+
readonly staged?: { readonly [string]: string | $ReadOnlyArray<string> },
|
|
1056
|
+
/**
|
|
1057
|
+
* Where `uf ui add` writes the components a project owns, and where
|
|
1058
|
+
* `uf ui list` and `uf ui diff` look for them.
|
|
1059
|
+
*
|
|
1060
|
+
* `directory` is relative to the project root, and `app/components/ui` when
|
|
1061
|
+
* absent. Every component goes in the one directory, because each imports
|
|
1062
|
+
* the ones it builds on as siblings (`./button.js`). A path that leaves the
|
|
1063
|
+
* project is refused before anything is written.
|
|
1064
|
+
*/
|
|
1065
|
+
readonly ui?: {
|
|
1066
|
+
readonly directory?: string,
|
|
1067
|
+
},
|
|
1068
|
+
/**
|
|
1069
|
+
* Vite's own configuration, merged over the one uf generates.
|
|
1070
|
+
*
|
|
1071
|
+
* uf reads none of it, which is the point: an option Vite adds tomorrow
|
|
1072
|
+
* works in a uf project tomorrow rather than after a uf release that names
|
|
1073
|
+
* it. Deliberately unshaped for the same reason — a Flow type over Vite's
|
|
1074
|
+
* options would be the re-declaration this key exists to avoid.
|
|
1075
|
+
*/
|
|
1076
|
+
readonly vite?: { readonly [string]: mixed },
|
|
295
1077
|
readonly vrt?: {
|
|
296
1078
|
readonly enabled?: boolean,
|
|
297
1079
|
readonly module?: "@uniflowed/vrt",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniflowed/config",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.41",
|
|
4
4
|
"description": "Flow declarations for @uniflowed/config, part of the Unified Toolchain for Flow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"index.js",
|
|
18
|
-
"internal"
|
|
18
|
+
"internal",
|
|
19
|
+
"!*.test.js"
|
|
19
20
|
]
|
|
20
21
|
}
|