
Security News
GitHub Actions Checkout Now Blocks Risky pull_request_target Checkouts
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.
@fluojs/core
Advanced tools
Shared contracts, decorators, and metadata helpers that form the foundation of every Fluo package.
English 한국어
Shared contracts, standard decorators, and metadata primitives that every fluo package builds on.
npm install @fluojs/core
Use this package when you are:
Every fluo application starts with module metadata declared through @fluojs/core.
import { Global, Inject, Module, Scope } from '@fluojs/core';
@Global()
@Module({
providers: [DatabaseService],
exports: [DatabaseService],
})
class CoreModule {}
@Module({
imports: [CoreModule],
providers: [UserService],
})
class AppModule {}
@Inject(DatabaseService)
@Scope('singleton')
class UserService {
constructor(private readonly db: DatabaseService) {}
}
fluo uses TC39 standard decorators. You do not need experimentalDecorators: true or emitDecoratorMetadata: true to use @Module, @Inject, @Global, or @Scope.
Core metadata is written through fluo-owned stores and TC39 Symbol.metadata integration points, never through reflect-metadata or compiler-emitted design types. Importing @fluojs/core does not install a global Symbol.metadata polyfill. Call ensureMetadataSymbol() at test or bootstrap boundaries when a runtime needs the polyfill installed before evaluating custom standard decorators.
import { ensureMetadataSymbol } from '@fluojs/core';
ensureMetadataSymbol();
@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.
const CONFIG_TOKEN = Symbol('CONFIG_TOKEN');
@Inject(CONFIG_TOKEN)
class UsesConfigValue {
constructor(private readonly config: Config) {}
}
Pass multiple tokens as variadic arguments such as @Inject(A, B).
The legacy array form @Inject([A, B]) remains normalized during the migration window, but new code should prefer the variadic form so constructor tokens stay aligned with standard decorator usage.
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.
Application code should import public decorators and ensureMetadataSymbol() from @fluojs/core. The @fluojs/core/internal subpath is reserved for fluo packages that need to read metadata records, merge explicit stores with Symbol.metadata, or build framework-level decorators. Standard metadata bag helpers handle mixed-era lookups across current/native Symbol.metadata and the fallback symbol: own metadata from either era overrides inherited metadata from either era for the same key, while inherited keys from parent constructors remain visible when the child owns a different key. To reduce DI and module-graph hot-path allocations, getModuleMetadata(), getOwnClassDiMetadata(), getInheritedClassDiMetadata(), and getClassDiMetadata() return frozen snapshots and may reuse the same reference between writes. Treat those results, their collection fields, and module provider descriptor wrappers, and middleware route-config wrappers (including their routes arrays) as immutable. useValue payload objects and runtime middleware/guard/interceptor instances remain mutable references and are not frozen by these snapshots. Other metadata readers keep their existing defensive-read behavior unless their own tests document stable-reference reuse.
import { getModuleMetadata } from '@fluojs/core/internal';
const metadata = getModuleMetadata(AppModule);
console.log(metadata.providers);
AsyncModuleOptions<T> is the standard contract for modules that require asynchronous initialization, such as those relying on an external ConfigService.
import { AsyncModuleOptions, MaybePromise, Token } from '@fluojs/core';
interface Config {
apiKey: string;
}
class EmailModule {
static forRootAsync(options: AsyncModuleOptions<Config>) {
return {
module: EmailModule,
providers: [
{
provide: 'CONFIG',
useFactory: options.useFactory,
inject: options.inject,
},
],
};
}
}
The @Scope decorator controls the lifetime of a provider instance. fluo supports three distinct levels:
singleton (default): A single instance is shared across the entire application.request: A new instance is created for every incoming HTTP request.transient: A new instance is created every time it is injected into a consumer.import { Scope } from '@fluojs/core';
@Scope('request')
class TransactionContext {}
@Scope('transient')
class Logger {}
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.
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.
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.
Module, Global, Inject, ScopeFluoError, InvariantError, FluoCodeErrorensureMetadataSymbolConstructor<T>, Token<T>, MaybePromise<T>, AsyncModuleOptions@fluojs/core/internal@fluojs/di: resolves the tokens and scopes defined here into live instances@fluojs/runtime: compiles the module graph from @Module metadata@fluojs/http: consumes controller and route metadata built on the same primitivespackages/core/src/index.tspackages/core/src/decorators.tspackages/core/src/metadata.tsFAQs
Shared contracts, decorators, and metadata helpers that form the foundation of every Fluo package.
The npm package @fluojs/core receives a total of 70 weekly downloads. As such, @fluojs/core popularity was classified as not popular.
We found that @fluojs/core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub Actions checkout now blocks risky pull_request_target checkouts by default to help prevent pwn request supply chain attacks.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.