Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
dba8c6a
Tests: Use Jest instead of Mocha and Nyc
snatalenko Feb 20, 2026
241a8d8
Fix spelling
snatalenko Feb 20, 2026
55536dc
Docs: Update README.md, add CONTRIBUTING.md, change license to Apache…
snatalenko Feb 20, 2026
f33baa2
Build: Add audit, tests, and coveralls build actions
snatalenko Feb 20, 2026
1fede25
New: `asOneOf` method for registering multiple types under the same a…
snatalenko Feb 20, 2026
cf9dfff
New: `addResolver` for automatic wiring later registered types
snatalenko Feb 20, 2026
f8ebc54
Tweak the headline
snatalenko Feb 20, 2026
5e95203
Docs: Remove gotchas section from CONTRIBUTING.md
snatalenko Feb 20, 2026
c39aaa3
Build: Add GitHub Actions workflow for publishing to NPM
snatalenko Feb 20, 2026
b9f2382
Build: Cleanup obsolete tags on new version creation
snatalenko Feb 20, 2026
43e99d2
1.3.0-0
snatalenko Feb 20, 2026
8e519f8
Build: Add separate ESM/CJS builds
snatalenko Feb 21, 2026
89bfbc2
Build: enable native Node.js type stripping support
snatalenko Feb 21, 2026
e079925
1.3.0-1
snatalenko Feb 21, 2026
889df75
Improve error message for multiple matches within resolver
snatalenko Feb 21, 2026
23c5138
Tests: Cover additional instance lifecycle cases
snatalenko Feb 21, 2026
3ffa95b
1.3.0-2
snatalenko Feb 21, 2026
33aac86
Docs: Add tests/audit badge
snatalenko Feb 21, 2026
31c2678
Internal Fix: Resolvers forcing instance creations and causing circul…
snatalenko Feb 23, 2026
c7c7f31
1.3.0-3
snatalenko Feb 23, 2026
9f9cc1e
Build: Exclude unnecessary configs and docs from package
snatalenko Feb 23, 2026
8cc0fc3
1.3.0-4
snatalenko Feb 23, 2026
47db2e5
Change: Allow instances registration w\o an alias
snatalenko Feb 26, 2026
7183bb9
Docs: Update instructions on how to run a single test
snatalenko Feb 26, 2026
0c7c91f
1.3.0-5
snatalenko Feb 26, 2026
66dc226
Internal Fix: extensionless imports in ESM module
snatalenko Feb 27, 2026
3ab1259
1.3.0-6
snatalenko Feb 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: tests/audit

on:
push:
branches:
- master
pull_request:

jobs:
audit:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [24.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm audit --parseable --omit=dev --audit-level=moderate

test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 24.x, 25.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci --omit=optional
env:
CI: true
- run: npm run test

coveralls:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [24.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci --no-optional
env:
CI: true
- run: npm run test:coverage
- name: Submit to Coveralls
uses: coverallsapp/github-action@v2
38 changes: 38 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Publish to NPM

on:
push:
tags:
- 'v*.*.*'

permissions:
id-token: write
contents: read

jobs:
publish:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'

- name: Upgrade npm
run: npm i -g npm@latest

- name: Install dependencies
run: npm ci --no-optional

- name: Publish pre-release to NPM
if: contains(github.ref_name, '-')
run: npm publish --provenance --tag next

- name: Publish release to NPM
if: "!contains(github.ref_name, '-')"
run: npm publish --provenance
15 changes: 9 additions & 6 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/.nyc_output/
/.vscode/
/coverage/
/scripts/
/tests/
.github/
.nyc_output/
.vscode/
coverage/
scripts/
tests/
.editorconfig
.eslintrc.json
*.md
*.tgz
jest.config.cjs
jsconfig.json
tsconfig.json
tsconfig*.json
5 changes: 0 additions & 5 deletions .vscode/settings.json

This file was deleted.

1 change: 1 addition & 0 deletions AGENTS.md
73 changes: 73 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,76 @@
# [1.3.0-6](https://github.com/snatalenko/di0/compare/v1.3.0-5...v1.3.0-6) (2026-02-27)



# [1.3.0-5](https://github.com/snatalenko/di0/compare/v1.3.0-4...v1.3.0-5) (2026-02-26)


### Changes

* Allow instances registration w\o an alias ([47db2e5](https://github.com/snatalenko/di0/commit/47db2e517f2fa3965d7a40bb5be143f5d5d388ae))

### Documentation

* Update instructions on how to run a single test ([7183bb9](https://github.com/snatalenko/di0/commit/7183bb98c21e351dfff33a50a98d604f419ef472))


# [1.3.0-4](https://github.com/snatalenko/di0/compare/v1.3.0-3...v1.3.0-4) (2026-02-23)


### Build System

* Exclude unnecessary configs and docs from package ([9f9cc1e](https://github.com/snatalenko/di0/commit/9f9cc1e3628a2a86f7af923b19d964aaf1d02d56))


# [1.3.0-3](https://github.com/snatalenko/di0/compare/v1.3.0-2...v1.3.0-3) (2026-02-23)


### Documentation

* Add tests/audit badge ([33aac86](https://github.com/snatalenko/di0/commit/33aac86facdcbe874ab33c02879bfff5fae8b231))


# [1.3.0-2](https://github.com/snatalenko/di0/compare/v1.3.0-1...v1.3.0-2) (2026-02-21)


### Tests

* Cover additional instance lifecycle cases ([23c5138](https://github.com/snatalenko/di0/commit/23c513807c46de1a411d7b31cf6331011c1f5b45))


# [1.3.0-1](https://github.com/snatalenko/di0/compare/v1.3.0-0...v1.3.0-1) (2026-02-21)


### Build System

* Enable native Node.js type stripping support ([89bfbc2](https://github.com/snatalenko/di0/commit/89bfbc250f6e0cc3f7ac22cadeb911c09bb6800f))
* Add separate ESM/CJS builds ([8e519f8](https://github.com/snatalenko/di0/commit/8e519f81c7607f5283393e8896c96a28f68587b1))


# [1.3.0-0](https://github.com/snatalenko/di0/compare/v1.2.0...v1.3.0-0) (2026-02-20)


### Features

* `addResolver` for automatic wiring later registered types ([cf9dfff](https://github.com/snatalenko/di0/commit/cf9dfff48acb72799a9021e0e283a7dbc311810d))
* `asOneOf` method for registering multiple types under the same alias ([1fede25](https://github.com/snatalenko/di0/commit/1fede25bf63489adbfe37306c3e44241123abcf9))

### Documentation

* Remove gotchas section from CONTRIBUTING.md ([5e95203](https://github.com/snatalenko/di0/commit/5e952032ca3085e142f03f373e9748c91023646f))
* Update README.md, add CONTRIBUTING.md, change license to Apache-2.0 ([55536dc](https://github.com/snatalenko/di0/commit/55536dc261b3a4f979ac15329c878f6a63117201))

### Tests

* Use Jest instead of Mocha and Nyc ([dba8c6a](https://github.com/snatalenko/di0/commit/dba8c6a8d431c63442a61d73c607bfa135322984))

### Build System

* Cleanup obsolete tags on new version creation ([b9f2382](https://github.com/snatalenko/di0/commit/b9f2382694e08a82f46d53b0e8f31b9e538c1f9b))
* Add GitHub Actions workflow for publishing to NPM ([c39aaa3](https://github.com/snatalenko/di0/commit/c39aaa382eff49a2e092e5fa15dbecf163bf825b))
* Add audit, tests, and coveralls build actions ([f33baa2](https://github.com/snatalenko/di0/commit/f33baa23e40ae7fcf083895603cb1a5671809349))


# [1.2.0](https://github.com/snatalenko/di0/compare/v1.1.0...v1.2.0) (2025-10-13)


Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
50 changes: 50 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Contributing

## Commands

```bash
npm run build # Compile TypeScript (src/ → dist/)
npm test # Run unit tests with Jest
npm run test:coverage # Run tests with lcov coverage report
npm run cleanup # Delete dist/ build output
```

Run a single test file:
```bash
npm test tests/unit/Container.test.ts
```

## Architecture

Source is TypeScript in `src/`, compiled to `dist/` (the published `main`). Tests are TypeScript (Jest + ts-jest) in `tests/unit/`. ts-jest compiles tests directly from source — no build step required before running tests.

### Core flow

1. `ContainerBuilder` collects `TypeConfig` registrations.
2. `builder.container()` freezes the type list and instantiates a `Container`.
3. `Container` defines a lazy getter per alias — instances are created on first access.
4. Types registered without an alias are instantiated eagerly at container creation (side-effect initializers).

### Key classes

- **`ContainerBuilder<TContainerInterface>`** (`src/ContainerBuilder.ts`) — fluent builder. Can be subclassed; `container.builder()` returns an instance of the same subclass so derived containers use the correct type.
- **`Container`** (`src/Container.ts`) — resolves aliases to instances. Tracks active resolutions in `_dependencyStack` to detect cycles. Binds its own methods (`get`, `getAll`, `createInstance`, `has`) and injects them as properties so they are available inside constructors and factories.
- **`TypeConfig<T>`** (`src/TypeConfig.ts`) — holds the factory, alias list, and lifetime mode. Returned by `builder.register()` for fluent chaining.

### Instance lifetime internals

Lifetimes are stored as a `LifetimeMode` string on `TypeConfig`:

- `INSTANCE_PER_CONTAINER` (default) — cached in `Container#instances`, scoped to the current container.
- `INSTANCE_SINGLE` — cached in the `singletons` object, which is passed through `builderFactory` and shared across the container tree.
- `INSTANCE_PER_DEPENDENCY` — not cached; factory is called on every access.

### Container inheritance

`container.builder()` calls `builderFactory({ singletons })`, producing a new builder of the same class seeded with:
- all aliased `TypeConfig` entries from the parent (anonymous initializers are excluded), and
- the shared `singletons` map.

Registering additional types on the derived builder and calling `.container()` creates a child container that sees both parent and new services.

When resolver auto-wiring is enabled (`builder.addResolver(...)`), the derived builder also receives unaliased registrations so resolver predicates can scan and expose them in derived containers.
Loading