@weave-framework/cli 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Weave app config (Angular-style) — one file declares everything the build/dev
3
+ * pipeline needs: the entry module, the HTML shell, the output dir, the global
4
+ * entry stylesheets, and the component style language. The CLI reads it instead
5
+ * of long `--out`/`--serve` flags.
6
+ *
7
+ * A `weave.config.ts` is compiled on the fly with esbuild (the `@weave-framework/cli` import
8
+ * is shimmed to a tiny `defineConfig` identity, so nothing heavy is pulled in) and
9
+ * imported via a `data:` URL — no temp file. A `weave.config.json` is parsed directly.
10
+ */
11
+ import type { StyleLang } from './styles.js';
12
+ export interface WeaveConfig {
13
+ /**
14
+ * Root component module (relative to the config file). When set, the framework
15
+ * OWNS the bootstrap: it generates the entry (import root, auto-register custom
16
+ * elements, mount) — no hand-written `main.ts`. Mutually exclusive with `entry`.
17
+ */
18
+ root?: string;
19
+ /** Mount target for the generated bootstrap — a CSS selector (default `#app`). Only with `root`. */
20
+ mount?: string;
21
+ /** App entry module (relative to the config file). The escape hatch when you want a hand-written bootstrap. */
22
+ entry?: string;
23
+ /** Static web root — served as-is in dev and copied verbatim into the build output. */
24
+ publicDir?: string;
25
+ /** HTML shell template (relative to the config file). */
26
+ index?: string;
27
+ /** Output directory for `weave build` (default `dist`). */
28
+ outDir?: string;
29
+ /** Component style language — the loader pairs `<base>.<styleLang>`, no probing (default `css`). */
30
+ styleLang?: StyleLang;
31
+ /**
32
+ * Pages directory for file-based routing (relative to the config file). When set,
33
+ * `weave build`/`dev` regenerate a `routes.gen.ts` from the directory before
34
+ * bundling — a new page file becomes a route with no central table to edit.
35
+ * Convention: `index.*` → `/`, `name.*` → `/name`, `[id].*` → `:id`, `[...x].*` → `*`.
36
+ */
37
+ routesDir?: string;
38
+ /** Global entry stylesheets, compiled + concatenated in order (first = base). */
39
+ styles?: string[];
40
+ dev?: {
41
+ port?: number;
42
+ };
43
+ build?: {
44
+ minify?: boolean;
45
+ };
46
+ }
47
+ /** Identity helper so a `weave.config.ts` gets full type-checking + inference. */
48
+ export declare function defineConfig(config: WeaveConfig): WeaveConfig;
49
+ /** A {@link WeaveConfig} with every path made absolute and defaults filled in. */
50
+ export interface ResolvedConfig {
51
+ /** Directory containing the config. */
52
+ root: string;
53
+ /** App entry (absolute) — set when the author hand-writes the bootstrap. */
54
+ entry?: string;
55
+ /** Root component (absolute) — set when the framework generates the bootstrap. */
56
+ rootComponent?: string;
57
+ /** Mount selector for the generated bootstrap. */
58
+ mount: string;
59
+ /** Static web root (absolute) — defaults to {@link root} when no `publicDir` is set. */
60
+ publicDir: string;
61
+ index?: string;
62
+ outDir: string;
63
+ styleLang: StyleLang;
64
+ /** Pages directory (absolute) for file-based routing, or undefined. */
65
+ routesDir?: string;
66
+ styles: string[];
67
+ port?: number;
68
+ minify: boolean;
69
+ }
70
+ /** Find + load a Weave config from `cwd` (or an explicit path). Returns null if none exists. */
71
+ export declare function loadConfig(cwd: string, explicit?: string): Promise<ResolvedConfig | null>;
package/dist/dev.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * `weave dev` — watch + rebuild + serve with live-reload. Two modes:
3
+ *
4
+ * - **in-memory** (config-driven): Weave runs its OWN dev server. The author's
5
+ * `index.html` is a clean shell — the framework injects the entry `<script>` and
6
+ * the live-reload client itself (so a developer never writes or forgets that
7
+ * boilerplate). Nothing is written to disk: the JS bundle is served from memory,
8
+ * component CSS self-injects, global styles ride a JS banner, and static assets
9
+ * (favicons, manifest) come from `publicDir`. Unmatched routes fall back to the
10
+ * injected shell so client routes survive a refresh.
11
+ *
12
+ * - **legacy** (flag-driven): esbuild's own serve over a static `servedir`, writing
13
+ * the collected stylesheet to `outdir/app.css`. Kept for `examples/__fixtures__/v2` + verify.
14
+ *
15
+ * Returns the build context so a caller (or test) can dispose it; the CLI keeps it running.
16
+ */
17
+ import { type BuildContext } from 'esbuild';
18
+ import { type StyleLang } from './styles.js';
19
+ export interface DevConfig {
20
+ /** Hand-written entry module (absolute). Mutually exclusive with {@link virtualEntry}. */
21
+ entry?: string;
22
+ /** Framework-generated entry (Level C): the module source + the dir its imports resolve against. */
23
+ virtualEntry?: {
24
+ code: string;
25
+ resolveDir: string;
26
+ };
27
+ servedir: string;
28
+ outdir: string;
29
+ port?: number;
30
+ styleLang?: StyleLang;
31
+ /** Global entry stylesheets (absolute paths) — injected via a JS banner in memory. */
32
+ styles?: string[];
33
+ /** HTML shell to inject + serve (in-memory mode). */
34
+ index?: string;
35
+ /** In-memory mode: write nothing to disk, run Weave's own dev server. Default false (legacy). */
36
+ inMemory?: boolean;
37
+ }
38
+ export interface DevServer {
39
+ ctx: BuildContext;
40
+ url: string;
41
+ }
42
+ export declare function dev(config: DevConfig): Promise<DevServer>;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Framework-owned bootstrap (Level C). When `weave.config` declares a `root`
3
+ * component, the CLI generates the app entry instead of the author hand-writing a
4
+ * `main.ts` + `mountComponent` + a `register-elements` file:
5
+ *
6
+ * 1. {@link discoverCustomElements} scans the project for components that declare
7
+ * `export const tag = '…'` (a custom-element name) and collects their props —
8
+ * so custom elements register themselves; nothing is imported by hand and
9
+ * nothing is forgotten. (A `<weave-badge>` in a template is a string tag, not an
10
+ * import, so the import graph can't find it — a filesystem scan is required.)
11
+ * 2. {@link generateEntry} emits the entry module: import the root, register every
12
+ * discovered custom element (before first render), mount the root at the
13
+ * configured selector.
14
+ * 3. {@link entryPlugin} serves that generated module to esbuild as a virtual entry.
15
+ *
16
+ * Fail loud: a tag declared twice, or a tag without the spec-required hyphen, aborts
17
+ * the build with a clear message.
18
+ */
19
+ import type { Plugin } from 'esbuild';
20
+ /** A component that opted in as a native custom element via `export const tag`. */
21
+ export interface CustomElement {
22
+ /** The hyphenated custom-element tag (e.g. `weave-badge`). */
23
+ tag: string;
24
+ /** Absolute path to the component `.ts`. */
25
+ file: string;
26
+ /** Prop names exposed as observed attributes + JS properties. */
27
+ props: string[];
28
+ }
29
+ /** The sentinel specifier esbuild resolves to the generated entry module. */
30
+ export declare const VIRTUAL_ENTRY: string;
31
+ /** Scan `rootDir` for components declaring a custom-element `tag`. Fails loud on dupes / bad names. */
32
+ export declare function discoverCustomElements(rootDir: string): CustomElement[];
33
+ /** Emit the app entry module: register discovered custom elements, then mount the root. */
34
+ export declare function generateEntry(rootComponent: string, mount: string, rootDir: string, elements: CustomElement[]): string;
35
+ /** esbuild plugin that serves the generated entry `code` for the {@link VIRTUAL_ENTRY} specifier. */
36
+ export declare function entryPlugin(code: string, resolveDir: string): Plugin;
package/dist/html.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * HTML shell injection — the framework wires the required `<script>`/`<link>` (and,
3
+ * in dev, the live-reload client) into the author's `index.html` at compile/serve
4
+ * time. The author writes a clean shell (no entry script, no reload boilerplate) and
5
+ * can't forget or misplace it: `weave build` and `weave dev` both inject here.
6
+ */
7
+ export interface InjectOptions {
8
+ /** Module entry to ensure as `<script type="module" src=…>` (e.g. `/main.js`). */
9
+ script: string;
10
+ /** Stylesheet href to ensure as `<link rel="stylesheet">` (prod only; dev injects CSS via JS). */
11
+ css?: string;
12
+ /** Live-reload SSE endpoint — wires an `EventSource` reload client (dev only). */
13
+ liveReload?: string;
14
+ }
15
+ /**
16
+ * Inject the entry script (always), an optional stylesheet link (prod), and an
17
+ * optional live-reload client (dev) into an HTML shell — each only if absent.
18
+ * Root-absolute hrefs so a client-route refresh (SPA fallback) still resolves them.
19
+ */
20
+ export declare function injectHtml(html: string, opts: InjectOptions): string;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The Weave esbuild plugin — the canonical loader (the inlined copy in
3
+ * `tools/verify-build.mjs` mirrors this). Compiles two authoring forms into one
4
+ * ES module each:
5
+ *
6
+ * - `.weave` SFC (split by `parseSfc`)
7
+ * - separate files (Angular-style): a `.ts` with a co-located `<base>.<styleLang>`
8
+ * template's `<base>.html` (and optional `<base>.<styleLang>` styles).
9
+ *
10
+ * Styles can be authored in `.css`, `.scss`, or `.sass` — picked per project via
11
+ * `options.styleLang` (so the loader pairs ONE extension, no filesystem probing) —
12
+ * and are compiled to CSS before scoping.
13
+ *
14
+ * Two CSS delivery modes:
15
+ * - **build** (`dev: false`): scoped CSS is collected into `state.css` for the
16
+ * one-shot step to emit as a single stylesheet.
17
+ * - **dev** (`dev: true`): scoped CSS is appended to the component module as a
18
+ * tiny `<style>`-injecting IIFE, so nothing is written to disk (the dev server
19
+ * serves entirely from memory — `dist/` is a build-only artifact).
20
+ *
21
+ * A `.ts` without a sibling template is an ordinary module (the callback returns
22
+ * `undefined`, so esbuild falls through to its default loader).
23
+ */
24
+ import type { Plugin } from 'esbuild';
25
+ import { type StyleLang } from './styles.js';
26
+ export interface WeaveState {
27
+ /** Scoped CSS collected from every component compiled this build (build mode only). */
28
+ css: string[];
29
+ }
30
+ export interface WeaveOptions {
31
+ /** Component style language — the sibling style file is `<base>.<styleLang>` (default `css`). */
32
+ styleLang?: StyleLang;
33
+ /** Dev mode: inject each component's CSS via JS instead of collecting it (default false). */
34
+ dev?: boolean;
35
+ }
36
+ export declare function weave(state: WeaveState, options?: WeaveOptions): Plugin;
@@ -0,0 +1,11 @@
1
+ /** `weave routes` — generate a `Route[]` module from a pages directory. */
2
+ /** Recursively collect page-file specifiers under `dir`, relative to it (POSIX, sorted). */
3
+ export declare function scanRoutes(dir: string): string[];
4
+ export interface GenerateRoutesOptions {
5
+ /** Output module path (default `<dir>/routes.gen.ts`). */
6
+ out?: string;
7
+ /** Code-split each page via `lazy()` (default true). */
8
+ lazy?: boolean;
9
+ }
10
+ /** Scan `dir`, build the manifest, and write the generated routes module. Returns its path. */
11
+ export declare function generateRoutes(dir: string, opts?: GenerateRoutesOptions): string;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Style compilation — turns a component's or app's authored styles (`.scss` /
3
+ * `.sass` / `.css`) into plain CSS. Sass is a **lazy** dev-dependency: it is only
4
+ * imported when a `.scss`/`.sass` source is actually compiled, so a pure-CSS app
5
+ * never loads it. `.css` passes through untouched (zero cost).
6
+ *
7
+ * Two entry points: file-based (resolves `@use`/`@import` relative to the file)
8
+ * and string-based (for inline `.weave` `<style>` blocks).
9
+ */
10
+ export type StyleLang = 'css' | 'scss' | 'sass';
11
+ /** The style language implied by a file extension (defaults to plain CSS). */
12
+ export declare function langFromExt(file: string): StyleLang;
13
+ /** Compile a style FILE to CSS — `@use`/`@import` resolve relative to it. */
14
+ export declare function compileStyleFile(path: string): Promise<string>;
15
+ /**
16
+ * Like {@link compileStyleFile} but also reports every file the compile pulled in —
17
+ * the entry itself plus any `@use`/`@import` partials (from sass's `loadedUrls`). The
18
+ * dev loader feeds these to esbuild's `watchFiles` so editing a partial (e.g. a tokens
19
+ * file) rebuilds the components that depend on it.
20
+ */
21
+ export declare function compileStyleFileTracked(path: string): Promise<{
22
+ css: string;
23
+ files: string[];
24
+ }>;
25
+ /** Compile a style STRING (inline `.weave` block) of `lang` to CSS. */
26
+ export declare function compileStyleSource(source: string, lang: StyleLang, fromDir?: string): Promise<string>;
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@weave-framework/cli",
3
+ "version": "0.2.0",
4
+ "description": "Weave CLI — `weave build`, `weave dev` (watch + live-reload), `weave check`, `weave routes`.",
5
+ "type": "module",
6
+ "bin": {
7
+ "weave": "./bin/weave-dist.mjs"
8
+ },
9
+ "main": "./dist/cli.js",
10
+ "types": "./dist/cli.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/cli.d.ts",
14
+ "import": "./dist/cli.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "bin"
20
+ ],
21
+ "engines": {
22
+ "node": ">=18"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/weave-framework/weave.git",
27
+ "directory": "packages/cli"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "esbuild": "^0.25.0",
34
+ "typescript": "^5.7.0"
35
+ },
36
+ "optionalDependencies": {
37
+ "sass": "^1.0.0"
38
+ },
39
+ "license": "MIT",
40
+ "module": "./dist/cli.js"
41
+ }