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