alloy-di 1.5.0 → 2.0.0

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 (39) hide show
  1. package/README.md +12 -7
  2. package/bin/alloy.js +9 -0
  3. package/dist/cli.d.ts +24 -0
  4. package/dist/cli.js +168 -0
  5. package/dist/generate.d.ts +28 -0
  6. package/dist/generate.js +46 -0
  7. package/dist/lib/container.d.ts +2 -1
  8. package/dist/lib/container.js +5 -4
  9. package/dist/lib/lazy.d.ts +5 -1
  10. package/dist/lib/scope.d.ts +1 -0
  11. package/dist/lib/types.d.ts +3 -1
  12. package/dist/plugins/consumer-plugin.d.ts +40 -0
  13. package/dist/plugins/consumer-plugin.js +101 -0
  14. package/dist/plugins/core/codegen.js +1 -1
  15. package/dist/plugins/core/container-loader.js +30 -16
  16. package/dist/plugins/core/generation-inputs.js +41 -0
  17. package/dist/plugins/core/utils.js +1 -1
  18. package/dist/plugins/core/visualization-utils.js +1 -1
  19. package/dist/plugins/rollup-plugin/index.js +3 -5
  20. package/dist/plugins/vite-plugin/index.d.ts +2 -29
  21. package/dist/plugins/vite-plugin/index.js +19 -73
  22. package/dist/plugins/webpack-like-plugin.d.ts +32 -0
  23. package/dist/plugins/webpack-like-plugin.js +86 -0
  24. package/dist/rspack.d.ts +7 -0
  25. package/dist/rspack.js +10 -0
  26. package/dist/runtime.d.ts +4 -4
  27. package/dist/runtime.js +3 -3
  28. package/dist/scopes.d.ts +2 -1
  29. package/dist/scopes.js +3 -0
  30. package/dist/tsconfig.tsbuildinfo +1 -1
  31. package/dist/vite.d.ts +2 -1
  32. package/dist/webpack.d.ts +7 -0
  33. package/dist/webpack.js +10 -0
  34. package/package.json +28 -12
  35. package/dist/lib/testing/mocking.d.ts +0 -12
  36. package/dist/lib/testing/mocking.js +0 -107
  37. package/dist/lib/testing/registry.js +0 -17
  38. package/dist/test.d.ts +0 -84
  39. package/dist/test.js +0 -83
@@ -0,0 +1,41 @@
1
+ import { walkSync } from "./utils.js";
2
+ import { createDiscoveryRuntime } from "./discovery-runtime.js";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+ //#region src/plugins/core/generation-inputs.ts
6
+ const DEFAULT_SOURCE_DIRS = ["src"];
7
+ function toLazyServiceKey(identifier) {
8
+ const description = identifier.description;
9
+ if (!description?.startsWith("alloy:")) throw new Error("[alloy] lazyServices entries must be serviceIdentifiers exported by Alloy manifests.");
10
+ return description;
11
+ }
12
+ function readPackageName(root) {
13
+ try {
14
+ const pkgPath = path.resolve(root, "package.json");
15
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
16
+ if (typeof pkg.name === "string") return pkg.name;
17
+ } catch {}
18
+ return "UNKNOWN_PACKAGE";
19
+ }
20
+ function isSourceFile(file) {
21
+ return /\.tsx?$/i.test(file) && !file.endsWith(".d.ts");
22
+ }
23
+ function scanSourceDirectories(discoveryRuntime, root, sourceDirs = DEFAULT_SOURCE_DIRS, options) {
24
+ for (const sourceDir of sourceDirs) {
25
+ const files = walkSync(path.isAbsolute(sourceDir) ? sourceDir : path.resolve(root, sourceDir));
26
+ for (const file of files) {
27
+ if (!isSourceFile(file)) continue;
28
+ try {
29
+ const code = fs.readFileSync(file, "utf-8");
30
+ discoveryRuntime.processUpdate(file, code, options);
31
+ } catch {}
32
+ }
33
+ }
34
+ }
35
+ function createDiscoveryRuntimeForSourceDirs(root, sourceDirs = DEFAULT_SOURCE_DIRS, options) {
36
+ const discoveryRuntime = createDiscoveryRuntime();
37
+ scanSourceDirectories(discoveryRuntime, root, sourceDirs, options);
38
+ return discoveryRuntime;
39
+ }
40
+ //#endregion
41
+ export { DEFAULT_SOURCE_DIRS, createDiscoveryRuntimeForSourceDirs, readPackageName, scanSourceDirectories, toLazyServiceKey };
@@ -1,5 +1,5 @@
1
- import path from "node:path";
2
1
  import fs from "node:fs";
2
+ import path from "node:path";
3
3
  //#region src/plugins/core/utils.ts
4
4
  const WINDOWS_DRIVE_PATTERN = /^[A-Za-z]:[\\/]/;
5
5
  function normalizeImportPath(p) {
@@ -1,5 +1,5 @@
1
- import path from "node:path";
2
1
  import fs from "node:fs";
2
+ import path from "node:path";
3
3
  //#region src/plugins/core/visualization-utils.ts
4
4
  const DEFAULT_MERMAID_FILENAME = "alloy-di.mmd";
5
5
  function resolveVisualizationOptions(input, projectRoot) {
@@ -5,8 +5,8 @@ import { determineBuildMode, hasPreserveModules, resolveImportPathForBuild } fro
5
5
  import { parseExportedNames } from "./barrel-exports.js";
6
6
  import { createManifestDependency } from "./manifest-deps.js";
7
7
  import { checkPackageExports } from "./package-exports.js";
8
- import path from "node:path";
9
8
  import fs from "node:fs";
9
+ import path from "node:path";
10
10
  //#region src/plugins/rollup-plugin/index.ts
11
11
  /**
12
12
  * Rollup/Rolldown plugin that scans decorated Alloy services and emits an ESM manifest.
@@ -47,10 +47,8 @@ function alloy(options = {}) {
47
47
  },
48
48
  generateBundle(outputOptions) {
49
49
  const buildMode = getBuildMode(outputOptions);
50
- if (options.scopes && Object.keys(options.scopes).length > 0) {
51
- validateScopesConfig(options.scopes);
52
- validateScopeStability([...discovery.fileMetas.values()].flat(), options.scopes);
53
- }
50
+ if (options.scopes && Object.keys(options.scopes).length > 0) validateScopesConfig(options.scopes);
51
+ validateScopeStability([...discovery.fileMetas.values()].flat(), options.scopes);
54
52
  const services = [];
55
53
  const missingExports = [];
56
54
  const exportedNames = buildMode === "preserve-modules" ? /* @__PURE__ */ new Set() : parseExportedNames(discovery.fileSources);
@@ -1,39 +1,12 @@
1
- import { AlloyManifest } from "../core/types.js";
2
- import { AlloyScopesConfig } from "../core/scopes-validation.js";
3
- import { ServiceIdentifier } from "../../lib/service-identifiers.js";
4
1
  import { AlloyMermaidVisualizerOptions, AlloyVisualizationOptions } from "../core/visualization-utils.js";
2
+ import { AlloyPluginOptions } from "../consumer-plugin.js";
5
3
  import { Plugin } from "vite";
6
4
 
7
5
  //#region src/plugins/vite-plugin/index.d.ts
8
- interface AlloyPluginOptions {
9
- providers?: string[];
10
- /** Optional list of manifest objects to ingest */
11
- manifests?: AlloyManifest[];
12
- /** List of ServiceIdentifiers to mark as instantiation-lazy (adds factory Lazy wrapper) */
13
- lazyServices?: ServiceIdentifier[];
14
- /**
15
- * Output directory for the generated `virtual-container.d.ts` file.
16
- * Relative paths are resolved against the project root.
17
- * Defaults to "./src".
18
- */
19
- containerDeclarationDir?: string;
20
- /**
21
- * Emit dependency graph artifacts. When `true`, writes a Mermaid diagram to
22
- * `${projectRoot}/alloy-di.mmd`. Provide an object to customize output.
23
- */
24
- visualize?: boolean | AlloyVisualizationOptions;
25
- /**
26
- * Declares custom, application-defined scopes and their parent ordering, e.g.
27
- * `{ session: { parent: 'singleton' }, request: { parent: 'session' } }`.
28
- * Drives type-safe scope names (emitted into the generated declaration),
29
- * runtime hierarchy registration, and build-time scope-stability validation.
30
- */
31
- scopes?: AlloyScopesConfig;
32
- }
33
6
  /**
34
7
  * Creates the Alloy Vite plugin that statically discovers injectable classes
35
8
  * and exposes them through a virtual container module at build time.
36
9
  */
37
10
  declare function alloy(options?: AlloyPluginOptions): Plugin;
38
11
  //#endregion
39
- export { AlloyPluginOptions, alloy };
12
+ export { alloy };
@@ -1,57 +1,28 @@
1
- import { normalizeImportPath, walkSync } from "../core/utils.js";
2
- import { resolveVisualizationOptions } from "../core/visualization-utils.js";
3
- import { loadVirtualContainerModule } from "../core/container-loader.js";
4
- import { createDiscoveryRuntime, isDiscoverableFile } from "../core/discovery-runtime.js";
1
+ import { ALLOY_PLUGIN_OPTIONS, createConsumerPluginContext, isAlloyDiscoverableFile } from "../consumer-plugin.js";
5
2
  import { invalidateContainerModule } from "./module-invalidation.js";
6
- import path from "node:path";
7
- import fs from "node:fs";
8
3
  //#region src/plugins/vite-plugin/index.ts
9
- function toLazyServiceKey(identifier) {
10
- const description = identifier.description;
11
- if (!description || !description.startsWith("alloy:")) throw new Error("[alloy] lazyServices entries must be serviceIdentifiers exported by Alloy manifests.");
12
- return description;
13
- }
4
+ const ALLOY_VITE_PLUGIN_OPTIONS = Symbol.for("alloy-di.vite-plugin-options");
14
5
  /**
15
6
  * Creates the Alloy Vite plugin that statically discovers injectable classes
16
7
  * and exposes them through a virtual container module at build time.
17
8
  */
18
9
  function alloy(options = {}) {
19
- const virtualModuleId = "virtual:alloy-container";
20
- const resolvedVirtualModuleId = "\0virtual:alloy-container";
21
- const configuredProviderEntries = Array.from(options.providers ?? []);
22
- const providerModuleRefs = [];
23
- let resolvedRoot = process.cwd();
24
- let packageName = "UNKNOWN_PACKAGE";
25
- let resolvedVisualization = null;
26
- let isDevMode;
27
- const lazyServiceKeys = new Set((options.lazyServices ?? []).map(toLazyServiceKey));
28
- const discoveryRuntime = createDiscoveryRuntime();
29
- const shouldTrackFactoryProviders = () => Boolean(resolvedVisualization);
10
+ const context = createConsumerPluginContext(options);
30
11
  return {
31
12
  name: "vite-plugin-alloy",
32
13
  enforce: "pre",
14
+ [ALLOY_VITE_PLUGIN_OPTIONS]: options,
15
+ [ALLOY_PLUGIN_OPTIONS]: options,
33
16
  configResolved(config) {
34
- resolvedRoot = config.root ?? process.cwd();
35
- isDevMode = !config.isProduction;
36
- try {
37
- const pkgPath = path.resolve(resolvedRoot, "package.json");
38
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
39
- if (typeof pkg.name === "string") packageName = pkg.name;
40
- } catch {}
41
- providerModuleRefs.length = 0;
42
- for (const entry of configuredProviderEntries) {
43
- const absPath = path.isAbsolute(entry) ? entry : path.resolve(resolvedRoot, entry);
44
- providerModuleRefs.push({
45
- absPath,
46
- importPath: normalizeImportPath(absPath)
47
- });
48
- }
49
- resolvedVisualization = resolveVisualizationOptions(options.visualize, resolvedRoot);
17
+ context.configure({
18
+ root: config.root ?? process.cwd(),
19
+ isDevMode: !config.isProduction
20
+ });
50
21
  },
51
22
  resolveId: {
52
23
  filter: { id: { include: [/^virtual:alloy-container$/] } },
53
24
  handler(id) {
54
- if (id === virtualModuleId) return resolvedVirtualModuleId;
25
+ if (id === context.virtualModuleId) return context.resolvedVirtualModuleId;
55
26
  }
56
27
  },
57
28
  transform: {
@@ -60,16 +31,16 @@ function alloy(options = {}) {
60
31
  exclude: [/\.d\.ts$/i, /node_modules/]
61
32
  } },
62
33
  handler(code, id) {
63
- discoveryRuntime.processUpdate(id, code, { factoryProviders: shouldTrackFactoryProviders() });
34
+ context.processTransform(code, id);
64
35
  return null;
65
36
  }
66
37
  },
67
38
  async hotUpdate(ctx) {
68
39
  if (this.environment.name !== "client") return;
69
40
  const { file } = ctx;
70
- if (!isDiscoverableFile(file)) return;
41
+ if (!isAlloyDiscoverableFile(file)) return;
71
42
  let discoveryChanged;
72
- if (ctx.type === "delete") discoveryChanged = discoveryRuntime.removeDiscoveredFile(file);
43
+ if (ctx.type === "delete") discoveryChanged = context.removeFile(file);
73
44
  else {
74
45
  let code;
75
46
  try {
@@ -77,49 +48,24 @@ function alloy(options = {}) {
77
48
  } catch {
78
49
  return;
79
50
  }
80
- discoveryChanged = discoveryRuntime.processUpdate(file, code, { factoryProviders: shouldTrackFactoryProviders() });
51
+ discoveryChanged = context.processFileUpdate(file, code);
81
52
  }
82
53
  if (!discoveryChanged) return;
83
- invalidateContainerModule(ctx.server, resolvedVirtualModuleId);
54
+ invalidateContainerModule(ctx.server, context.resolvedVirtualModuleId);
84
55
  this.environment.hot.send({ type: "full-reload" });
85
56
  return [];
86
57
  },
87
58
  buildStart() {
88
- discoveryRuntime.clear();
89
- for (const ref of providerModuleRefs) {
90
- this.addWatchFile(ref.absPath);
91
- if (shouldTrackFactoryProviders()) try {
92
- const code = fs.readFileSync(ref.absPath, "utf-8");
93
- discoveryRuntime.processUpdate(ref.absPath, code, { factoryProviders: true });
94
- } catch {}
95
- }
96
- const files = walkSync(path.join(resolvedRoot, "src"));
97
- for (const file of files) if (/\.(tsx?|ts)$/i.test(file) && !file.endsWith(".d.ts")) try {
98
- const code = fs.readFileSync(file, "utf-8");
99
- discoveryRuntime.processUpdate(file, code, { factoryProviders: shouldTrackFactoryProviders() });
100
- } catch {}
59
+ context.buildStart((file) => this.addWatchFile(file));
101
60
  },
102
61
  load: {
103
62
  filter: { id: { include: [/^\0virtual:alloy-container$/] } },
104
63
  async handler(id) {
105
- if (id !== resolvedVirtualModuleId) return;
106
- return loadVirtualContainerModule({
107
- localMetas: Array.from(discoveryRuntime.discoveredClasses.values()),
108
- lazyReferencedClassKeys: discoveryRuntime.lazyReferencedClassKeys,
109
- manifests: options.manifests ?? [],
110
- providerImportPaths: providerModuleRefs.map((ref) => ref.importPath),
111
- factoryProviders: shouldTrackFactoryProviders() ? Array.from(discoveryRuntime.factoryProvidersByFile.values()).flat() : [],
112
- lazyServiceKeys,
113
- packageName,
114
- resolvedRoot,
115
- containerDeclarationDir: options.containerDeclarationDir,
116
- resolvedVisualization,
117
- isDevMode,
118
- scopes: options.scopes
119
- });
64
+ if (id !== context.resolvedVirtualModuleId) return;
65
+ return context.loadContainer();
120
66
  }
121
67
  }
122
68
  };
123
69
  }
124
70
  //#endregion
125
- export { alloy };
71
+ export { ALLOY_VITE_PLUGIN_OPTIONS, alloy };
@@ -0,0 +1,32 @@
1
+ import { ALLOY_PLUGIN_OPTIONS, AlloyPluginOptions } from "./consumer-plugin.js";
2
+
3
+ //#region src/plugins/webpack-like-plugin.d.ts
4
+ interface TapHook {
5
+ tap?(name: string, handler: (...args: unknown[]) => unknown): void;
6
+ tapPromise?(name: string, handler: (...args: unknown[]) => Promise<unknown>): void;
7
+ }
8
+ interface WebpackLikeCompiler {
9
+ context?: string;
10
+ options?: {
11
+ context?: string;
12
+ mode?: string;
13
+ resolve?: {
14
+ alias?: Record<string, string | false | string[]> | {
15
+ name?: string;
16
+ alias?: string | false | string[];
17
+ }[];
18
+ };
19
+ };
20
+ hooks?: {
21
+ beforeCompile?: TapHook;
22
+ thisCompilation?: TapHook;
23
+ normalModuleFactory?: TapHook;
24
+ };
25
+ }
26
+ interface AlloyWebpackLikePlugin {
27
+ readonly name: string;
28
+ readonly [ALLOY_PLUGIN_OPTIONS]: AlloyPluginOptions;
29
+ apply(compiler: WebpackLikeCompiler): void;
30
+ }
31
+ //#endregion
32
+ export { AlloyWebpackLikePlugin };
@@ -0,0 +1,86 @@
1
+ import { ALLOY_PLUGIN_OPTIONS, createConsumerPluginContext } from "./consumer-plugin.js";
2
+ import path from "node:path";
3
+ //#region src/plugins/webpack-like-plugin.ts
4
+ function addDependency(deps, file) {
5
+ deps?.add(file);
6
+ }
7
+ function addContextDependency(deps, dir) {
8
+ deps?.add(dir);
9
+ }
10
+ function isObject(value) {
11
+ return Boolean(value) && typeof value === "object";
12
+ }
13
+ function isWebpackLikeNormalModuleFactory(value) {
14
+ return isObject(value) && isObject(value.hooks);
15
+ }
16
+ function isResolveRequest(value) {
17
+ return value === void 0 || isObject(value);
18
+ }
19
+ function isWebpackLikeCompilation(value) {
20
+ return isObject(value);
21
+ }
22
+ function createWebpackLikeAlloyPlugin(options, pluginOptions) {
23
+ const context = createConsumerPluginContext(options);
24
+ let cacheFilePath = "";
25
+ async function writeContainer() {
26
+ context.buildStart();
27
+ await context.writeContainerCache(cacheFilePath);
28
+ }
29
+ function configureAlias(compiler) {
30
+ compiler.options ??= {};
31
+ compiler.options.resolve ??= {};
32
+ const alias = compiler.options.resolve.alias;
33
+ if (Array.isArray(alias)) {
34
+ const existing = alias.find((entry) => entry.name === context.virtualModuleId);
35
+ if (existing) existing.alias = cacheFilePath;
36
+ else alias.push({
37
+ name: context.virtualModuleId,
38
+ alias: cacheFilePath
39
+ });
40
+ return;
41
+ }
42
+ compiler.options.resolve.alias = {
43
+ ...alias,
44
+ [context.virtualModuleId]: cacheFilePath
45
+ };
46
+ }
47
+ function configureVirtualResolve(compiler) {
48
+ compiler.hooks?.normalModuleFactory?.tap?.(pluginOptions.name, (factory) => {
49
+ if (!isWebpackLikeNormalModuleFactory(factory)) return;
50
+ factory.hooks?.beforeResolve?.tap?.(pluginOptions.name, (request) => {
51
+ if (!isResolveRequest(request)) return;
52
+ const resolveRequest = request;
53
+ if (resolveRequest?.request === context.virtualModuleId) resolveRequest.request = cacheFilePath;
54
+ });
55
+ });
56
+ }
57
+ function configureLifecycleHooks(compiler) {
58
+ compiler.hooks?.beforeCompile?.tapPromise?.(pluginOptions.name, async () => {
59
+ await writeContainer();
60
+ });
61
+ compiler.hooks?.thisCompilation?.tap?.(pluginOptions.name, (compilation) => {
62
+ if (!isWebpackLikeCompilation(compilation)) return;
63
+ addDependency(compilation.fileDependencies, cacheFilePath);
64
+ for (const watchFile of context.getWatchFiles()) addDependency(compilation.fileDependencies, watchFile);
65
+ for (const watchRoot of context.getWatchDirectories()) addContextDependency(compilation.contextDependencies, watchRoot);
66
+ });
67
+ }
68
+ return {
69
+ name: pluginOptions.name,
70
+ [ALLOY_PLUGIN_OPTIONS]: options,
71
+ apply(compiler) {
72
+ const root = compiler.options?.context ?? compiler.context ?? process.cwd();
73
+ const isDevMode = compiler.options?.mode ? compiler.options.mode !== "production" : void 0;
74
+ context.configure({
75
+ root,
76
+ isDevMode
77
+ });
78
+ cacheFilePath = path.resolve(root, "node_modules/.cache/alloy-di", pluginOptions.cacheFileName);
79
+ configureAlias(compiler);
80
+ configureVirtualResolve(compiler);
81
+ configureLifecycleHooks(compiler);
82
+ }
83
+ };
84
+ }
85
+ //#endregion
86
+ export { createWebpackLikeAlloyPlugin };
@@ -0,0 +1,7 @@
1
+ import { AlloyPluginOptions } from "./plugins/consumer-plugin.js";
2
+ import { AlloyWebpackLikePlugin } from "./plugins/webpack-like-plugin.js";
3
+
4
+ //#region src/rspack.d.ts
5
+ declare function alloy(options?: AlloyPluginOptions): AlloyWebpackLikePlugin;
6
+ //#endregion
7
+ export { type AlloyPluginOptions, alloy, alloy as default };
package/dist/rspack.js ADDED
@@ -0,0 +1,10 @@
1
+ import { createWebpackLikeAlloyPlugin } from "./plugins/webpack-like-plugin.js";
2
+ //#region src/rspack.ts
3
+ function alloy(options = {}) {
4
+ return createWebpackLikeAlloyPlugin(options, {
5
+ name: "alloy-di-rspack",
6
+ cacheFileName: "rspack-virtual-container.js"
7
+ });
8
+ }
9
+ //#endregion
10
+ export { alloy, alloy as default };
package/dist/runtime.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { Newable, Token, createToken } from "./lib/types.js";
2
- import { AlloyScopes, ResolutionContext, ServiceScope } from "./lib/scope.js";
1
+ import { Constructor, Newable, Token, createToken, isConstructor, isToken } from "./lib/types.js";
3
2
  import { ServiceIdentifier, clearServiceIdentifierRegistry, getConstructorByIdentifier, getServiceIdentifier, registerServiceIdentifier } from "./lib/service-identifiers.js";
3
+ import { AlloyScopes, ResolutionContext, ServiceScope } from "./lib/scope.js";
4
4
  import { Container, FactoryFn } from "./lib/container.js";
5
5
  import { EnvDetectionOverrides, setEnvDetectionOverrides } from "./lib/env-detection.js";
6
- import { LAZY_IDENTIFIER, Lazy } from "./lib/lazy.js";
6
+ import { LAZY_IDENTIFIER, Lazy, isLazy } from "./lib/lazy.js";
7
7
  import { Injectable, Singleton, assertDeps, dependenciesRegistry, deps } from "./lib/decorators.js";
8
8
  import { FactoryProviderDescriptor, ProviderDefinitions, applyProviders, asClass, asFactory, asLazyClass, asValue, defineProviders, lifecycle } from "./lib/providers.js";
9
- export { type AlloyScopes, Container, type EnvDetectionOverrides, type FactoryFn, type FactoryProviderDescriptor, Injectable, LAZY_IDENTIFIER, Lazy, type Lazy as LazyInterface, type Newable, type ProviderDefinitions, type ResolutionContext, type ServiceIdentifier, ServiceScope, Singleton, type Token, applyProviders, asClass, asFactory, asLazyClass, asValue, assertDeps, clearServiceIdentifierRegistry, createToken, defineProviders, dependenciesRegistry, deps, getConstructorByIdentifier, getServiceIdentifier, lifecycle, registerServiceIdentifier, setEnvDetectionOverrides };
9
+ export { type AlloyScopes, type Constructor, Container, type EnvDetectionOverrides, type FactoryFn, type FactoryProviderDescriptor, Injectable, LAZY_IDENTIFIER, Lazy, type Lazy as LazyInterface, type Newable, type ProviderDefinitions, type ResolutionContext, type ServiceIdentifier, ServiceScope, Singleton, type Token, applyProviders, asClass, asFactory, asLazyClass, asValue, assertDeps, clearServiceIdentifierRegistry, createToken, defineProviders, dependenciesRegistry, deps, getConstructorByIdentifier, getServiceIdentifier, isConstructor, isLazy, isToken, lifecycle, registerServiceIdentifier, setEnvDetectionOverrides };
package/dist/runtime.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ServiceScope } from "./lib/scope.js";
2
- import { createToken } from "./lib/types.js";
3
- import { LAZY_IDENTIFIER, Lazy } from "./lib/lazy.js";
2
+ import { createToken, isConstructor, isToken } from "./lib/types.js";
3
+ import { LAZY_IDENTIFIER, Lazy, isLazy } from "./lib/lazy.js";
4
4
  import { Injectable, Singleton, assertDeps, dependenciesRegistry, deps } from "./lib/decorators.js";
5
5
  import { clearServiceIdentifierRegistry, getConstructorByIdentifier, getServiceIdentifier, registerServiceIdentifier } from "./lib/service-identifiers.js";
6
6
  import { setEnvDetectionOverrides } from "./lib/env-detection.js";
7
7
  import { Container } from "./lib/container.js";
8
8
  import { applyProviders, asClass, asFactory, asLazyClass, asValue, defineProviders, lifecycle } from "./lib/providers.js";
9
- export { Container, Injectable, LAZY_IDENTIFIER, Lazy, ServiceScope, Singleton, applyProviders, asClass, asFactory, asLazyClass, asValue, assertDeps, clearServiceIdentifierRegistry, createToken, defineProviders, dependenciesRegistry, deps, getConstructorByIdentifier, getServiceIdentifier, lifecycle, registerServiceIdentifier, setEnvDetectionOverrides };
9
+ export { Container, Injectable, LAZY_IDENTIFIER, Lazy, ServiceScope, Singleton, applyProviders, asClass, asFactory, asLazyClass, asValue, assertDeps, clearServiceIdentifierRegistry, createToken, defineProviders, dependenciesRegistry, deps, getConstructorByIdentifier, getServiceIdentifier, isConstructor, isLazy, isToken, lifecycle, registerServiceIdentifier, setEnvDetectionOverrides };
package/dist/scopes.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Constructor, Newable, Token } from "./lib/types.js";
2
- import { FactoryCacheEntry, FactoryPendingEntry, ResolutionContext, ServiceScope } from "./lib/scope.js";
3
2
  import { ServiceIdentifier } from "./lib/service-identifiers.js";
3
+ import { FactoryCacheEntry, FactoryPendingEntry, ResolutionContext, ServiceScope } from "./lib/scope.js";
4
4
  import { Container } from "./lib/container.js";
5
5
 
6
6
  //#region src/scopes.d.ts
@@ -25,6 +25,7 @@ declare class Scope implements ResolutionContext {
25
25
  */
26
26
  getContainer(): Container;
27
27
  getCached(target: Constructor): unknown;
28
+ hasCached(target: Constructor): boolean;
28
29
  setCached(target: Constructor, instance: unknown): void;
29
30
  getPending(target: Constructor): Promise<unknown> | undefined;
30
31
  setPending(target: Constructor, promise: Promise<unknown>): void;
package/dist/scopes.js CHANGED
@@ -29,6 +29,9 @@ var Scope = class Scope {
29
29
  getCached(target) {
30
30
  return this.cached.get(target);
31
31
  }
32
+ hasCached(target) {
33
+ return this.cached.has(target);
34
+ }
32
35
  setCached(target, instance) {
33
36
  this.cached.set(target, instance);
34
37
  this.instantiatedInstances.push(instance);
@@ -1 +1 @@
1
- {"root":["../src/entry-points.test.ts","../src/fixture-subpaths.test.ts","../src/rollup.ts","../src/runtime.ts","../src/scopes.ts","../src/test.test.ts","../src/test.ts","../src/vite.ts","../src/lib/container.factories-scoped.test.ts","../src/lib/container.factories.test.ts","../src/lib/container.identifiers.test.ts","../src/lib/container.internals.test.ts","../src/lib/container.test.ts","../src/lib/container.testing-features.test.ts","../src/lib/container.ts","../src/lib/decorators.runtime.test.ts","../src/lib/decorators.test-d.ts","../src/lib/decorators.ts","../src/lib/dependency-error.ts","../src/lib/env-detection.test.ts","../src/lib/env-detection.ts","../src/lib/lazy-retry.test.ts","../src/lib/lazy.ts","../src/lib/providers.test.ts","../src/lib/providers.ts","../src/lib/scope.ts","../src/lib/scopes.test.ts","../src/lib/service-identifiers.test.ts","../src/lib/service-identifiers.ts","../src/lib/tokens.test.ts","../src/lib/types.ts","../src/lib/testing/mocking.test.ts","../src/lib/testing/mocking.ts","../src/lib/testing/registry.test.ts","../src/lib/testing/registry.ts","../src/plugins/core/codegen.test.ts","../src/plugins/core/codegen.ts","../src/plugins/core/container-loader.test.ts","../src/plugins/core/container-loader.ts","../src/plugins/core/decorators.helpers.test.ts","../src/plugins/core/decorators.ts","../src/plugins/core/discovery-runtime.ts","../src/plugins/core/discovery-store.test.ts","../src/plugins/core/discovery-store.ts","../src/plugins/core/identifier-resolver.test.ts","../src/plugins/core/identifier-resolver.ts","../src/plugins/core/lazy-utils.ts","../src/plugins/core/lazy.helpers.test.ts","../src/plugins/core/lazy.ts","../src/plugins/core/manifest-utils.ts","../src/plugins/core/manifest-utils.validation.test.ts","../src/plugins/core/scanner.test.ts","../src/plugins/core/scanner.ts","../src/plugins/core/scopes-validation.test.ts","../src/plugins/core/scopes-validation.ts","../src/plugins/core/types.ts","../src/plugins/core/utils.ts","../src/plugins/core/utils.walk.test.ts","../src/plugins/core/utils.write.test.ts","../src/plugins/core/visualization-utils.ts","../src/plugins/core/visualizer.test.ts","../src/plugins/core/visualizer.ts","../src/plugins/rollup-plugin/barrel-exports.test.ts","../src/plugins/rollup-plugin/barrel-exports.ts","../src/plugins/rollup-plugin/build-utils.test.ts","../src/plugins/rollup-plugin/build-utils.ts","../src/plugins/rollup-plugin/dependency-resolution.test.ts","../src/plugins/rollup-plugin/dependency-resolution.ts","../src/plugins/rollup-plugin/index.test.ts","../src/plugins/rollup-plugin/index.ts","../src/plugins/rollup-plugin/manifest-deps.test.ts","../src/plugins/rollup-plugin/manifest-deps.ts","../src/plugins/rollup-plugin/package-exports.test.ts","../src/plugins/rollup-plugin/package-exports.ts","../src/plugins/rollup-plugin/types.ts","../src/plugins/vite-plugin/duplicate-registrations.test.ts","../src/plugins/vite-plugin/index.ts","../src/plugins/vite-plugin/lazy-services.test.ts","../src/plugins/vite-plugin/lifecycle-and-hmr.test.ts","../src/plugins/vite-plugin/module-generation.test.ts","../src/plugins/vite-plugin/module-invalidation.ts","../src/plugins/vite-plugin/test-utils.ts","../src/plugins/vite-plugin/transform-guards.test.ts","../src/plugins/vite-plugin/visualization-option.test.ts"],"version":"6.0.3"}
1
+ {"root":["../src/cli.test.ts","../src/cli.ts","../src/entry-points.test.ts","../src/fixture-subpaths.test.ts","../src/generate.test.ts","../src/generate.ts","../src/rollup.ts","../src/rspack.ts","../src/runtime.ts","../src/scopes.ts","../src/vite.ts","../src/webpack.ts","../src/lib/container.factories-scoped.test.ts","../src/lib/container.factories.test.ts","../src/lib/container.identifiers.test.ts","../src/lib/container.internals.test.ts","../src/lib/container.test.ts","../src/lib/container.testing-features.test.ts","../src/lib/container.ts","../src/lib/decorators.runtime.test.ts","../src/lib/decorators.test-d.ts","../src/lib/decorators.ts","../src/lib/dependency-error.ts","../src/lib/env-detection.test.ts","../src/lib/env-detection.ts","../src/lib/lazy-retry.test.ts","../src/lib/lazy.ts","../src/lib/providers.test.ts","../src/lib/providers.ts","../src/lib/scope.ts","../src/lib/scopes.test.ts","../src/lib/service-identifiers.test.ts","../src/lib/service-identifiers.ts","../src/lib/tokens.test.ts","../src/lib/types.ts","../src/plugins/consumer-plugin.ts","../src/plugins/webpack-like-plugin.test.ts","../src/plugins/webpack-like-plugin.ts","../src/plugins/core/codegen.test.ts","../src/plugins/core/codegen.ts","../src/plugins/core/container-loader.test.ts","../src/plugins/core/container-loader.ts","../src/plugins/core/decorators.helpers.test.ts","../src/plugins/core/decorators.ts","../src/plugins/core/discovery-runtime.ts","../src/plugins/core/discovery-store.test.ts","../src/plugins/core/discovery-store.ts","../src/plugins/core/generation-inputs.ts","../src/plugins/core/identifier-resolver.test.ts","../src/plugins/core/identifier-resolver.ts","../src/plugins/core/lazy-utils.ts","../src/plugins/core/lazy.helpers.test.ts","../src/plugins/core/lazy.ts","../src/plugins/core/manifest-utils.ts","../src/plugins/core/manifest-utils.validation.test.ts","../src/plugins/core/scanner.test.ts","../src/plugins/core/scanner.ts","../src/plugins/core/scopes-validation.test.ts","../src/plugins/core/scopes-validation.ts","../src/plugins/core/types.ts","../src/plugins/core/utils.ts","../src/plugins/core/utils.walk.test.ts","../src/plugins/core/utils.write.test.ts","../src/plugins/core/visualization-utils.ts","../src/plugins/core/visualizer.test.ts","../src/plugins/core/visualizer.ts","../src/plugins/rollup-plugin/barrel-exports.test.ts","../src/plugins/rollup-plugin/barrel-exports.ts","../src/plugins/rollup-plugin/build-utils.test.ts","../src/plugins/rollup-plugin/build-utils.ts","../src/plugins/rollup-plugin/dependency-resolution.test.ts","../src/plugins/rollup-plugin/dependency-resolution.ts","../src/plugins/rollup-plugin/index.test.ts","../src/plugins/rollup-plugin/index.ts","../src/plugins/rollup-plugin/manifest-deps.test.ts","../src/plugins/rollup-plugin/manifest-deps.ts","../src/plugins/rollup-plugin/package-exports.test.ts","../src/plugins/rollup-plugin/package-exports.ts","../src/plugins/rollup-plugin/types.ts","../src/plugins/vite-plugin/duplicate-registrations.test.ts","../src/plugins/vite-plugin/index.ts","../src/plugins/vite-plugin/lazy-services.test.ts","../src/plugins/vite-plugin/lifecycle-and-hmr.test.ts","../src/plugins/vite-plugin/module-generation.test.ts","../src/plugins/vite-plugin/module-invalidation.ts","../src/plugins/vite-plugin/options-metadata.test.ts","../src/plugins/vite-plugin/test-utils.ts","../src/plugins/vite-plugin/transform-guards.test.ts","../src/plugins/vite-plugin/visualization-option.test.ts"],"version":"6.0.3"}
package/dist/vite.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- import { AlloyPluginOptions, alloy } from "./plugins/vite-plugin/index.js";
1
+ import { AlloyPluginOptions } from "./plugins/consumer-plugin.js";
2
+ import { alloy } from "./plugins/vite-plugin/index.js";
2
3
  export { type AlloyPluginOptions, alloy, alloy as default };
@@ -0,0 +1,7 @@
1
+ import { AlloyPluginOptions } from "./plugins/consumer-plugin.js";
2
+ import { AlloyWebpackLikePlugin } from "./plugins/webpack-like-plugin.js";
3
+
4
+ //#region src/webpack.d.ts
5
+ declare function alloy(options?: AlloyPluginOptions): AlloyWebpackLikePlugin;
6
+ //#endregion
7
+ export { type AlloyPluginOptions, alloy, alloy as default };
@@ -0,0 +1,10 @@
1
+ import { createWebpackLikeAlloyPlugin } from "./plugins/webpack-like-plugin.js";
2
+ //#region src/webpack.ts
3
+ function alloy(options = {}) {
4
+ return createWebpackLikeAlloyPlugin(options, {
5
+ name: "alloy-di-webpack",
6
+ cacheFileName: "webpack-virtual-container.js"
7
+ });
8
+ }
9
+ //#endregion
10
+ export { alloy, alloy as default };
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "alloy-di",
3
- "version": "1.5.0",
4
- "description": "A build-time dependency injection plugin for Vite",
3
+ "version": "2.0.0",
4
+ "description": "A build-time dependency injection plugin for TypeScript apps",
5
5
  "keywords": [
6
6
  "dependency-injection",
7
7
  "di",
8
+ "rspack",
8
9
  "typescript",
9
10
  "vite",
10
- "vite-plugin"
11
+ "vite-plugin",
12
+ "webpack"
11
13
  ],
12
14
  "homepage": "https://alloy-di.dev",
13
15
  "license": "MIT",
@@ -16,15 +18,21 @@
16
18
  "type": "git",
17
19
  "url": "https://github.com/ciddan/alloy-di/tree/main/packages/alloy"
18
20
  },
21
+ "bin": {
22
+ "alloy": "./bin/alloy.js"
23
+ },
19
24
  "files": [
25
+ "bin",
20
26
  "dist",
21
27
  "README.md"
22
28
  ],
23
29
  "type": "module",
24
30
  "sideEffects": false,
25
- "module": "./dist/index.mjs",
26
- "types": "./dist/index.d.ts",
27
31
  "exports": {
32
+ "./generate": {
33
+ "types": "./dist/generate.d.ts",
34
+ "import": "./dist/generate.js"
35
+ },
28
36
  "./runtime": {
29
37
  "types": "./dist/runtime.d.ts",
30
38
  "import": "./dist/runtime.js"
@@ -37,13 +45,17 @@
37
45
  "types": "./dist/vite.d.ts",
38
46
  "import": "./dist/vite.js"
39
47
  },
48
+ "./webpack": {
49
+ "types": "./dist/webpack.d.ts",
50
+ "import": "./dist/webpack.js"
51
+ },
52
+ "./rspack": {
53
+ "types": "./dist/rspack.d.ts",
54
+ "import": "./dist/rspack.js"
55
+ },
40
56
  "./rollup": {
41
57
  "types": "./dist/rollup.d.ts",
42
58
  "import": "./dist/rollup.js"
43
- },
44
- "./test": {
45
- "types": "./dist/test.d.ts",
46
- "import": "./dist/test.js"
47
59
  }
48
60
  },
49
61
  "publishConfig": {
@@ -57,19 +69,23 @@
57
69
  "devDependencies": {
58
70
  "@rollup/plugin-typescript": "^12.3.0",
59
71
  "rimraf": "^6.1.3",
60
- "rolldown": "1.1.0",
72
+ "rolldown": "^1.1.0",
61
73
  "rolldown-plugin-dts": "^0.25.2"
62
74
  },
63
75
  "peerDependencies": {
76
+ "@rspack/core": "^1.0.0 || ^2.0.0",
64
77
  "typescript": ">=5.0.0",
65
78
  "vite": "^7.0.0 || ^8.0.0",
66
- "vitest": ">=4.0.14 <5.0.0"
79
+ "webpack": "^5.0.0"
67
80
  },
68
81
  "peerDependenciesMeta": {
82
+ "@rspack/core": {
83
+ "optional": true
84
+ },
69
85
  "vite": {
70
86
  "optional": true
71
87
  },
72
- "vitest": {
88
+ "webpack": {
73
89
  "optional": true
74
90
  }
75
91
  },
@@ -1,12 +0,0 @@
1
- import { Newable } from "../types.js";
2
- import { vi } from "vitest";
3
-
4
- //#region src/lib/testing/mocking.d.ts
5
- type MethodKeys<T> = { [K in keyof T]: T[K] extends ((...args: any[]) => any) ? K : never }[keyof T];
6
- /** Typed mock shape returned for class auto-mocking. */
7
- type MockOf<T> = Partial<T> & {
8
- /** Map of method name -> vi spy function */spies: Record<Extract<MethodKeys<T>, string>, ReturnType<typeof vi.fn>>; /** Original constructor reference for introspection */
9
- __target: Newable<T>;
10
- };
11
- //#endregion
12
- export { MockOf };