@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.
Files changed (51) hide show
  1. package/README.md +97 -0
  2. package/dist/debugBuildPlugin.d.ts +7 -0
  3. package/dist/debugBuildPlugin.d.ts.map +1 -0
  4. package/dist/debugBuildPlugin.js +54 -0
  5. package/dist/index.d.ts +71 -4
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +122 -5
  8. package/package.json +27 -29
  9. package/src/index.test.ts +97 -0
  10. package/src/index.ts +224 -4
  11. package/dist/cjs/constants.d.ts +0 -2
  12. package/dist/cjs/constants.d.ts.map +0 -1
  13. package/dist/cjs/constants.js +0 -5
  14. package/dist/cjs/constants.js.map +0 -1
  15. package/dist/cjs/index.d.ts +0 -5
  16. package/dist/cjs/index.d.ts.map +0 -1
  17. package/dist/cjs/index.js +0 -26
  18. package/dist/cjs/index.js.map +0 -1
  19. package/dist/cjs/resolveTypedConfig.d.ts +0 -20
  20. package/dist/cjs/resolveTypedConfig.d.ts.map +0 -1
  21. package/dist/cjs/resolveTypedConfig.js +0 -16
  22. package/dist/cjs/resolveTypedConfig.js.map +0 -1
  23. package/dist/cjs/vite-plugin.d.ts +0 -56
  24. package/dist/cjs/vite-plugin.d.ts.map +0 -1
  25. package/dist/cjs/vite-plugin.js +0 -212
  26. package/dist/cjs/vite-plugin.js.map +0 -1
  27. package/dist/constants.d.ts +0 -2
  28. package/dist/constants.d.ts.map +0 -1
  29. package/dist/constants.js +0 -2
  30. package/dist/constants.js.map +0 -1
  31. package/dist/index.js.map +0 -1
  32. package/dist/resolveTypedConfig.d.ts +0 -20
  33. package/dist/resolveTypedConfig.d.ts.map +0 -1
  34. package/dist/resolveTypedConfig.js +0 -12
  35. package/dist/resolveTypedConfig.js.map +0 -1
  36. package/dist/tsconfig.cjs.build.tsbuildinfo +0 -1
  37. package/dist/vite-plugin.d.ts +0 -56
  38. package/dist/vite-plugin.d.ts.map +0 -1
  39. package/dist/vite-plugin.js +0 -179
  40. package/dist/vite-plugin.js.map +0 -1
  41. package/eslintrc.json +0 -3
  42. package/project.json +0 -44
  43. package/readme.md +0 -3
  44. package/src/constants.ts +0 -1
  45. package/src/resolveTypedConfig.ts +0 -35
  46. package/src/vite-plugin.ts +0 -312
  47. package/tsconfig.build.json +0 -8
  48. package/tsconfig.build.tsbuildinfo +0 -1
  49. package/tsconfig.cjs.build.json +0 -13
  50. package/tsconfig.json +0 -18
  51. 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 typed from './vite-plugin.js';
2
- export default typed;
3
- export * from './vite-plugin.js';
4
- export { resolveTypedConfig } from './resolveTypedConfig.js';
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,kBAAkB,CAAA;AAEpC,eAAe,KAAK,CAAA;AAEpB,cAAc,kBAAkB,CAAA;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA"}
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 typed from './vite-plugin.js';
2
- export default typed;
3
- export * from './vite-plugin.js';
4
- export { resolveTypedConfig } from './resolveTypedConfig.js';
5
- //# sourceMappingURL=index.js.map
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.17.1",
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
- "import": "./dist/index.js",
12
- "require": "./dist/cjs/index.js",
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
- "@effect/data": "^0.17.6",
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": "^4.2.0"
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
- "peerDependencies": {
32
- "vite-node": "^0.28.3"
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
- "gitHead": "8cba441523534aa1bd327bd84eb0e71334bb914e",
35
- "publishConfig": {
36
- "access": "public"
28
+ "peerDependencies": {
29
+ "typescript": ">=5.0.0",
30
+ "vite": ">=5.0.0"
37
31
  },
38
- "sideEffects": false,
39
- "devDependencies": {
40
- "@types/node": "^20.5.6"
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
+ });