@weft-js/cli 0.1.1 → 0.1.2
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 +38 -14
- 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
package/src/cli.mjs
CHANGED
|
@@ -24,9 +24,55 @@ import { formatGate, gate } from './gate.mjs'
|
|
|
24
24
|
import { browserCommand } from './browser/cli.mjs'
|
|
25
25
|
import { metaTable } from './meta-table.mjs'
|
|
26
26
|
import { audit } from './audit.mjs'
|
|
27
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
buildCommand,
|
|
29
|
+
dbCommand,
|
|
30
|
+
devCommand,
|
|
31
|
+
doctorCommand,
|
|
32
|
+
routesCommand,
|
|
33
|
+
startCommand,
|
|
34
|
+
unsafeAllowed,
|
|
35
|
+
} from './start.mjs'
|
|
28
36
|
import { deployCommand, formatHosts, hostsCommand, initCommand } from './deploy/index.mjs'
|
|
29
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
explainTarget,
|
|
39
|
+
findGroups,
|
|
40
|
+
formatExplain,
|
|
41
|
+
formatFind,
|
|
42
|
+
styleMatrix,
|
|
43
|
+
writeMatrixFile,
|
|
44
|
+
} from './style.mjs'
|
|
45
|
+
|
|
46
|
+
import {
|
|
47
|
+
commandLsp,
|
|
48
|
+
commandTsc,
|
|
49
|
+
commandCheck,
|
|
50
|
+
commandDoctor,
|
|
51
|
+
commandTest,
|
|
52
|
+
commandBrowser,
|
|
53
|
+
commandDev,
|
|
54
|
+
commandBuild,
|
|
55
|
+
commandAudit,
|
|
56
|
+
commandDeploy,
|
|
57
|
+
commandStart,
|
|
58
|
+
commandDb,
|
|
59
|
+
commandRoutes,
|
|
60
|
+
commandSurfaces,
|
|
61
|
+
commandTasks,
|
|
62
|
+
commandRun,
|
|
63
|
+
commandDocs,
|
|
64
|
+
commandAgentsMd,
|
|
65
|
+
} from './cli/project.mjs'
|
|
66
|
+
import {
|
|
67
|
+
commandMap,
|
|
68
|
+
commandIcons,
|
|
69
|
+
commandAdd,
|
|
70
|
+
commandPlugins,
|
|
71
|
+
commandFix,
|
|
72
|
+
commandTokens,
|
|
73
|
+
commandStyle,
|
|
74
|
+
commandMcp,
|
|
75
|
+
} from './cli/authoring.mjs'
|
|
30
76
|
|
|
31
77
|
const usage = `usage: weft <command> [--json] [--root <dir>]
|
|
32
78
|
|
|
@@ -43,7 +89,7 @@ const usage = `usage: weft <command> [--json] [--root <dir>]
|
|
|
43
89
|
build [--runtime node|bun|deno] [--preset <p>] production build to .output, and .weft/contract.json; then the
|
|
44
90
|
built pages are audited (L-codes) and an error fails the build
|
|
45
91
|
[--unsafe-allow <codes>] go past these codes (R002, L003, a family like L, or all): forces a deploy
|
|
46
|
-
audit [routes…] [--url <u>] [--all] [--max <n>] the built pages, or a running site, in a clean Chrome at a phone's
|
|
92
|
+
audit [routes…] [--url <u>] [--indexing public|private|auto] [--all] [--max <n>] the built pages, or a running site, in a clean Chrome at a phone's
|
|
47
93
|
and a desktop's width: axe-core's WCAG rules, console, deprecations, head, sideways scroll, shift
|
|
48
94
|
deploy [--prod] [--yes] [--target t] fit check, build for the target, then the host's own CLI; without --yes a dry
|
|
49
95
|
run that prints what would run. Netlify, Vercel, Cloudflare, Fly, Render; the live URL at the end
|
|
@@ -55,11 +101,13 @@ const usage = `usage: weft <command> [--json] [--root <dir>]
|
|
|
55
101
|
db live a migration with change triggers for the tables in \`changes\`
|
|
56
102
|
db listen the change feed as its own process, for an app on functions
|
|
57
103
|
routes [--meta] the route table; --meta: every route's merged metadata, tags, card mode and H-diagnostics
|
|
104
|
+
surfaces the canvas and WebGL surfaces this project already defines
|
|
58
105
|
tasks commands and project tasks
|
|
59
106
|
run <task> run a project task from weft.config.ts
|
|
60
107
|
docs [topic|code] docs for agents (rules, props, lists, async, testing, config, diagnostics, commands, W014…)
|
|
61
108
|
agents-md [--check] write AGENTS.md (--check: exit 1 when stale; --stdout: print it)
|
|
62
109
|
map [--stdout] write .weft/map.md and .json: a matrix of what to call in this app
|
|
110
|
+
icons publish <dir> every icon and variant as static .svg files with a manifest.json, for a CDN
|
|
63
111
|
add <feature> install a plugin and wire it into the config; also tailwind, auth, db [engine] [--layer drizzle|prisma|native], and rust [name] [--remote] [--dry-run] [--no-install]
|
|
64
112
|
plugins [list] plugins, the slots they provide and bind, permissions, diagnostics
|
|
65
113
|
plugins explain <slot> binding chain: config → plugin → module → .weft/slots/<id>.ts
|
|
@@ -70,16 +118,67 @@ const usage = `usage: weft <command> [--json] [--root <dir>]
|
|
|
70
118
|
style explain <group|selector> [--<axis> <value>] [--states a,b] [--accent intent:token] [--part p]
|
|
71
119
|
resolved CSS for one variation, and where each value came from
|
|
72
120
|
style matrix write .weft/styles.json (every group: axes, parts, accents, resolved CSS, uses)
|
|
73
|
-
mcp MCP server on stdio: docs, check,
|
|
121
|
+
mcp MCP server on stdio: docs, check, audit, routes_meta, map, tasks, surfaces, style_find,
|
|
122
|
+
style_explain, test_gate, browser_*`
|
|
74
123
|
|
|
75
124
|
/** Flags that take a value (`--base main` or `--base=main`), and boolean flags, beyond the global ones. */
|
|
76
|
-
const valued = new Set([
|
|
125
|
+
const valued = new Set([
|
|
126
|
+
'layer',
|
|
127
|
+
'base',
|
|
128
|
+
'budget',
|
|
129
|
+
'max-mutants',
|
|
130
|
+
'concurrency',
|
|
131
|
+
'url',
|
|
132
|
+
'indexing',
|
|
133
|
+
'tab',
|
|
134
|
+
'out',
|
|
135
|
+
'component',
|
|
136
|
+
'from',
|
|
137
|
+
'props',
|
|
138
|
+
'name',
|
|
139
|
+
'scope',
|
|
140
|
+
'timeout',
|
|
141
|
+
'preset',
|
|
142
|
+
'port',
|
|
143
|
+
'runtime',
|
|
144
|
+
'unsafe-allow',
|
|
145
|
+
'max',
|
|
146
|
+
'target',
|
|
147
|
+
])
|
|
77
148
|
/** `weft style explain` takes the group's own axes as flags (`--status late`); these are its fixed ones. */
|
|
78
149
|
const styleFlags = new Set(['states', 'accent', 'part'])
|
|
79
|
-
const booleans = new Set([
|
|
150
|
+
const booleans = new Set([
|
|
151
|
+
'dry-run',
|
|
152
|
+
'no-install',
|
|
153
|
+
'remote',
|
|
154
|
+
'gate',
|
|
155
|
+
'refactor',
|
|
156
|
+
'no-mutation',
|
|
157
|
+
'interactive',
|
|
158
|
+
'delta',
|
|
159
|
+
'graph-only',
|
|
160
|
+
'no-graph',
|
|
161
|
+
'headed',
|
|
162
|
+
'full',
|
|
163
|
+
'reload',
|
|
164
|
+
'meta',
|
|
165
|
+
'all',
|
|
166
|
+
'verbose',
|
|
167
|
+
'prod',
|
|
168
|
+
'yes',
|
|
169
|
+
'force',
|
|
170
|
+
])
|
|
80
171
|
|
|
81
172
|
export function parse(argv) {
|
|
82
|
-
const out = {
|
|
173
|
+
const out = {
|
|
174
|
+
command: argv[0],
|
|
175
|
+
positional: [],
|
|
176
|
+
json: false,
|
|
177
|
+
root: process.cwd(),
|
|
178
|
+
check: false,
|
|
179
|
+
stdout: false,
|
|
180
|
+
flags: {},
|
|
181
|
+
}
|
|
83
182
|
for (let i = 1; i < argv.length; i++) {
|
|
84
183
|
const a = argv[i]
|
|
85
184
|
if (a === '--json') out.json = true
|
|
@@ -91,262 +190,134 @@ export function parse(argv) {
|
|
|
91
190
|
const [name, inline] = a.slice(2).split(/=(.*)/s)
|
|
92
191
|
if (valued.has(name)) out.flags[name] = inline ?? argv[++i]
|
|
93
192
|
else if (booleans.has(name) && inline === undefined) out.flags[name] = true
|
|
94
|
-
else if (out.command === 'style' && styleFlags.has(name))
|
|
95
|
-
|
|
193
|
+
else if (out.command === 'style' && styleFlags.has(name))
|
|
194
|
+
out.flags[name] = inline ?? argv[++i]
|
|
195
|
+
else if (
|
|
196
|
+
out.command === 'style' &&
|
|
197
|
+
/^[a-z][\w-]*$/i.test(name) &&
|
|
198
|
+
(inline ?? argv[i + 1]) !== undefined
|
|
199
|
+
)
|
|
200
|
+
(out.flags.axes ??= {})[name] = inline ?? argv[++i]
|
|
96
201
|
else throw Object.assign(new Error(`unknown flag ${a}`), { code: 'E_USAGE' })
|
|
97
202
|
} else out.positional.push(a)
|
|
98
203
|
}
|
|
99
204
|
return out
|
|
100
205
|
}
|
|
101
206
|
|
|
207
|
+
const dependencies = {
|
|
208
|
+
fix,
|
|
209
|
+
writeTokens,
|
|
210
|
+
createRequire,
|
|
211
|
+
existsSync,
|
|
212
|
+
join,
|
|
213
|
+
resolve,
|
|
214
|
+
pathToFileURL,
|
|
215
|
+
addCommand,
|
|
216
|
+
writeAgentsMd,
|
|
217
|
+
check,
|
|
218
|
+
formatHuman,
|
|
219
|
+
sortDiagnostics,
|
|
220
|
+
docs,
|
|
221
|
+
compilerLine,
|
|
222
|
+
doctor,
|
|
223
|
+
formatDoctor,
|
|
224
|
+
formatMap,
|
|
225
|
+
writeMap,
|
|
226
|
+
serve,
|
|
227
|
+
explain,
|
|
228
|
+
list,
|
|
229
|
+
sync,
|
|
230
|
+
approveCommand,
|
|
231
|
+
auditCommand,
|
|
232
|
+
formatTrust,
|
|
233
|
+
loadConfig,
|
|
234
|
+
listSurfaces,
|
|
235
|
+
runTask,
|
|
236
|
+
tasks,
|
|
237
|
+
formatGate,
|
|
238
|
+
gate,
|
|
239
|
+
browserCommand,
|
|
240
|
+
metaTable,
|
|
241
|
+
audit,
|
|
242
|
+
buildCommand,
|
|
243
|
+
dbCommand,
|
|
244
|
+
devCommand,
|
|
245
|
+
doctorCommand,
|
|
246
|
+
routesCommand,
|
|
247
|
+
startCommand,
|
|
248
|
+
unsafeAllowed,
|
|
249
|
+
deployCommand,
|
|
250
|
+
formatHosts,
|
|
251
|
+
hostsCommand,
|
|
252
|
+
initCommand,
|
|
253
|
+
explainTarget,
|
|
254
|
+
findGroups,
|
|
255
|
+
formatExplain,
|
|
256
|
+
formatFind,
|
|
257
|
+
styleMatrix,
|
|
258
|
+
writeMatrixFile,
|
|
259
|
+
}
|
|
260
|
+
|
|
102
261
|
export async function main(argv, io = { stdout: process.stdout, stderr: process.stderr }) {
|
|
103
|
-
const print = data => io.stdout.write(`${JSON.stringify(data, null, 2)}\n`)
|
|
104
|
-
const say = text => text && io.stderr.write(`${text}\n`)
|
|
262
|
+
const print = (data) => io.stdout.write(`${JSON.stringify(data, null, 2)}\n`)
|
|
263
|
+
const say = (text) => text && io.stderr.write(`${text}\n`)
|
|
105
264
|
let args
|
|
106
265
|
try {
|
|
107
266
|
args = parse(argv)
|
|
267
|
+
const context = { ...dependencies, args, print, say, io }
|
|
108
268
|
switch (args.command) {
|
|
109
|
-
case 'lsp':
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return await
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
say(`weft tsc: ${diagnostics.filter(d => d.severity === 'error').length} errors`)
|
|
120
|
-
return diagnostics.some(d => d.severity === 'error') ? 1 : 0
|
|
121
|
-
}
|
|
122
|
-
case 'check': {
|
|
123
|
-
const result = await check(args.root, { files: args.positional, preset: args.flags.preset })
|
|
124
|
-
if (args.json) print(result)
|
|
125
|
-
say(formatHuman(result.diagnostics))
|
|
126
|
-
if (args.flags.verbose) say(compilerLine(doctor(args.root).compiler))
|
|
127
|
-
say(`weft check: ${result.summary.files} files, ${result.summary.errors} errors, ${result.summary.warnings} warnings (${result.ms} ms)`)
|
|
128
|
-
return result.ok ? 0 : 1
|
|
129
|
-
}
|
|
130
|
-
case 'doctor': {
|
|
131
|
-
// What this install compiles with, always; what live data does on the target, for an app that has any.
|
|
132
|
-
const result = doctor(args.root)
|
|
133
|
-
const plan = args.flags.preset || existsSync(join(args.root, 'src/realtime.server.ts')) ? await doctorCommand(args.root, { preset: args.flags.preset, runtime: args.flags.runtime }) : undefined
|
|
134
|
-
const hosts = hostsCommand(args.root, (await loadConfig(args.root)).config)
|
|
135
|
-
if (args.json) print({ ...result, live: plan, deploy: hosts })
|
|
136
|
-
else say(`${formatDoctor(result)}\n\nweft doctor: deploy${hosts.target ? ` (target ${hosts.target})` : ''}\n${formatHosts(hosts).replace(/^/gm, ' ')}`)
|
|
137
|
-
if (!plan) return 0
|
|
138
|
-
say(`weft doctor: ${plan.preset} (${plan.host})\n live mode: ${plan.mode}\n ${plan.says}${plan.required.length ? `\n required: ${plan.required.join(', ')}` : ''}${plan.options.length ? `\n options:\n${plan.options.map(o => ` - ${o}`).join('\n')}` : ''}`)
|
|
139
|
-
say(formatHuman(plan.diagnostics))
|
|
140
|
-
return plan.diagnostics.some(d => d.severity === 'error') ? 1 : 0
|
|
141
|
-
}
|
|
142
|
-
case 'test': {
|
|
143
|
-
if (!args.flags.gate) throw Object.assign(new Error('`weft test` runs the gate with --gate; run the suite itself with vitest'), { code: 'E_USAGE' })
|
|
144
|
-
const num = name => (args.flags[name] === undefined ? undefined : Number(args.flags[name]))
|
|
145
|
-
const result = await gate(args.root, {
|
|
146
|
-
base: args.flags.base, budgetSec: num('budget'), maxMutants: num('max-mutants'), concurrency: num('concurrency'),
|
|
147
|
-
refactor: !!args.flags.refactor, mutation: !args.flags['no-mutation'], log: line => say(line),
|
|
148
|
-
})
|
|
149
|
-
if (args.json) print(result)
|
|
150
|
-
say(formatHuman(result.diagnostics))
|
|
151
|
-
say(formatGate(result))
|
|
152
|
-
say(`weft test --gate: ${result.ok ? 'pass' : 'fail'}, ${result.summary.changedTests} changed tests, ${result.summary.errors} errors, ${result.summary.warnings} warnings (${result.ms} ms)`)
|
|
153
|
-
return result.ok ? 0 : 1
|
|
154
|
-
}
|
|
269
|
+
case 'lsp':
|
|
270
|
+
return await commandLsp(context)
|
|
271
|
+
case 'tsc':
|
|
272
|
+
return await commandTsc(context)
|
|
273
|
+
case 'check':
|
|
274
|
+
return await commandCheck(context)
|
|
275
|
+
case 'doctor':
|
|
276
|
+
return await commandDoctor(context)
|
|
277
|
+
case 'test':
|
|
278
|
+
return await commandTest(context)
|
|
155
279
|
case 'browser':
|
|
156
|
-
return await
|
|
157
|
-
case 'dev':
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
await
|
|
161
|
-
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const result = await buildCommand(args.root, { preset: args.flags.preset, runtime: args.flags.runtime, unsafeAllow: args.flags['unsafe-allow'] })
|
|
166
|
-
if (args.json) print(result)
|
|
167
|
-
say(formatHuman(result.diagnostics))
|
|
168
|
-
say(`weft build: ${result.preset} → ${result.output}, ${result.functions} functions in the contract, ${result.audited} pages audited (${result.ms} ms)`)
|
|
169
|
-
if (!result.ok) say('weft build: failed. The output is written, but fix the errors above before it ships, or `--unsafe-allow <code>` to force it.')
|
|
170
|
-
return result.ok ? 0 : 1
|
|
171
|
-
}
|
|
172
|
-
case 'audit': {
|
|
173
|
-
const result = await audit(args.root, { url: args.flags.url, routes: args.positional.length ? args.positional : undefined, all: !!args.flags.all, max: args.flags.max && Number(args.flags.max) })
|
|
174
|
-
if (args.json) print(result)
|
|
175
|
-
say(formatHuman(result.diagnostics))
|
|
176
|
-
say(`weft audit: ${result.skipped ?? `${result.pages.length} pages at a phone's and a desktop's width, ${result.diagnostics.length} findings (${result.ms} ms)`}`)
|
|
177
|
-
return result.ok ? 0 : 1
|
|
178
|
-
}
|
|
179
|
-
case 'deploy': {
|
|
180
|
-
const loaded = await loadConfig(args.root)
|
|
181
|
-
const sub = args.positional[0]
|
|
182
|
-
if (sub === 'hosts') {
|
|
183
|
-
const result = hostsCommand(args.root, loaded.config)
|
|
184
|
-
if (args.json) print(result)
|
|
185
|
-
else say(formatHosts(result))
|
|
186
|
-
return 0
|
|
187
|
-
}
|
|
188
|
-
const unsafe = unsafeAllowed(args.flags['unsafe-allow'], loaded.config)
|
|
189
|
-
if (sub === 'init') {
|
|
190
|
-
const result = initCommand(args.root, loaded.config, { target: args.positional[1] ?? args.flags.target, dryRun: !!args.flags['dry-run'], force: !!args.flags.force, unsafe })
|
|
191
|
-
if (args.json) print(result)
|
|
192
|
-
say(formatHuman(result.findings))
|
|
193
|
-
say([`weft deploy init ${result.target}${result.dryRun ? ' (dry run: nothing written)' : ''}:`, ...result.actions.map(a => ` ${a}`), '', 'then, once:', ...result.next.map(n => ` ${n}`)].join('\n'))
|
|
194
|
-
return 0
|
|
195
|
-
}
|
|
196
|
-
if (sub !== undefined) throw Object.assign(new Error(`weft deploy ${sub}: use \`weft deploy\`, \`weft deploy hosts\` or \`weft deploy init [target]\``), { code: 'E_USAGE' })
|
|
197
|
-
const result = await deployCommand(args.root, loaded.config, { target: args.flags.target, prod: !!args.flags.prod, yes: !!args.flags.yes, unsafe, build: (root, o) => buildCommand(root, { ...o, unsafeAllow: args.flags['unsafe-allow'] }) })
|
|
198
|
-
if (args.json) print(result)
|
|
199
|
-
say(formatHuman(result.diagnostics))
|
|
200
|
-
if (result.dryRun) say([`weft deploy: a dry run for ${result.target}${result.prod ? ' (production)' : ' (a preview)'}. With --yes it runs:`, ...result.steps.map(s => ` ${s.what}${s.reads.length ? `\n reads ${s.reads.join(', ')} from the environment` : ''}`)].join('\n'))
|
|
201
|
-
else say(`weft deploy: ${result.target}${result.prod ? ' (production)' : ''} → ${result.url ?? 'deployed; the host printed no URL'}`)
|
|
202
|
-
return 0
|
|
203
|
-
}
|
|
280
|
+
return await commandBrowser(context)
|
|
281
|
+
case 'dev':
|
|
282
|
+
return await commandDev(context)
|
|
283
|
+
case 'build':
|
|
284
|
+
return await commandBuild(context)
|
|
285
|
+
case 'audit':
|
|
286
|
+
return await commandAudit(context)
|
|
287
|
+
case 'deploy':
|
|
288
|
+
return await commandDeploy(context)
|
|
204
289
|
case 'start':
|
|
205
|
-
return await
|
|
206
|
-
case 'db':
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
case '
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
case '
|
|
233
|
-
|
|
234
|
-
return await runTask(args.root, args.positional[0])
|
|
235
|
-
}
|
|
236
|
-
case 'docs': {
|
|
237
|
-
const page = await docs(args.root, args.positional[0])
|
|
238
|
-
if (args.json) print(page)
|
|
239
|
-
else io.stdout.write(`${page.text}\n`)
|
|
240
|
-
return 0
|
|
241
|
-
}
|
|
242
|
-
case 'agents-md': {
|
|
243
|
-
const out = await writeAgentsMd(args.root, { check: args.check || args.stdout })
|
|
244
|
-
if (args.stdout) io.stdout.write(out.text)
|
|
245
|
-
if (args.json) print({ path: out.path, bytes: out.bytes, limit: 8192, overLimit: out.overLimit, current: out.current, written: out.written })
|
|
246
|
-
say(`AGENTS.md: ${out.bytes} bytes${out.overLimit ? ' (over the 8 KB limit)' : ''}, ${out.written ? 'written' : out.current ? 'current' : 'stale'}`)
|
|
247
|
-
return (args.check && !out.current) || out.overLimit ? 1 : 0
|
|
248
|
-
}
|
|
249
|
-
case 'map': {
|
|
250
|
-
const map = await writeMap(args.root)
|
|
251
|
-
if (args.json) print(map)
|
|
252
|
-
else if (args.stdout) process.stdout.write(formatMap(map))
|
|
253
|
-
else say(`.weft/map.md: ${map.rows.length} rows`)
|
|
254
|
-
return 0
|
|
255
|
-
}
|
|
256
|
-
case 'icons': {
|
|
257
|
-
if (args.positional[0] !== 'publish' || !args.positional[1]) { say('usage: weft icons publish <dir>'); return 1 }
|
|
258
|
-
const { publish } = await import(pathToFileURL(createRequire(join(args.root, 'package.json')).resolve('@weft-js/warp-icons/compile')).href)
|
|
259
|
-
const out = await publish(resolve(args.root, args.positional[1]))
|
|
260
|
-
if (args.json) print(out)
|
|
261
|
-
else say(`${out.files} files for ${out.icons} icons in ${out.dir}. Nothing was uploaded: host that folder, then set icons({ source }).`)
|
|
262
|
-
return 0
|
|
263
|
-
}
|
|
264
|
-
case 'add': {
|
|
265
|
-
const result = await addCommand(args.root, args.positional[0], { dryRun: args.flags['dry-run'], install: !args.flags['no-install'], engine: args.positional[1], layer: args.flags.layer, remote: args.flags.remote })
|
|
266
|
-
if (args.json) print(result)
|
|
267
|
-
else say(result.already ? `${result.package} is already in ${result.config}` : result.actions.map(a => `${args.flags['dry-run'] ? 'would ' : ''}${a}`).join('\n'))
|
|
268
|
-
return 0
|
|
269
|
-
}
|
|
270
|
-
case 'plugins': {
|
|
271
|
-
const sub = args.positional[0] ?? 'list'
|
|
272
|
-
if (sub === 'list') {
|
|
273
|
-
const result = await list(args.root)
|
|
274
|
-
if (args.json) print(result)
|
|
275
|
-
else say(result.plugins.map(p => `${p.name}@${p.version ?? '?'} ${p.provides.map(s => `${s.slot}${s.key ? `[${s.key}]` : ''}${s.bound ? '' : ' (not bound)'}`).join(', ') || 'no slots'}${p.tokens ? ` tokens --${p.tokens}-*` : ''}`).join('\n') || 'no plugins')
|
|
276
|
-
say(formatHuman(result.diagnostics))
|
|
277
|
-
return result.ok ? 0 : 1
|
|
278
|
-
}
|
|
279
|
-
if (sub === 'explain') {
|
|
280
|
-
const result = await explain(args.root, args.positional[1])
|
|
281
|
-
if (args.json) print(result)
|
|
282
|
-
else say(JSON.stringify(result.binding, null, 2))
|
|
283
|
-
return 0
|
|
284
|
-
}
|
|
285
|
-
if (sub === 'sync') {
|
|
286
|
-
const loaded = await loadConfig(args.root)
|
|
287
|
-
const errors = loaded.diagnostics.filter(d => d.severity === 'error')
|
|
288
|
-
const written = loaded.diagnostics.some(d => d.code === 'P007') ? [] : sync(args.root, loaded)
|
|
289
|
-
if (args.json) print({ ok: errors.length === 0, written, diagnostics: loaded.diagnostics })
|
|
290
|
-
say(formatHuman(loaded.diagnostics))
|
|
291
|
-
say(`weft plugins sync: ${written.length} files written`)
|
|
292
|
-
return errors.length ? 1 : 0
|
|
293
|
-
}
|
|
294
|
-
if (sub === 'audit') {
|
|
295
|
-
const loaded = await loadConfig(args.root)
|
|
296
|
-
const result = auditCommand(args.root, loaded)
|
|
297
|
-
if (args.json) print(result)
|
|
298
|
-
else say(result.plugins.map(formatTrust).join('\n') || 'no plugins')
|
|
299
|
-
say(formatHuman(result.diagnostics))
|
|
300
|
-
return result.ok ? 0 : 1
|
|
301
|
-
}
|
|
302
|
-
if (sub === 'approve') {
|
|
303
|
-
const result = approveCommand(args.root, await loadConfig(args.root), { names: args.positional.slice(1), all: !!args.flags.all })
|
|
304
|
-
if (args.json) print(result)
|
|
305
|
-
else say([...(result.written ? result.approved : result.pending).map(formatTrust), result.written ? `${result.lock}: ${result.approved.length} approved` : result.pending.length ? 'nothing written: name a plugin, or pass --all' : 'nothing waiting', ...result.written ? result.pending.map(p => `still waiting: ${p.name}`) : [], ...(result.gitignore ? ['.gitignore: the lock is no longer ignored, so commit it'] : [])].join('\n'))
|
|
306
|
-
return result.ok ? 0 : 1
|
|
307
|
-
}
|
|
308
|
-
throw Object.assign(new Error(`unknown plugins subcommand ${String(sub)}`), { code: 'E_USAGE' })
|
|
309
|
-
}
|
|
310
|
-
case 'fix': {
|
|
311
|
-
const result = await fix(args.root, { files: args.positional })
|
|
312
|
-
if (args.json) print(result)
|
|
313
|
-
else say(result.applied.length ? result.applied.map(a => `${a.file}:${a.span[0]}:${a.span[1]} ${a.code}`).join('\n') : 'nothing to fix')
|
|
314
|
-
return 0
|
|
315
|
-
}
|
|
316
|
-
case 'tokens': {
|
|
317
|
-
const result = await writeTokens(args.root)
|
|
318
|
-
if (args.json) print(result)
|
|
319
|
-
else say(`${result.dir}: ${result.files.length} files`)
|
|
320
|
-
return 0
|
|
321
|
-
}
|
|
322
|
-
case 'style': {
|
|
323
|
-
const sub = args.positional[0]
|
|
324
|
-
if (sub === 'find') {
|
|
325
|
-
const result = findGroups((await styleMatrix(args.root)).matrix, args.positional.slice(1).join(' '))
|
|
326
|
-
if (args.json) print(result)
|
|
327
|
-
else say(formatFind(result))
|
|
328
|
-
return 0
|
|
329
|
-
}
|
|
330
|
-
if (sub === 'explain') {
|
|
331
|
-
const accent = args.flags.accent ? Object.fromEntries(args.flags.accent.split(/[\s,]+/).filter(Boolean).map(w => w.split(':'))) : undefined
|
|
332
|
-
const states = args.flags.states?.split(',').map(s => s.trim()).filter(Boolean)
|
|
333
|
-
const result = explainTarget(await styleMatrix(args.root), args.positional.slice(1).join(' '), { axes: args.flags.axes, states, accent, part: args.flags.part })
|
|
334
|
-
if (args.json) print(result)
|
|
335
|
-
else say(formatExplain(result))
|
|
336
|
-
return 0
|
|
337
|
-
}
|
|
338
|
-
if (sub === 'matrix') {
|
|
339
|
-
const { matrix } = await styleMatrix(args.root)
|
|
340
|
-
const written = args.stdout ? false : writeMatrixFile(args.root, matrix)
|
|
341
|
-
if (args.stdout || args.json) print(matrix)
|
|
342
|
-
say(`.weft/styles.json: ${Object.keys(matrix.groups).length} groups, ${matrix.diagnostics.length} diagnostics, ${args.stdout ? 'not written' : written ? 'written' : 'current'}`)
|
|
343
|
-
return 0
|
|
344
|
-
}
|
|
345
|
-
throw Object.assign(new Error(`weft style ${sub ?? ''}: use find <query>, explain <group|selector> or matrix`), { code: 'E_USAGE' })
|
|
346
|
-
}
|
|
290
|
+
return await commandStart(context)
|
|
291
|
+
case 'db':
|
|
292
|
+
return await commandDb(context)
|
|
293
|
+
case 'routes':
|
|
294
|
+
return await commandRoutes(context)
|
|
295
|
+
case 'surfaces':
|
|
296
|
+
return commandSurfaces(context)
|
|
297
|
+
case 'tasks':
|
|
298
|
+
return await commandTasks(context)
|
|
299
|
+
case 'run':
|
|
300
|
+
return await commandRun(context)
|
|
301
|
+
case 'docs':
|
|
302
|
+
return await commandDocs(context)
|
|
303
|
+
case 'agents-md':
|
|
304
|
+
return await commandAgentsMd(context)
|
|
305
|
+
case 'map':
|
|
306
|
+
return await commandMap(context)
|
|
307
|
+
case 'icons':
|
|
308
|
+
return await commandIcons(context)
|
|
309
|
+
case 'add':
|
|
310
|
+
return await commandAdd(context)
|
|
311
|
+
case 'plugins':
|
|
312
|
+
return await commandPlugins(context)
|
|
313
|
+
case 'fix':
|
|
314
|
+
return await commandFix(context)
|
|
315
|
+
case 'tokens':
|
|
316
|
+
return await commandTokens(context)
|
|
317
|
+
case 'style':
|
|
318
|
+
return await commandStyle(context)
|
|
347
319
|
case 'mcp':
|
|
348
|
-
await
|
|
349
|
-
return 0
|
|
320
|
+
return await commandMcp(context)
|
|
350
321
|
case undefined:
|
|
351
322
|
case 'help':
|
|
352
323
|
case '--help':
|
|
@@ -357,7 +328,8 @@ export async function main(argv, io = { stdout: process.stdout, stderr: process.
|
|
|
357
328
|
}
|
|
358
329
|
} catch (error) {
|
|
359
330
|
const code = error.code ?? 'E_INTERNAL'
|
|
360
|
-
if (args?.json || argv.includes('--json'))
|
|
331
|
+
if (args?.json || argv.includes('--json'))
|
|
332
|
+
print({ ok: false, error: { code, message: error.message } })
|
|
361
333
|
say(`weft: ${error.message}${code === 'E_USAGE' ? `\n\n${usage}` : ''}`)
|
|
362
334
|
return code === 'E_REFUSED' ? 1 : 2
|
|
363
335
|
}
|
package/src/config.mjs
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
// Apps import it from `@weft-js/core/config`; the CLI's loader falls back here when a project's weft doesn't resolve.
|
|
3
3
|
|
|
4
4
|
/** @type {import('@weft-js/core/config').defineConfig} */
|
|
5
|
-
export const defineConfig = config => config
|
|
5
|
+
export const defineConfig = (config) => config
|