@webjsdev/cli 0.10.70 → 0.10.72

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/bin/webjs.js CHANGED
@@ -99,6 +99,8 @@ const USAGE = `webjs commands:
99
99
  webjs elision [--json] [--verify] Report which component modules are elided and why each shipped one ships;
100
100
  --verify diffs SSR output with elision on vs off (exits non-zero on a divergence)
101
101
  webjs mcp Start the read-only MCP server (routes / actions / components / elision / check)
102
+ webjs source <Export> [--pkg <name>] Print the signature plus doc comment of one export from the installed @webjsdev/*
103
+ packages (typed declarations first, the authored JSDoc as the fallback); exit 1 on a miss
102
104
  webjs doctor [--json] [--strict] Verify project health (Node, tsconfig, env, vendor pins, importmap coherence, @webjsdev versions, git hook, page/layout elision, component elision, un-versioned stylesheet links).
103
105
  --json emits the structured results (with stable codes). --strict additionally fails on every remaining warning.
104
106
  Per-check severity is CONFIG: map a code to off/warn/error under "webjs": { "doctor": { "gate": {...} } }
@@ -326,6 +328,19 @@ const HELP = {
326
328
  summary: 'Start the read-only MCP server (routes / actions / components / elision / check + a docs/source knowledge layer).',
327
329
  examples: ['webjs mcp'],
328
330
  },
331
+ source: {
332
+ usage: 'webjs source <Export> [--pkg <name>]',
333
+ summary: 'Print one framework export\'s signature plus the doc comment above it, read from the installed @webjsdev/* packages (the typed declarations first, the authored JSDoc when none carries a doc; every overload). The cheap way to check a contract before opening the source file.',
334
+ options: [
335
+ { flag: '--pkg <name>', description: 'Search one package only: core, server, cli, ui or intellisense.' },
336
+ ],
337
+ notesTitle: 'Exit status',
338
+ notes: [
339
+ '0 when at least one declaration printed; 1 on a miss (the message names the packages that were searched).',
340
+ 'The read-only MCP `source` tool returns the same text for { export: "<Export>" }.',
341
+ ],
342
+ examples: ['webjs source createAuth', 'webjs source optimistic --pkg core', 'webjs source getFileStore'],
343
+ },
329
344
  version: {
330
345
  usage: 'webjs version',
331
346
  summary: 'Print the installed @webjsdev/cli version. Also available as webjs --version / -v.',
@@ -1968,6 +1983,29 @@ Full docs: https://webjs.dev/docs`);
1968
1983
  ` --from PROVIDER CDN to resolve through. One of: ${[...SUPPORTED_PROVIDERS].join(', ')}. Default: jspm.`);
1969
1984
  process.exit(1);
1970
1985
  }
1986
+ case 'source': {
1987
+ // One export's signature plus its doc comment from the installed
1988
+ // @webjsdev/* packages (#1623): the same lookup the MCP `source` tool
1989
+ // runs for its `export` arg, so a Bash-only agent (no MCP) checks a
1990
+ // contract for the price of the declaration instead of the whole file.
1991
+ // Read-only: it reads the resolved package roots and loads no module.
1992
+ const name = rest.find((a) => !a.startsWith('--'));
1993
+ const pkgAt = rest.indexOf('--pkg');
1994
+ const pkg = pkgAt >= 0 ? rest[pkgAt + 1] : undefined;
1995
+ if (!name) {
1996
+ console.error('usage: webjs source <Export> [--pkg core|server|cli|ui|intellisense]');
1997
+ process.exit(1);
1998
+ }
1999
+ const { lookupExport, resolveFrameworkRoots } = await import('@webjsdev/mcp');
2000
+ const { existsSync, readdirSync } = await import('node:fs');
2001
+ const { readFile } = await import('node:fs/promises');
2002
+ const roots = resolveFrameworkRoots(process.cwd(), { exists: existsSync });
2003
+ const readdir = (d) => readdirSync(d, { withFileTypes: true }).map((e) => ({ name: e.name, isDir: e.isDirectory() }));
2004
+ const out = await lookupExport({ roots, readFile, readdir }, name, pkg);
2005
+ console.log(out);
2006
+ if (!/^@webjsdev\//m.test(out)) process.exit(1);
2007
+ break;
2008
+ }
1971
2009
  case 'mcp': {
1972
2010
  // Read-only MCP server (#262, #415) over stdio. STDOUT is the JSON-RPC
1973
2011
  // channel, so nothing here may write to stdout: the data functions are
package/lib/app-icon.js CHANGED
@@ -43,13 +43,3 @@ export function appManifest(name) {
43
43
  icons: [{ src: '/icon.svg', sizes: 'any', type: 'image/svg+xml' }],
44
44
  }, null, 2) + '\n';
45
45
  }
46
-
47
- /**
48
- * Whether an SVG is the WebJs brand mark earlier scaffolds shipped as
49
- * `public/favicon.svg` (a rounded square with the gallery's grey gradient).
50
- * Apps made before the placeholder still serve it as their favicon.
51
- * @param {string} svg
52
- */
53
- export function isLegacyBrandFavicon(svg) {
54
- return /aria-label="WebJs"/.test(svg) && /<linearGradient id="wj"/.test(svg);
55
- }
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- import { PLACEHOLDER_MARKER, isLegacyBrandFavicon } from '../../app-icon.js';
3
+ import { PLACEHOLDER_MARKER } from '../../app-icon.js';
4
4
 
5
5
  /**
6
6
  * @typedef {import('../codes.js').DoctorResult} DoctorResult
@@ -12,11 +12,9 @@ function read(file) {
12
12
  }
13
13
 
14
14
  /**
15
- * Warn when the app's favicon is still the one `webjs create` shipped: the
16
- * neutral `app/icon.svg` placeholder, or the WebJs brand mark earlier
17
- * scaffolds put at `public/favicon.svg`. Either way every app made from the
18
- * scaffold shows the same tab icon, which reads as a demo rather than a
19
- * product. An app with no `app/` directory (a library, the api template with
15
+ * Warn when the app's favicon is still the neutral `app/icon.svg` placeholder
16
+ * `webjs create` shipped: every app made from the scaffold would show the same
17
+ * tab icon, which reads as a demo rather than a product. An app with no `app/` directory (a library, the api template with
20
18
  * no pages) passes.
21
19
  *
22
20
  * @param {string} appDir
@@ -25,12 +23,9 @@ function read(file) {
25
23
  export function checkAppIcon(appDir) {
26
24
  const name = 'app-icon';
27
25
  if (!existsSync(join(appDir, 'app'))) return { name, status: 'pass', message: 'no app/ directory to analyse' };
28
- const fix = 'Replace app/icon.svg with an icon for this app (a simple symbol for what it is, in its own colours, legible at 16px), and delete public/favicon.svg plus any metadata.icons that still points at it.';
26
+ const fix = 'Replace app/icon.svg with an icon for this app (a simple symbol for what it is, in its own colours, legible at 16px).';
29
27
  if (read(join(appDir, 'app', 'icon.svg')).includes(PLACEHOLDER_MARKER)) {
30
28
  return { name, status: 'warn', message: 'app/icon.svg is still the scaffold placeholder icon', fix };
31
29
  }
32
- if (isLegacyBrandFavicon(read(join(appDir, 'public', 'favicon.svg')))) {
33
- return { name, status: 'warn', message: 'public/favicon.svg is still the WebJs mark an earlier scaffold shipped', fix };
34
- }
35
30
  return { name, status: 'pass', message: 'the app has its own icon (or declares none)' };
36
31
  }
@@ -23,11 +23,9 @@
23
23
  * - the `dev` / `start` scripts force `bun --bun` (the server is Bun),
24
24
  * - every other command stays `bun run` / `webjs ...` (runs on Node via the
25
25
  * `webjs` bin's `#!/usr/bin/env node` shebang),
26
- * - the Dockerfile is a pure `oven/bun:1-slim` base (#595, #1606). This is safe as of
27
- * `@webjsdev/cli@0.10.20` (#570): `webjs db migrate` resolves drizzle-kit
28
- * and runs it under Bun (no `npx`), so a Node-less image works. (Before
29
- * #570 shipped as `latest`, this stayed on `node:24-alpine` + a copied Bun
30
- * binary, since the installed CLI could still shell `npx`.)
26
+ * - the Dockerfile is a pure `oven/bun:1-slim` base (#595, #1606): `webjs db
27
+ * migrate` resolves drizzle-kit and runs it under Bun (no `npx`, #570), so
28
+ * a Node-less image works.
31
29
  */
32
30
 
33
31
  /**
@@ -97,15 +95,11 @@ export function bunifyProse(s) {
97
95
  * Rewrite the scaffolded Dockerfile for Bun.
98
96
  *
99
97
  * Base decision (acceptance criterion): a pure `oven/bun:1-slim` image (no Node).
100
- * Safe as of `@webjsdev/cli@0.10.20` (#570): `webjs db` / `webjs test` resolve
101
- * their tools (drizzle-kit, wtr) and spawn them with the current runtime instead
102
- * of `npx`, so the boot-time `webjs db migrate` runs under Bun with no Node
103
- * toolchain. (Before #570 was the published `latest`, this stayed on a
104
- * `node:24-alpine` base with a copied Bun binary, since the installed CLI could
105
- * still shell `npx`, which a pure Bun image lacks. #595 flipped it once the
106
- * npx-free CLI shipped.) `oven/bun:1` is Debian-based: `ca-certificates` ship in
107
- * the image, and SQLite uses the built-in bun:sqlite (no native module), so no
108
- * build toolchain is needed.
98
+ * `webjs db` / `webjs test` resolve their tools (drizzle-kit, wtr) and spawn
99
+ * them with the current runtime instead of `npx` (#570), so the boot-time
100
+ * `webjs db migrate` runs under Bun with no Node toolchain. `oven/bun:1` is
101
+ * Debian-based: `ca-certificates` ship in the image, and SQLite uses the
102
+ * built-in bun:sqlite (no native module), so no build toolchain is needed.
109
103
  *
110
104
  * @param {string} s
111
105
  * @returns {string}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webjsdev/cli",
3
- "version": "0.10.70",
3
+ "version": "0.10.72",
4
4
  "type": "module",
5
5
  "description": "The CLI for WebJs, a full-stack JavaScript framework built on web components with server-side rendering and no build step. Runs the dev and production servers, scaffolds apps, validates conventions, and drives the database. Node 24+ or Bun.",
6
6
  "bin": {
@@ -17,8 +17,8 @@
17
17
  "README.md"
18
18
  ],
19
19
  "dependencies": {
20
- "@webjsdev/mcp": "^0.1.0",
21
- "@webjsdev/server": "^0.8.88",
20
+ "@webjsdev/mcp": "^0.1.16",
21
+ "@webjsdev/server": "^0.8.89",
22
22
  "@webjsdev/ui": "^0.3.15"
23
23
  },
24
24
  "publishConfig": {
@@ -9,7 +9,7 @@ Use this skill for end-to-end WebJs app work. It helps you choose the right laye
9
9
 
10
10
  ## Full Documentation
11
11
 
12
- This skill is the quick guide. When you need the full API reference for a surface, load the matching file in `references/` (listed below). For even deeper framework detail, WebJs ships buildless, so the source you run IS the source you read: look in `node_modules/@webjsdev/{core,server,cli}/` (each package ships its own `AGENTS.md`). The complete hosted docs live at https://webjs.dev/docs.
12
+ This skill is the quick guide. When you need the full API reference for a surface, load the matching file in `references/` (listed below). For even deeper framework detail, WebJs ships buildless, so the source you run IS the source you read: look in `node_modules/@webjsdev/{core,server,cli}/` (each package ships its own `AGENTS.md`). To check ONE export's contract, run `npx webjs source <Export>` (for example `npx webjs source createAuth`, or `--pkg core` to narrow): it prints that export's signature and the doc comment above it from the installed package, so you read the declaration instead of the file. The MCP `source` tool does the same with `export`. Open the source file when the question is about behaviour the signature does not state. The complete hosted docs live at https://webjs.dev/docs.
13
13
 
14
14
  ## What WebJs Is
15
15
 
@@ -155,7 +155,7 @@ Find the right export fast. Load the linked reference for full examples.
155
155
 
156
156
  ### `@webjsdev/core` (browser + isomorphic)
157
157
 
158
- - `html` / `css` tagged templates. `WebComponent({ ... })` base-class factory; `prop(type?, opts?)` declares one reactive property. `register(tag, C)` / `Class.register('tag')`.
158
+ - `html` / `css` tagged templates. `WebComponent({ ... })` base-class factory; `prop(type?, opts?)` declares one reactive property. `Class.register('tag')` binds the tag.
159
159
  - `signal` / `computed` reactive state, `effect(fn)` client-only reaction (returns a disposer), `batch(fn)` coalesced writes; `render(v, el)` client render.
160
160
  - `notFound()` / `redirect(url[, status])` control-flow throws (page/layout/action only, NOT `route.ts`). `forbidden()` / `unauthorized()` render the nearest boundary.
161
161
  - `Suspense({fallback, children})` page-level streaming; `<webjs-suspense>` component-level streaming.
@@ -296,7 +296,7 @@ Three levels, the same scale ESLint uses: `error` fails the exit, `warn` reports
296
296
 
297
297
  Two guarantees worth knowing. A result that could not check (a network or toolchain outage) is capped at `warn` and can never be escalated, so a jspm or npm outage cannot red your CI. And a malformed gate exits 1 naming the offender rather than being ignored, so a typo cannot silently un-gate the build. That covers an unknown code, a bad severity, a wrong shape (a non-object `doctor` or `gate`), and a misspelled sibling of `gate` such as `gates`, since every one of those would otherwise leave the build un-gated while the `package.json` looks gated. Under `--json` the offenders come back as a `configErrors` array alongside an empty `results`, each entry a `{ kind }` of `malformed` / `unknown-key` / `unknown-code` / `bad-severity`. Wire it up with one workflow step, `npm run doctor`, and change what is fatal in `package.json` rather than in the workflow.
298
298
 
299
- `APP_ICON` warns while the favicon is still the scaffold's: the placeholder `app/icon.svg` (marked `data-webjs-placeholder`) or the WebJs mark older scaffolds shipped at `public/favicon.svg`. Replace it with the app's own icon (`references/routing-and-pages.md`, "App icon and manifest").
299
+ `APP_ICON` warns while the favicon is still the scaffold's placeholder `app/icon.svg` (marked `data-webjs-placeholder`). Replace it with the app's own icon (`references/routing-and-pages.md`, "App icon and manifest").
300
300
 
301
301
  ### Dependency audit allowlist
302
302
 
@@ -22,10 +22,13 @@ This is what separates a working app from a broken one.
22
22
  rules (git, tests, review) are in `.agents/rules/workflow.md`; follow them
23
23
  too.
24
24
  3. **Read the framework source for exact contracts.** WebJs is 100% buildless
25
- native ES modules, so the source you run IS the source you read. When you
26
- need a precise API signature or behavior, open the package source under
27
- `node_modules/@webjsdev/*` directly (each package ships its own `AGENTS.md`).
28
- The full hosted docs are at https://webjs.dev/docs.
25
+ native ES modules, so the source you run IS the source you read. For one
26
+ export's signature and doc comment run `npx webjs source <Export>` (for
27
+ example `npx webjs source createAuth`); it reads the installed package and
28
+ prints the declaration, not the file. When you need the behaviour behind a
29
+ signature, open the package source under `node_modules/@webjsdev/*` directly
30
+ (each package ships its own `AGENTS.md`). The full hosted docs are at
31
+ https://webjs.dev/docs.
29
32
 
30
33
  {{PLAYBOOK}}
31
34