@fluojs/core 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/LICENSE +21 -0
  2. package/README.ko.md +165 -0
  3. package/README.md +167 -0
  4. package/dist/decorators.d.ts +51 -0
  5. package/dist/decorators.d.ts.map +1 -0
  6. package/dist/decorators.js +79 -0
  7. package/dist/errors.d.ts +60 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +89 -0
  10. package/dist/index.d.ts +5 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +3 -0
  13. package/dist/internal.d.ts +3 -0
  14. package/dist/internal.d.ts.map +1 -0
  15. package/dist/internal.js +2 -0
  16. package/dist/metadata/class-di.d.ts +30 -0
  17. package/dist/metadata/class-di.d.ts.map +1 -0
  18. package/dist/metadata/class-di.js +72 -0
  19. package/dist/metadata/controller-route.d.ts +7 -0
  20. package/dist/metadata/controller-route.d.ts.map +1 -0
  21. package/dist/metadata/controller-route.js +109 -0
  22. package/dist/metadata/injection.d.ts +5 -0
  23. package/dist/metadata/injection.d.ts.map +1 -0
  24. package/dist/metadata/injection.js +31 -0
  25. package/dist/metadata/module.d.ts +16 -0
  26. package/dist/metadata/module.d.ts.map +1 -0
  27. package/dist/metadata/module.js +57 -0
  28. package/dist/metadata/shared.d.ts +128 -0
  29. package/dist/metadata/shared.d.ts.map +1 -0
  30. package/dist/metadata/shared.js +231 -0
  31. package/dist/metadata/store.d.ts +16 -0
  32. package/dist/metadata/store.d.ts.map +1 -0
  33. package/dist/metadata/store.js +25 -0
  34. package/dist/metadata/symbol-metadata-polyfill.d.ts +2 -0
  35. package/dist/metadata/symbol-metadata-polyfill.d.ts.map +1 -0
  36. package/dist/metadata/symbol-metadata-polyfill.js +4 -0
  37. package/dist/metadata/types.d.ts +210 -0
  38. package/dist/metadata/types.d.ts.map +1 -0
  39. package/dist/metadata/types.js +1 -0
  40. package/dist/metadata/validation.d.ts +11 -0
  41. package/dist/metadata/validation.d.ts.map +1 -0
  42. package/dist/metadata/validation.js +93 -0
  43. package/dist/metadata.d.ts +9 -0
  44. package/dist/metadata.d.ts.map +1 -0
  45. package/dist/metadata.js +7 -0
  46. package/dist/types.d.ts +43 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +1 -0
  49. package/dist/utils.d.ts +19 -0
  50. package/dist/utils.d.ts.map +1 -0
  51. package/dist/utils.js +103 -0
  52. package/package.json +52 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 fluo contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ko.md ADDED
@@ -0,0 +1,165 @@
1
+ # @fluojs/core
2
+
3
+ <p><a href="./README.md"><kbd>English</kbd></a> <strong><kbd>한국어</kbd></strong></p>
4
+
5
+ 모든 fluo 패키지가 공통으로 사용하는 표준 데코레이터, 공유 계약, 메타데이터 프리미티브를 제공하는 기반 패키지입니다.
6
+
7
+ ## 목차
8
+
9
+ - [설치](#설치)
10
+ - [사용 시점](#사용-시점)
11
+ - [빠른 시작](#빠른-시작)
12
+ - [주요 기능](#주요-기능)
13
+ - [문제 해결](#문제-해결)
14
+ - [공개 API](#공개-api)
15
+ - [관련 패키지](#관련-패키지)
16
+ - [예제 소스](#예제-소스)
17
+
18
+ ## 설치
19
+
20
+ ```bash
21
+ npm install @fluojs/core
22
+ ```
23
+
24
+ ## 사용 시점
25
+
26
+ - 표준 데코레이터로 모듈, 프로바이더, 컨트롤러를 선언할 때
27
+ - fluo 모듈 그래프에 참여하는 프레임워크 확장이나 내부 라이브러리를 만들 때
28
+ - `Constructor<T>`, `Token<T>`, 프레임워크 공통 에러 같은 기본 타입과 계약을 직접 다뤄야 할 때
29
+
30
+ ## 빠른 시작
31
+
32
+ 모든 fluo 애플리케이션은 `@fluojs/core`가 기록하는 모듈 메타데이터에서 시작합니다.
33
+
34
+ ```ts
35
+ import { Global, Inject, Module, Scope } from '@fluojs/core';
36
+
37
+ @Global()
38
+ @Module({
39
+ providers: [DatabaseService],
40
+ exports: [DatabaseService],
41
+ })
42
+ class CoreModule {}
43
+
44
+ @Module({
45
+ imports: [CoreModule],
46
+ providers: [UserService],
47
+ })
48
+ class AppModule {}
49
+
50
+ @Inject(DatabaseService)
51
+ @Scope('singleton')
52
+ class UserService {
53
+ constructor(private readonly db: DatabaseService) {}
54
+ }
55
+ ```
56
+
57
+ ## 주요 기능
58
+
59
+ ### TC39 데코레이터를 사용하는 표준 데코레이터
60
+
61
+ fluo는 TC39 표준 데코레이터를 사용하므로 `experimentalDecorators: true`나 `emitDecoratorMetadata: true`에 의존하지 않습니다.
62
+
63
+ ### 명시적인 의존성 메타데이터
64
+
65
+ `@Inject(...)`는 리플렉션 기반 추론 대신 코드 안에서 의존성 토큰을 직접 드러냅니다. 상속된 constructor 토큰을 명시적으로 비우려면 `@Inject()`를 사용하면 됩니다.
66
+
67
+ ```ts
68
+ const CONFIG_TOKEN = Symbol('CONFIG_TOKEN');
69
+
70
+ @Inject(CONFIG_TOKEN)
71
+ class UsesConfigValue {
72
+ constructor(private readonly config: Config) {}
73
+ }
74
+ ```
75
+
76
+ 여러 토큰을 지정할 때는 `@Inject(A, B)`처럼 variadic 호출을 사용하면 됩니다.
77
+
78
+ ### 형제 패키지를 위한 공용 메타데이터 헬퍼
79
+
80
+ 내부 메타데이터 reader/writer는 `@fluojs/core/internal` 아래에 있으며, `@fluojs/di`, `@fluojs/http`, `@fluojs/runtime` 같은 패키지들이 같은 메타데이터 모델을 공유할 수 있게 합니다.
81
+
82
+ ```ts
83
+ import { getModuleMetadata } from '@fluojs/core/internal';
84
+
85
+ const metadata = getModuleMetadata(AppModule);
86
+ console.log(metadata.providers);
87
+ ```
88
+
89
+ ### 동적 설정을 위한 AsyncModuleOptions
90
+
91
+ `AsyncModuleOptions<T>`는 외부 `ConfigService` 등에 의존하여 비동기적으로 초기화가 필요한 모듈을 위한 표준 계약입니다.
92
+
93
+ ```ts
94
+ import { AsyncModuleOptions, MaybePromise, Token } from '@fluojs/core';
95
+
96
+ interface Config {
97
+ apiKey: string;
98
+ }
99
+
100
+ class EmailModule {
101
+ static forRootAsync(options: AsyncModuleOptions<Config>) {
102
+ return {
103
+ module: EmailModule,
104
+ providers: [
105
+ {
106
+ provide: 'CONFIG',
107
+ useFactory: options.useFactory,
108
+ inject: options.inject,
109
+ },
110
+ ],
111
+ };
112
+ }
113
+ }
114
+ ```
115
+
116
+ ### @Scope를 이용한 생명주기 제어
117
+
118
+ `@Scope` 데코레이터는 프로바이더 인스턴스의 생존 범위를 결정합니다. fluo는 세 가지 스코프를 지원합니다.
119
+
120
+ - `singleton` (기본값): 애플리케이션 전체에서 단 하나의 인스턴스를 공유합니다.
121
+ - `request`: 각 HTTP 요청마다 새로운 인스턴스를 생성합니다.
122
+ - `transient`: 주입될 때마다 매번 새로운 인스턴스를 생성합니다.
123
+
124
+ ```ts
125
+ import { Scope } from '@fluojs/core';
126
+
127
+ @Scope('request')
128
+ class TransactionContext {}
129
+
130
+ @Scope('transient')
131
+ class Logger {}
132
+ ```
133
+
134
+ ## 문제 해결
135
+
136
+ ### 데코레이터 메타데이터를 찾을 수 없음
137
+
138
+ 표준 TC39 데코레이터를 사용하고 있는지 확인하세요. fluo는 `reflect-metadata`를 사용하지 않습니다. NestJS에서 전환하는 경우, `tsconfig.json`에서 `experimentalDecorators`와 `emitDecoratorMetadata` 설정을 제거하여 표준 데코레이터 동작과 충돌하지 않도록 하세요.
139
+
140
+ ### 모듈 간 순환 참조
141
+
142
+ 두 모듈이 서로를 import하면 모듈 그래프를 컴파일할 수 없습니다. 공통 의존성을 담은 "Common"이나 "Core" 모듈을 만들어 분리하거나, 공유 로직을 별도 패키지로 추출하세요.
143
+
144
+ ### 추상 클래스에 대한 @Inject 누락
145
+
146
+ 표준 데코레이터는 추상 클래스나 인터페이스의 타입을 자동으로 추론할 수 없습니다. 구체적인 클래스 생성자가 아닌 대상을 주입할 때는 반드시 `@Inject(TOKEN)`을 사용하세요.
147
+
148
+ ## 공개 API
149
+
150
+ - **데코레이터**: `Module`, `Global`, `Inject`, `Scope`
151
+ - **에러**: `FluoError`, `InvariantError`, `FluoCodeError`
152
+ - **타입**: `Constructor<T>`, `Token<T>`, `MaybePromise<T>`, `AsyncModuleOptions`
153
+ - **내부 서브패스**: `@fluojs/core/internal`을 통한 메타데이터 헬퍼
154
+
155
+ ## 관련 패키지
156
+
157
+ - `@fluojs/di`: 여기서 선언된 토큰과 스코프를 실제 인스턴스로 해석합니다.
158
+ - `@fluojs/runtime`: `@Module` 메타데이터로 모듈 그래프를 컴파일합니다.
159
+ - `@fluojs/http`: 동일한 메타데이터 프리미티브 위에서 컨트롤러와 라우트 정보를 읽습니다.
160
+
161
+ ## 예제 소스
162
+
163
+ - `packages/core/src/index.ts`
164
+ - `packages/core/src/decorators.ts`
165
+ - `packages/core/src/metadata.ts`
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # @fluojs/core
2
+
3
+ <p><strong><kbd>English</kbd></strong> <a href="./README.ko.md"><kbd>한국어</kbd></a></p>
4
+
5
+ Shared contracts, standard decorators, and metadata primitives that every fluo package builds on.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Installation](#installation)
10
+ - [When to Use](#when-to-use)
11
+ - [Quick Start](#quick-start)
12
+ - [Key Capabilities](#key-capabilities)
13
+ - [Troubleshooting](#troubleshooting)
14
+ - [Public API](#public-api)
15
+ - [Related Packages](#related-packages)
16
+ - [Example Sources](#example-sources)
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @fluojs/core
22
+ ```
23
+
24
+ ## When to Use
25
+
26
+ Use this package when you are:
27
+
28
+ - defining modules, providers, or controllers with fluo's standard decorators
29
+ - building framework extensions that need to participate in the module graph
30
+ - working with shared framework errors, tokens, or constructor-based utility types
31
+
32
+ ## Quick Start
33
+
34
+ Every fluo application starts with module metadata declared through `@fluojs/core`.
35
+
36
+ ```ts
37
+ import { Global, Inject, Module, Scope } from '@fluojs/core';
38
+
39
+ @Global()
40
+ @Module({
41
+ providers: [DatabaseService],
42
+ exports: [DatabaseService],
43
+ })
44
+ class CoreModule {}
45
+
46
+ @Module({
47
+ imports: [CoreModule],
48
+ providers: [UserService],
49
+ })
50
+ class AppModule {}
51
+
52
+ @Inject(DatabaseService)
53
+ @Scope('singleton')
54
+ class UserService {
55
+ constructor(private readonly db: DatabaseService) {}
56
+ }
57
+ ```
58
+
59
+ ## Key Capabilities
60
+
61
+ ### Standard decorators with TC39 decorator support
62
+
63
+ fluo uses TC39 standard decorators. You do not need `experimentalDecorators: true` or `emitDecoratorMetadata: true` to use `@Module`, `@Inject`, `@Global`, or `@Scope`.
64
+
65
+ ### Explicit dependency metadata
66
+
67
+ `@Inject(...)` keeps dependency wiring visible in code instead of relying on emitted reflection metadata. Call `@Inject()` when you want to record an explicit empty override for inherited constructor tokens.
68
+
69
+ ```ts
70
+ const CONFIG_TOKEN = Symbol('CONFIG_TOKEN');
71
+
72
+ @Inject(CONFIG_TOKEN)
73
+ class UsesConfigValue {
74
+ constructor(private readonly config: Config) {}
75
+ }
76
+ ```
77
+
78
+ Pass multiple tokens as variadic arguments such as `@Inject(A, B)`.
79
+
80
+ ### Shared metadata helpers for sibling packages
81
+
82
+ Internal readers and writers live under `@fluojs/core/internal`, which is how packages like `@fluojs/di`, `@fluojs/http`, and `@fluojs/runtime` consume the same metadata model.
83
+
84
+ ```ts
85
+ import { getModuleMetadata } from '@fluojs/core/internal';
86
+
87
+ const metadata = getModuleMetadata(AppModule);
88
+ console.log(metadata.providers);
89
+ ```
90
+
91
+ ### AsyncModuleOptions for dynamic configuration
92
+
93
+ `AsyncModuleOptions<T>` is the standard contract for modules that require asynchronous initialization, such as those relying on an external `ConfigService`.
94
+
95
+ ```ts
96
+ import { AsyncModuleOptions, MaybePromise, Token } from '@fluojs/core';
97
+
98
+ interface Config {
99
+ apiKey: string;
100
+ }
101
+
102
+ class EmailModule {
103
+ static forRootAsync(options: AsyncModuleOptions<Config>) {
104
+ return {
105
+ module: EmailModule,
106
+ providers: [
107
+ {
108
+ provide: 'CONFIG',
109
+ useFactory: options.useFactory,
110
+ inject: options.inject,
111
+ },
112
+ ],
113
+ };
114
+ }
115
+ }
116
+ ```
117
+
118
+ ### Lifecycle scopes with @Scope
119
+
120
+ The `@Scope` decorator controls the lifetime of a provider instance. fluo supports three distinct levels:
121
+
122
+ - `singleton` (default): A single instance is shared across the entire application.
123
+ - `request`: A new instance is created for every incoming HTTP request.
124
+ - `transient`: A new instance is created every time it is injected into a consumer.
125
+
126
+ ```ts
127
+ import { Scope } from '@fluojs/core';
128
+
129
+ @Scope('request')
130
+ class TransactionContext {}
131
+
132
+ @Scope('transient')
133
+ class Logger {}
134
+ ```
135
+
136
+ ## Troubleshooting
137
+
138
+ ### Decorator metadata not found
139
+
140
+ Ensure you are using standard TC39 decorators. fluo does not use `reflect-metadata`. If you are migrating from NestJS, remove `experimentalDecorators` and `emitDecoratorMetadata` from your `tsconfig.json` to prevent conflicts with standard decorator behavior.
141
+
142
+ ### Circular dependencies in modules
143
+
144
+ If two modules import each other, the module graph cannot be compiled. Use a shared "Common" or "Core" module to house providers that both modules depend on, or refactor the shared logic into a separate package.
145
+
146
+ ### Missing @Inject for abstract classes
147
+
148
+ Standard decorators cannot automatically infer types for abstract classes or interfaces. Always use `@Inject(TOKEN)` when injecting anything that is not a concrete class constructor.
149
+
150
+ ## Public API
151
+
152
+ - **Decorators**: `Module`, `Global`, `Inject`, `Scope`
153
+ - **Errors**: `FluoError`, `InvariantError`, `FluoCodeError`
154
+ - **Types**: `Constructor<T>`, `Token<T>`, `MaybePromise<T>`, `AsyncModuleOptions`
155
+ - **Internal subpath**: metadata helpers via `@fluojs/core/internal`
156
+
157
+ ## Related Packages
158
+
159
+ - `@fluojs/di`: resolves the tokens and scopes defined here into live instances
160
+ - `@fluojs/runtime`: compiles the module graph from `@Module` metadata
161
+ - `@fluojs/http`: consumes controller and route metadata built on the same primitives
162
+
163
+ ## Example Sources
164
+
165
+ - `packages/core/src/index.ts`
166
+ - `packages/core/src/decorators.ts`
167
+ - `packages/core/src/metadata.ts`
@@ -0,0 +1,51 @@
1
+ import { type ClassDiMetadata, type ModuleMetadata } from './metadata.js';
2
+ import type { Token } from './types.js';
3
+ type StandardClassDecoratorFn = (value: Function, context: ClassDecoratorContext) => void;
4
+ type TupleOnly<T extends readonly unknown[]> = number extends T['length'] ? never : T;
5
+ /**
6
+ * Declares module-level metadata (`imports`, `providers`, `controllers`, `exports`, `global`) on a class.
7
+ *
8
+ * @param definition Module composition metadata consumed by the runtime module-graph compiler.
9
+ * @returns A standard class decorator that records the module contract on the target class.
10
+ */
11
+ export declare function Module(definition: ModuleMetadata): StandardClassDecoratorFn;
12
+ /**
13
+ * Marks the decorated module as global so its exported providers are visible without explicit imports.
14
+ *
15
+ * @returns A standard class decorator that marks the target module as globally visible.
16
+ */
17
+ export declare function Global(): StandardClassDecoratorFn;
18
+ /**
19
+ * Defines explicit constructor injection tokens for the decorated class.
20
+ *
21
+ * Passing tokens variadically (`@Inject(A, B)`) is the canonical API. Calling `@Inject()` records an
22
+ * explicit empty inject list so subclasses can intentionally clear inherited constructor tokens.
23
+ * During the staged migration window, the legacy array form (`@Inject([A, B])`) is still normalized.
24
+ *
25
+ * @param tokens Constructor-parameter token list used by `@fluojs/di` during dependency resolution.
26
+ * @returns A standard class decorator that stores explicit injection metadata on the target class.
27
+ */
28
+ export declare function Inject(): StandardClassDecoratorFn;
29
+ /**
30
+ * Defines explicit constructor injection tokens for the decorated class.
31
+ *
32
+ * @param tokens Constructor-parameter token list used by `@fluojs/di` during dependency resolution.
33
+ * @returns A standard class decorator that stores explicit injection metadata on the target class.
34
+ */
35
+ export declare function Inject<const TTokens extends readonly Token[]>(...tokens: TupleOnly<TTokens>): StandardClassDecoratorFn;
36
+ /**
37
+ * Defines explicit constructor injection tokens for the decorated class.
38
+ *
39
+ * @param tokens Constructor-parameter token list used by `@fluojs/di` during dependency resolution.
40
+ * @returns A standard class decorator that stores explicit injection metadata on the target class.
41
+ */
42
+ export declare function Inject(tokens: readonly Token[]): StandardClassDecoratorFn;
43
+ /**
44
+ * Sets the provider lifecycle scope used by the DI container.
45
+ *
46
+ * @param scope Provider lifetime strategy (`singleton`, `request`, or `transient`).
47
+ * @returns A standard class decorator that stores scope metadata on the target class.
48
+ */
49
+ export declare function Scope(scope: NonNullable<ClassDiMetadata['scope']>): StandardClassDecoratorFn;
50
+ export {};
51
+ //# sourceMappingURL=decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,KAAK,wBAAwB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AAE1F,KAAK,SAAS,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,IAAI,MAAM,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAEtF;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,UAAU,EAAE,cAAc,GAAG,wBAAwB,CAI3E;AAED;;;;GAIG;AACH,wBAAgB,MAAM,IAAI,wBAAwB,CAIjD;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,IAAI,wBAAwB,CAAC;AACnD;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,KAAK,CAAC,OAAO,SAAS,SAAS,KAAK,EAAE,EAC3D,GAAG,MAAM,EAAE,SAAS,CAAC,OAAO,CAAC,GAC5B,wBAAwB,CAAC;AAC5B;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,GAAG,wBAAwB,CAAC;AAiB3E;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,GAAG,wBAAwB,CAI5F"}
@@ -0,0 +1,79 @@
1
+ import { defineClassDiMetadata, defineModuleMetadata } from './metadata.js';
2
+ /**
3
+ * Declares module-level metadata (`imports`, `providers`, `controllers`, `exports`, `global`) on a class.
4
+ *
5
+ * @param definition Module composition metadata consumed by the runtime module-graph compiler.
6
+ * @returns A standard class decorator that records the module contract on the target class.
7
+ */
8
+ export function Module(definition) {
9
+ return target => {
10
+ defineModuleMetadata(target, definition);
11
+ };
12
+ }
13
+
14
+ /**
15
+ * Marks the decorated module as global so its exported providers are visible without explicit imports.
16
+ *
17
+ * @returns A standard class decorator that marks the target module as globally visible.
18
+ */
19
+ export function Global() {
20
+ return target => {
21
+ defineModuleMetadata(target, {
22
+ global: true
23
+ });
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Defines explicit constructor injection tokens for the decorated class.
29
+ *
30
+ * Passing tokens variadically (`@Inject(A, B)`) is the canonical API. Calling `@Inject()` records an
31
+ * explicit empty inject list so subclasses can intentionally clear inherited constructor tokens.
32
+ * During the staged migration window, the legacy array form (`@Inject([A, B])`) is still normalized.
33
+ *
34
+ * @param tokens Constructor-parameter token list used by `@fluojs/di` during dependency resolution.
35
+ * @returns A standard class decorator that stores explicit injection metadata on the target class.
36
+ */
37
+
38
+ /**
39
+ * Defines explicit constructor injection tokens for the decorated class.
40
+ *
41
+ * @param tokens Constructor-parameter token list used by `@fluojs/di` during dependency resolution.
42
+ * @returns A standard class decorator that stores explicit injection metadata on the target class.
43
+ */
44
+
45
+ /**
46
+ * Defines explicit constructor injection tokens for the decorated class.
47
+ *
48
+ * @param tokens Constructor-parameter token list used by `@fluojs/di` during dependency resolution.
49
+ * @returns A standard class decorator that stores explicit injection metadata on the target class.
50
+ */
51
+
52
+ /**
53
+ * Defines explicit constructor injection tokens for the decorated class.
54
+ *
55
+ * @param tokensOrList Constructor-parameter token list used by `@fluojs/di` during dependency resolution.
56
+ * @returns A standard class decorator that stores explicit injection metadata on the target class.
57
+ */
58
+ export function Inject(...tokensOrList) {
59
+ const tokens = tokensOrList.length === 1 && Array.isArray(tokensOrList[0]) ? [...tokensOrList[0]] : [...tokensOrList];
60
+ return target => {
61
+ defineClassDiMetadata(target, {
62
+ inject: [...tokens]
63
+ });
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Sets the provider lifecycle scope used by the DI container.
69
+ *
70
+ * @param scope Provider lifetime strategy (`singleton`, `request`, or `transient`).
71
+ * @returns A standard class decorator that stores scope metadata on the target class.
72
+ */
73
+ export function Scope(scope) {
74
+ return target => {
75
+ defineClassDiMetadata(target, {
76
+ scope
77
+ });
78
+ };
79
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Options for creating a {@link FluoError}.
3
+ */
4
+ export interface FluoErrorOptions {
5
+ /** Stable error code for programmatic identification. */
6
+ code?: string;
7
+ /** Original error that caused this failure. */
8
+ cause?: unknown;
9
+ /** Additional structured metadata for diagnostics. */
10
+ meta?: Record<string, unknown>;
11
+ }
12
+ /**
13
+ * Base error class for all fluo framework errors.
14
+ */
15
+ export declare class FluoError extends Error {
16
+ /** Stable error code. */
17
+ readonly code: string;
18
+ /** Additional structured metadata. */
19
+ readonly meta?: Record<string, unknown>;
20
+ /**
21
+ * Creates a new FluoError.
22
+ *
23
+ * @param message Human-readable error message.
24
+ * @param options Optional error configuration including `code`, `cause`, and `meta`.
25
+ */
26
+ constructor(message: string, options?: FluoErrorOptions);
27
+ }
28
+ /**
29
+ * Error thrown when a system invariant is violated.
30
+ */
31
+ export declare class InvariantError extends FluoError {
32
+ /**
33
+ * Creates an invariant error.
34
+ *
35
+ * @param message Human-readable description of the violation.
36
+ * @param options Optional error configuration.
37
+ */
38
+ constructor(message: string, options?: Omit<FluoErrorOptions, 'code'>);
39
+ }
40
+ /**
41
+ * Abstract base class for errors that require a specific error code.
42
+ */
43
+ export declare abstract class FluoCodeError extends FluoError {
44
+ /**
45
+ * Creates a code-specific error.
46
+ *
47
+ * @param message Human-readable error message.
48
+ * @param code Programmatic error code.
49
+ * @param options Optional error configuration.
50
+ */
51
+ constructor(message: string, code: string, options?: Omit<FluoErrorOptions, 'code'>);
52
+ }
53
+ /**
54
+ * Formats a DI token into a human-readable string for error messages.
55
+ *
56
+ * @param token The token to format.
57
+ * @returns A string representation of the token.
58
+ */
59
+ export declare function formatTokenName(token: unknown): string;
60
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,yBAAyB;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAExC;;;;;OAKG;gBACS,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;CAgB5D;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAC3C;;;;;OAKG;gBACS,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAM;CAG1E;AAED;;GAEG;AACH,8BAAsB,aAAc,SAAQ,SAAS;IACnD;;;;;;OAMG;gBACS,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAM;CAGxF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAUtD"}
package/dist/errors.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Options for creating a {@link FluoError}.
3
+ */
4
+
5
+ /**
6
+ * Base error class for all fluo framework errors.
7
+ */
8
+ export class FluoError extends Error {
9
+ /** Stable error code. */
10
+ code;
11
+ /** Additional structured metadata. */
12
+ meta;
13
+
14
+ /**
15
+ * Creates a new FluoError.
16
+ *
17
+ * @param message Human-readable error message.
18
+ * @param options Optional error configuration including `code`, `cause`, and `meta`.
19
+ */
20
+ constructor(message, options = {}) {
21
+ super(message, options.cause instanceof Error ? {
22
+ cause: options.cause
23
+ } : undefined);
24
+ this.name = new.target.name;
25
+ this.code = options.code ?? 'FLUO_ERROR';
26
+ this.meta = options.meta;
27
+ if (!(options.cause instanceof Error) && options.cause !== undefined) {
28
+ Object.defineProperty(this, 'cause', {
29
+ configurable: true,
30
+ enumerable: false,
31
+ value: options.cause,
32
+ writable: true
33
+ });
34
+ }
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Error thrown when a system invariant is violated.
40
+ */
41
+ export class InvariantError extends FluoError {
42
+ /**
43
+ * Creates an invariant error.
44
+ *
45
+ * @param message Human-readable description of the violation.
46
+ * @param options Optional error configuration.
47
+ */
48
+ constructor(message, options = {}) {
49
+ super(message, {
50
+ ...options,
51
+ code: 'INVARIANT_ERROR'
52
+ });
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Abstract base class for errors that require a specific error code.
58
+ */
59
+ export class FluoCodeError extends FluoError {
60
+ /**
61
+ * Creates a code-specific error.
62
+ *
63
+ * @param message Human-readable error message.
64
+ * @param code Programmatic error code.
65
+ * @param options Optional error configuration.
66
+ */
67
+ constructor(message, code, options = {}) {
68
+ super(message, {
69
+ ...options,
70
+ code
71
+ });
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Formats a DI token into a human-readable string for error messages.
77
+ *
78
+ * @param token The token to format.
79
+ * @returns A string representation of the token.
80
+ */
81
+ export function formatTokenName(token) {
82
+ if (typeof token === 'function' && 'name' in token && token.name) {
83
+ return String(token.name);
84
+ }
85
+ if (typeof token === 'symbol') {
86
+ return token.toString();
87
+ }
88
+ return String(token);
89
+ }
@@ -0,0 +1,5 @@
1
+ export { Global, Inject, Module, Scope } from './decorators.js';
2
+ export { InvariantError, FluoCodeError, FluoError, formatTokenName, type FluoErrorOptions } from './errors.js';
3
+ export { ensureMetadataSymbol } from './metadata.js';
4
+ export type { AsyncModuleOptions, Constructor, MaybePromise, MetadataPropertyKey, MetadataSource, Token } from './types.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/G,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { Global, Inject, Module, Scope } from './decorators.js';
2
+ export { InvariantError, FluoCodeError, FluoError, formatTokenName } from './errors.js';
3
+ export { ensureMetadataSymbol } from './metadata.js';
@@ -0,0 +1,3 @@
1
+ export * from './metadata.js';
2
+ export { cloneWithFallback, fallbackClone } from './utils.js';
3
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './metadata.js';
2
+ export { cloneWithFallback, fallbackClone } from './utils.js';