- Add
react-native
export key, move upbrowser
key - Update packages
- Use default import for
fast-glob
- Rename
awilix.browser.js
toawilix.browser.mjs
, most tools prefer this - More
exports
conditions
- Fix browser build
- BREAKING: Bump TypeScript transpilation target for browser build from
ES5
toES2020
- Update packages
- Add
exports
field topackage.json
, allowing you to explicitly import the browser build usingimport { createContainer } from 'awilix/browser'
- Undo all
exports
changes as it broke downstream consumers
- Add
lib
to exports lists
- Add
default
entry in every export
- Add "exports" field to package.json
- BREAKING: Drop Node 14 support, add Node 22 to build matrix.
- Migrate to ESLint v9
- Upgrade packages
Node 14 is no longer officially supported, as it is not an active LTS anymore.
- Add back
createBuildResolver
andcreateDisposableResolver
exports (#358)
- Add back some type exports (#351)
- Add (optional, off by default) strict mode to enforce extra correctness checks in both resolution and registration (#349 by @fnimick)
- Reduce the publicly accessible API surface to only that which is needed to use Awilix. This is potentially a breaking change if you were using any of the internal type definitions (#349 by @fnimick)
- Upgrade packages
- Fix
aliasTo
to allow passingsymbol
(#342 by @zb-sj) - Migrate from TSLint to ESLint
- BREAKING CHANGE: Drop Node 12 support for real this time (updated the
engines
field)
- Upgrade packages
- Move CI from Travis to GitHub Actions
- BREAKING: Drop Node 12 support, add Node 18 to build matrix
- BREAKING: #300 Rename
awilix.module.js
toawilix.module.mjs
- #293 Update packages, including
fast-glob
Node 12 is no longer officially supported, as it is not an active LTS anymore.
I am not sure if this is actually a breaking change, but if someone is importing the module directly using the file name, then it would be.
- Use
LoadedModuleDescriptor
inNameFormatter
delegate parameter - Update packages
- #291 Fix
listModules
regression on Windows - Update packages
- #288 Don't use
Error.captureStackTrace
on unsupported platforms
- BREAKING: #286 Support
Symbol.toStringTag
. This should fix es5-shim/480. - Update packages
The Awilix Cradle's string representation when used by util.inspect
, .toJSON()
and others returned [AwilixContainer.cradle]
. This has been
changed to [object AwilixContainerCradle]
to align with other common string representations in JavaScript.
When using Object.prototype.toString.call(container.cradle)
, it would return [object Object]
. With this change, it now returns [object AwilixContainerCradle]
.
- #284 Use
fast-glob
instead ofglob
(Sebastian Plaza) - Update packages
Please see the list of breaking changes below.
- Update packages
- BREAKING: #198 Don't parse parameters from base class
- #270 Fix exponential performance slowdown for large containers
- This was done by not relying on
rollUpRegistrations
in theresolve
path. As a trade-off, performance for iterating thecradle
proxy has degraded in order to guarantee accuracy. We consider this acceptable as iterating thecradle
is not something one should be doing for anything besides debugging. Thanks to @code-ape for the diagnosis and for coming up with a fix!
- This was done by not relying on
- The
container.registrations
getter on a scoped container no longer rolls up registrations from its' parent. - In
CLASSIC
mode, when parsing the constructor of a derived class, Awilix will no longer parse the base class' constructor in case the derived class' defined constructor does not define any arguments. However, if the derived class does not define a constructor, then Awilix will parse the base class' constructor. Please keep in mind that this only works for native classes, as Awilix works on thetoString
representation of the class/function in order to determine when a class with no defined constructor is encountered. - Renamed
container.has
tocontainer.hasRegistration
to avoid ambiguity. Does it have a registration? Does it have a cached module? Who knows? Let's gooo!
- Improve internal
uniq
function performance by using aSet
(#253, Anderson Leite) - Update packages
- Improve resolve typing (#247, Goran Mržljak)
- Update packages
Dropped Node 10 support. Minimum supported Node version is now 12.
- Move rollup-plugin-copy to devDependencies (#236, Evan Sosenko)
- Update packages
- Convert paths to file URLs in
loadModules
with ESM, fixes #225. (#227, Jamie Corkhill)
GlobWithOptions
now includesBuildResolverOptions
instead ofResolverOptions
(fixes #214)
- Add support for Native Node ES modules on Node v14+ (#211, Richard Simko)
- Fixes AwilixResolutionError throwing TypeError if resolution stack contains symbols (#205, astephens25)
- Update packages
- Fix return type for
createScope
when using a cradle typing. (#182, moltar) - Remove
yarn.lock
, contributing docs now recommendnpm
. - Update packages, upgrade to Prettier 2.0
- Add optional generic parameter to container typing. Allows for a typed
ICradle
. (#169, roikoren755)
- Fix issue with parsing comments (#165, reported by Jamie Corkhill)
- Fix issue where calling
JSON.stringify
on the cradle would result in memory leak (#153, berndartmueller) - Update packages
- Fix issue where the tokenizer was being too eager. (#30)
- Make tests pass on Node v12
- Update packages
- Fix
register
option inloadModules
(#124) - Update packages
- Add
has
method to container to check for an existing registration (#119, faustbrian)
- Extract dependencies from base class when no parameters were extracted. This works for ES6 classes as well as the old-school prototype approach to inheritance. Uses
Object.getPrototypeOf
. (#107) - Allow auto-loading of named exports that expose a
RESOLVER
symbol prop. (#115)
- Support returning the
cradle
inasync
functions (#109, andyfleming)) - Update packages
- [BREAKING CHANGE]: Scoped containers no longer use the parent's cache for
Lifetime.SCOPED
registrations (#92) - Change the
"react-native"
module path to useawilix.browser.js
(#104) - Update packages
Awilix v4 corrects a misunderstanding in how the scoped caching should work. For full context, please see issue #92, but the TL:DR version is that prior v4
, scoped registrations (Lifetime.SCOPED
/ .scoped()
) would travel up the family tree and use a parent's cached resolution if there is any. If there is not, the resolving scope would cache it locally.
While this was by design, it was not very useful, and it was designed based on a misunderstanding of how Unity's HierarchicalLifetimeManager
works. In v4
, Lifetime.SCOPED
now works the same way: the container performing the resolution also caches it, not looking outside itself for cached resolutions of Lifetime.SCOPED
registrations.
A prime use case for this is having a scoped logger, as well as a root logger. This is actually what prompted this change.
// logger.js
export class Logger {
constructor(loggerPrefix = 'root') {
this.prefix = loggerPrefix
}
log(message) {
console.log(`[${this.prefix}]: ${message}`)
}
}
// app.js
import { Logger } from './logger'
import { createContainer, asClass, InjectionMode } from 'awilix'
const container = createContainer({
injectionMode: InjectionMode.CLASSIC,
}).register({
logger: asClass(Logger).scoped(),
})
const scope = container.createScope()
scope.register({
loggerPrefix: asValue('dope scope'),
})
const rootLogger = container.resolve('logger')
const scopeLogger = scope.resolve('logger')
rootLogger.log('yo!') // [root]: yo!
scopeLogger.log('wassup!') // [dope scope]: wassup!
Prior to v4
, the scopeLogger
would have resolved to the same as rootLogger
because it would ask it's ancestors if they had a logger
cached.
Now it works as you would probably expect it to: it keeps it's own cache.
- Updated packages.
- Add support for parsing async and generator functions; these no longer break the parser. (#90)
- Update dependencies.
- Skip code comments in parser (#87)
- Make the parser smarter by including full member expression paths so we get less false positives when scanning for the constructor token.
- Updated dependencies
- Fix TS 2.7 compilation issue
- Fix the
GlobWithOptions
type to includeLifetimeType
- Fix #76: don't overwrite declarations when building with Rollup.
- Adjust Rollup config to use latest config format
- Updated packages, fix an internal typing issue as a result of updated typings.
- Use
Reflect.construct()
instead ofnew
internally; fixes TS transpilation issue. - Add note on browser support to README.
A lot of cool stuff has made it into version 3, and a few things were broken in the process. I have done my best to list everything here.
With v3 comes a few new cool features.
Disposer support (#48)
This has been a very requested feature. The idea is you can tell Awilix how to
dispose of a dependency—for example, to close a database connection—when calling
container.dispose()
.
const pg = require('pg')
const { createContainer, asFunction } = require('awilix')
const container = createContainer()
.register({
pool: (
asFunction(() => new pg.Pool({ ... }))
.singleton()
.disposer((pool) => pool.end())
)
})
// .. later, but only if a `pool` was ever created
container.dispose().then(() => {
console.log('One disposable connection.. disposed! Huehehehe')
})
alias
resolver (#55)
This new resolver lets you alias a registration. This is best illustrated with an example:
const { alias, asValue, createContainer } = require('awilix')
const container = createContainer()
container.register({
laughingOutLoud: asValue('hahahahaha'),
lol: alias('laughingOutLoud'),
})
container.resolve('lol') // 'hahahahaha'
It's essentially the exact same as calling
container.resolve('laughingOutLoad')
, but lol
might be easier to type out in
your constructors. 😎
Default values in constructors/functions (#46)
This is a pretty small feature but was the most difficult to land, mainly because I had to write a smarter parser and tokenizer, not to mention they are now way better at skipping over code. Check out the tests, it's pretty wild.
class MyClass {
constructor(db, timeout = 1000) { /*...*/ }
}
container.register({
db: asFunction(..)
})
// Look! No errors!! :D
container.build(MyClass) instanceof MyClass // true
Official support for running in the browser (#69)
Awilix now ships with 4 module flavors: CommonJS (same old), ES Modules for Node, ES Modules for the Browser and UMD.
Please see the Universal Module section in the readme for details.
The following is a list of known breaking changes. If there's any I've missed feel free to let me know.
The entire library is now written in TypeScript! (#49)
This means a bunch of interfaces have been renamed and made more correct. If you're a TypeScript user, this is great news for you. 😄
ResolutionMode
is now InjectionMode
(#57)
ResolutionMode.js
renamed toinjection-mode.ts
ResolutionMode
renamed toInjectionMode
"Registrations" are now "Resolvers" (#51)
The terminology is now "you register a resolver to a name".
- TypeScript interfaces renamed
REGISTRATION
symbol renamed toRESOLVER
registrations.js
renamed toresolvers.ts
registrationOptions
inloadModules
renamed toresolverOptions
registerClass
, registerFunction
and registerValue
removed (#60)
This was done to simplify the API surface, and also simplifies the
implementation greatly (less overloads). You should be using
container.register
with asClass
, asFunction
and asValue
instead.
Resolver configuration chaining API is now immutable (#62)
This simplifies the TypeScript types and is also considered a good practice. All
configuration functions rely on this
, meaning you should not do:
// I don't know why you would, but DONT DO THIS!
const singleton = asClass(MyClass).singleton
singleton()
However, this also means you can now "split" a resolver to configure it differently. For example:
class GenericSender {
constructor(transport) {
this.transport = transport
}
send() {
if (this.transport === 'email') {
// ... etc
}
}
dispose() { /*...*/ }
}
const base = asClass(GenericSender).scoped().disposer((g) => g.dispose())
const emailSender = base.inject(() => ({ transport: 'email' })
const pushSender = base.inject(() => ({ transport: 'push' })
container.register({
emailSender,
pushSender
})
Removed AwilixNotAFunctionError
in favor of a generic AwilixTypeError
(#52)
This should not have an impact on userland code but I thought I'd mention it.
There are a bunch of internal uses of this error, so I thought it made sense to consolidate them into one error type.
- Code is now formatted with Prettier
- Awilix is now using
husky
+lint-staged
to lint, format and test every commit to ensure top code quality. - Switched to Jest from Mocha
- Switched from eslint to tslint
- Rewrote the function parameter parser, it is now much better at correctly skipping over default value expressions to reach the next parameter.
- Most (if not all) of the code is now documented and should be readable.
- Deprecated the
registerFunction
,registerValue
andregisterClass
shortcuts.
- Fix typings for
container.build
- Add support for
container.build()
- see relevant docs
- Add support for
Object.keys()
on the cradle; now returns the names of available modules that can be resolved by accessing them.- There's a gotcha though;
Object.getOwnPropertyDescriptor()
will return a gibberish descriptor. This is required for the keys to show up in the result.
- There's a gotcha though;
- Fix iterating over cradle - generator now yields registration names, thanks @neerfri! (#40)
- Fix issue with
console.log
on the cradle throwing an error. (#7)- This should not break anything, but just to be safe I did a minor version bump.
- Add support for
Symbol
s (although not recommended).
- Change
RegistrationOptions
typing to union of string and options
- Fix typing for
REGISTRATION
symbol
- Fix typing for
loadModules
— it didn't allow the shortcut version of['glob.js', Lifetime.SCOPED]
- Add Prettier formatting as well as
lint-staged
to keep the tests passing and the code fresh before committing.
- Remove
is-plain-object
andis-string
, use simple checks instead. Trying to keep the dependencies as thin as possible.
- [NEW]: Support inline registration options (#34)
- [FIXED]:
container.loadModules()
typing fix, thanks @dboune!
- [BREAKING]: Custom
isClass
function that will treatfunction Capital () {}
as a class due to the capital first letter of the function name. This is to improve compatibility with Babel's ES5 code generator, and is also a pretty commonly accepted standard naming convention. (#28) - [NEW]: Added support for passing in a
register
function toloadModules
. (#28)
- [FIXED]: Parsing regression in 2.6.1 (#30)
- [FIXED]: Implemented a crude arguments parser to replace regex. (#30)
- [NEW]: infer function name for
registerClass
/registerFunction
(#26) - [FIXED]: Corrected some TypeScript typings related to
registerClass
andregisterFunction
.
- [NEW]: Implemented per-module locals injection (#24).
- Fixed issue where passing a
Lifetime
like.registerFunction('name', func, Lifetime.SCOPED)
didn't work. - Documented
asClass
,asValue
andasFunction
. - [FIXED]: nasty options leaking when using
registerClass/Function({ test1: [Test1, { }], test2: [Test2, { }] })
.
- [BREAKING]: Guard assertions added to
asFunction
andasClass
. This will prevent some nasty runtime behaviors. (#20), thanks @zer0tonin!
- [NEW]: Classic dependency resolution mode using parameter name matching implemented, thanks to @cjhoward92! This is an alternative to the default proxy mechanism.
- [BREAKING]: The
registerX({ name: [value, options]})
pattern is not needed forregisterValue
because it is so simple is requires no configuration. It was causing trouble when attempting to register an array as a value, because theregister
function would think it was the value-options-array pattern when it shouldn't be. This change is breaking in the sense that it solves the unexpected behavior, but it breaks existing registrations that would register arrays by usingregisterValue({ name: [[1, 2]] })
(multi-dimensional array to work around the pre-2.3.0 behavior) - [chore]: Updated packages.
- Pass in the module descriptor to
formatName
- thanks @anasinnyk! - Fixed some issues with TypeScript definitions.
- Fixed
registerFunction
return type definition - thanks @ycros!
- TypeScript definitions - thanks @blove!
- Webpack 2 compatibility - thanks @ewrogers!
console.log
ing the container will, instead of throwing an error, display a string summary of the container. Fixes #7.- started logging changes to a changelog (sorry about being so late to the party)