@evjs/webpack-plugin 0.0.1-alpha.5 → 0.0.1-alpha.7

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
@@ -1,15 +1,34 @@
1
1
  # @evjs/webpack-plugin
2
2
 
3
- Build-time integration for React Server Functions in the **ev** framework.
3
+ Webpack adapter for the **ev** framework. Thin wrapper over [`@evjs/build-tools`](../build-tools) that connects bundler-agnostic build logic to Webpack's plugin and loader APIs.
4
4
 
5
- ## Features
5
+ ## Installation
6
6
 
7
- - **`EvWebpackPlugin`**: Zero-config plugin that:
8
- - Auto-discovers `"use server"` files on server builds (`target: "node"`).
9
- - Emits a versioned `manifest.json` mapping function IDs to source locations.
10
- - **`server-fn-loader`**: Transforms files marked with `"use server"`.
11
- - On the **server**: Keeps source code and registers the function.
12
- - On the **client**: Replaces the implementation with an RPC stub.
7
+ ```bash
8
+ npm install @evjs/webpack-plugin
9
+ ```
10
+
11
+ ## Exports
12
+
13
+ | Export | Description |
14
+ |--------|-------------|
15
+ | `EvWebpackPlugin` | Plugin that auto-discovers `"use server"` files and manages server builds |
16
+ | `server-fn-loader` | Loader that transforms `"use server"` files for client/server |
17
+
18
+ ## How It Works
19
+
20
+ ### EvWebpackPlugin
21
+
22
+ 1. **Scans client modules** for `"use server"` files via `detectUseServer()` from build-tools.
23
+ 2. **Generates a server entry** via `generateServerEntry()` — produces a virtual data-URI module.
24
+ 3. **Spawns a child compiler** targeting Node.js — builds the server bundle alongside the client.
25
+ 4. **Emits `manifest.json`** mapping function IDs to their module and export names.
26
+
27
+ ### server-fn-loader
28
+
29
+ Auto-detects whether it's running in the client or server compiler and delegates to `transformServerFile()`:
30
+ - **Client compiler** → replaces function bodies with RPC stubs.
31
+ - **Server compiler** → keeps original source, appends registrations, and reports to the manifest.
13
32
 
14
33
  ## Usage
15
34
 
@@ -18,7 +37,18 @@ const { EvWebpackPlugin } = require("@evjs/webpack-plugin");
18
37
 
19
38
  module.exports = {
20
39
  plugins: [
21
- new EvWebpackPlugin()
40
+ new EvWebpackPlugin({
41
+ server: {
42
+ // App factory (default: "@evjs/runtime/server#createApp")
43
+ appFactory: "@evjs/runtime/server#createApp",
44
+ // Runner — bake into bundle for self-starting dev server
45
+ runner: process.env.NODE_ENV === "development"
46
+ ? "@evjs/runtime/server#runNodeServer"
47
+ : undefined,
48
+ // Extra imports (middleware, config, etc.)
49
+ setup: [],
50
+ },
51
+ }),
22
52
  ],
23
53
  module: {
24
54
  rules: [
@@ -26,16 +56,19 @@ module.exports = {
26
56
  test: /\.tsx?$/,
27
57
  exclude: /node_modules/,
28
58
  use: [
29
- { loader: "swc-loader", /* ... */ },
30
- {
31
- loader: "@evjs/webpack-plugin/server-fn-loader",
32
- options: { isServer: false }
33
- }
34
- ]
35
- }
36
- ]
37
- }
59
+ { loader: "swc-loader" },
60
+ { loader: "@evjs/webpack-plugin/server-fn-loader" },
61
+ ],
62
+ },
63
+ ],
64
+ },
38
65
  };
39
66
  ```
40
67
 
41
- On server builds, `EvWebpackPlugin` automatically discovers all `"use server"` files under `./src/` and injects them as Webpack entries — no manual imports needed.
68
+ ### Plugin Options
69
+
70
+ | Option | Type | Default | Description |
71
+ |--------|------|---------|-------------|
72
+ | `server.appFactory` | `string` | `"@evjs/runtime/server#createApp"` | Module ref for app factory |
73
+ | `server.runner` | `string?` | `undefined` | Module ref for auto-starting the server |
74
+ | `server.setup` | `string[]` | `[]` | Extra imports to prepend to server entry |
package/esm/index.d.ts CHANGED
@@ -1,12 +1,18 @@
1
+ import { type ServerEntryConfig } from "@evjs/build-tools";
1
2
  import type { Compiler } from "webpack";
3
+ export type { ServerEntryConfig };
4
+ export interface EvWebpackPluginOptions {
5
+ server?: ServerEntryConfig;
6
+ }
2
7
  /**
3
8
  * Webpack plugin for the ev framework.
4
9
  *
5
- * On server builds (target: "node"), automatically discovers files with
6
- * the "use server" directive and adds them as entries.
7
- * On all builds, emits the `manifest.json` mapping function IDs to assets.
10
+ * Automatically discovers files with the "use server" directive based on the client dependencies
11
+ * and manages the server-side build via a child compiler.
8
12
  */
9
13
  export declare class EvWebpackPlugin {
14
+ private options;
15
+ constructor(options?: EvWebpackPluginOptions);
10
16
  apply(compiler: Compiler): void;
11
17
  }
12
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA+BxC;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B,KAAK,CAAC,QAAQ,EAAE,QAAQ;CAqEzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAmBxC,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAElC,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED;;;;;GAKG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAAyB;gBAE5B,OAAO,CAAC,EAAE,sBAAsB;IAG5C,KAAK,CAAC,QAAQ,EAAE,QAAQ;CA8JzB"}
package/esm/index.js CHANGED
@@ -1,93 +1,136 @@
1
1
  import fs from "node:fs";
2
- import path from "node:path";
3
- import { glob } from "node:fs";
2
+ import { detectUseServer, generateServerEntry, } from "@evjs/build-tools";
4
3
  class ManifestCollector {
5
- serverFunctions = {};
4
+ serverFns = {};
6
5
  addServerFn(id, meta) {
7
- this.serverFunctions[id] = meta;
6
+ this.serverFns[id] = meta;
8
7
  }
9
8
  getManifest() {
10
9
  return {
11
10
  version: 1,
12
- serverFunctions: this.serverFunctions,
11
+ serverFns: this.serverFns,
13
12
  };
14
13
  }
15
14
  }
16
- /**
17
- * Check if a file starts with the "use server" directive.
18
- */
19
- function hasUseServerDirective(filePath) {
20
- try {
21
- const content = fs.readFileSync(filePath, "utf-8");
22
- const firstLine = content.trimStart().split("\n")[0];
23
- return /^["']use server["'];?\s*$/.test(firstLine.trim());
24
- }
25
- catch {
26
- return false;
27
- }
28
- }
29
15
  /**
30
16
  * Webpack plugin for the ev framework.
31
17
  *
32
- * On server builds (target: "node"), automatically discovers files with
33
- * the "use server" directive and adds them as entries.
34
- * On all builds, emits the `manifest.json` mapping function IDs to assets.
18
+ * Automatically discovers files with the "use server" directive based on the client dependencies
19
+ * and manages the server-side build via a child compiler.
35
20
  */
36
21
  export class EvWebpackPlugin {
22
+ options;
23
+ constructor(options) {
24
+ this.options = options ?? {};
25
+ }
37
26
  apply(compiler) {
38
27
  const collector = new ManifestCollector();
39
28
  // Attach collector to compiler so the loader can access it
40
29
  compiler._ev_manifest_collector = collector;
41
- // Auto-discover server function files on server builds
42
- const isServer = compiler.options.target === "node" ||
43
- (Array.isArray(compiler.options.target) &&
44
- compiler.options.target.includes("node"));
45
- if (isServer) {
46
- const context = compiler.context;
47
- compiler.hooks.make.tapAsync("EvWebpackPlugin", (compilation, callback) => {
48
- // Scan all .ts/.tsx files under src/ for "use server" directive
49
- glob("./src/**/*.{ts,tsx}", { cwd: context }, (err, files) => {
50
- if (err) {
51
- callback(err);
52
- return;
53
- }
54
- const serverFiles = files.filter((f) => hasUseServerDirective(path.resolve(context, f)));
55
- if (serverFiles.length === 0) {
56
- callback();
57
- return;
58
- }
59
- const webpack = compiler.webpack;
60
- let pending = serverFiles.length;
61
- for (const file of serverFiles) {
62
- const absolutePath = path.resolve(context, file);
63
- const dep = webpack.EntryPlugin.createDependency(absolutePath, {
64
- name: undefined,
65
- });
66
- compilation.addEntry(context, dep, { name: undefined }, (addErr) => {
67
- if (addErr) {
68
- callback(addErr);
69
- return;
70
- }
71
- pending--;
72
- if (pending === 0) {
73
- callback();
30
+ // Check if the current compiler is already the Node Child Compiler
31
+ const isServer = compiler.options.name === "evServer" ||
32
+ compiler.options.target === "node";
33
+ if (!isServer) {
34
+ // We are in the Client compiler.
35
+ compiler.hooks.make.tapAsync("EvWebpackPlugin", async (compilation, callback) => {
36
+ compilation.hooks.finishModules.tapAsync("EvWebpackPlugin", (modules, finishCallback) => {
37
+ const serverModulePaths = [];
38
+ for (const module of modules) {
39
+ const resource = "resource" in module ? module.resource : null;
40
+ if (!resource || typeof resource !== "string")
41
+ continue;
42
+ if (resource.includes("node_modules") ||
43
+ !/\.(ts|tsx|js|jsx)$/.test(resource)) {
44
+ continue;
45
+ }
46
+ try {
47
+ const content = fs.readFileSync(resource, "utf-8");
48
+ if (detectUseServer(content)) {
49
+ serverModulePaths.push(resource);
74
50
  }
75
- });
51
+ }
52
+ catch (_err) {
53
+ // Ignore read errors for dynamically generated Webpack modules
54
+ }
76
55
  }
56
+ if (serverModulePaths.length === 0) {
57
+ return finishCallback();
58
+ }
59
+ // Generate server entry using build-tools (bundler-agnostic)
60
+ const serverEntryContent = generateServerEntry(this.options.server, serverModulePaths);
61
+ // Use a Data URI as a virtual entry point
62
+ const serverEntryPath = `data:text/javascript,${encodeURIComponent(serverEntryContent)}`;
63
+ // Spawn the Node Server child compiler (webpack-specific)
64
+ const outputOptions = {
65
+ filename: "../server/index.js",
66
+ library: { type: "commonjs", name: "evServer" },
67
+ chunkFormat: "commonjs",
68
+ };
69
+ const childCompiler = compilation.createChildCompiler("evServer", outputOptions, [
70
+ new compiler.webpack.node.NodeTemplatePlugin({
71
+ asyncChunkLoading: false,
72
+ }),
73
+ new compiler.webpack.node.NodeTargetPlugin(),
74
+ new compiler.webpack.ExternalsPlugin("commonjs", [
75
+ ({ request }, cb) => {
76
+ if (request &&
77
+ typeof request === "string" &&
78
+ (request.startsWith("node:") ||
79
+ [
80
+ "http",
81
+ "https",
82
+ "http2",
83
+ "fs",
84
+ "path",
85
+ "crypto",
86
+ "stream",
87
+ "os",
88
+ "assert",
89
+ "util",
90
+ "events",
91
+ "url",
92
+ "buffer",
93
+ "zlib",
94
+ "child_process",
95
+ "net",
96
+ "tls",
97
+ "querystring",
98
+ "worker_threads",
99
+ ].includes(request))) {
100
+ return cb(null, request);
101
+ }
102
+ cb();
103
+ },
104
+ ]),
105
+ new compiler.webpack.EntryPlugin(compiler.context, serverEntryPath, { name: "main" }),
106
+ ]);
107
+ childCompiler._ev_manifest_collector = collector;
108
+ childCompiler.runAsChild((err, _entries, childCompilation) => {
109
+ if (err)
110
+ return finishCallback(err);
111
+ if (childCompilation?.errors &&
112
+ childCompilation.errors.length > 0) {
113
+ return finishCallback(childCompilation.errors[0]);
114
+ }
115
+ finishCallback();
116
+ });
77
117
  });
118
+ callback();
78
119
  });
79
120
  }
80
- // Emit manifest
81
- compiler.hooks.emit.tap("EvWebpackPlugin", (compilation) => {
82
- const manifest = collector.getManifest();
83
- if (Object.keys(manifest.serverFunctions).length === 0) {
84
- return;
85
- }
86
- const content = JSON.stringify(manifest, null, 2);
87
- compilation.assets["manifest.json"] = {
88
- source: () => content,
89
- size: () => content.length,
90
- };
121
+ // Emit manifest using modern processAssets hook
122
+ compiler.hooks.thisCompilation.tap("EvWebpackPlugin", (compilation) => {
123
+ compilation.hooks.processAssets.tap({
124
+ name: "EvWebpackPlugin",
125
+ stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS,
126
+ }, () => {
127
+ const manifest = collector.getManifest();
128
+ if (Object.keys(manifest.serverFns).length === 0) {
129
+ return;
130
+ }
131
+ const content = JSON.stringify(manifest, null, 2);
132
+ compilation.emitAsset("../server/manifest.json", new compiler.webpack.sources.RawSource(content));
133
+ });
91
134
  });
92
135
  }
93
136
  }
package/esm/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,23 @@
1
+ import type { Compiler } from "webpack";
1
2
  interface LoaderContext {
2
3
  getOptions(): {
3
4
  isServer?: boolean;
4
5
  };
5
6
  resourcePath: string;
6
7
  rootContext: string;
8
+ _compiler?: Compiler & {
9
+ _ev_manifest_collector?: {
10
+ addServerFn(id: string, meta: {
11
+ moduleId: string;
12
+ export: string;
13
+ }): void;
14
+ };
15
+ };
7
16
  }
17
+ /**
18
+ * Webpack loader for "use server" files.
19
+ * Thin wrapper that delegates to @evjs/build-tools for the actual transformation.
20
+ */
8
21
  export default function serverFnLoader(this: LoaderContext, source: string): Promise<string>;
9
22
  export {};
10
23
  //# sourceMappingURL=server-fn-loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-fn-loader.d.ts","sourceRoot":"","sources":["../src/server-fn-loader.ts"],"names":[],"mappings":"AAGA,UAAU,aAAa;IACrB,UAAU,IAAI;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAuBD,wBAA8B,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiFjG"}
1
+ {"version":3,"file":"server-fn-loader.d.ts","sourceRoot":"","sources":["../src/server-fn-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,UAAU,aAAa;IACrB,UAAU,IAAI;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,QAAQ,GAAG;QACrB,sBAAsB,CAAC,EAAE;YACvB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;gBAAE,QAAQ,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI,CAAC;SAC3E,CAAC;KACH,CAAC;CACH;AAED;;;GAGG;AACH,wBAA8B,cAAc,CAC1C,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAmBjB"}
@@ -1,97 +1,24 @@
1
- import { createHash } from "node:crypto";
2
- import { parse } from "@swc/core";
3
- import path from "node:path";
1
+ import { transformServerFile } from "@evjs/build-tools";
4
2
  /**
5
- * Derive a stable function ID from the file path and export name.
3
+ * Webpack loader for "use server" files.
4
+ * Thin wrapper that delegates to @evjs/build-tools for the actual transformation.
6
5
  */
7
- function makeFnId(rootContext, resourcePath, exportName) {
8
- const relativePath = path.relative(rootContext, resourcePath);
9
- return createHash("sha256")
10
- .update(`${relativePath}:${exportName}`)
11
- .digest("hex")
12
- .slice(0, 16);
13
- }
14
- /**
15
- * Check whether the source starts with the "use server" directive.
16
- */
17
- function hasUseServerDirective(source) {
18
- const trimmed = source.replace(/^(\s|\/\/[^\n]*\n|\/\*[\s\S]*?\*\/)*/, "");
19
- return /^["']use server["'];?\s/.test(trimmed);
20
- }
21
6
  export default async function serverFnLoader(source) {
22
- if (!hasUseServerDirective(source)) {
23
- return source;
24
- }
25
- const { isServer = false } = this.getOptions();
26
- // Parse the source into an AST
27
- const program = await parse(source, {
28
- syntax: "typescript",
29
- tsx: true,
30
- comments: false,
31
- script: false,
32
- });
33
- const exportNames = [];
34
- // Iterate through module items to find exports
35
- for (const item of program.body) {
36
- if (item.type === "ExportDeclaration") {
37
- const decl = item.declaration;
38
- if (decl.type === "FunctionDeclaration") {
39
- if (decl.identifier.value)
40
- exportNames.push(decl.identifier.value);
41
- }
42
- else if (decl.type === "VariableDeclaration") {
43
- for (const v of decl.declarations) {
44
- if (v.id.type === "Identifier") {
45
- exportNames.push(v.id.value);
46
- }
47
- }
48
- }
49
- }
50
- else if (item.type === "ExportNamedDeclaration") {
51
- for (const specifier of item.specifiers) {
52
- if (specifier.type === "ExportSpecifier") {
53
- if (specifier.exported?.type === "Identifier") {
54
- exportNames.push(specifier.exported.value);
55
- }
56
- else if (specifier.orig.type === "Identifier") {
57
- exportNames.push(specifier.orig.value);
58
- }
59
- }
60
- }
61
- }
62
- }
63
- if (exportNames.length === 0) {
64
- return source;
7
+ const explicitOptions = this.getOptions() || {};
8
+ let isServer = explicitOptions.isServer;
9
+ if (typeof isServer === "undefined") {
10
+ const compilerName = this._compiler?.name;
11
+ const target = this._compiler?.options?.target;
12
+ isServer = compilerName === "evServer" || target === "node";
65
13
  }
66
14
  const manifestCollector = this._compiler?._ev_manifest_collector;
67
- if (isServer) {
68
- // Server build: keep original + register
69
- const registrations = exportNames
70
- .map((name) => {
71
- const fnId = makeFnId(this.rootContext, this.resourcePath, name);
72
- if (manifestCollector) {
73
- const relativePath = path.relative(this.rootContext, this.resourcePath);
74
- const moduleId = createHash("sha256")
75
- .update(relativePath)
76
- .digest("hex")
77
- .slice(0, 16);
78
- manifestCollector.addServerFn(fnId, {
79
- moduleId,
80
- export: name,
81
- });
82
- }
83
- return `registerServerFn("${fnId}", ${name});`;
84
- })
85
- .join("\n");
86
- return `import { registerServerFn } from "@evjs/runtime/server";\n${source}\n${registrations}\n`;
87
- }
88
- // Client build: replace with RPC stubs
89
- const stubCode = exportNames
90
- .map((name) => {
91
- const fnId = makeFnId(this.rootContext, this.resourcePath, name);
92
- return `export function ${name}(...args) {\n return __ev_rpc("${fnId}", args);\n}`;
93
- })
94
- .join("\n\n");
95
- return `import { __ev_rpc } from "@evjs/runtime/client";\n\n${stubCode}\n`;
15
+ return transformServerFile(source, {
16
+ resourcePath: this.resourcePath,
17
+ rootContext: this.rootContext,
18
+ isServer: !!isServer,
19
+ onServerFn: manifestCollector
20
+ ? (fnId, meta) => manifestCollector.addServerFn(fnId, meta)
21
+ : undefined,
22
+ });
96
23
  }
97
24
  //# sourceMappingURL=server-fn-loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server-fn-loader.js","sourceRoot":"","sources":["../src/server-fn-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server-fn-loader.js","sourceRoot":"","sources":["../src/server-fn-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAcxD;;;GAGG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,cAAc,CAE1C,MAAc;IAEd,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC;IAChD,IAAI,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC;IACxC,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC;QAC/C,QAAQ,GAAG,YAAY,KAAK,UAAU,IAAI,MAAM,KAAK,MAAM,CAAC;IAC9D,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAEjE,OAAO,mBAAmB,CAAC,MAAM,EAAE;QACjC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,UAAU,EAAE,iBAAiB;YAC3B,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC;YAC3D,CAAC,CAAC,SAAS;KACd,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evjs/webpack-plugin",
3
- "version": "0.0.1-alpha.5",
3
+ "version": "0.0.1-alpha.7",
4
4
  "description": "Webpack plugin and loaders for the ev framework",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -35,8 +35,8 @@
35
35
  "author": "xusd320",
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@evjs/manifest": "0.0.1-alpha.5",
39
- "@swc/core": "^1.15.18"
38
+ "@evjs/build-tools": "0.0.1-alpha.7",
39
+ "@evjs/manifest": "0.0.1-alpha.7"
40
40
  },
41
41
  "devDependencies": {
42
42
  "typescript": "^5.7.3",
package/esm/version.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export declare const VERSION = "0.0.1-alpha.5";
2
- //# sourceMappingURL=version.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,kBAAkB,CAAC"}
package/esm/version.js DELETED
@@ -1,2 +0,0 @@
1
- export const VERSION = "0.0.1-alpha.5";
2
- //# sourceMappingURL=version.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC"}