@blotch/rsbuild-plugin-angular-lynx 22.2.0 → 22.2.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 CHANGED
@@ -4,12 +4,14 @@ Rsbuild plugin that compiles Angular apps for the [Lynx](https://lynxjs.org/) na
4
4
 
5
5
  ## Installation
6
6
 
7
+ > **Using the Angular CLI?** You don't need this package directly. `ng add @blotch/angular-lynx` installs [`@blotch/angular-lynx-build`](../build), whose `ng build` and `ng serve` builders depend on this plugin and add it to rspeedy's config. To pass it options, import it from there: `import { pluginAngularLynx } from '@blotch/angular-lynx-build'`.
8
+
9
+ To run rspeedy directly:
10
+
7
11
  ```bash
8
12
  npm install @blotch/rsbuild-plugin-angular-lynx
9
13
  ```
10
14
 
11
- > Starting a new project? `ng add @blotch/angular-lynx` sets this up automatically.
12
-
13
15
  ## Usage
14
16
 
15
17
  Add the plugin to your `lynx.config.ts`:
@@ -32,6 +34,21 @@ export default defineConfig({
32
34
  - Splits each entry into **main-thread** and **background-thread** bundles for Lynx's dual-thread model
33
35
  - Bundles component stylesheets and processes CSS
34
36
  - Registers `CUSTOM_ELEMENTS_SCHEMA` so Angular accepts Lynx elements (`<view>`, `<text>`, etc.)
37
+ - Enforces the build target's `budgets` with `ng build`'s units and messages: a warning is printed, an error fails the build
38
+
39
+ ## Budgets
40
+
41
+ Budgets in angular.json are checked against the `lynx` environment, the bundles devices load. The `web` preview isn't checked. A Lynx app ships `.bundle` files rather than separate scripts and stylesheets, so each budget type measures:
42
+
43
+ | Type | Measures |
44
+ | ------------------- | ------------------------------------------------------------------ |
45
+ | `initial` | Each entry's bundle on its own, since a Lynx page loads one bundle |
46
+ | `bundle` | The bundle of the entry named by `name` |
47
+ | `all` / `allScript` | All bundles and scripts together (scripts ship inside the bundles) |
48
+ | `any` / `anyScript` | Each bundle and script |
49
+ | `anyComponentStyle` | Each component stylesheet, compiled |
50
+
51
+ Media and fonts aren't counted. Under plain `rspeedy dev` budgets are skipped: the plugin then reads angular.json's default configuration, usually production, whose budgets don't fit a development build. `ng serve` checks them when the configuration it serves has them, as Angular's dev server does.
35
52
 
36
53
  ## Documentation
37
54
 
@@ -0,0 +1,34 @@
1
+ import type { RsbuildPlugin, RsbuildPluginAPI } from '@lynx-js/rspeedy';
2
+ /**
3
+ * What Angular CLI knows about the build that a plain rspeedy run doesn't:
4
+ * which project it is for, and its build target's options as Angular CLI
5
+ * resolved them. `ng build` and `ng serve` (@blotch/angular-lynx-build) hand
6
+ * it to the plugin through {@link pluginAngularCliContext}.
7
+ */
8
+ export type AngularCliContext = {
9
+ /** The workspace root, where angular.json is. */
10
+ readonly workspaceRoot: string;
11
+ /** The angular.json project being built. */
12
+ readonly project: string;
13
+ /**
14
+ * The project's build target options: its base options, then each
15
+ * configuration selected with `-c` (or the default one), then command-line
16
+ * overrides, merged by Angular CLI.
17
+ */
18
+ readonly buildOptions: Readonly<Record<string, unknown>>;
19
+ };
20
+ export declare const ANGULAR_CLI_CONTEXT_PLUGIN_NAME = "lynx:angular-cli-context";
21
+ /**
22
+ * Hands the Angular CLI context to `pluginAngularLynx()` through Rsbuild's
23
+ * plugin-to-plugin API (`api.expose` / `api.useExposed`). The builders add it
24
+ * to rspeedy's config; lynx.config.ts never lists it.
25
+ *
26
+ * It works whether the builders added `pluginAngularLynx()` themselves or
27
+ * lynx.config.ts lists it with options, which a constructor argument couldn't.
28
+ */
29
+ export declare const pluginAngularCliContext: (context: AngularCliContext) => RsbuildPlugin;
30
+ /**
31
+ * The Angular CLI context, or undefined when rspeedy runs on its own (then
32
+ * the plugin reads angular.json itself).
33
+ */
34
+ export declare const getAngularCliContext: (api: Pick<RsbuildPluginAPI, "useExposed">) => AngularCliContext | undefined;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Where an Angular diagnostic points. Mirrors the esbuild `Location` shape that
3
+ * `@angular/build` converts TypeScript and Angular compiler diagnostics into:
4
+ * `line` is 1-based and `column` 0-based.
5
+ */
6
+ export type AngularDiagnosticLocation = {
7
+ readonly file?: string;
8
+ readonly line?: number;
9
+ readonly column?: number;
10
+ readonly length?: number;
11
+ readonly lineText?: string;
12
+ };
13
+ /**
14
+ * One diagnostic from `compilation.diagnoseFiles()`: an esbuild
15
+ * `PartialMessage`, whose `text` starts with the code (`TS2307: ...`,
16
+ * `NG8001: ...`).
17
+ */
18
+ export type AngularDiagnosticMessage = {
19
+ readonly text?: string;
20
+ readonly location?: AngularDiagnosticLocation | null;
21
+ readonly notes?: readonly {
22
+ readonly text?: string;
23
+ readonly location?: AngularDiagnosticLocation | null;
24
+ }[];
25
+ };
26
+ /**
27
+ * The diagnostics of one Angular compile, normalized so callers don't have to
28
+ * handle `diagnoseFiles()` leaving either list out.
29
+ */
30
+ export type AngularDiagnostics = {
31
+ readonly errors: readonly AngularDiagnosticMessage[];
32
+ readonly warnings: readonly AngularDiagnosticMessage[];
33
+ };
34
+ /**
35
+ * The shape rspack accepts in `compilation.errors` and `compilation.warnings`.
36
+ * rsbuild prints `file` as the error's `File:` line, so a `path:line:column`
37
+ * value makes it clickable in terminals and editors.
38
+ */
39
+ export type AngularDiagnosticError = Error & {
40
+ file?: string;
41
+ hideStack: boolean;
42
+ };
43
+ /**
44
+ * Keeps only the diagnostics a user can act on. Angular's template checker
45
+ * doesn't know Lynx's native elements and their attributes, so it reports
46
+ * them as unknown even though the renderer supports them.
47
+ */
48
+ export declare const filterAngularDiagnostics: (diagnostics: {
49
+ errors?: readonly AngularDiagnosticMessage[];
50
+ warnings?: readonly AngularDiagnosticMessage[];
51
+ }) => AngularDiagnostics;
52
+ /**
53
+ * Converts an Angular diagnostic into an error rspack can report. Pushing it
54
+ * into `compilation.errors` is what makes `rspeedy build` exit non-zero (and
55
+ * the dev server show it) the way `ng build` and `ng serve` do; printing it
56
+ * with `console.log` let builds with type errors succeed and ship.
57
+ */
58
+ export declare const toAngularDiagnosticError: (message: AngularDiagnosticMessage, severity: "error" | "warning") => AngularDiagnosticError;
@@ -0,0 +1 @@
1
+ export {};
package/dist/angular.d.ts CHANGED
@@ -21,7 +21,8 @@ import type { PluginAngularLynxOptions } from './utils/options.js';
21
21
  * → compilation.update (rebuilds only: invalidate the changed files)
22
22
  * → compilation.initialize (Angular AOT walk + transformStylesheet callback)
23
23
  * → emitAffectedFiles (refreshes typeScriptFileCache)
24
- * → diagnoseFiles (filtered to suppress Lynx-element false positives)
24
+ * → diagnoseFiles (filtered to suppress Lynx-element false positives, then
25
+ * reported as rspack errors/warnings so type errors fail the build)
25
26
  * → rspack rebuilds the changed files plus any whose compiled output changed
26
27
  *
27
28
  * Then for each module request the `api.transform` hook delegates the per-module
@@ -0,0 +1,64 @@
1
+ import type { RsbuildPluginAPI, Rspack } from '@lynx-js/rspeedy';
2
+ import { type BudgetAsset, type BudgetFailure, type ComponentStyleSize } from './utils/angular/budgets.js';
3
+ import type { Budget } from './utils/angular/options.js';
4
+ /** The shape rspack accepts in `compilation.errors` and `compilation.warnings`. */
5
+ export type BudgetError = Error & {
6
+ hideStack: boolean;
7
+ };
8
+ /**
9
+ * Turns a budget failure into an rspack error or warning. As an error it
10
+ * fails `ng build` / `rspeedy build`, like a budget error fails `ng build`
11
+ * for a web app; as a warning it's printed and the build succeeds.
12
+ */
13
+ export declare const toBudgetError: (failure: BudgetFailure) => BudgetError;
14
+ /**
15
+ * The entry (page) a Lynx template was built from, or undefined for a lazy
16
+ * bundle. A template covers an entry and its main-thread twin; lazy bundles
17
+ * cover async chunk groups, which aren't entry points.
18
+ */
19
+ export declare const bundleEntryName: (chunkGroups: readonly {
20
+ readonly name?: string | null;
21
+ }[], entrypoints: {
22
+ has: (name: string) => boolean;
23
+ }) => string | undefined;
24
+ /**
25
+ * The emitted files budgets count: the bundles and any scripts left outside
26
+ * them. Leaves out source maps and hot updates (as Angular does), media and
27
+ * fonts, and the build's intermediate directory, where the Lynx template
28
+ * plugin writes debug copies of what it encoded into the bundles.
29
+ */
30
+ export declare const collectBudgetAssets: (assets: readonly {
31
+ readonly name: string;
32
+ readonly source: {
33
+ size: () => number;
34
+ };
35
+ readonly info: {
36
+ readonly hotModuleReplacement?: boolean;
37
+ };
38
+ }[], entryBundles: ReadonlyMap<string, string>, intermediateDir: string | undefined) => BudgetAsset[];
39
+ export type AngularBudgetsPluginOptions = {
40
+ readonly budgets: readonly Budget[];
41
+ /** Kept current by the Angular compile, which runs before each compilation. */
42
+ readonly componentStyleSizes: ReadonlyMap<string, ComponentStyleSize>;
43
+ readonly intermediateDir: string | undefined;
44
+ };
45
+ /**
46
+ * Checks the budgets after every compilation of the `lynx` environment,
47
+ * including watch rebuilds, once its bundles are final.
48
+ */
49
+ export declare class AngularBudgetsPlugin {
50
+ #private;
51
+ constructor(options: AngularBudgetsPluginOptions);
52
+ apply(compiler: Rspack.Compiler): void;
53
+ }
54
+ /**
55
+ * Enforces angular.json's `budgets` on the `lynx` environment, the bundles
56
+ * devices load. The `web` environment only builds a browser preview, so its
57
+ * sizes say nothing about the app.
58
+ */
59
+ export declare const applyBudgets: (api: Pick<RsbuildPluginAPI, "context" | "modifyBundlerChain" | "useExposed">, { budgets, componentStyleSizes, underAngularCli, }: {
60
+ readonly budgets: readonly Budget[];
61
+ readonly componentStyleSizes: ReadonlyMap<string, ComponentStyleSize>;
62
+ /** Whether `ng build` / `ng serve` resolved the build options. */
63
+ readonly underAngularCli: boolean;
64
+ }) => void;
@@ -0,0 +1 @@
1
+ export {};
@@ -1,3 +1,4 @@
1
+ import type { ComponentStyleSize } from './utils/angular/budgets.js';
1
2
  /**
2
3
  * Per-component stylesheet bookkeeping. `imports` lists the on-disk scoped CSS
3
4
  * paths the loader will prepend as `import` statements; `inlineStyles` mirrors
@@ -14,6 +15,11 @@ export type ComponentScopeInfo = {
14
15
  className: string;
15
16
  scopeId: string;
16
17
  };
18
+ /**
19
+ * Drops the recorded stylesheet sizes of a component whose file was deleted,
20
+ * so `anyComponentStyle` budgets stop reporting styles that no longer ship.
21
+ */
22
+ export declare const forgetComponentStyleSizes: (componentStyleSizes: Map<string, ComponentStyleSize>, containingFile: string) => void;
17
23
  /**
18
24
  * Builds the `transformStylesheet` callback that Angular's AOT compiler invokes
19
25
  * for every component stylesheet (inline `styles: []` and external `styleUrls`).
@@ -40,4 +46,10 @@ export declare const createTransformStylesheet: (params: {
40
46
  * following rebuild.
41
47
  */
42
48
  onStylesheetWritten?: (filePath: string) => void;
49
+ /**
50
+ * The compiled size of every component stylesheet, for `anyComponentStyle`
51
+ * budgets. Overwritten each time Angular compiles a stylesheet, so watch
52
+ * rebuilds check the current sizes.
53
+ */
54
+ componentStyleSizes?: Map<string, ComponentStyleSize>;
43
55
  }) => ((data: string, containingFile: string, stylesheetFile: string | undefined, order: number, className: string | undefined) => Promise<string>);
package/dist/entry.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  import type { RsbuildPluginAPI, Rspack } from '@lynx-js/rspeedy';
2
2
  import type { UndefinedOnPartialDeep } from 'type-fest';
3
3
  import type { PluginAngularLynxOptions } from './utils/options.js';
4
+ /**
5
+ * The key `pluginLynx` (the Lynx build engine, which Rspeedy registers) exposes
6
+ * its resolved config under. Mirrors `S_LYNX_CONFIG` in React Lynx's plugin.
7
+ */
8
+ export declare const S_LYNX_CONFIG: unique symbol;
4
9
  export declare const applyEntry: (api: RsbuildPluginAPI, options: Required<PluginAngularLynxOptions>) => void;
5
10
  /**
6
11
  * This is copied from https://github.com/web-infra-dev/rsbuild/blob/037da7b9d92e20c7136c8b2efa21eef539fa2f88/packages/core/src/plugins/html.ts#L168
package/dist/index.d.ts CHANGED
@@ -1 +1,3 @@
1
- export { pluginAngularLynx } from './plugin-angular-lynx';
1
+ export { pluginAngularLynx } from './plugin-angular-lynx.js';
2
+ export type { PluginAngularLynxOptions } from './utils/options.js';
3
+ export { type AngularCliContext, pluginAngularCliContext, } from './angular-cli-context.js';