@weft-js/cli 0.1.1 → 0.1.3
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/README.md +534 -54
- package/bin/weft.mjs +8 -1
- package/docs/async.md +16 -6
- package/docs/browser.md +22 -8
- package/docs/config.md +39 -9
- package/docs/core.md +30 -0
- package/docs/deploy.md +33 -8
- package/docs/design.md +12 -3
- package/docs/entrypoints.md +79 -0
- package/docs/fonts.md +12 -2
- package/docs/icons.md +13 -7
- package/docs/lists.md +3 -1
- package/docs/meta.md +13 -3
- package/docs/plugins.md +32 -9
- package/docs/props.md +13 -2
- package/docs/reactivity.md +26 -0
- package/docs/rules.md +19 -12
- package/docs/rust.md +47 -17
- package/docs/start-short.md +3 -2
- package/docs/start.md +226 -52
- package/docs/state.md +33 -7
- package/docs/style.md +31 -8
- package/docs/surface.md +61 -15
- package/docs/testing.md +15 -5
- package/docs/theme.md +182 -0
- package/docs/ui-state.md +19 -6
- package/docs/verify.md +13 -0
- package/package.json +13 -4
- package/src/add/config.mjs +93 -0
- package/src/add/errors.mjs +2 -0
- package/src/add/setup.mjs +88 -0
- package/src/add-rust.mjs +82 -27
- package/src/add.mjs +209 -181
- package/src/agents-md.mjs +144 -43
- package/src/alias.mjs +16 -5
- package/src/audit/page.mjs +313 -0
- package/src/audit/report.mjs +69 -0
- package/src/audit/utils.mjs +5 -0
- package/src/audit.mjs +159 -206
- package/src/browser/cli.mjs +24 -5
- package/src/browser/client.mjs +189 -25
- package/src/browser/commands.mjs +166 -51
- package/src/catalog/audit.mjs +129 -0
- package/src/catalog/auth.mjs +40 -0
- package/src/catalog/compiler.mjs +337 -0
- package/src/catalog/contracts.mjs +18 -0
- package/src/catalog/database.mjs +52 -0
- package/src/catalog/deploy.mjs +117 -0
- package/src/catalog/design.mjs +159 -0
- package/src/catalog/forms.mjs +25 -0
- package/src/catalog/hydration.mjs +29 -0
- package/src/catalog/icons.mjs +24 -0
- package/src/catalog/media.mjs +163 -0
- package/src/catalog/metadata.mjs +116 -0
- package/src/catalog/plugins.mjs +228 -0
- package/src/catalog/realtime.mjs +195 -0
- package/src/catalog/rust.mjs +75 -0
- package/src/catalog/server-functions.mjs +92 -0
- package/src/catalog/state.mjs +39 -0
- package/src/catalog/style-groups.mjs +54 -0
- package/src/catalog/tests.mjs +127 -0
- package/src/catalog/text.mjs +200 -0
- package/src/catalog/ui-state.mjs +42 -0
- package/src/catalog.mjs +67 -460
- package/src/check/runtime.mjs +280 -0
- package/src/check.mjs +198 -208
- package/src/cli/authoring.mjs +213 -0
- package/src/cli/project.mjs +302 -0
- package/src/cli.mjs +222 -250
- package/src/config.mjs +1 -1
- package/src/contributions.mjs +75 -25
- package/src/db-layer.mjs +13 -5
- package/src/deploy/cdn.mjs +94 -16
- package/src/deploy/files.mjs +100 -21
- package/src/deploy/fit.mjs +127 -23
- package/src/deploy/hosts.mjs +90 -20
- package/src/deploy/index/cli.mjs +20 -0
- package/src/deploy/index/environment.mjs +69 -0
- package/src/deploy/index/steps.mjs +87 -0
- package/src/deploy/index.mjs +228 -114
- package/src/deploy/needs.mjs +88 -31
- package/src/design-checks/accessible-names.mjs +62 -0
- package/src/design-checks/contrast.mjs +43 -0
- package/src/design-checks/csp.mjs +60 -0
- package/src/design-checks/files.mjs +59 -0
- package/src/design-checks/heading-links.mjs +61 -0
- package/src/design-checks/interaction.mjs +65 -0
- package/src/design-checks/jsx.mjs +67 -0
- package/src/design-checks/layout-values.mjs +68 -0
- package/src/design-checks/native-controls.mjs +48 -0
- package/src/design-checks/outline.mjs +39 -0
- package/src/design-checks/reporter.mjs +37 -0
- package/src/design-checks/rules.mjs +274 -0
- package/src/design-checks/values.mjs +262 -0
- package/src/design-checks.mjs +10 -400
- package/src/diag.mjs +32 -8
- package/src/docs.mjs +138 -43
- package/src/doctor.mjs +20 -8
- package/src/files.mjs +18 -5
- package/src/fix.mjs +10 -2
- package/src/gate/after.mjs +40 -0
- package/src/gate/before.mjs +54 -0
- package/src/gate/classify.mjs +72 -0
- package/src/gate/mutation.mjs +209 -0
- package/src/gate/resolve-cases.mjs +22 -0
- package/src/gate/result.mjs +63 -0
- package/src/gate/run.mjs +75 -0
- package/src/gate.mjs +104 -202
- package/src/infer/box-props.cjs +140 -0
- package/src/infer/core-boxes.cjs +46 -0
- package/src/infer/derived-writes.cjs +95 -0
- package/src/infer/engine/checks.cjs +193 -0
- package/src/infer/engine/flow.cjs +293 -0
- package/src/infer/engine/report.cjs +158 -0
- package/src/infer/engine/utils.cjs +15 -0
- package/src/infer/engine.cjs +108 -368
- package/src/infer/facts/sites.cjs +114 -0
- package/src/infer/facts.cjs +210 -117
- package/src/infer/hosts.cjs +69 -22
- package/src/infer/lsp.mjs +149 -40
- package/src/infer/session.cjs +73 -17
- package/src/infer/shadow.cjs +13 -5
- package/src/infer/worker.cjs +57 -9
- package/src/jsx-scan.mjs +63 -21
- package/src/load-config/schema.mjs +281 -0
- package/src/load-config.mjs +137 -138
- package/src/map.mjs +93 -26
- package/src/mcp/browser-tools.mjs +155 -0
- package/src/mcp.mjs +147 -69
- package/src/meta-table.mjs +43 -8
- package/src/mutate.mjs +120 -36
- package/src/plugin-checks.mjs +52 -23
- package/src/plugins.mjs +125 -39
- package/src/project.mjs +170 -79
- package/src/props-checks.mjs +24 -6
- package/src/props-listener.mjs +27 -9
- package/src/react-checks.mjs +35 -4
- package/src/server-state-checks.mjs +34 -0
- package/src/share-checks.mjs +121 -37
- package/src/site.mjs +33 -6
- package/src/slots.mjs +104 -19
- package/src/start/build.mjs +116 -0
- package/src/start/routes.mjs +38 -0
- package/src/start.mjs +193 -95
- package/src/state-checks/core-state.mjs +223 -0
- package/src/state-checks/modules.mjs +17 -0
- package/src/state-checks/scan.mjs +232 -0
- package/src/state-checks/server-graph.mjs +65 -0
- package/src/state-checks.mjs +109 -133
- package/src/style/find.mjs +121 -0
- package/src/style.mjs +133 -127
- package/src/surface-checks.mjs +212 -46
- package/src/tailwind.mjs +5 -4
- package/src/tasks.mjs +189 -27
- package/src/test-rules/context.mjs +109 -0
- package/src/test-rules/file-rules.mjs +279 -0
- package/src/test-rules/rule-helpers.mjs +244 -0
- package/src/test-rules/syntax.mjs +223 -0
- package/src/test-rules/test-rules.mjs +127 -0
- package/src/testdiff.mjs +94 -32
- package/src/tests.mjs +31 -483
- package/src/text-checks.mjs +229 -69
- package/src/tokens.mjs +12 -4
- package/src/trust/scan.mjs +95 -0
- package/src/trust.mjs +214 -102
- package/src/weft.mjs +41 -9
- package/src/workspace.mjs +96 -19
- package/ts-plugin/context.js +57 -0
- package/ts-plugin/index.js +4 -124
- package/ts-plugin/mapping.js +65 -0
- package/ts-plugin/proxy.js +144 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/** pluginConfig diagnostic entries in catalog order. */
|
|
2
|
+
export const pluginConfig = [
|
|
3
|
+
{
|
|
4
|
+
code: 'P001',
|
|
5
|
+
severity: 'warning',
|
|
6
|
+
by: 'reserved',
|
|
7
|
+
catches: 'Stray top-level script file outside a declared task',
|
|
8
|
+
fix: 'Declare it in `tasks`, or delete it',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
code: 'P002',
|
|
12
|
+
severity: 'warning',
|
|
13
|
+
by: 'cli',
|
|
14
|
+
catches: '`package.json` script that is not a `weft …` alias',
|
|
15
|
+
fix: 'Move it to `tasks` in weft.config.ts and alias `weft run <name>`',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
code: 'P003',
|
|
19
|
+
severity: 'error',
|
|
20
|
+
by: 'cli',
|
|
21
|
+
catches: 'Task duplicates a built-in command or another task (same name or same command)',
|
|
22
|
+
fix: 'Rename it or remove the duplicate',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
code: 'P004',
|
|
26
|
+
severity: 'error',
|
|
27
|
+
by: 'cli',
|
|
28
|
+
catches: 'Task without `description` or `sideEffects`',
|
|
29
|
+
fix: 'Add both (`sideEffects: []` when it has none)',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
code: 'P005',
|
|
33
|
+
severity: 'error',
|
|
34
|
+
by: 'reserved',
|
|
35
|
+
catches: 'Write outside `scope.write`',
|
|
36
|
+
fix: 'Revert the write, or widen `scope.write` deliberately',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
code: 'P006',
|
|
40
|
+
severity: 'warning',
|
|
41
|
+
by: 'reserved',
|
|
42
|
+
catches: 'Unreferenced one-off script',
|
|
43
|
+
fix: 'Delete it, or declare it as a task',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
code: 'P007',
|
|
47
|
+
severity: 'error',
|
|
48
|
+
by: 'cli',
|
|
49
|
+
proposed: true,
|
|
50
|
+
catches: 'weft.config.ts fails to load or fails the schema (the Zod path is given)',
|
|
51
|
+
fix: 'Fix the key at the path shown',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
code: 'P008',
|
|
55
|
+
severity: 'error',
|
|
56
|
+
by: 'cli',
|
|
57
|
+
proposed: true,
|
|
58
|
+
catches: '`slots` names a slot id weft does not define',
|
|
59
|
+
fix: 'Use an id from `weft check --json` `slots`',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
code: 'P009',
|
|
63
|
+
severity: 'error',
|
|
64
|
+
by: 'cli',
|
|
65
|
+
proposed: true,
|
|
66
|
+
catches: '`slots` picks a winner that is not in `plugins` (or does not provide that slot)',
|
|
67
|
+
fix: 'Add the plugin, or pick one that provides the slot',
|
|
68
|
+
},
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
/** pluginSlots diagnostic entries in catalog order. */
|
|
72
|
+
export const pluginSlots = [
|
|
73
|
+
{
|
|
74
|
+
code: 'P010',
|
|
75
|
+
severity: 'error',
|
|
76
|
+
by: 'cli',
|
|
77
|
+
catches: 'More than one weft.config file',
|
|
78
|
+
fix: 'Keep one: `.ts`, `.json` or `.yaml`',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
code: 'P100',
|
|
82
|
+
severity: 'error',
|
|
83
|
+
by: 'cli',
|
|
84
|
+
catches: 'Two providers for a `one` slot (or the same key in a `keyed` slot)',
|
|
85
|
+
fix: 'Remove one, or name the winner in `slots: {}`',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
code: 'P101',
|
|
89
|
+
severity: 'error',
|
|
90
|
+
by: 'cli',
|
|
91
|
+
catches: 'A slot consumer is used but nothing provides it',
|
|
92
|
+
fix: 'Add the plugin, or set the option that disables it back',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
code: 'P102',
|
|
96
|
+
severity: 'error',
|
|
97
|
+
by: 'reserved',
|
|
98
|
+
catches:
|
|
99
|
+
'Provider implements no slot interface version this weft supports (P102w: bound through an adapter)',
|
|
100
|
+
fix: 'Upgrade the plugin or weft',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
code: 'P103',
|
|
104
|
+
severity: 'error',
|
|
105
|
+
by: 'reserved',
|
|
106
|
+
catches: "Plugin's `weft` peer range doesn't include the installed weft",
|
|
107
|
+
fix: 'Upgrade either side',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
code: 'P104',
|
|
111
|
+
severity: 'error',
|
|
112
|
+
by: 'reserved',
|
|
113
|
+
catches: '`requires` names a slot that nothing provides',
|
|
114
|
+
fix: 'Add a provider',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
code: 'P105',
|
|
118
|
+
severity: 'error',
|
|
119
|
+
by: 'reserved',
|
|
120
|
+
catches: 'Cycle in `order.before`/`after`',
|
|
121
|
+
fix: 'Remove one edge',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
code: 'P106',
|
|
125
|
+
severity: 'error',
|
|
126
|
+
by: 'reserved',
|
|
127
|
+
catches: "Two plugins' `transform` filters matched one module with no declared order",
|
|
128
|
+
fix: 'Add `order.after` to one',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
code: 'P107',
|
|
132
|
+
severity: 'error',
|
|
133
|
+
by: 'reserved',
|
|
134
|
+
catches: 'Unfiltered `resolveId`/`load`/`transform`, or a `config` hook',
|
|
135
|
+
fix: 'Add `filter`; move config to data',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
code: 'P108',
|
|
139
|
+
severity: 'warning',
|
|
140
|
+
by: 'reserved',
|
|
141
|
+
catches: 'Plugin over its HMR budget share',
|
|
142
|
+
fix: 'Narrow filters, cache, or move work to `check`',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
code: 'P109',
|
|
146
|
+
severity: 'error',
|
|
147
|
+
by: 'cli',
|
|
148
|
+
catches: 'Undeclared permission used, or permissions widened since the lock',
|
|
149
|
+
fix: 'Declare it, then `weft plugins approve`',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
code: 'P110',
|
|
153
|
+
severity: 'error',
|
|
154
|
+
by: 'cli',
|
|
155
|
+
catches: 'Installed plugin integrity differs from `.weft/plugins.lock.json`',
|
|
156
|
+
fix: 'Reinstall, or approve the update',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
code: 'P111',
|
|
160
|
+
severity: 'error',
|
|
161
|
+
by: 'cli',
|
|
162
|
+
catches: "Diagnostic code outside the plugin's namespace, or a namespace collision",
|
|
163
|
+
fix: 'Use `<short-name>/<CODE>`',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
code: 'P112',
|
|
167
|
+
severity: 'error',
|
|
168
|
+
by: 'cli',
|
|
169
|
+
catches: 'Plugin AGENTS section over 1 KB',
|
|
170
|
+
fix: 'Shorten; move detail to the MCP `docs` tool',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
code: 'P113',
|
|
174
|
+
severity: 'error',
|
|
175
|
+
by: 'cli',
|
|
176
|
+
catches: 'Token, catalog, compiler-data or Vite-config key collision',
|
|
177
|
+
fix: 'Rename in the namespace',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
code: 'P114',
|
|
181
|
+
severity: 'error',
|
|
182
|
+
by: 'reserved',
|
|
183
|
+
catches: 'Provider runtime code in an entry chunk (eager import)',
|
|
184
|
+
fix: "Reach it only through the slot's `load()`",
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
code: 'P115',
|
|
188
|
+
severity: 'error',
|
|
189
|
+
by: 'cli',
|
|
190
|
+
catches: 'Invalid plugin options (Zod path given)',
|
|
191
|
+
fix: 'Fix the option',
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
code: 'P116',
|
|
195
|
+
severity: 'error',
|
|
196
|
+
by: 'cli',
|
|
197
|
+
catches: 'Same plugin twice, or `name`/`version` does not match `package.json`',
|
|
198
|
+
fix: 'Remove the duplicate',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
code: 'P117',
|
|
202
|
+
severity: 'error',
|
|
203
|
+
by: 'cli',
|
|
204
|
+
catches: '`contribute()` is not pure',
|
|
205
|
+
fix: 'Move IO to a build-side provider',
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
code: 'P118',
|
|
209
|
+
severity: 'error',
|
|
210
|
+
by: 'reserved',
|
|
211
|
+
catches: 'Server code registered outside a server-side slot',
|
|
212
|
+
fix: 'Provide a slot, or move it into app code',
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
code: 'P119',
|
|
216
|
+
severity: 'error',
|
|
217
|
+
by: 'reserved',
|
|
218
|
+
catches: "Provider failed its slot's conformance suite",
|
|
219
|
+
fix: 'Fix the provider; the failing cases are listed',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
code: 'P120',
|
|
223
|
+
severity: 'error',
|
|
224
|
+
by: 'cli',
|
|
225
|
+
catches: "A weft plugin's `vite` part registered directly in `vite.config.ts`",
|
|
226
|
+
fix: 'Move it to `plugins` in weft.config.ts',
|
|
227
|
+
},
|
|
228
|
+
]
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/** realtime diagnostic entries in catalog order. */
|
|
2
|
+
export const realtime = [
|
|
3
|
+
// Realtime (research 30 §8, research 32 §8; R for realtime).
|
|
4
|
+
{
|
|
5
|
+
code: 'R001',
|
|
6
|
+
severity: 'error',
|
|
7
|
+
by: 'start',
|
|
8
|
+
catches:
|
|
9
|
+
'`channel` or `sharedState` without `authorize` (`weft check`, `weft build`, and thrown at definition)',
|
|
10
|
+
fix: 'Add it (`() => true` must be written explicitly)',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
code: 'R002',
|
|
14
|
+
severity: 'error',
|
|
15
|
+
by: 'cli',
|
|
16
|
+
catches:
|
|
17
|
+
"The memory bus on a multi-instance preset, or `durableObjectBus` outside `cloudflare_durable` (`weft build` fails): a message reaches one instance's clients",
|
|
18
|
+
fix: '`weft add redis` or `weft add nats`, or `realtime({ bus: postgresBus({ url }) })` in `src/realtime.server.ts`',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
code: 'R003',
|
|
22
|
+
severity: 'warning',
|
|
23
|
+
by: 'start',
|
|
24
|
+
catches:
|
|
25
|
+
"A mutation wrote a table a live query reads, and their tags don't intersect (dev): open pages won't update",
|
|
26
|
+
fix: "Add one of the query's tags to `invalidates`",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
code: 'R004',
|
|
30
|
+
severity: 'error',
|
|
31
|
+
by: 'start',
|
|
32
|
+
catches:
|
|
33
|
+
"A wildcard in `realtime({ origins })`, or a hand-written WebSocket handler (`crossws`, `defineWebSocketHandler`) that skips the Origin check: any site could join with a visitor's cookies",
|
|
34
|
+
fix: 'List the origins, scheme and port included; use `channel`',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
code: 'R005',
|
|
38
|
+
severity: 'warning',
|
|
39
|
+
by: 'cli',
|
|
40
|
+
catches:
|
|
41
|
+
"A stream's `input`, a channel's `params` or client messages, or a shared key or value has an unbounded string or array (`weft build`): a client decides how much the server holds",
|
|
42
|
+
fix: 'Add `.max()`',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
code: 'R006',
|
|
46
|
+
severity: 'warning',
|
|
47
|
+
by: 'start',
|
|
48
|
+
catches:
|
|
49
|
+
"A stream's `run` read the database before it subscribed to a topic (dev): what's published in between is lost",
|
|
50
|
+
fix: 'Call `topic.subscribe()` first, or pass `after`',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
code: 'R007',
|
|
54
|
+
severity: 'warning',
|
|
55
|
+
by: 'cli',
|
|
56
|
+
catches:
|
|
57
|
+
'`ws`, `socket.io-client`, `reconnecting-websocket` or `@microsoft/fetch-event-source` in dependencies: weft owns the connection',
|
|
58
|
+
fix: 'Use `stream`, `.live()` or `channel`',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
code: 'R008',
|
|
62
|
+
severity: 'error',
|
|
63
|
+
by: 'start',
|
|
64
|
+
catches:
|
|
65
|
+
'A message over 1 MiB, a request or socket frame over 64 KiB, or a client over the channel rate limit (20 messages a second)',
|
|
66
|
+
fix: 'Send less, or an id the client fetches; `limits` raises it',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
code: 'R009',
|
|
70
|
+
severity: 'error',
|
|
71
|
+
by: 'start',
|
|
72
|
+
catches:
|
|
73
|
+
'Over 100 subscriptions or joins on a connection, or 10 connections or sockets for a user',
|
|
74
|
+
fix: 'Read fewer keys; `limits` raises it',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
code: 'R010',
|
|
78
|
+
severity: 'error',
|
|
79
|
+
by: 'start',
|
|
80
|
+
catches:
|
|
81
|
+
"An origin that isn't the app's own or in `realtime({ origins })` tried to open a connection",
|
|
82
|
+
fix: 'List it, scheme and port included',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
code: 'R011',
|
|
86
|
+
severity: 'error',
|
|
87
|
+
by: 'start',
|
|
88
|
+
catches:
|
|
89
|
+
"A channel's `authorize` refused a join or a write (the status is `unauthorized`), at the join or a session re-check",
|
|
90
|
+
fix: 'Sign in, or check `authorize`',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
code: 'R012',
|
|
94
|
+
severity: 'warning',
|
|
95
|
+
by: 'start',
|
|
96
|
+
catches:
|
|
97
|
+
"A live query reads a table `changes` reports and no tag names it, or a table `changes` doesn't list (dev): writes from outside the app won't refresh it",
|
|
98
|
+
fix: "Add the table's name to `tags`, or the table to `dbChanges`",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
code: 'R013',
|
|
102
|
+
severity: 'error',
|
|
103
|
+
by: 'cli',
|
|
104
|
+
catches:
|
|
105
|
+
"A query marked `live: { required: true }` on a target that can't deliver a change feed: a functions preset with no external listener, or no `changes` at all (`weft check`, `weft build`, `weft doctor`)",
|
|
106
|
+
fix: "Run `weft db listen` on an always-on host and set `listener: 'external'`, deploy to a server preset, add `changes: dbChanges(db, [tables])`, or drop `required`",
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
code: 'R014',
|
|
110
|
+
severity: 'warning',
|
|
111
|
+
by: 'cli',
|
|
112
|
+
catches:
|
|
113
|
+
"`changes` on a preset with no long-running process: writes from outside the app won't reach `.live()`, which shows `degraded`",
|
|
114
|
+
fix: "Run `weft db listen` on an always-on host and set `listener: 'external'`, or deploy to a server preset",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
code: 'R015',
|
|
118
|
+
severity: 'error',
|
|
119
|
+
by: 'start',
|
|
120
|
+
catches:
|
|
121
|
+
"A required live query, and the server's startup probe found no real change feed (a pooler, no trigger, no trigger permission, a Mongo without a replica set): the server stops rather than serve stale data, and dev answers 503",
|
|
122
|
+
fix: 'What the error names: `dbChanges(db, tables, { listenUrl })` for a direct connection, `weft db live` for triggers',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
code: 'R016',
|
|
126
|
+
severity: 'warning',
|
|
127
|
+
by: 'start',
|
|
128
|
+
catches:
|
|
129
|
+
'The server settled on a degraded live mode (`poll` or `off`), or a working feed went down: `.live()` shows `degraded` or `reconnecting`',
|
|
130
|
+
fix: 'What the log line names; `weft doctor` lists the options',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
code: 'R017',
|
|
134
|
+
severity: 'error',
|
|
135
|
+
by: 'start',
|
|
136
|
+
catches:
|
|
137
|
+
"`dbChanges` on a client it can't watch or something that isn't a table, or `weft db listen` on the memory bus, which stops at that process",
|
|
138
|
+
fix: 'Use a client from `@weft-js/start/db/*` or `mongoChanges`; set `bus` in `src/realtime.server.ts`',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
code: 'R019',
|
|
142
|
+
severity: 'error',
|
|
143
|
+
by: 'cli',
|
|
144
|
+
catches:
|
|
145
|
+
"A query's `live: { verify }` round trip failed against its target (`weft check`, `weft build`): the message names the link that broke, from `trigger` to `cleanup`",
|
|
146
|
+
fix: "What the link says: `weft db live` for a trigger, the app's log for a poke, `verify.row` for a row the query can't see",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
code: 'R020',
|
|
150
|
+
severity: 'error',
|
|
151
|
+
by: 'cli',
|
|
152
|
+
catches:
|
|
153
|
+
'A connection string with a password in source, in a `verify` or a target: it would be committed',
|
|
154
|
+
fix: 'Read it from the environment: `verify: { db: process.env.STAGING_DATABASE_URL }`',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
code: 'R021',
|
|
158
|
+
severity: 'error',
|
|
159
|
+
by: 'cli',
|
|
160
|
+
catches:
|
|
161
|
+
"A `verify` target isn't available here: fails `weft build`, and `weft check` warns and skips",
|
|
162
|
+
fix: 'Set `WEFT_STAGING_URL`, `STAGING_DATABASE_URL`, or the variable its target names',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
code: 'R022',
|
|
166
|
+
severity: 'error',
|
|
167
|
+
by: 'cli',
|
|
168
|
+
catches:
|
|
169
|
+
'A `verify` target that looks like production, or that nothing marks as not: a round trip writes rows',
|
|
170
|
+
fix: 'Name it in `live.targets` with `production: false`; a name or host that says production is always refused',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
code: 'R023',
|
|
174
|
+
severity: 'warning',
|
|
175
|
+
by: 'cli',
|
|
176
|
+
catches: 'A `verify` passed with only one kind of target, so some links went untested',
|
|
177
|
+
fix: 'Give it both a URL and a database',
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
code: 'R024',
|
|
181
|
+
severity: 'error',
|
|
182
|
+
by: 'cli',
|
|
183
|
+
catches:
|
|
184
|
+
"A `channel` or `sharedState` built for a target that can't hold a WebSocket (Netlify, Vercel, AWS Lambda): `weft build` fails, and where it is let through the page never dials, the channel's `status` is `unavailable` and a send rejects with R024",
|
|
185
|
+
fix: '`weft deploy hosts`, then a server host (`fly`, `render`); or `--unsafe-allow R024` with why, for a demo that may stay offline there',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
code: 'R018',
|
|
189
|
+
severity: 'warning',
|
|
190
|
+
by: 'cli',
|
|
191
|
+
catches:
|
|
192
|
+
'A table in `changes` that no migration gives a change trigger (`weft check`, `weft build`): the server would fall back to polling',
|
|
193
|
+
fix: 'Run `weft db live`',
|
|
194
|
+
},
|
|
195
|
+
]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** rust diagnostic entries in catalog order. */
|
|
2
|
+
export const rust = [
|
|
3
|
+
{
|
|
4
|
+
code: 'R101',
|
|
5
|
+
severity: 'error',
|
|
6
|
+
by: 'cli',
|
|
7
|
+
catches:
|
|
8
|
+
"A function with `impl` has no `output`, a type JSON can't carry (`z.date()`, `z.bigint()`, `z.void()`, `z.custom()`), or a one-way `.transform()` on its input (`weft build`, `weft check`, `weft dev`)",
|
|
9
|
+
fix: 'Use a codec: `z.codec(z.iso.datetime(), z.date(), { decode, encode })`. `z.null()` says a function returns nothing',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
code: 'R102',
|
|
13
|
+
severity: 'error',
|
|
14
|
+
by: 'cli',
|
|
15
|
+
catches:
|
|
16
|
+
"A plain `z.union` of objects in a function with `impl`: it has no tag, so Rust can't tell its arms apart reliably. Scalar unions and `.nullable()` are fine",
|
|
17
|
+
fix: "Use `z.discriminatedUnion`, or set `rust: { unions: 'allow' }`",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
code: 'R103',
|
|
21
|
+
severity: 'error',
|
|
22
|
+
by: 'cli',
|
|
23
|
+
catches:
|
|
24
|
+
"A sidecar doesn't match the contract: cargo stops where a generated type or method no longer fits (with the function's id), a binary built from another contract, an output the `output` schema rejects, or input serde refuses",
|
|
25
|
+
fix: "Fix the Rust to fit the TS declaration, which is the source of truth; `.weft/rust/<service>.rs` shows what's generated",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
code: 'R104',
|
|
29
|
+
severity: 'error',
|
|
30
|
+
by: 'cli',
|
|
31
|
+
catches:
|
|
32
|
+
"`native()` on a preset that can't run it (no file system for an addon or a `.wasm`), on a preset with no WASM when `wasm: false` is set, or a `.wasm` that won't build (a warning on a preset the addon runs on). At run time, a build with neither for this platform (503)",
|
|
33
|
+
fix: "Use `remote('rust://<name>')`, the same crate behind `weft::router`. `rustup target add wasm32-unknown-unknown`, or `rust.services.<name>.wasm: false` if nothing needs a fallback",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
code: 'R105',
|
|
37
|
+
severity: 'warning',
|
|
38
|
+
by: 'cli',
|
|
39
|
+
catches:
|
|
40
|
+
"A cached Rust query with `tags` that reports no table (`weft check` reads the method; `weft dev` sees the call): Q011 can't see into Rust, so nothing checks that the tags cover what it reads",
|
|
41
|
+
fix: 'Call `ctx.touch("table")` in the Rust, or drop `tags` from a query that reads no table',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
code: 'R106',
|
|
45
|
+
severity: 'error',
|
|
46
|
+
by: 'start',
|
|
47
|
+
catches:
|
|
48
|
+
"A `remote()` call can't be made: no address, no `WEFT_RUST_SECRET`, or the sidecar refused the signature (503)",
|
|
49
|
+
fix: 'Set `WEFT_RUST_<NAME>_URL` and the same `WEFT_RUST_SECRET` on both sides. `weft dev` and `weft start` do it for what they supervise',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
code: 'R107',
|
|
53
|
+
severity: 'error',
|
|
54
|
+
by: 'start',
|
|
55
|
+
catches:
|
|
56
|
+
"A sidecar didn't answer, or ran past the deadline (503, 504). Only that function fails",
|
|
57
|
+
fix: "Check that it's running, or raise `timeout` on `remote()`",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
code: 'R108',
|
|
61
|
+
severity: 'error',
|
|
62
|
+
by: 'start',
|
|
63
|
+
catches:
|
|
64
|
+
"A sidecar function panicked or returned an undeclared error (500). The detail stays in the sidecar's log, under the request id",
|
|
65
|
+
fix: "Find the request id in the sidecar's log, or declare the failure in `errors`",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
code: 'R109',
|
|
69
|
+
severity: 'error',
|
|
70
|
+
by: 'cli',
|
|
71
|
+
catches:
|
|
72
|
+
"A sidecar doesn't build for a reason no contract function explains: a compile error, no crate, or no `cargo`",
|
|
73
|
+
fix: 'Fix the crate, point `rust.services.<name>.crate` at it, or set `external: true` for one built elsewhere',
|
|
74
|
+
},
|
|
75
|
+
]
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** serverFunctions diagnostic entries in catalog order. */
|
|
2
|
+
export const serverFunctions = [
|
|
3
|
+
// Server functions and the query cache (research 27 §6; Q for query). `start`: reported by @weft-js/start while serving
|
|
4
|
+
// (the server log, and the error the call rejects with); `runtime`: thrown or warned by the client runtime.
|
|
5
|
+
{
|
|
6
|
+
code: 'Q001',
|
|
7
|
+
severity: 'error',
|
|
8
|
+
by: 'runtime',
|
|
9
|
+
catches:
|
|
10
|
+
'`q()` (a live query, a Resource) called with no owner: in `load`, a handler, a timer or module scope',
|
|
11
|
+
fix: '`await q.fetch(input)` there; `q()` in components and defineState scopes',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
code: 'Q002',
|
|
15
|
+
severity: 'error',
|
|
16
|
+
by: 'start',
|
|
17
|
+
catches:
|
|
18
|
+
"A query's or mutation's input failed its schema (400, with the issues and their paths)",
|
|
19
|
+
fix: 'Pass what the schema accepts',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
code: 'Q003',
|
|
23
|
+
severity: 'error',
|
|
24
|
+
by: 'start',
|
|
25
|
+
catches:
|
|
26
|
+
'`query`/`mutation` defined outside a server module: its `run` and imports would ship to the client (the build fails)',
|
|
27
|
+
fix: 'Move it to `src/server/**` or a `*.server.ts` file',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
code: 'Q004',
|
|
31
|
+
severity: 'error',
|
|
32
|
+
by: 'start',
|
|
33
|
+
catches:
|
|
34
|
+
"A mutation called while the server handles a GET (`load`, a page render, a query's `run`)",
|
|
35
|
+
fix: 'Call it from a handler or another mutation; reads go in queries',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
code: 'Q005',
|
|
39
|
+
severity: 'warning',
|
|
40
|
+
by: 'start',
|
|
41
|
+
catches:
|
|
42
|
+
"A server function's result doesn't survive JSON (`Date`, `Map`, `Set`, a class, `undefined` in an array, a function, `NaN`): the client sees another value",
|
|
43
|
+
fix: 'Send plain data (ISO strings, arrays, objects)',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
code: 'Q006',
|
|
47
|
+
severity: 'error',
|
|
48
|
+
by: 'start',
|
|
49
|
+
catches:
|
|
50
|
+
'A cached (`cache: { life }`) query reads `ctx.request`, `ctx.response` or `ctx.user`: its value is shared by every user',
|
|
51
|
+
fix: 'Drop `cache`, or pass the value as input',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
code: 'Q007',
|
|
55
|
+
severity: 'error',
|
|
56
|
+
by: 'start',
|
|
57
|
+
catches:
|
|
58
|
+
"`redirect()` after the page started streaming (a component's query): the status is already sent",
|
|
59
|
+
fix: "Call the query in the route's `load`, which runs before the first byte",
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
code: 'Q008',
|
|
63
|
+
severity: 'warning',
|
|
64
|
+
by: 'start',
|
|
65
|
+
catches: `A mutation \`invalidates\` a tag no query declares (\`todo:*\` covers \`todo:\${id}\`): nothing refreshes`,
|
|
66
|
+
fix: "Fix the tag name, or add it to the query's `tags`",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
code: 'Q009',
|
|
70
|
+
severity: 'error',
|
|
71
|
+
by: 'start',
|
|
72
|
+
catches:
|
|
73
|
+
"`/_weft/fn/<id>` names no function: the page is older than the server, or the module isn't a server module",
|
|
74
|
+
fix: 'Reload; keep `query`/`mutation` exports in server modules',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
code: 'Q010',
|
|
78
|
+
severity: 'error',
|
|
79
|
+
by: 'start',
|
|
80
|
+
catches:
|
|
81
|
+
'A mutation request without the CSRF proof (POST, JSON, `x-weft: 1`, same origin): 403',
|
|
82
|
+
fix: 'Call mutations through their stub, not a hand-made `fetch` or form',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
code: 'S011',
|
|
86
|
+
severity: 'warning',
|
|
87
|
+
by: 'runtime',
|
|
88
|
+
catches:
|
|
89
|
+
"`mutation({ optimistic })` updated a query its invalidated tags didn't cover: the prediction has no fresh value to land on (held until a refetch)",
|
|
90
|
+
fix: "Add one of the query's tags to `invalidates`",
|
|
91
|
+
},
|
|
92
|
+
]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** serverState diagnostic entries in catalog order. */
|
|
2
|
+
export const serverState = [
|
|
3
|
+
{
|
|
4
|
+
code: 'S001',
|
|
5
|
+
severity: 'error',
|
|
6
|
+
by: 'cli',
|
|
7
|
+
catches:
|
|
8
|
+
'A server object or array (`q().value`, `await q.fetch()`, or a map, filter or spread of one) copied into `state`: it goes stale and its rows lose their identity',
|
|
9
|
+
fix: 'Reference the query and `derived` from it; store ids; `state.linked` for edits, `untrack` for a deliberate snapshot',
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
code: 'S002',
|
|
13
|
+
severity: 'error',
|
|
14
|
+
by: 'runtime',
|
|
15
|
+
catches:
|
|
16
|
+
'A `defineState` scope reached on the server outside a render (module scope, `load`, a server function, a timer): it would be shared by every request',
|
|
17
|
+
fix: 'Read it in a component, a handler or a `derived`; pass values into server code as arguments',
|
|
18
|
+
},
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
/** stateTransport diagnostic entries in catalog order. */
|
|
22
|
+
export const stateTransport = [
|
|
23
|
+
{
|
|
24
|
+
code: 'S012',
|
|
25
|
+
severity: 'warning',
|
|
26
|
+
by: 'cli',
|
|
27
|
+
catches:
|
|
28
|
+
'`state.linked` over a query value with no `key`: a refetch resets what someone is typing',
|
|
29
|
+
fix: 'Add `{ key: () => source.value?.id }`',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
code: 'S013',
|
|
33
|
+
severity: 'warning',
|
|
34
|
+
by: 'runtime',
|
|
35
|
+
catches:
|
|
36
|
+
'A `local` or `session` persisted box read in a server render: the page shows `init`, then flashes to the stored value',
|
|
37
|
+
fix: "`persist: { in: 'cookie' }` if it's small, or render it client-only",
|
|
38
|
+
},
|
|
39
|
+
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** styleGroups diagnostic entries in catalog order. */
|
|
2
|
+
export const styleGroups = [
|
|
3
|
+
// Style groups (research 23 §3). D010 is warp's contrast gate (its own plugin); D040 and D081 are reserved by warp's docs.
|
|
4
|
+
{
|
|
5
|
+
code: 'D020',
|
|
6
|
+
severity: 'warning',
|
|
7
|
+
by: 'cli',
|
|
8
|
+
catches:
|
|
9
|
+
'Class soup: a static `class`/`className` with more than 8 classes, or the same class list (4+ classes) in two or more places',
|
|
10
|
+
fix: "Extract a style group (`group('order-card', …)`, name suggested from the component) and spread it; `weft style find` first, one may already fit",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
code: 'D021',
|
|
14
|
+
severity: 'warning',
|
|
15
|
+
by: 'cli',
|
|
16
|
+
catches:
|
|
17
|
+
'Two style groups resolve to 90% or more of the same CSS (`similar` in .weft/styles.json)',
|
|
18
|
+
fix: 'Merge them into one group with an axis for what differs',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
code: 'D022',
|
|
22
|
+
severity: 'info',
|
|
23
|
+
by: 'cli',
|
|
24
|
+
catches: 'The same accent (`accent: { … }` at a call site) on one group at 3 or more sites',
|
|
25
|
+
fix: 'Promote it to an axis value and pass that value at those sites',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
code: 'D023',
|
|
29
|
+
severity: 'warning',
|
|
30
|
+
by: 'cli',
|
|
31
|
+
catches: 'A `css: { … }` escape (raw CSS) in a style group',
|
|
32
|
+
fix: 'Use the token the fix names; keep the escape only where no intent sets the property',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
code: 'D024',
|
|
36
|
+
severity: 'error',
|
|
37
|
+
by: 'compiler',
|
|
38
|
+
catches:
|
|
39
|
+
"Styles that fight with no order: two group roots spread on one element; two compounds that can match at once and set one property differently, or an accent that sets what the site's own axis value sets (`weft check`)",
|
|
40
|
+
fix: 'One group per element (nest an element, or make it an axis); exclusive compound `when`s; drop the accent or make it an axis value',
|
|
41
|
+
example:
|
|
42
|
+
"import { group } from '@weft-js/core/style'\nconst a = group('a', { base: { pad: 'group' } })\nconst b = group('b', { base: { gap: 'related' } })\nexport function X() { return <li {...a()} {...b()} /> }",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
code: 'D025',
|
|
46
|
+
severity: 'error',
|
|
47
|
+
by: 'compiler',
|
|
48
|
+
catches:
|
|
49
|
+
"Unknown name in a style group: an axis value, axis, state or part a call site uses that the group doesn't have, or an intent or token that isn't in the vocabulary (also a type error)",
|
|
50
|
+
fix: 'Use one of the names listed (the closest come first); `weft style explain <group>` shows them all',
|
|
51
|
+
example:
|
|
52
|
+
"import { group } from '@weft-js/core/style'\nconst card = group('card', { axes: { status: { open: {}, late: {} } } })\nexport function X() { return <article {...card({ status: 'lost' })} /> }",
|
|
53
|
+
},
|
|
54
|
+
]
|