@savvy-web/rspress-builder 1.0.30 → 1.1.1

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
@@ -13,7 +13,7 @@ npm install --save-dev @savvy-web/rspress-builder
13
13
  pnpm add -D @savvy-web/rspress-builder
14
14
  ```
15
15
 
16
- `@rspress/core`, `react`, `react-dom` and `@tsdown/css` are peer dependencies the host plugin provides.
16
+ `@rspress/core`, `react`, `react-dom` and `typescript` are peer dependencies the host plugin provides. `@tsdown/css` is a regular dependency of this package, so you do not install it yourself — tsdown loads it lazily when a CSS file is encountered.
17
17
 
18
18
  ## Quick start
19
19
 
@@ -29,7 +29,7 @@ await build();
29
29
  Pass options to tune the preset — for example, to bundle `@rspress/core` declarations into the output types or disable the runtime bundle for a plugin with no browser component:
30
30
 
31
31
  ```ts
32
- await build({ dtsBundledPackages: ["@rspress/core"] });
32
+ await build({ bundledPackages: ["@rspress/core"] });
33
33
  await build({ runtime: false });
34
34
  ```
35
35
 
@@ -52,12 +52,27 @@ For advanced use, `definePlugin` and `runBuild` remain exported as primitives.
52
52
 
53
53
  `definePlugin` keeps a small surface because RSPress plugins have a fixed shape:
54
54
 
55
- - `runtime` — build the `./runtime` bundle. `true` (default) builds it, `false` disables it for a plugin with no runtime, an object tunes its externals. It does not probe the filesystem; pass `false` when there is no runtime entry.
56
- - `plugin` — externals tuning for the plugin (`.`) bundle.
57
- - `dtsBundledPackages` — packages whose declarations are inlined into the bundled `.d.ts`, for example `["@rspress/core"]`.
58
- - `apiModel` — API Extractor api-model generation, on by default. Pass `false` to opt out.
55
+ - `runtime` — build the `./runtime` bundle. `true` (default) builds it, `false` disables it for a plugin with no runtime, an object tunes its dependency posture (`externals`, `bundledPackages`, `dtsExternals`, `bundleNodeModules`). It does not probe the filesystem; pass `false` when there is no runtime entry.
56
+ - `plugin` — dependency posture tuning for the plugin (`.`) bundle; same shape as `runtime`'s object form.
57
+ - `externals` — build-wide externals merged into both bundles' built-in lists.
58
+ - `bundledPackages` — packages whose declarations are inlined into the bundled `.d.ts`, for example `["@rspress/core"]`.
59
+ - `dtsExternals` — packages externalized in the dts pass only (referenced via `import` in the emitted `.d.ts`) while the JS pass still bundles them.
60
+ - `bundleNodeModules` — force-bundle node_modules (and workspace) JS dependencies into the package output.
61
+ - `meta` — API Extractor api-model generation, on by default. Pass `false` to opt out.
59
62
  - `transform`, `jsx`, `define` — forwarded to the underlying bundler config.
60
63
 
64
+ `bundledPackages`, `dtsExternals` and `bundleNodeModules` can be set build-wide and/or tuned per bundle via `plugin`/`runtime`; a per-bundle value wins over the build-wide one. `externals` is the exception — a build-wide value merges into BOTH bundles rather than being overridden.
65
+
66
+ ## Ambient environment types
67
+
68
+ `@savvy-web/rspress-builder` ships a `./env` types-only export with the ambient declarations an RSPress runtime component needs: `import.meta.env` (Vite's build-mode env, `SSG_MD`/`SSR`/`MODE`/`BASE_URL`/`PROD`/`DEV`) plus `*.css` and `*.module.css` module declarations. Add a triple-slash reference to a `.d.ts` in your project to pull them in:
69
+
70
+ ```ts
71
+ /// <reference types="@savvy-web/rspress-builder/env" />
72
+ ```
73
+
74
+ `@savvy-web/bundler` ships the same pattern for its own build-injected key — see [its README](https://www.npmjs.com/package/@savvy-web/bundler#readme) — via `/// <reference types="@savvy-web/bundler/env" />`, which gives you `process.env.__PACKAGE_VERSION__`.
75
+
61
76
  ## License
62
77
 
63
78
  [MIT](LICENSE)
package/ecma.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
+ "//": "types and lib REPLACE the base list rather than merging with it. If you override either, re-list every entry you still need, including node.",
2
3
  "$schema": "https://json.schemastore.org/tsconfig.json",
3
4
  "compilerOptions": {
4
5
  "allowSyntheticDefaultImports": true,
5
- "composite": true,
6
+ "composite": false,
6
7
  "declaration": true,
7
8
  "declarationDir": "${configDir}/dist",
8
9
  "declarationMap": false,
@@ -42,7 +43,8 @@
42
43
  "${configDir}/__fixtures__/**/*"
43
44
  ],
44
45
  "include": [
45
- "${configDir}/types/*.ts",
46
+ "${configDir}/src/*.d.ts",
47
+ "${configDir}/types/*.d.ts",
46
48
  "${configDir}/package.json",
47
49
  "${configDir}/*.ts",
48
50
  "${configDir}/*.cts",
package/env.d.ts ADDED
@@ -0,0 +1,114 @@
1
+ // Ambient module + import.meta.env declarations for RSPress plugin runtimes built with
2
+ // @savvy-web/rspress-builder. Replaces the rslib-era @rslib/core/types reference.
3
+
4
+ type CSSModuleClasses = Readonly<Record<string, string>>;
5
+
6
+ declare module "*.module.css" {
7
+ const classes: CSSModuleClasses;
8
+ export default classes;
9
+ }
10
+ declare module "*.css" {}
11
+
12
+ /**
13
+ * The `ImportMetaEnv` interface defines the shape of the `import.meta.env` object, which contains environment variables
14
+ * injected by Vite during the build process. These variables provide information about the build environment,
15
+ * such as whether the app is running in development or production mode, whether it is being server-side rendered, and other relevant details.
16
+ * @see {@link https://vite.dev/guide/env-and-mode|Vite | Env and Modes }
17
+ */
18
+ interface ImportMetaEnv {
19
+ /**
20
+ * Environment variable so React components can distinguish SSG-MD (markdown)
21
+ * rendering from browser rendering and customize their output
22
+ * @example
23
+ * ```typescript
24
+ * export function Tab({ label }: { label: string }) {
25
+ * if (import.meta.env.SSG_MD) {
26
+ * // This will be returned as a static string in the markdown output
27
+ * return <>{`** Here is a Tab named ${label}**`}</>;
28
+ * }
29
+ * // This will be returned as a React component in the browser
30
+ * return <div class="tab">{label}</div>;
31
+ * }
32
+ * ```
33
+ * @see {@link https://rspress.rs/guide/basic/ssg-md|RSPress | SSG-MD }
34
+ * @see {@link https://vite.dev/guide/env-and-mode|Vite | Env and Modes }
35
+ * */
36
+
37
+ readonly SSG_MD: boolean;
38
+ /**
39
+ * whether the Vite app is running in SSR (server-side rendering) mode. Allows you to
40
+ * conditionally render React components differently for SSR vs. browser rendering.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * export function DebugInfo() {
45
+ * if (import.meta.env.SSR) {
46
+ * return <div class="debug-info">Debug info here</div>;
47
+ * }
48
+ * return null;
49
+ * }
50
+ * @see {@link https://vite.dev/guide/env-and-mode|Vite | Env and Modes }
51
+ */
52
+ readonly SSR: boolean;
53
+
54
+ /**
55
+ * Environment variable so React components can distinguish between development and
56
+ * production builds
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * export function DebugInfo() {
61
+ * if (import.meta.env.MODE === "development") {
62
+ * return <div class="debug-info">Debug info here</div>;
63
+ * }
64
+ * return null;
65
+ * }
66
+ * ```
67
+ * @see {@link https://vite.dev/guide/env-and-mode#modes|Vite | Modes }
68
+ */
69
+ readonly MODE: "development" | "production";
70
+
71
+ /**
72
+ * Base public path when served in development or production. Valid values include:
73
+ * Absolute URL pathname, e.g. `/foo/`
74
+ * - Full URL, e.g. `https://bar.com/foo/` (The origin part won't be used in development so the value is the same as /foo/)
75
+ * - Empty string or `./` (for embedded deployment)
76
+ * @see {@link https://vite.dev/guide/env-and-mode|Vite | Env and Modes }
77
+ */
78
+ readonly BASE_URL: string;
79
+
80
+ /**
81
+ * whether the Vite app is running in production mode:
82
+ * - running the dev server with `NODE_ENV='production'`
83
+ * - running an app built with `NODE_ENV='production'`)
84
+ *
85
+ * Always the opposite of `import.meta.env.DEV`
86
+ *
87
+ * @see {@link https://vite.dev/guide/env-and-mode#env-files|Vite | Modes }
88
+ */
89
+ readonly PROD: boolean;
90
+
91
+ /**
92
+ * whether the Vite app is running in development mode:
93
+ * - running the dev server with `NODE_ENV='development'`
94
+ * - running an app built with `NODE_ENV='development'`
95
+ *
96
+ * Always the opposite of `import.meta.env.PROD`.
97
+ * @see {@link https://vite.dev/guide/env-and-mode#env-files|Vite | Modes }
98
+ */
99
+ readonly DEV: boolean;
100
+ }
101
+
102
+ // biome-ignore lint/correctness/noUnusedVariables: ImportMeta is used by TypeScript but may appear unused to the linter
103
+ interface ImportMeta {
104
+ /**
105
+ * The `import.meta` object contains metadata about the current module. It is a standard
106
+ * feature in JavaScript modules. The `env` property on `import.meta` is a custom property injected
107
+ * by Vite that provides access to environment variables defined in the Vite configuration or `.env` files.
108
+ * RSPress uses this to provide information about the build environment, such as whether the app is running
109
+ * in development or production mode, whether it is being server-side rendered, and other relevant environment details.
110
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta|}
111
+ * @see {@link https://vite.dev/guide/env-and-mode|Vite | Env and Modes }
112
+ */
113
+ env: ImportMetaEnv;
114
+ }
package/index.d.ts CHANGED
@@ -1,13 +1,21 @@
1
- import { BuildConfig, BuildConfigInput, RunOptions, runBuild } from "@savvy-web/bundler";
1
+ import { BuildConfig, BuildConfigInput, BuildEntryOverride, RunOptions, runBuild } from "@savvy-web/bundler";
2
2
  //#region src/index.d.ts
3
3
  /**
4
- * Per-bundle externals tuning for a single partition (plugin or runtime).
4
+ * Per-bundle dependency posture for a single partition (plugin or runtime). Mirrors the
5
+ * bundler's `BuildEntryOverride`; a value set here wins over the build-wide option of the
6
+ * same name.
5
7
  *
6
8
  * @public
7
9
  */
8
10
  interface RspressBundleOptions {
9
- /** Additional externals merged with the built-ins for that bundle. */
11
+ /** Additional externals merged with this bundle's built-ins and the build-wide `externals`. */
10
12
  readonly externals?: ReadonlyArray<string>;
13
+ /** Packages whose declarations are inlined into this bundle's dts. */
14
+ readonly bundledPackages?: ReadonlyArray<string> | undefined;
15
+ /** Packages externalized in this bundle's dts pass only, referenced via import in the emitted `.d.ts`. */
16
+ readonly dtsExternals?: ReadonlyArray<string> | undefined;
17
+ /** Force-bundle node_modules JS dependencies into this bundle's output. */
18
+ readonly bundleNodeModules?: boolean | undefined;
11
19
  }
12
20
  /**
13
21
  * Options for `definePlugin`. Deliberately small — RSPress plugins have a fixed shape.
@@ -23,10 +31,20 @@ interface RspressPluginOptions {
23
31
  readonly runtime?: boolean | RspressBundleOptions;
24
32
  /** Tuning for the plugin (`.`) bundle (node, bundled). */
25
33
  readonly plugin?: RspressBundleOptions;
34
+ /** Build-wide externals merged into BOTH bundles' built-in lists. */
35
+ readonly externals?: ReadonlyArray<string>;
26
36
  /** Packages whose declarations are inlined into the bundled dts (e.g. [`@rspress/core`]). */
27
- readonly dtsBundledPackages?: ReadonlyArray<string>;
37
+ readonly bundledPackages?: ReadonlyArray<string> | undefined;
38
+ /**
39
+ * Packages externalized in the dts pass ONLY — referenced via `import` in the emitted
40
+ * `.d.ts` rather than inlined — while the JS pass still bundles them. Declare these as
41
+ * package dependencies so consumers can resolve the emitted type imports.
42
+ */
43
+ readonly dtsExternals?: ReadonlyArray<string> | undefined;
44
+ /** Force-bundle node_modules (and workspace) JS dependencies into the package output. */
45
+ readonly bundleNodeModules?: boolean | undefined;
28
46
  /** API-model generation. Defaults to on (documents plugin options AND runtime components). `false` opts out. */
29
- readonly apiModel?: BuildConfigInput["meta"];
47
+ readonly meta?: BuildConfigInput["meta"];
30
48
  /** Final package.json mutation; defaults to the bundler's defaultManifestTransform. */
31
49
  readonly transform?: BuildConfigInput["transform"];
32
50
  /** JSX override; defaults to tsconfig-inferred. */
@@ -56,5 +74,5 @@ declare function definePlugin(options?: RspressPluginOptions): BuildConfig;
56
74
  */
57
75
  declare function build(options?: RspressPluginOptions, overrides?: Partial<RunOptions>): Promise<void>;
58
76
  //#endregion
59
- export { RspressBundleOptions, RspressPluginOptions, type RunOptions, build, definePlugin, runBuild };
77
+ export { type BuildConfig, type BuildConfigInput, type BuildEntryOverride, RspressBundleOptions, RspressPluginOptions, type RunOptions, build, definePlugin, runBuild };
60
78
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -24,7 +24,13 @@ function definePlugin(options = {}) {
24
24
  const runtimeEnabled = runtimeOpt !== false;
25
25
  const runtimeTuning = typeof runtimeOpt === "object" ? runtimeOpt : {};
26
26
  const pluginTuning = options.plugin ?? {};
27
- const pluginExternals = [...PLUGIN_EXTERNALS, ...pluginTuning.externals ?? []];
27
+ const dedupe = (xs) => [...new Set(xs)];
28
+ const sharedExternals = options.externals ?? [];
29
+ const pluginExternals = dedupe([
30
+ ...PLUGIN_EXTERNALS,
31
+ ...sharedExternals,
32
+ ...pluginTuning.externals ?? []
33
+ ]);
28
34
  const overrides = runtimeEnabled ? [{
29
35
  entries: ["./runtime"],
30
36
  outSubdir: "runtime",
@@ -36,20 +42,34 @@ function definePlugin(options = {}) {
36
42
  },
37
43
  inject: true
38
44
  },
39
- externals: [...RUNTIME_EXTERNALS, ...runtimeTuning.externals ?? []]
45
+ externals: dedupe([
46
+ ...RUNTIME_EXTERNALS,
47
+ ...sharedExternals,
48
+ ...runtimeTuning.externals ?? []
49
+ ]),
50
+ ...(runtimeTuning.bundledPackages ?? options.bundledPackages) !== void 0 ? { bundledPackages: runtimeTuning.bundledPackages ?? options.bundledPackages } : {},
51
+ ...(runtimeTuning.dtsExternals ?? options.dtsExternals) !== void 0 ? { dtsExternals: runtimeTuning.dtsExternals ?? options.dtsExternals } : {},
52
+ ...(runtimeTuning.bundleNodeModules ?? options.bundleNodeModules) !== void 0 ? { bundleNodeModules: runtimeTuning.bundleNodeModules ?? options.bundleNodeModules } : {}
40
53
  }] : [];
41
- return defineBuild({
54
+ const define = {
55
+ "import.meta.env": "import.meta.env",
56
+ ...options.define
57
+ };
58
+ const bundledPackages = pluginTuning.bundledPackages ?? options.bundledPackages;
59
+ const dtsExternals = pluginTuning.dtsExternals ?? options.dtsExternals;
60
+ const bundleNodeModules = pluginTuning.bundleNodeModules ?? options.bundleNodeModules;
61
+ const input = {
42
62
  externals: pluginExternals,
43
- define: {
44
- "import.meta.env": "import.meta.env",
45
- ...options.define
46
- },
47
- ...options.dtsBundledPackages !== void 0 ? { bundledPackages: options.dtsBundledPackages } : {},
48
- ...options.apiModel !== void 0 ? { meta: options.apiModel } : {},
63
+ define,
64
+ ...bundledPackages !== void 0 ? { bundledPackages } : {},
65
+ ...dtsExternals !== void 0 ? { dtsExternals } : {},
66
+ ...bundleNodeModules !== void 0 ? { bundleNodeModules } : {},
67
+ ...options.meta !== void 0 ? { meta: options.meta } : {},
49
68
  ...options.transform !== void 0 ? { transform: options.transform } : {},
50
69
  ...options.jsx !== void 0 ? { jsx: options.jsx } : {},
51
70
  ...overrides.length > 0 ? { overrides } : {}
52
- });
71
+ };
72
+ return defineBuild(input);
53
73
  }
54
74
  /**
55
75
  * Front door for building an RSPress plugin. Applies the {@link definePlugin} preset
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/rspress-builder",
3
- "version": "1.0.30",
3
+ "version": "1.1.1",
4
4
  "private": false,
5
5
  "description": "RSPress plugin builder for the Silk Suite, built on @savvy-web/bundler",
6
6
  "homepage": "https://github.com/savvy-web/systems/tree/main/packages/rspress-builder",
@@ -25,14 +25,15 @@
25
25
  "import": "./index.js",
26
26
  "default": "./index.js"
27
27
  },
28
- "./rspress-env.d.ts": "./rspress-env.d.ts",
28
+ "./env": {
29
+ "types": "./env.d.ts"
30
+ },
29
31
  "./tsconfig/ecma.json": "./ecma.json",
30
32
  "./tsconfig/plugin.json": "./tsconfig/plugin.json",
31
33
  "./package.json": "./package.json"
32
34
  },
33
35
  "dependencies": {
34
- "@savvy-web/bundler": "2.0.13",
35
- "@savvy-web/tsdown-plugins": "2.2.2",
36
+ "@savvy-web/bundler": "2.1.1",
36
37
  "@tsdown/css": "^0.22.14"
37
38
  },
38
39
  "peerDependencies": {
@@ -1,11 +1,65 @@
1
1
  {
2
- "$schema": "https://json.schemastore.org/tsconfig",
2
+ "//": "types and lib REPLACE the base list rather than merging with it. If you override either, re-list every entry you still need, including node.",
3
+ "$schema": "https://json.schemastore.org/tsconfig.json",
3
4
  "compilerOptions": {
5
+ "allowSyntheticDefaultImports": true,
6
+ "composite": false,
7
+ "declaration": true,
8
+ "declarationDir": "${configDir}/dist",
9
+ "declarationMap": false,
10
+ "emitDeclarationOnly": false,
11
+ "esModuleInterop": true,
12
+ "exactOptionalPropertyTypes": true,
13
+ "explainFiles": false,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "incremental": true,
16
+ "isolatedDeclarations": false,
17
+ "isolatedModules": true,
4
18
  "jsx": "react-jsx",
5
19
  "lib": ["es2025", "dom"],
6
- "types": ["node", "react", "react-dom"]
20
+ "module": "nodenext",
21
+ "moduleResolution": "nodenext",
22
+ "outDir": "${configDir}/dist",
23
+ "resolveJsonModule": true,
24
+ "rootDir": "${configDir}",
25
+ "skipLibCheck": true,
26
+ "sourceMap": false,
27
+ "strict": true,
28
+ "strictNullChecks": true,
29
+ "target": "es2025",
30
+ "tsBuildInfoFile": "${configDir}/dist/.tsbuildinfo.lib",
31
+ "typeRoots": ["${configDir}/node_modules/@types", "${configDir}/types"],
32
+ "types": ["node", "react", "react-dom"],
33
+ "verbatimModuleSyntax": true
7
34
  },
8
- "exclude": ["${configDir}/node_modules", "${configDir}/dist"],
9
- "extends": "../ecma.json",
10
- "include": ["${configDir}/types/*.d.ts", "${configDir}/src/**/*.ts", "${configDir}/src/**/*.tsx"]
35
+ "exclude": [
36
+ "${configDir}/node_modules",
37
+ "${configDir}/dist/**/*",
38
+ "${configDir}/__test__/fixtures/*.ts",
39
+ "${configDir}/__test__/fixtures/*.tsx",
40
+ "${configDir}/__test__/fixtures/*.cts",
41
+ "${configDir}/__test__/fixtures/*.mts",
42
+ "${configDir}/__test__/**/fixtures/**/*",
43
+ "${configDir}/__fixtures__/**/*"
44
+ ],
45
+ "include": [
46
+ "${configDir}/types/*.d.ts",
47
+ "${configDir}/package.json",
48
+ "${configDir}/*.ts",
49
+ "${configDir}/*.cts",
50
+ "${configDir}/*.mts",
51
+ "${configDir}/src/**/*.ts",
52
+ "${configDir}/src/**/*.tsx",
53
+ "${configDir}/src/**/*.cts",
54
+ "${configDir}/src/**/*.mts",
55
+ "${configDir}/lib/**/*.ts",
56
+ "${configDir}/lib/**/*.tsx",
57
+ "${configDir}/lib/**/*.cts",
58
+ "${configDir}/lib/**/*.mts",
59
+ "${configDir}/__test__/**/*.ts",
60
+ "${configDir}/__test__/**/*.tsx",
61
+ "${configDir}/__test__/**/*.cts",
62
+ "${configDir}/__test__/**/*.mts",
63
+ "${configDir}/public/**/*.json"
64
+ ]
11
65
  }
package/rspress-env.d.ts DELETED
@@ -1,19 +0,0 @@
1
- // Ambient module + import.meta.env declarations for RSPress plugin runtimes built with
2
- // @savvy-web/rspress-builder. Replaces the rslib-era @rslib/core/types reference.
3
-
4
- type CSSModuleClasses = Readonly<Record<string, string>>;
5
-
6
- declare module "*.module.css" {
7
- const classes: CSSModuleClasses;
8
- export default classes;
9
- }
10
- declare module "*.css" {}
11
-
12
- interface ImportMetaEnv {
13
- readonly [key: string]: string | boolean | undefined;
14
- /** RSPress static-site-generation markdown flag, resolved per site build. */
15
- readonly SSG_MD?: boolean;
16
- }
17
- interface ImportMeta {
18
- readonly env: ImportMetaEnv;
19
- }