@typed/vite-plugin 0.17.1 → 1.0.0-beta.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 +97 -0
- package/dist/debugBuildPlugin.d.ts +7 -0
- package/dist/debugBuildPlugin.d.ts.map +1 -0
- package/dist/debugBuildPlugin.js +54 -0
- package/dist/index.d.ts +71 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -5
- package/package.json +27 -29
- package/src/index.test.ts +97 -0
- package/src/index.ts +224 -4
- package/dist/cjs/constants.d.ts +0 -2
- package/dist/cjs/constants.d.ts.map +0 -1
- package/dist/cjs/constants.js +0 -5
- package/dist/cjs/constants.js.map +0 -1
- package/dist/cjs/index.d.ts +0 -5
- package/dist/cjs/index.d.ts.map +0 -1
- package/dist/cjs/index.js +0 -26
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/resolveTypedConfig.d.ts +0 -20
- package/dist/cjs/resolveTypedConfig.d.ts.map +0 -1
- package/dist/cjs/resolveTypedConfig.js +0 -16
- package/dist/cjs/resolveTypedConfig.js.map +0 -1
- package/dist/cjs/vite-plugin.d.ts +0 -56
- package/dist/cjs/vite-plugin.d.ts.map +0 -1
- package/dist/cjs/vite-plugin.js +0 -212
- package/dist/cjs/vite-plugin.js.map +0 -1
- package/dist/constants.d.ts +0 -2
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -2
- package/dist/constants.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/resolveTypedConfig.d.ts +0 -20
- package/dist/resolveTypedConfig.d.ts.map +0 -1
- package/dist/resolveTypedConfig.js +0 -12
- package/dist/resolveTypedConfig.js.map +0 -1
- package/dist/tsconfig.cjs.build.tsbuildinfo +0 -1
- package/dist/vite-plugin.d.ts +0 -56
- package/dist/vite-plugin.d.ts.map +0 -1
- package/dist/vite-plugin.js +0 -179
- package/dist/vite-plugin.js.map +0 -1
- package/eslintrc.json +0 -3
- package/project.json +0 -44
- package/readme.md +0 -3
- package/src/constants.ts +0 -1
- package/src/resolveTypedConfig.ts +0 -35
- package/src/vite-plugin.ts +0 -312
- package/tsconfig.build.json +0 -8
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.cjs.build.json +0 -13
- package/tsconfig.json +0 -18
- package/vite.config.js +0 -3
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @typed/vite-plugin
|
|
2
|
+
|
|
3
|
+
> **Beta:** This package is in beta; APIs may change.
|
|
4
|
+
|
|
5
|
+
`@typed/vite-plugin` provides a **one-stop Vite preset**: tsconfig path resolution, virtual modules (router + HttpApi from @typed/app), optional bundle analyzer, and Brotli compression. Use it as the main plugin array for typed-smol Vite projects.
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
`typedVitePlugin` is the recommended way to configure Vite for typed-smol apps. One call gives you: path resolution from `tsconfig.json`, virtual `router:` and `api:` imports that generate typed route matchers and API clients from convention-based source, optional bundle analysis, and Brotli compression for build output.
|
|
10
|
+
|
|
11
|
+
## Capabilities
|
|
12
|
+
|
|
13
|
+
| Area | What you get |
|
|
14
|
+
|------|--------------|
|
|
15
|
+
| **Router VM** | `router:./path` → typed Matcher from route files |
|
|
16
|
+
| **HttpApi VM** | `api:./path` → typed Api + Client + OpenAPI (when `apiVmOptions` set) |
|
|
17
|
+
| **TypeInfo** | Structural type-checking of route/endpoint contracts (when `createTypeInfoApiSession` provided) |
|
|
18
|
+
| **tsconfig paths** | Path alias resolution (default: on) |
|
|
19
|
+
| **Analyzer** | `dist/stats.html` treemap when `ANALYZE=1` |
|
|
20
|
+
| **Compression** | Brotli `.br` for build output (default: on) |
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
|
|
24
|
+
```mermaid
|
|
25
|
+
flowchart TB
|
|
26
|
+
subgraph plugins [Plugin array from typedVitePlugin]
|
|
27
|
+
Tsconfig[tsconfig paths]
|
|
28
|
+
VM[virtualModulesVitePlugin]
|
|
29
|
+
Viz[visualizer]
|
|
30
|
+
Comp[viteCompression]
|
|
31
|
+
end
|
|
32
|
+
subgraph vmResolver [VM resolver]
|
|
33
|
+
RouterVM[router VM]
|
|
34
|
+
ApiVM[HttpApi VM]
|
|
35
|
+
end
|
|
36
|
+
VM --> vmResolver
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Dependencies
|
|
40
|
+
|
|
41
|
+
- `@typed/app`
|
|
42
|
+
- `@typed/virtual-modules`
|
|
43
|
+
- `@typed/virtual-modules-vite`
|
|
44
|
+
|
|
45
|
+
Peer: `vite` (>=5).
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pnpm add @typed/vite-plugin @typed/app
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { defineConfig } from "vite";
|
|
57
|
+
import { typedVitePlugin } from "@typed/vite-plugin";
|
|
58
|
+
|
|
59
|
+
export default defineConfig({
|
|
60
|
+
plugins: typedVitePlugin(),
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For router VM type-checking, pass `createTypeInfoApiSession` (e.g. from a custom Vite plugin that builds a TypeScript program):
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { typedVitePlugin } from "@typed/vite-plugin";
|
|
68
|
+
import { createTypeInfoApiSessionForApp } from "@typed/app";
|
|
69
|
+
|
|
70
|
+
export default defineConfig({
|
|
71
|
+
plugins: typedVitePlugin({
|
|
72
|
+
createTypeInfoApiSession: ({ ts, program }) =>
|
|
73
|
+
createTypeInfoApiSessionForApp({ ts, program }),
|
|
74
|
+
routerVmOptions: {},
|
|
75
|
+
apiVmOptions: {},
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## API overview
|
|
81
|
+
|
|
82
|
+
- **`typedVitePlugin(options)`** — Returns an array of Vite plugins.
|
|
83
|
+
- **`createTypedViteResolver(options)`** — Builds the virtual-module resolver (for tests or custom compositions).
|
|
84
|
+
|
|
85
|
+
## Options
|
|
86
|
+
|
|
87
|
+
| Option | Type | Default | Description |
|
|
88
|
+
| ------ | ---- | ------- | ----------- |
|
|
89
|
+
| `routerVmOptions` | `RouterVirtualModulePluginOptions` | `{}` | Options for the router VM plugin. |
|
|
90
|
+
| `apiVmOptions` | `HttpApiVirtualModulePluginOptions` | — | When set, enables the HttpApi VM plugin. |
|
|
91
|
+
| `createTypeInfoApiSession` | `CreateTypeInfoApiSession` | — | Required for router VM type-checking in dev. |
|
|
92
|
+
| `tsconfig` | `string` | — | Path to `tsconfig.json` (relative to cwd or absolute). When set, both the Language Service session and vite-tsconfig-paths use this tsconfig. Default: auto-discovered from project root. |
|
|
93
|
+
| `tsconfigPaths` | `boolean \| object` | `true` | Enable tsconfig path resolution. |
|
|
94
|
+
| `analyze` | `boolean \| object` | `process.env.ANALYZE === '1'` | Enable bundle analyzer (dist/stats.html). |
|
|
95
|
+
| `warnOnError` | `boolean` | `true` | Log virtual module resolution errors. |
|
|
96
|
+
| `compression` | `boolean \| object` | `true` | Brotli compression for build output. |
|
|
97
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug plugin for tracing build failures. Enabled when DEBUG_TYPED_BUILD=1.
|
|
3
|
+
* Logs config resolution and module resolution to diagnose realworld/counter build issues.
|
|
4
|
+
*/
|
|
5
|
+
import type { Plugin } from "vite";
|
|
6
|
+
export declare function createDebugBuildPlugin(): Plugin;
|
|
7
|
+
//# sourceMappingURL=debugBuildPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debugBuildPlugin.d.ts","sourceRoot":"","sources":["../src/debugBuildPlugin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAsBnC,wBAAgB,sBAAsB,IAAI,MAAM,CAmC/C"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const LOG_URL = "http://127.0.0.1:7563/ingest/ae4c829f-512d-4a3a-9ef6-9b34461b49d9";
|
|
2
|
+
const SESSION = "d02fd1";
|
|
3
|
+
function log(msg, data, hypothesisId) {
|
|
4
|
+
// #region agent log
|
|
5
|
+
fetch(LOG_URL, {
|
|
6
|
+
method: "POST",
|
|
7
|
+
headers: { "Content-Type": "application/json", "X-Debug-Session-Id": SESSION },
|
|
8
|
+
body: JSON.stringify({
|
|
9
|
+
sessionId: SESSION,
|
|
10
|
+
location: "debugBuildPlugin.ts",
|
|
11
|
+
message: msg,
|
|
12
|
+
data,
|
|
13
|
+
timestamp: Date.now(),
|
|
14
|
+
hypothesisId,
|
|
15
|
+
}),
|
|
16
|
+
}).catch(() => { });
|
|
17
|
+
// #endregion
|
|
18
|
+
}
|
|
19
|
+
export function createDebugBuildPlugin() {
|
|
20
|
+
return {
|
|
21
|
+
name: "typed:debug-build",
|
|
22
|
+
enforce: "pre",
|
|
23
|
+
config(config) {
|
|
24
|
+
// #region agent log
|
|
25
|
+
log("config() received", { hasBuild: !!config.build, hasRoot: !!config.root, base: config.base }, "H-counter-1");
|
|
26
|
+
// #endregion
|
|
27
|
+
return null;
|
|
28
|
+
},
|
|
29
|
+
configResolved(viteConfig) {
|
|
30
|
+
// #region agent log
|
|
31
|
+
log("configResolved", {
|
|
32
|
+
root: viteConfig.root,
|
|
33
|
+
base: viteConfig.base,
|
|
34
|
+
outDir: viteConfig.build?.outDir,
|
|
35
|
+
rollupInput: viteConfig.build?.rollupOptions?.input,
|
|
36
|
+
assetsDir: viteConfig.build?.assetsDir,
|
|
37
|
+
}, "H-counter-2");
|
|
38
|
+
// #endregion
|
|
39
|
+
},
|
|
40
|
+
resolveId(id, importer) {
|
|
41
|
+
if (id.includes("virtual-modules") || id.includes("@typed/virtual-modules")) {
|
|
42
|
+
// #region agent log
|
|
43
|
+
log("resolveId: virtual-modules requested", { id, importer: importer?.slice(-120) }, "H-realworld-1");
|
|
44
|
+
// #endregion
|
|
45
|
+
}
|
|
46
|
+
if (importer && importer.includes("node_modules/@typed/app") && !id.startsWith(".") && !id.startsWith("/")) {
|
|
47
|
+
// #region agent log
|
|
48
|
+
log("resolveId: from @typed/app", { id: id.slice(0, 80), importer: importer.slice(-100) }, "H-realworld-2");
|
|
49
|
+
// #endregion
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { HttpApiVirtualModulePluginOptions, RouterVirtualModulePluginOptions } from "@typed/app";
|
|
2
|
+
import type { CreateTypeInfoApiSession, VirtualModuleResolver } from "@typed/virtual-modules";
|
|
3
|
+
import type { Plugin } from "vite";
|
|
4
|
+
/** Options for vite-plugin-compression when compression is enabled. */
|
|
5
|
+
export type TypedViteCompressionOptions = boolean | {
|
|
6
|
+
readonly algorithm?: "gzip" | "brotliCompress" | "deflate" | "deflateRaw";
|
|
7
|
+
readonly ext?: string;
|
|
8
|
+
readonly threshold?: number;
|
|
9
|
+
readonly [key: string]: unknown;
|
|
10
|
+
};
|
|
11
|
+
export interface TypedVitePluginOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Options for the router VM plugin from @typed/app.
|
|
14
|
+
*/
|
|
15
|
+
readonly routerVmOptions?: RouterVirtualModulePluginOptions;
|
|
16
|
+
/**
|
|
17
|
+
* Options for the HttpApi VM plugin from @typed/app. HttpApi VM plugin is always
|
|
18
|
+
* registered (router first, then HttpApi). Use this to customize its behavior.
|
|
19
|
+
*/
|
|
20
|
+
readonly apiVmOptions?: HttpApiVirtualModulePluginOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Session factory for TypeInfo API. When not provided, a Language Service-backed
|
|
23
|
+
* session is auto-created from the project's tsconfig (evolves as files change).
|
|
24
|
+
* Override for custom session setup.
|
|
25
|
+
*/
|
|
26
|
+
readonly createTypeInfoApiSession?: CreateTypeInfoApiSession;
|
|
27
|
+
/**
|
|
28
|
+
* Path to tsconfig.json (relative to cwd or absolute). When set, both the
|
|
29
|
+
* Language Service session and vite-tsconfig-paths use this tsconfig.
|
|
30
|
+
* Default: auto-discovered from project root.
|
|
31
|
+
*/
|
|
32
|
+
readonly tsconfig?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Enable tsconfig path resolution. Default true.
|
|
35
|
+
*/
|
|
36
|
+
readonly tsconfigPaths?: boolean | Record<string, unknown>;
|
|
37
|
+
/**
|
|
38
|
+
* Enable bundle analyzer. Default: process.env.ANALYZE === '1'.
|
|
39
|
+
*/
|
|
40
|
+
readonly analyze?: boolean | {
|
|
41
|
+
filename?: string;
|
|
42
|
+
open?: boolean;
|
|
43
|
+
template?: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* When true, virtual module resolution errors are logged. Default true.
|
|
47
|
+
*/
|
|
48
|
+
readonly warnOnError?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Enable Brotli compression for build. Default true.
|
|
51
|
+
* Set false to disable, or pass options to customize (algorithm, ext, threshold).
|
|
52
|
+
*/
|
|
53
|
+
readonly compression?: TypedViteCompressionOptions;
|
|
54
|
+
}
|
|
55
|
+
/** Optional dependency injection for createTypedViteResolver (e.g. for tests). */
|
|
56
|
+
export interface TypedViteResolverDependencies {
|
|
57
|
+
createHttpApiVirtualModulePlugin?: (opts: HttpApiVirtualModulePluginOptions) => import("@typed/virtual-modules").VirtualModulePlugin;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Invariant: ALL @typed/app VM plugins are always registered. There are no optional
|
|
61
|
+
* or conditional app plugins. When adding a new VM plugin to @typed/app, add it here.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createTypedViteResolver(options?: TypedVitePluginOptions, dependencies?: TypedViteResolverDependencies): VirtualModuleResolver;
|
|
64
|
+
/**
|
|
65
|
+
* Returns Vite plugins: tsconfig paths, virtual modules (@typed/app), and optional bundle analyzer.
|
|
66
|
+
* Use as: `defineConfig({ plugins: typedVitePlugin() })`.
|
|
67
|
+
*
|
|
68
|
+
* When called with no arguments, auto-discovers `typed.config.ts` in the project root.
|
|
69
|
+
* When called with explicit options, those take full precedence (config file is not loaded).
|
|
70
|
+
*/
|
|
71
|
+
export declare function typedVitePlugin(options?: TypedVitePluginOptions): Plugin[];
|
|
5
72
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,iCAAiC,EAEjC,gCAAgC,EACjC,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAW9F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,uEAAuE;AACvE,MAAM,MAAM,2BAA2B,GACnC,OAAO,GACP;IACE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,GAAG,YAAY,CAAC;IAC1E,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC,CAAC;AAEN,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,gCAAgC,CAAC;IAE5D;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,iCAAiC,CAAC;IAE1D;;;;OAIG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;IAE7D;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B;;OAEG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE3D;;OAEG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAEtF;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAE/B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,2BAA2B,CAAC;CACpD;AAED,kFAAkF;AAClF,MAAM,WAAW,6BAA6B;IAC5C,gCAAgC,CAAC,EAAE,CACjC,IAAI,EAAE,iCAAiC,KACpC,OAAO,wBAAwB,EAAE,mBAAmB,CAAC;CAC3D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,sBAA2B,EACpC,YAAY,CAAC,EAAE,6BAA6B,GAC3C,qBAAqB,CAQvB;AAgBD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAgG1E"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,122 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { createHttpApiVirtualModulePlugin, createRouterVirtualModulePlugin, loadTypedConfig, } from "@typed/app";
|
|
2
|
+
import { collectTypeTargetSpecsFromPlugins, createLanguageServiceSessionFactory, PluginManager, } from "@typed/virtual-modules";
|
|
3
|
+
import { virtualModulesVitePlugin } from "@typed/virtual-modules-vite";
|
|
4
|
+
import { dirname, relative, resolve } from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import { visualizer } from "rollup-plugin-visualizer";
|
|
7
|
+
import ts from "typescript";
|
|
8
|
+
import viteCompression from "vite-plugin-compression";
|
|
9
|
+
import tsconfigPaths from "vite-tsconfig-paths";
|
|
10
|
+
/**
|
|
11
|
+
* Invariant: ALL @typed/app VM plugins are always registered. There are no optional
|
|
12
|
+
* or conditional app plugins. When adding a new VM plugin to @typed/app, add it here.
|
|
13
|
+
*/
|
|
14
|
+
export function createTypedViteResolver(options = {}, dependencies) {
|
|
15
|
+
const httpApiFactory = dependencies?.createHttpApiVirtualModulePlugin ?? createHttpApiVirtualModulePlugin;
|
|
16
|
+
const plugins = [
|
|
17
|
+
createRouterVirtualModulePlugin(options.routerVmOptions ?? {}),
|
|
18
|
+
httpApiFactory(options.apiVmOptions ?? {}),
|
|
19
|
+
];
|
|
20
|
+
return new PluginManager(plugins);
|
|
21
|
+
}
|
|
22
|
+
function optionsFromTypedConfig(config) {
|
|
23
|
+
return {
|
|
24
|
+
routerVmOptions: config.router ? { prefix: config.router.prefix } : undefined,
|
|
25
|
+
apiVmOptions: config.api
|
|
26
|
+
? { prefix: config.api.prefix, pathPrefix: config.api.pathPrefix }
|
|
27
|
+
: undefined,
|
|
28
|
+
tsconfig: config.tsconfig,
|
|
29
|
+
tsconfigPaths: config.tsconfigPaths,
|
|
30
|
+
analyze: config.analyze,
|
|
31
|
+
warnOnError: config.warnOnError,
|
|
32
|
+
compression: config.compression,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns Vite plugins: tsconfig paths, virtual modules (@typed/app), and optional bundle analyzer.
|
|
37
|
+
* Use as: `defineConfig({ plugins: typedVitePlugin() })`.
|
|
38
|
+
*
|
|
39
|
+
* When called with no arguments, auto-discovers `typed.config.ts` in the project root.
|
|
40
|
+
* When called with explicit options, those take full precedence (config file is not loaded).
|
|
41
|
+
*/
|
|
42
|
+
export function typedVitePlugin(options) {
|
|
43
|
+
const resolvedOptions = (() => {
|
|
44
|
+
if (options)
|
|
45
|
+
return options;
|
|
46
|
+
const result = loadTypedConfig({ projectRoot: process.cwd(), ts });
|
|
47
|
+
if (result.status === "loaded")
|
|
48
|
+
return optionsFromTypedConfig(result.config);
|
|
49
|
+
return {};
|
|
50
|
+
})();
|
|
51
|
+
const resolver = createTypedViteResolver(resolvedOptions);
|
|
52
|
+
const analyze = resolvedOptions.analyze ?? (process.env.ANALYZE === "1" ? true : false);
|
|
53
|
+
let createTypeInfoApiSession = resolvedOptions.createTypeInfoApiSession;
|
|
54
|
+
if (createTypeInfoApiSession === undefined) {
|
|
55
|
+
try {
|
|
56
|
+
const manager = resolver;
|
|
57
|
+
const typeTargetSpecs = collectTypeTargetSpecsFromPlugins(manager.plugins);
|
|
58
|
+
const cwd = process.cwd();
|
|
59
|
+
const tsconfigPath = resolvedOptions.tsconfig
|
|
60
|
+
? resolve(cwd, resolvedOptions.tsconfig)
|
|
61
|
+
: undefined;
|
|
62
|
+
const projectRoot = tsconfigPath ? dirname(tsconfigPath) : cwd;
|
|
63
|
+
createTypeInfoApiSession = createLanguageServiceSessionFactory({
|
|
64
|
+
ts,
|
|
65
|
+
projectRoot,
|
|
66
|
+
typeTargetSpecs,
|
|
67
|
+
tsconfigPath,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Graceful degradation: no session, plugins get noop TypeInfoApi
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const plugins = [];
|
|
75
|
+
if (resolvedOptions.tsconfigPaths !== false) {
|
|
76
|
+
const basePathsOpts = typeof resolvedOptions.tsconfigPaths === "object" ? resolvedOptions.tsconfigPaths : {};
|
|
77
|
+
const cwd = process.cwd();
|
|
78
|
+
const resolvedTsconfig = resolvedOptions.tsconfig
|
|
79
|
+
? resolve(cwd, resolvedOptions.tsconfig)
|
|
80
|
+
: undefined;
|
|
81
|
+
const pathsOpts = resolvedTsconfig !== undefined
|
|
82
|
+
? {
|
|
83
|
+
...basePathsOpts,
|
|
84
|
+
root: cwd,
|
|
85
|
+
projects: [relative(cwd, resolvedTsconfig)],
|
|
86
|
+
}
|
|
87
|
+
: basePathsOpts;
|
|
88
|
+
plugins.push(tsconfigPaths(pathsOpts));
|
|
89
|
+
}
|
|
90
|
+
plugins.push(virtualModulesVitePlugin({
|
|
91
|
+
resolver,
|
|
92
|
+
createTypeInfoApiSession,
|
|
93
|
+
warnOnError: resolvedOptions.warnOnError ?? true,
|
|
94
|
+
}));
|
|
95
|
+
if (analyze) {
|
|
96
|
+
const vizOpts = typeof analyze === "object"
|
|
97
|
+
? analyze
|
|
98
|
+
: { filename: "dist/stats.html", template: "treemap" };
|
|
99
|
+
plugins.push(visualizer({
|
|
100
|
+
filename: vizOpts.filename ?? "dist/stats.html",
|
|
101
|
+
open: vizOpts.open ?? false,
|
|
102
|
+
template: vizOpts.template ?? "treemap",
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
const compression = resolvedOptions.compression ?? true;
|
|
106
|
+
if (compression !== false) {
|
|
107
|
+
const compressionOpts = typeof compression === "object"
|
|
108
|
+
? {
|
|
109
|
+
algorithm: "brotliCompress",
|
|
110
|
+
ext: ".br",
|
|
111
|
+
threshold: 1024,
|
|
112
|
+
...compression,
|
|
113
|
+
}
|
|
114
|
+
: {
|
|
115
|
+
algorithm: "brotliCompress",
|
|
116
|
+
ext: ".br",
|
|
117
|
+
threshold: 1024,
|
|
118
|
+
};
|
|
119
|
+
plugins.push(viteCompression(compressionOpts));
|
|
120
|
+
}
|
|
121
|
+
return plugins;
|
|
122
|
+
}
|
package/package.json
CHANGED
|
@@ -1,42 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typed/vite-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.js",
|
|
7
|
-
"typings": "dist/index.d.ts",
|
|
8
|
-
"types": "dist/index.d.ts",
|
|
9
5
|
"exports": {
|
|
10
6
|
".": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"types": "./dist/index.d.ts"
|
|
14
|
-
},
|
|
15
|
-
"./*": {
|
|
16
|
-
"import": "./dist/*.js",
|
|
17
|
-
"require": "./dist/cjs/*.js",
|
|
18
|
-
"types": "./dist/*.d.ts"
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.js"
|
|
19
9
|
}
|
|
20
10
|
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
21
14
|
"dependencies": {
|
|
22
|
-
"
|
|
23
|
-
"@typed/virtual-module": "0.1.2",
|
|
24
|
-
"fast-glob": "^3.3.1",
|
|
25
|
-
"rollup-plugin-visualizer": "^5.9.2",
|
|
26
|
-
"vavite": "^2.0.2",
|
|
27
|
-
"vite": "^4.4.9",
|
|
15
|
+
"rollup-plugin-visualizer": "^5.12.0",
|
|
28
16
|
"vite-plugin-compression": "^0.5.1",
|
|
29
|
-
"vite-tsconfig-paths": "^
|
|
17
|
+
"vite-tsconfig-paths": "^6.1.0",
|
|
18
|
+
"@typed/app": "1.0.0-beta.2",
|
|
19
|
+
"@typed/virtual-modules-vite": "1.0.0-beta.2",
|
|
20
|
+
"@typed/virtual-modules": "1.0.0-beta.2"
|
|
30
21
|
},
|
|
31
|
-
"
|
|
32
|
-
"
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^25.3.0",
|
|
24
|
+
"typescript": "5.9.3",
|
|
25
|
+
"vite": "^7.3.1",
|
|
26
|
+
"vitest": "4.0.18"
|
|
33
27
|
},
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
"
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"typescript": ">=5.0.0",
|
|
30
|
+
"vite": ">=5.0.0"
|
|
37
31
|
},
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
"
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"src"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "[ -d dist ] || rm -f tsconfig.tsbuildinfo; tsc",
|
|
38
|
+
"test": "vitest run --passWithNoTests"
|
|
41
39
|
}
|
|
42
|
-
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for typedVitePlugin and createTypedViteResolver: plugin order and options pass-through.
|
|
3
|
+
* See .docs/specs/httpapi-virtual-module-plugin/spec.md (Vite Plugin Integration Surface)
|
|
4
|
+
* and testing-strategy.md (typedVitePlugin registration order and option wiring).
|
|
5
|
+
*/
|
|
6
|
+
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { PluginManager } from "@typed/virtual-modules";
|
|
8
|
+
import type { VirtualModulePlugin } from "@typed/virtual-modules";
|
|
9
|
+
import {
|
|
10
|
+
createTypedViteResolver,
|
|
11
|
+
typedVitePlugin,
|
|
12
|
+
type HttpApiVirtualModulePluginOptions,
|
|
13
|
+
} from "./index.js";
|
|
14
|
+
|
|
15
|
+
function fakeHttpApiPlugin(opts: HttpApiVirtualModulePluginOptions): VirtualModulePlugin {
|
|
16
|
+
return {
|
|
17
|
+
name: "httpapi-virtual-module",
|
|
18
|
+
shouldResolve: () => false,
|
|
19
|
+
build: () => "",
|
|
20
|
+
_testOpts: opts,
|
|
21
|
+
} as VirtualModulePlugin & { _testOpts: HttpApiVirtualModulePluginOptions };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
describe("createTypedViteResolver", () => {
|
|
25
|
+
it("always registers router and HttpApi VM plugins", () => {
|
|
26
|
+
const resolver = createTypedViteResolver({});
|
|
27
|
+
expect(resolver).toBeInstanceOf(PluginManager);
|
|
28
|
+
const manager = resolver as PluginManager;
|
|
29
|
+
expect(manager.plugins).toHaveLength(2);
|
|
30
|
+
expect(manager.plugins[0].name).toBe("router-virtual-module");
|
|
31
|
+
expect(manager.plugins[1].name).toBe("httpapi-virtual-module");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("uses DI override for HttpApi plugin when provided", () => {
|
|
35
|
+
const resolver = createTypedViteResolver(
|
|
36
|
+
{ apiVmOptions: { prefix: "api:" } },
|
|
37
|
+
{ createHttpApiVirtualModulePlugin: fakeHttpApiPlugin },
|
|
38
|
+
);
|
|
39
|
+
const manager = resolver as PluginManager;
|
|
40
|
+
expect(manager.plugins).toHaveLength(2);
|
|
41
|
+
expect(manager.plugins[0].name).toBe("router-virtual-module");
|
|
42
|
+
expect(manager.plugins[1].name).toBe("httpapi-virtual-module");
|
|
43
|
+
const apiPlugin = manager.plugins[1] as VirtualModulePlugin & {
|
|
44
|
+
_testOpts: HttpApiVirtualModulePluginOptions;
|
|
45
|
+
};
|
|
46
|
+
expect(apiPlugin._testOpts).toEqual({ prefix: "api:" });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("passes apiVmOptions through to createHttpApiVirtualModulePlugin", () => {
|
|
50
|
+
const opts: HttpApiVirtualModulePluginOptions = { custom: "value", count: 1 };
|
|
51
|
+
const resolver = createTypedViteResolver(
|
|
52
|
+
{ apiVmOptions: opts },
|
|
53
|
+
{ createHttpApiVirtualModulePlugin: fakeHttpApiPlugin },
|
|
54
|
+
);
|
|
55
|
+
const manager = resolver as PluginManager;
|
|
56
|
+
const apiPlugin = manager.plugins[1] as VirtualModulePlugin & {
|
|
57
|
+
_testOpts: HttpApiVirtualModulePluginOptions;
|
|
58
|
+
};
|
|
59
|
+
expect(apiPlugin._testOpts).toEqual(opts);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("uses routerVmOptions for the router plugin", () => {
|
|
63
|
+
const resolver = createTypedViteResolver({
|
|
64
|
+
routerVmOptions: { prefix: "routes:", name: "custom-router" },
|
|
65
|
+
});
|
|
66
|
+
const manager = resolver as PluginManager;
|
|
67
|
+
expect(manager.plugins).toHaveLength(2);
|
|
68
|
+
expect(manager.plugins[0].name).toBe("custom-router");
|
|
69
|
+
expect(manager.plugins[1].name).toBe("httpapi-virtual-module");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("typedVitePlugin", () => {
|
|
74
|
+
it("returns a non-empty plugin array", () => {
|
|
75
|
+
const plugins = typedVitePlugin();
|
|
76
|
+
expect(Array.isArray(plugins)).toBe(true);
|
|
77
|
+
expect(plugins.length).toBeGreaterThan(0);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("returns virtual-modules plugin with resolveId and load", () => {
|
|
81
|
+
const plugins = typedVitePlugin({ tsconfigPaths: false, compression: false });
|
|
82
|
+
const virtualPlugin = plugins.find(
|
|
83
|
+
(p) => p && typeof p === "object" && "name" in p && (p as { name?: string }).name === "virtual-modules",
|
|
84
|
+
);
|
|
85
|
+
expect(virtualPlugin).toBeDefined();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("auto-creates LS-backed session when createTypeInfoApiSession is not provided", () => {
|
|
89
|
+
const plugins = typedVitePlugin({ tsconfigPaths: false, compression: false });
|
|
90
|
+
const virtualPlugin = plugins.find(
|
|
91
|
+
(p) => p && typeof p === "object" && "name" in p && (p as { name?: string }).name === "virtual-modules",
|
|
92
|
+
);
|
|
93
|
+
expect(virtualPlugin).toBeDefined();
|
|
94
|
+
expect(virtualPlugin).toHaveProperty("resolveId");
|
|
95
|
+
expect(virtualPlugin).toHaveProperty("load");
|
|
96
|
+
});
|
|
97
|
+
});
|