@uniflowed/config 0.0.0-alpha.15 → 0.0.0-alpha.17
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 +5 -0
- package/internal/schema.js +249 -17
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -5,8 +5,13 @@
|
|
|
5
5
|
export type {
|
|
6
6
|
CapabilityJsHost,
|
|
7
7
|
CoverageThresholds,
|
|
8
|
+
DeployAdapter,
|
|
9
|
+
PackageManagerPreference,
|
|
8
10
|
Permissions,
|
|
11
|
+
PluginEntry,
|
|
9
12
|
RuleLevel,
|
|
13
|
+
RuntimeEngine,
|
|
14
|
+
SizeBudget,
|
|
10
15
|
TaskDefinition,
|
|
11
16
|
UniflowedConfig,
|
|
12
17
|
} from "./internal/schema.js";
|
package/internal/schema.js
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
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.
|
|
5
29
|
|
|
6
30
|
export type RuleLevel = "off" | "warn" | "error" | 0 | 1 | 2 | boolean;
|
|
7
31
|
|
|
@@ -25,6 +49,68 @@ export type TaskDefinition =
|
|
|
25
49
|
|
|
26
50
|
export type CapabilityJsHost = "node" | "deno" | "bun";
|
|
27
51
|
|
|
52
|
+
/**
|
|
53
|
+
* The package manager uf drives, overriding what it infers from the project.
|
|
54
|
+
*
|
|
55
|
+
* `"auto"` reads the project itself: an explicit `"packageManager"` field, then
|
|
56
|
+
* a lockfile, then the nearest workspace root, then uf's own resolver.
|
|
57
|
+
*/
|
|
58
|
+
// The eight below are the *names a project may pin*, not commands this module
|
|
59
|
+
// runs: `@uniflowed/config` declares a type and executes nothing at all.
|
|
60
|
+
// `uniflowed/no-npm-script-invocation` is a line scanner, and a string whose
|
|
61
|
+
// entire contents is `pnpm` reads exactly like the `spawn("pnpm", […])` the
|
|
62
|
+
// rule exists to catch — `crates/uf_lint/src/scan/search.rs` says so in its own
|
|
63
|
+
// documentation and calls what is left "rare and suppressible". This is that
|
|
64
|
+
// residue, and there is no spelling of these values that is not one of them.
|
|
65
|
+
// uf-lint-disable uniflowed/no-npm-script-invocation
|
|
66
|
+
export type PackageManagerPreference =
|
|
67
|
+
| "auto"
|
|
68
|
+
| "uf"
|
|
69
|
+
| "npm"
|
|
70
|
+
| "pnpm"
|
|
71
|
+
| "yarn"
|
|
72
|
+
| "yarn-classic"
|
|
73
|
+
| "yarn-berry"
|
|
74
|
+
| "bun";
|
|
75
|
+
// uf-lint-enable uniflowed/no-npm-script-invocation
|
|
76
|
+
|
|
77
|
+
export type RuntimeEngine = "uf" | "node" | "deno" | "bun" | "edge" | "serverless" | "container";
|
|
78
|
+
|
|
79
|
+
export type DeployAdapter =
|
|
80
|
+
| "node"
|
|
81
|
+
| "bun"
|
|
82
|
+
| "deno"
|
|
83
|
+
| "edge"
|
|
84
|
+
| "serverless"
|
|
85
|
+
| "static"
|
|
86
|
+
| "container";
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* One entry of `plugins: [...]`.
|
|
90
|
+
*
|
|
91
|
+
* A bare name takes the default band and applies to every pipeline; the long
|
|
92
|
+
* form says otherwise. Declaration order decides within a band, so the
|
|
93
|
+
* resolved pipeline is a function of this file alone.
|
|
94
|
+
*/
|
|
95
|
+
export type PluginEntry =
|
|
96
|
+
| string
|
|
97
|
+
| {
|
|
98
|
+
readonly name: string,
|
|
99
|
+
readonly order?: "pre" | "normal" | "post",
|
|
100
|
+
readonly apply?: "build" | "serve" | "always",
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* A ceiling `uf build` fails over, and what it is measured on.
|
|
105
|
+
*
|
|
106
|
+
* `max` accepts a byte count or a size a person would write — `"180kb"` —
|
|
107
|
+
* because a budget is written by hand and read back by a report.
|
|
108
|
+
*/
|
|
109
|
+
export type SizeBudget = {
|
|
110
|
+
readonly max: number | string,
|
|
111
|
+
readonly metric?: "raw" | "gzip" | "brotli",
|
|
112
|
+
};
|
|
113
|
+
|
|
28
114
|
/**
|
|
29
115
|
* What the project's own code may reach.
|
|
30
116
|
*
|
|
@@ -70,7 +156,52 @@ export type CoverageThresholds = {
|
|
|
70
156
|
};
|
|
71
157
|
|
|
72
158
|
export type UniflowedConfig = {
|
|
159
|
+
/**
|
|
160
|
+
* The runtime accessibility audit: `expect(el).toHaveNoAxeViolations()` in a
|
|
161
|
+
* test, and the page `uf dev` is serving.
|
|
162
|
+
*
|
|
163
|
+
* One block for both on purpose. A rule a project has decided cannot be
|
|
164
|
+
* judged here — `color-contrast` against a DOM with no layout is the
|
|
165
|
+
* standing example — has to be the same rule in CI and in the loop somebody
|
|
166
|
+
* is working in, or the audit that finds a violation while the component is
|
|
167
|
+
* being written disagrees with the one that blocks the pull request.
|
|
168
|
+
*
|
|
169
|
+
* Inert without axe-core, which uf does not install: add it and both halves
|
|
170
|
+
* start working.
|
|
171
|
+
*
|
|
172
|
+
* Not the same thing as `lint.rules`' `a11y/*`, which read JSX that was
|
|
173
|
+
* never rendered.
|
|
174
|
+
*/
|
|
175
|
+
readonly accessibility?: {
|
|
176
|
+
readonly devAudit?: boolean,
|
|
177
|
+
readonly axe?: {
|
|
178
|
+
// Run only rules carrying one of these axe tags; every rule when absent.
|
|
179
|
+
readonly tags?: $ReadOnlyArray<string>,
|
|
180
|
+
readonly disabledRules?: $ReadOnlyArray<string>,
|
|
181
|
+
readonly minImpact?: "minor" | "moderate" | "serious" | "critical",
|
|
182
|
+
},
|
|
183
|
+
},
|
|
73
184
|
readonly app?: {
|
|
185
|
+
// Whether a component with no directive is rendered on the server or
|
|
186
|
+
// shipped to the browser.
|
|
187
|
+
readonly componentDefault?: "server" | "client",
|
|
188
|
+
readonly framework?: "uniflowed" | "react" | "react-native",
|
|
189
|
+
readonly react?: {
|
|
190
|
+
// React 19's Strict Mode, on by default in `uf dev`: it double-invokes
|
|
191
|
+
// render and effects so an impurity shows up in development rather
|
|
192
|
+
// than in production. Off has to be a choice a project makes.
|
|
193
|
+
readonly strictMode?: boolean,
|
|
194
|
+
readonly version?: string,
|
|
195
|
+
readonly asyncReact?: boolean,
|
|
196
|
+
readonly suspense?: boolean,
|
|
197
|
+
readonly useHook?: boolean,
|
|
198
|
+
},
|
|
199
|
+
// Whether the project builds React Server Components at all, and whether
|
|
200
|
+
// a `"use server"` export is wired to an endpoint.
|
|
201
|
+
readonly rsc?: boolean,
|
|
202
|
+
readonly serverActions?: boolean,
|
|
203
|
+
// The runtimes the build must satisfy.
|
|
204
|
+
readonly targets?: $ReadOnlyArray<"web" | "react-native" | "server" | "hermes">,
|
|
74
205
|
readonly orm?: {
|
|
75
206
|
readonly enabled?: boolean,
|
|
76
207
|
readonly module?: "@uniflowed/orm",
|
|
@@ -79,11 +210,18 @@ export type UniflowedConfig = {
|
|
|
79
210
|
readonly preparedByDefault?: true,
|
|
80
211
|
},
|
|
81
212
|
readonly builtins?: {
|
|
213
|
+
readonly data?: "uniflowed-query",
|
|
214
|
+
readonly effect?: "uniflowed-effect",
|
|
82
215
|
readonly fetch?: {
|
|
83
216
|
readonly module?: "@uniflowed/fetch",
|
|
84
217
|
readonly overrideGlobalFetch?: false,
|
|
85
218
|
},
|
|
86
219
|
readonly cell?: boolean,
|
|
220
|
+
readonly frameworkLints?: boolean,
|
|
221
|
+
readonly nativeTestRunner?: boolean,
|
|
222
|
+
readonly reactTestingLibrary?: boolean,
|
|
223
|
+
readonly relay?: boolean,
|
|
224
|
+
readonly style?: "style-x",
|
|
87
225
|
readonly reactCompiler?: {
|
|
88
226
|
readonly enabled?: boolean,
|
|
89
227
|
readonly implementation?: "official-rust",
|
|
@@ -106,6 +244,19 @@ export type UniflowedConfig = {
|
|
|
106
244
|
readonly extensions?: $ReadOnlyArray<".mdx">,
|
|
107
245
|
readonly jsxImportSource?: "@uniflowed/jsx-runtime",
|
|
108
246
|
readonly pipelinePlugin?: "built-in",
|
|
247
|
+
// Colours are computed during the build and written into the HTML,
|
|
248
|
+
// so nothing ships to the browser to do it. Both themes are emitted
|
|
249
|
+
// together as CSS variables, because a build cannot know which the
|
|
250
|
+
// reader prefers.
|
|
251
|
+
readonly highlight?: {
|
|
252
|
+
readonly enabled?: boolean,
|
|
253
|
+
readonly themes?: {
|
|
254
|
+
readonly light?: string,
|
|
255
|
+
readonly dark?: string,
|
|
256
|
+
},
|
|
257
|
+
// Grammars beyond the ones a uf project uses by default.
|
|
258
|
+
readonly langs?: $ReadOnlyArray<string>,
|
|
259
|
+
},
|
|
109
260
|
},
|
|
110
261
|
readonly cache?: "opt-in",
|
|
111
262
|
},
|
|
@@ -179,10 +330,8 @@ export type UniflowedConfig = {
|
|
|
179
330
|
},
|
|
180
331
|
},
|
|
181
332
|
readonly runtime?: {
|
|
182
|
-
readonly default?:
|
|
183
|
-
readonly compatibility?: $ReadOnlyArray<
|
|
184
|
-
"node" | "bun" | "deno" | "edge" | "serverless" | "container",
|
|
185
|
-
>,
|
|
333
|
+
readonly default?: RuntimeEngine,
|
|
334
|
+
readonly compatibility?: $ReadOnlyArray<RuntimeEngine>,
|
|
186
335
|
readonly capabilityJsHost?: {
|
|
187
336
|
readonly default?: CapabilityJsHost,
|
|
188
337
|
readonly hosts?: $ReadOnlyArray<CapabilityJsHost>,
|
|
@@ -190,15 +339,20 @@ export type UniflowedConfig = {
|
|
|
190
339
|
},
|
|
191
340
|
readonly deploy?: {
|
|
192
341
|
readonly enabled?: boolean,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
342
|
+
// The target `uf build` writes an artefact for when none is named on
|
|
343
|
+
// the command line; `--adapter` beats it.
|
|
344
|
+
readonly adapter?: DeployAdapter,
|
|
345
|
+
readonly adapters?: $ReadOnlyArray<DeployAdapter>,
|
|
196
346
|
},
|
|
197
347
|
},
|
|
198
348
|
readonly router?: {
|
|
349
|
+
// `false` says this project is not a uf application, and is the only way
|
|
350
|
+
// to say it: a library has no routes to scan for.
|
|
351
|
+
readonly enabled?: boolean,
|
|
199
352
|
readonly entry?: string,
|
|
200
353
|
readonly root?: string,
|
|
201
354
|
readonly manifest?: string,
|
|
355
|
+
readonly convention?: "file-system",
|
|
202
356
|
// Turning the file-system router off is what makes a project a
|
|
203
357
|
// **library** rather than an application, and `uf build` reads it: see
|
|
204
358
|
// `build.lib` below and docs/app/reference/config.
|
|
@@ -215,7 +369,17 @@ export type UniflowedConfig = {
|
|
|
215
369
|
},
|
|
216
370
|
},
|
|
217
371
|
readonly build?: {
|
|
372
|
+
// Size ceilings that fail the build. Unset by default: failing a build
|
|
373
|
+
// nobody asked uf to police is worse than reporting the size.
|
|
374
|
+
readonly budgets?: {
|
|
375
|
+
readonly total?: SizeBudget,
|
|
376
|
+
readonly initialJs?: SizeBudget,
|
|
377
|
+
readonly perRoute?: SizeBudget,
|
|
378
|
+
readonly perAsset?: SizeBudget,
|
|
379
|
+
},
|
|
218
380
|
readonly entries?: $ReadOnlyArray<string>,
|
|
381
|
+
// Commands to run around the build, in the same shape as `tasks`.
|
|
382
|
+
readonly hooks?: { readonly [string]: TaskDefinition },
|
|
219
383
|
readonly outDir?: string,
|
|
220
384
|
// Prerender every route and leave no server bundle behind. Read together
|
|
221
385
|
// with `app.rendering.modes`; see docs/app/reference/config.
|
|
@@ -257,6 +421,17 @@ export type UniflowedConfig = {
|
|
|
257
421
|
readonly host?: string,
|
|
258
422
|
readonly port?: number,
|
|
259
423
|
readonly strictPort?: boolean,
|
|
424
|
+
// Which files the dev server may serve. `deny` is evaluated on the
|
|
425
|
+
// canonical path and beats `allow`; see docs/security.md.
|
|
426
|
+
readonly fs?: {
|
|
427
|
+
readonly allow?: $ReadOnlyArray<string>,
|
|
428
|
+
readonly deny?: $ReadOnlyArray<string>,
|
|
429
|
+
},
|
|
430
|
+
// `--host` refuses to bind a routable address while this is empty: a dev
|
|
431
|
+
// server reachable from the network with no host allow-list is a file
|
|
432
|
+
// server for your source tree.
|
|
433
|
+
readonly allowedHosts?: $ReadOnlyArray<string>,
|
|
434
|
+
readonly allowedOrigins?: $ReadOnlyArray<string>,
|
|
260
435
|
},
|
|
261
436
|
readonly docs?: {
|
|
262
437
|
readonly enabled?: boolean,
|
|
@@ -266,13 +441,19 @@ export type UniflowedConfig = {
|
|
|
266
441
|
readonly staticBuild?: boolean,
|
|
267
442
|
readonly deploy?: "void",
|
|
268
443
|
},
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
444
|
+
/**
|
|
445
|
+
* The `.env` cascade, the mode it is read for, and the pinned toolchain.
|
|
446
|
+
*
|
|
447
|
+
* `active` empty means the command decides — `development` for `uf dev`,
|
|
448
|
+
* `production` for a build, `test` for `uf test`. `files` empty selects the
|
|
449
|
+
* conventional cascade rather than no files at all.
|
|
450
|
+
*/
|
|
451
|
+
readonly env?: {
|
|
452
|
+
readonly active?: string,
|
|
453
|
+
readonly files?: $ReadOnlyArray<string>,
|
|
454
|
+
// Runtimes and package managers by exact version — `{ node: "24.14.0" }`.
|
|
455
|
+
// Exact, because a range is not an environment.
|
|
456
|
+
readonly toolchain?: { readonly [string]: string },
|
|
276
457
|
},
|
|
277
458
|
readonly fmt?: {
|
|
278
459
|
readonly indentWidth?: number,
|
|
@@ -298,6 +479,43 @@ export type UniflowedConfig = {
|
|
|
298
479
|
readonly quotes?: "single" | "double",
|
|
299
480
|
readonly semicolons?: boolean,
|
|
300
481
|
},
|
|
482
|
+
/**
|
|
483
|
+
* Paths no command walks into.
|
|
484
|
+
*
|
|
485
|
+
* Top level because every command that walks the project reads it: `uf fmt`,
|
|
486
|
+
* `uf lint`, `uf check`, `uf test` and `uf doc`. A bare name — `dist` — names
|
|
487
|
+
* a kind of directory and matches at any depth; a path — `src/generated` —
|
|
488
|
+
* names one place. `.uf` and `.git` are uf's and git's and are not a
|
|
489
|
+
* project's to opt back into.
|
|
490
|
+
*
|
|
491
|
+
* Absent takes uf's own list, `["node_modules", "dist", "target"]`. An empty
|
|
492
|
+
* list is a different instruction: it is a project that has looked at that
|
|
493
|
+
* list and wants none of it.
|
|
494
|
+
*/
|
|
495
|
+
readonly ignore?: $ReadOnlyArray<string>,
|
|
496
|
+
readonly lint?: {
|
|
497
|
+
readonly engine?: "rust",
|
|
498
|
+
// Globs to lint.
|
|
499
|
+
readonly files?: $ReadOnlyArray<string>,
|
|
500
|
+
/**
|
|
501
|
+
* The old spelling of the top-level `ignore`.
|
|
502
|
+
*
|
|
503
|
+
* **Deprecated**, and read only when `ignore` is absent. It was never
|
|
504
|
+
* `uf lint`'s alone: `uf fmt`, `uf check`, `uf test` and `uf doc` walk the
|
|
505
|
+
* project through the same code and have always obeyed it, so the key was
|
|
506
|
+
* named after one of the five commands that read it. It keeps working for
|
|
507
|
+
* as long as alpha lasts, and every one of those commands says so once.
|
|
508
|
+
* See ubugeeei-prod/uf#575.
|
|
509
|
+
*/
|
|
510
|
+
readonly ignore?: $ReadOnlyArray<string>,
|
|
511
|
+
readonly flow?: {
|
|
512
|
+
readonly builtins?: "mixed",
|
|
513
|
+
readonly parser?: "official-flow-rust",
|
|
514
|
+
},
|
|
515
|
+
// Changes to uf's rule table, not the whole of it: a rule you did not
|
|
516
|
+
// mention keeps the level uf ships. Say `"off"` to switch one off.
|
|
517
|
+
readonly rules?: { readonly [string]: RuleLevel },
|
|
518
|
+
},
|
|
301
519
|
readonly package?: {
|
|
302
520
|
readonly generator?: "napi-rs",
|
|
303
521
|
readonly targets?: $ReadOnlyArray<
|
|
@@ -306,12 +524,17 @@ export type UniflowedConfig = {
|
|
|
306
524
|
readonly typescriptDeclarationsToFlow?: true,
|
|
307
525
|
},
|
|
308
526
|
readonly permissions?: Permissions,
|
|
527
|
+
// Plugins the project adds, appended to uf's own and resolved in the order
|
|
528
|
+
// they are written. A name that names a file is code to run, so `uf_plugin`
|
|
529
|
+
// refuses any that reaches outside the project root.
|
|
530
|
+
readonly plugins?: $ReadOnlyArray<PluginEntry>,
|
|
309
531
|
readonly pm?: {
|
|
310
532
|
readonly module?: "@uniflowed/pm",
|
|
311
533
|
readonly resolver?: "uf-native",
|
|
312
534
|
readonly lockfile?: "uf.lock",
|
|
313
535
|
readonly storeDir?: string,
|
|
314
536
|
readonly allowLifecycleScripts?: false,
|
|
537
|
+
readonly packageManager?: PackageManagerPreference,
|
|
315
538
|
/**
|
|
316
539
|
* The registry uf *reads* from: packuments, provenance attestations, and
|
|
317
540
|
* the versions `uf update` reports against.
|
|
@@ -471,10 +694,10 @@ export type UniflowedConfig = {
|
|
|
471
694
|
readonly test?: {
|
|
472
695
|
readonly module?: "@uniflowed/test",
|
|
473
696
|
readonly runner?: {
|
|
474
|
-
readonly runtime?: "capability-js-host" | "uf-self-hosted",
|
|
697
|
+
readonly runtime?: "vite-task" | "capability-js-host" | "uf-self-hosted",
|
|
475
698
|
readonly jsHosts?: $ReadOnlyArray<CapabilityJsHost>,
|
|
476
|
-
readonly scheduler?: "native-work-stealing",
|
|
477
|
-
readonly performanceTarget?: "faster-than-bun",
|
|
699
|
+
readonly scheduler?: "vite-task-cache" | "native-work-stealing",
|
|
700
|
+
readonly performanceTarget?: "vite-task" | "faster-than-bun",
|
|
478
701
|
readonly officialFlowParser?: true,
|
|
479
702
|
},
|
|
480
703
|
readonly reactTestingLibraryNative?: true,
|
|
@@ -497,6 +720,15 @@ export type UniflowedConfig = {
|
|
|
497
720
|
},
|
|
498
721
|
},
|
|
499
722
|
readonly tasks?: { readonly [string]: TaskDefinition },
|
|
723
|
+
/**
|
|
724
|
+
* Vite's own configuration, merged over the one uf generates.
|
|
725
|
+
*
|
|
726
|
+
* uf reads none of it, which is the point: an option Vite adds tomorrow
|
|
727
|
+
* works in a uf project tomorrow rather than after a uf release that names
|
|
728
|
+
* it. Deliberately unshaped for the same reason — a Flow type over Vite's
|
|
729
|
+
* options would be the re-declaration this key exists to avoid.
|
|
730
|
+
*/
|
|
731
|
+
readonly vite?: { readonly [string]: mixed },
|
|
500
732
|
readonly vrt?: {
|
|
501
733
|
readonly enabled?: boolean,
|
|
502
734
|
readonly module?: "@uniflowed/vrt",
|