From 07272557198cb73882bc4a5a55b08fd6ddba03a5 Mon Sep 17 00:00:00 2001 From: Alec Gibson <12036746+alecgibson@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:50:37 +0000 Subject: [PATCH] feat(strongly-typed): initial commit Add an initial offering for , which will let consumers optionally apply strong typing to their . --- .../libraries/strongly-typed/.gitignore | 19 ++ .../strongly-typed/.lintstagedrc.json | 9 + .../libraries/strongly-typed/.npmignore | 17 ++ .../libraries/strongly-typed/CHANGELOG.md | 1 + .../libraries/strongly-typed/README.md | 110 +++++++++ .../strongly-typed/eslint.config.mjs | 3 + .../libraries/strongly-typed/jest.config.mjs | 3 + .../strongly-typed/jest.js.config.mjs | 3 + .../libraries/strongly-typed/package.json | 71 ++++++ .../strongly-typed/prettier.config.mjs | 3 + .../strongly-typed/src/container.spec.ts | 206 +++++++++++++++++ .../libraries/strongly-typed/src/container.ts | 210 ++++++++++++++++++ .../libraries/strongly-typed/src/index.ts | 1 + .../strongly-typed/tsconfig.cjs.json | 10 + .../strongly-typed/tsconfig.esm.json | 10 + .../libraries/strongly-typed/tsconfig.json | 4 + .../strongly-typed/webpack.config.mjs | 12 + 17 files changed, 692 insertions(+) create mode 100644 packages/container/libraries/strongly-typed/.gitignore create mode 100644 packages/container/libraries/strongly-typed/.lintstagedrc.json create mode 100644 packages/container/libraries/strongly-typed/.npmignore create mode 100644 packages/container/libraries/strongly-typed/CHANGELOG.md create mode 100644 packages/container/libraries/strongly-typed/README.md create mode 100644 packages/container/libraries/strongly-typed/eslint.config.mjs create mode 100644 packages/container/libraries/strongly-typed/jest.config.mjs create mode 100644 packages/container/libraries/strongly-typed/jest.js.config.mjs create mode 100644 packages/container/libraries/strongly-typed/package.json create mode 100644 packages/container/libraries/strongly-typed/prettier.config.mjs create mode 100644 packages/container/libraries/strongly-typed/src/container.spec.ts create mode 100644 packages/container/libraries/strongly-typed/src/container.ts create mode 100644 packages/container/libraries/strongly-typed/src/index.ts create mode 100644 packages/container/libraries/strongly-typed/tsconfig.cjs.json create mode 100644 packages/container/libraries/strongly-typed/tsconfig.esm.json create mode 100644 packages/container/libraries/strongly-typed/tsconfig.json create mode 100644 packages/container/libraries/strongly-typed/webpack.config.mjs diff --git a/packages/container/libraries/strongly-typed/.gitignore b/packages/container/libraries/strongly-typed/.gitignore new file mode 100644 index 0000000..288feba --- /dev/null +++ b/packages/container/libraries/strongly-typed/.gitignore @@ -0,0 +1,19 @@ +# Typescript compiled files +/lib/** + +/tsconfig.tsbuildinfo +/tsconfig.cjs.tsbuildinfo +/tsconfig.esm.tsbuildinfo + +# Test coverage report +/coverage + +# Test mutation report +/reports + +# node modules +/node_modules/ + +# Turborepo files +.turbo/ + diff --git a/packages/container/libraries/strongly-typed/.lintstagedrc.json b/packages/container/libraries/strongly-typed/.lintstagedrc.json new file mode 100644 index 0000000..0061dfc --- /dev/null +++ b/packages/container/libraries/strongly-typed/.lintstagedrc.json @@ -0,0 +1,9 @@ +{ + "*.js": [ + "prettier --write" + ], + "*.ts": [ + "prettier --write", + "eslint" + ] +} diff --git a/packages/container/libraries/strongly-typed/.npmignore b/packages/container/libraries/strongly-typed/.npmignore new file mode 100644 index 0000000..2259a25 --- /dev/null +++ b/packages/container/libraries/strongly-typed/.npmignore @@ -0,0 +1,17 @@ +**/*.spec.js +**/*.spec.js.map +**/*.ts +!lib/**/*.d.ts +lib/**/*.spec.d.ts + +.lintstagedrc.json +eslint.config.mjs +jest.config.mjs +jest.config.stryker.mjs +jest.js.config.mjs +prettier.config.mjs +stryker.config.mjs +tsconfig.json +tsconfig.cjs.json +tsconfig.esm.json +tsconfig.tsbuildinfo diff --git a/packages/container/libraries/strongly-typed/CHANGELOG.md b/packages/container/libraries/strongly-typed/CHANGELOG.md new file mode 100644 index 0000000..8f2dcd7 --- /dev/null +++ b/packages/container/libraries/strongly-typed/CHANGELOG.md @@ -0,0 +1 @@ +# @inversifyjs/strongly-typed diff --git a/packages/container/libraries/strongly-typed/README.md b/packages/container/libraries/strongly-typed/README.md new file mode 100644 index 0000000..c48fedc --- /dev/null +++ b/packages/container/libraries/strongly-typed/README.md @@ -0,0 +1,110 @@ +[![Test coverage](https://codecov.io/gh/inversify/monorepo/branch/main/graph/badge.svg?flag=%40inversifyjs%2Fstrongly-typed)](https://codecov.io/gh/inversify/monorepo/branch/main/graph/badge.svg?flag=%40inversifyjs%2Fstrongly-typed) +[![npm version](https://img.shields.io/github/package-json/v/inversify/monorepo?filename=packages%2Fcontainer%2Flibraries%2Fstrongly-typed%2Fpackage.json&style=plastic)](https://www.npmjs.com/package/@inversifyjs/strongly-typed) + +# @inversifyjs/strongly-typed + +Type definitions for adding strong typing to the `Container` and `@inject()` decorator. + + +## Getting started + +This library can be used in a couple of ways, depending on your preference. + +All usages wind up with you having a strongly-typed `TypedContainer`, which is a generic class that accepts a binding map as a type argument, which forms the contract that your container will adhere to: + +```ts +import { TypedContainer } from '@inversifyjs/strongly-typed'; + +interface Foo { foo: string } +interface Bar { bar: string } + +interface BindingMap { + foo: Foo; + bar: Bar; +} + +const container = new TypedContainer(); + +// Bindings are now strongly typed: + +container.bind('foo').toConstantValue({foo: 'abc'}); // ok +container.rebind('foo').toConstantValue({unknown: 'uh-oh'}) // compilation error + +let foo: Foo = container.get('foo') // ok +foo = container.get('bar') // compilation error +foo = container.get('unknown-identifier') // compilation error +``` + +### Instantiation + +The simplest way to use the library is to directly construct a `TypedContainer`: + +```ts +import { TypedContainer } from '@inversifyjs/strongly-typed'; + +const container = new TypedContainer(); +``` + +This class is actually just a re-typed re-export of the vanilla `Container`, so shares all underlying functionality. + +### Type assertion + +If you'd prefer to keep this library out of your final dependency tree, you can just import the types and perform a type assertion: + +```ts +import { Container } from 'inversify'; +// The type import will be stripped during transpilation +import type { TypedContainer } from '@inversifyjs/strongly-typed'; + +const container = new Container() as TypedContainer; +``` + + +## Advanced usage + +### `Promise` bindings + +`inversify` allows binding `Promise`s, but these **must** be retrieved using `getAsync()` trying to resolve them using `get()` will throw. + +The type signatures will help to enforce this if you show an async binding in the binding map with a `Promise`: + +```ts +interface BindingMap { + number: number; + asyncNumber: Promise; +} + +const container = new TypedContainer(); + +container.get('number') // number +container.get('asyncNumber') // compiler error +container.getAsync('asyncNumber') // Promise +``` + +### Container hierarchies + +A strongly-typed child container can be created from a parent container. + +This strong typing is optional for the child: + +```ts +const parent = new TypedContainer(); +const child = parent.createChild(); // weakly typed +``` + +If the child is strongly-typed, its binding will automatically be adjusted to include the parent types: + +```ts +const parent = new TypedContainer<{foo: Foo}>(); +const child = parent.createChild<{bar: Bar}>(); +child.get('bar') // ok +child.get('foo') // ok +``` + +A child may also override a parent's bindings with a completely unrelated type: + +```ts +const parent = new TypedContainer<{foo: Foo}>(); +const child = parent.createChild<{foo: Bar}>(); +const resolved: Bar = child.get('foo'); +``` diff --git a/packages/container/libraries/strongly-typed/eslint.config.mjs b/packages/container/libraries/strongly-typed/eslint.config.mjs new file mode 100644 index 0000000..4200228 --- /dev/null +++ b/packages/container/libraries/strongly-typed/eslint.config.mjs @@ -0,0 +1,3 @@ +import myconfig from '@inversifyjs/foundation-eslint-config'; + +export default [...myconfig]; diff --git a/packages/container/libraries/strongly-typed/jest.config.mjs b/packages/container/libraries/strongly-typed/jest.config.mjs new file mode 100644 index 0000000..7425b9f --- /dev/null +++ b/packages/container/libraries/strongly-typed/jest.config.mjs @@ -0,0 +1,3 @@ +import { tsGlobalConfig } from '@inversifyjs/foundation-jest-config'; + +export default tsGlobalConfig; diff --git a/packages/container/libraries/strongly-typed/jest.js.config.mjs b/packages/container/libraries/strongly-typed/jest.js.config.mjs new file mode 100644 index 0000000..773dbb6 --- /dev/null +++ b/packages/container/libraries/strongly-typed/jest.js.config.mjs @@ -0,0 +1,3 @@ +import { jsGlobalConfig } from '@inversifyjs/foundation-jest-config'; + +export default jsGlobalConfig; diff --git a/packages/container/libraries/strongly-typed/package.json b/packages/container/libraries/strongly-typed/package.json new file mode 100644 index 0000000..6747f4b --- /dev/null +++ b/packages/container/libraries/strongly-typed/package.json @@ -0,0 +1,71 @@ +{ + "author": "Alec Gibson", + "bugs": { + "url": "https://github.com/inversify/monorepo/issues" + }, + "description": "InversifyJs strong type definitions", + "devDependencies": { + "@eslint/js": "9.13.0", + "@jest/globals": "29.7.0", + "@types/node": "20.17.4", + "@typescript-eslint/eslint-plugin": "8.12.2", + "@typescript-eslint/parser": "8.12.2", + "eslint": "9.13.0", + "jest": "29.7.0", + "prettier": "3.3.3", + "rimraf": "6.0.1", + "ts-jest": "29.2.5", + "typescript": "5.6.3" + }, + "devEngines": { + "node": "^20.18.0", + "pnpm": "^9.12.1" + }, + "homepage": "https://inversify.io", + "keywords": [ + "dependency injection", + "dependency inversion", + "di", + "inversion of control container", + "ioc", + "javascript", + "node", + "typescript" + ], + "license": "MIT", + "main": "lib/cjs/index.js", + "module": "lib/esm/index.js", + "exports": { + ".": { + "import": "./lib/esm/index.js", + "require": "./lib/cjs/index.js" + } + }, + "name": "@inversifyjs/strongly-typed", + "peerDependencies": { + "inversify": ">=6.0.3" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/inversify/monorepo.git" + }, + "scripts": { + "build": "pnpm run build:cjs && pnpm run build:esm", + "build:cjs": "tsc --build tsconfig.cjs.json && pnpm exec foundation-ts-package-cjs ./lib/cjs", + "build:esm": "webpack && pnpm exec foundation-ts-package-esm ./lib/esm", + "build:clean": "rimraf lib", + "format": "prettier --write ./src/**/*.ts", + "lint": "eslint ./src", + "prebuild": "pnpm run build:clean", + "test": "jest --config=jest.config.mjs --runInBand", + "test:js": "jest --config=jest.js.config.mjs --runInBand", + "test:js:coverage": "pnpm run test:unit:js --coverage", + "test:uncommitted": "pnpm run test --changedSince=HEAD", + "test:unit:js": "pnpm run test:js --selectProjects Unit" + }, + "sideEffects": false, + "version": "1.0.0" +} diff --git a/packages/container/libraries/strongly-typed/prettier.config.mjs b/packages/container/libraries/strongly-typed/prettier.config.mjs new file mode 100644 index 0000000..70361db --- /dev/null +++ b/packages/container/libraries/strongly-typed/prettier.config.mjs @@ -0,0 +1,3 @@ +import config from '@inversifyjs/foundation-prettier-config'; + +export default config; diff --git a/packages/container/libraries/strongly-typed/src/container.spec.ts b/packages/container/libraries/strongly-typed/src/container.spec.ts new file mode 100644 index 0000000..58abe56 --- /dev/null +++ b/packages/container/libraries/strongly-typed/src/container.spec.ts @@ -0,0 +1,206 @@ +/* eslint-disable @typescript-eslint/typedef */ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable jest/expect-expect */ +import { beforeEach, describe, expect, it } from '@jest/globals'; + +import 'reflect-metadata'; + +import { Container, injectable } from 'inversify'; + +import { TypedContainer } from './index'; + +describe('interfaces', () => { + @injectable() + class Foo { + public foo: string = ''; + } + + @injectable() + class Bar { + public bar: string = ''; + } + + describe('Container', () => { + let foo: Foo; + let foos: Foo[]; + + beforeEach(() => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + foo; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + foos; + }); + + describe('no binding map', () => { + let container: TypedContainer; + + beforeEach(() => { + container = new Container() as TypedContainer; + }); + + describe('bind()', () => { + it('binds without a type argument', () => { + container.bind('foo').to(Foo); + container.bind(Foo).to(Foo); + }); + + it('checks bindings with an explicit type argument', () => { + container.bind('foo').to(Foo); + // @ts-expect-error :: can't bind Bar to Foo + container.bind('foo').to(Bar); + }); + + it('binds a class as a service identifier', () => { + container.bind(Foo).to(Foo); + // @ts-expect-error :: can't bind Bar to Foo + container.bind(Foo).to(Bar); + }); + }); + + describe('get()', () => { + beforeEach(() => { + container.bind('foo').to(Foo); + container.bind('bar').to(Bar); + container.bind(Foo).to(Foo); + container.bind(Bar).to(Bar); + }); + + it('gets an anonymous binding', () => { + foo = container.get('foo'); + }); + + it('enforces type arguments', () => { + foo = container.get('foo'); + // @ts-expect-error :: can't assign Bar to Foo + foo = container.get('bar'); + }); + + it('gets a class identifier', () => { + foo = container.get(Foo); + // @ts-expect-error :: can't assign Bar to Foo + foo = container.get(Bar); + }); + + it('gets all', () => { + foos = container.getAll('foo'); + // @ts-expect-error :: can't assign Bar to Foo + foos = container.getAll('bar'); + }); + }); + }); + + describe('binding map', () => { + interface BindingMap { + foo: Foo; + bar: Bar; + asyncNumber: Promise; + } + + let container: TypedContainer; + + beforeEach(() => { + container = new Container() as TypedContainer; + }); + + describe('bind()', () => { + it('enforces strict bindings', () => { + container.bind('foo').to(Foo); + // @ts-expect-error :: can't bind Bar to Foo + container.bind('foo').to(Bar); + // @ts-expect-error :: unknown service identifier + container.bind('unknown').to(Foo); + }); + }); + + describe('get()', () => { + beforeEach(() => { + container.bind('foo').to(Foo); + container.bind('bar').to(Bar); + container.bind('asyncNumber').toConstantValue(Promise.resolve(1)); + }); + + it('gets a promise', async () => { + // @ts-expect-error :: can't call get() to get Promise + expect(() => container.get('asyncNumber')).toThrow( + 'it has asynchronous dependencies', + ); + const n: Promise = container.getAsync('asyncNumber'); + expect(await n).toBe(1); + }); + + it('enforces strict bindings', () => { + foo = container.get('foo'); + // @ts-expect-error :: can't assign Bar to Foo + foo = container.get('bar'); + // @ts-expect-error :: unknown service identifier + expect(() => container.get('unknown') as unknown).toThrow( + 'No matching bindings', + ); + }); + + it('gets all', () => { + foos = container.getAll('foo'); + // @ts-expect-error :: can't assign Bar to Foo + foos = container.getAll('bar'); + }); + }); + + describe('ancestry', () => { + beforeEach(() => { + container.bind('foo').to(Foo); + container.bind('bar').to(Bar); + }); + + it('defaults a child to have an `any` map', () => { + const child = container.createChild(); + child.bind('unknown').toConstantValue('unknown'); + expect(child.get('unknown')).toBe('unknown'); + }); + + it('automatically extends parent types', () => { + const child = container.createChild<{ childProp: string }>(); + child.bind('childProp').toConstantValue('child'); + // @ts-expect-error :: unknown key + child.bind('unknown').toConstantValue('unknown'); + expect(child.get('childProp')).toBe('child'); + expect(child.get('foo')).toBeTruthy(); + }); + + it('allows a child to rebind different types to its parent bindings', () => { + type OverridingChildMap = Omit & { foo: string }; + const child = container.createChild(); + child.bind('foo').toConstantValue('foo'); + expect(child.get('foo')).toBe('foo'); + }); + + it('tracks the types of ancestors', () => { + type ChildMap = BindingMap & { lorem: string }; + const child = container.createChild(); + child.bind('lorem').toConstantValue('lorem'); + foo = child.parent!.get('foo'); + // @ts-expect-error :: can't assign Bar to Foo + foo = child.parent!.get('bar'); + + type GrandchildMap = ChildMap & { ipsum: string }; + const grandchild = child.createChild(); + const lorem: string = grandchild.parent!.get('lorem'); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + lorem; + + foo = grandchild.parent!.parent!.get('foo'); + // @ts-expect-error :: can't assign Bar to Foo + foo = grandchild.parent!.parent!.get('bar'); + }); + }); + + describe('instantiation', () => { + it('constructs', () => { + container = new TypedContainer(); + container.bind('foo').to(Foo); + // @ts-expect-error :: can't bind Bar to Foo + container.bind('foo').to(Bar); + }); + }); + }); + }); +}); diff --git a/packages/container/libraries/strongly-typed/src/container.ts b/packages/container/libraries/strongly-typed/src/container.ts new file mode 100644 index 0000000..15a1c8b --- /dev/null +++ b/packages/container/libraries/strongly-typed/src/container.ts @@ -0,0 +1,210 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unnecessary-type-parameters */ +import { Container, type interfaces } from 'inversify'; + +type IfAny = 0 extends 1 & T ? TYes : TNo; + +type BindingMapProperty = string | symbol; +type BindingMap = Record; +type MappedServiceIdentifier = IfAny< + T, + interfaces.ServiceIdentifier, + keyof T +>; +type ContainerBinding< + TBindingMap extends BindingMap, + TKey extends MappedServiceIdentifier = any, +> = TKey extends keyof TBindingMap + ? TBindingMap[TKey] + : TKey extends interfaces.Newable + ? C + : // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + TKey extends Function + ? any + : never; + +type Synchronous = IfAny< + T, + any, + { [K in keyof T as T[K] extends Promise ? never : K]: T[K] } +>; + +type First = T extends [infer TFirst, ...any[]] + ? TFirst + : never; + +type AllButFirst = T extends [any, ...infer TRest] + ? TRest + : never; + +interface ContainerOverrides< + T extends BindingMap = any, + TAncestors extends BindingMap[] = any[], +> { + parent: ContainerOverrides, AllButFirst> | null; + bind: Bind; + get: < + TBound extends ContainerBinding, TKey>, + TKey extends MappedServiceIdentifier> = any, + >( + serviceIdentifier: TKey, + ) => TBound; + getNamed: < + TBound extends ContainerBinding, TKey>, + TKey extends MappedServiceIdentifier> = any, + >( + serviceIdentifier: TKey, + named: PropertyKey, + ) => TBound; + getTagged: < + TBound extends ContainerBinding, TKey>, + TKey extends MappedServiceIdentifier> = any, + >( + serviceIdentifier: TKey, + key: PropertyKey, + value: unknown, + ) => TBound; + getAll: < + TBound extends ContainerBinding, TKey>, + TKey extends MappedServiceIdentifier> = any, + >( + serviceIdentifier: TKey, + ) => TBound[]; + getAllTagged: < + TBound extends ContainerBinding, TKey>, + TKey extends MappedServiceIdentifier> = any, + >( + serviceIdentifier: TKey, + key: PropertyKey, + value: unknown, + ) => TBound[]; + getAllNamed: < + TBound extends ContainerBinding, TKey>, + TKey extends MappedServiceIdentifier> = any, + >( + serviceIdentifier: TKey, + named: PropertyKey, + ) => TBound[]; + getAsync: < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + ) => Promise>; + getNamedAsync: < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + named: PropertyKey, + ) => Promise>; + getTaggedAsync: < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + key: PropertyKey, + value: unknown, + ) => Promise>; + getAllAsync: < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + ) => Promise[]>; + getAllTaggedAsync: < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + key: PropertyKey, + value: unknown, + ) => Promise; + getAllNamedAsync: < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + named: PropertyKey, + ) => Promise[]>; + isBound: IsBound; + isBoundNamed: ( + serviceIdentifier: MappedServiceIdentifier, + named: PropertyKey, + ) => boolean; + isBoundTagged: ( + serviceIdentifier: MappedServiceIdentifier, + key: PropertyKey, + value: unknown, + ) => boolean; + isCurrentBound: IsBound; + rebind: Rebind; + rebindAsync: RebindAsync; + unbind: Unbind; + unbindAsync: UnbindAsync; + onActivation< + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + onActivation: interfaces.BindingActivation, + ): void; + onDeactivation< + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, + >( + serviceIdentifier: TKey, + onDeactivation: interfaces.BindingDeactivation, + ): void; + resolve(constructorFunction: interfaces.Newable): TBound; + createChild( + containerOptions?: interfaces.ContainerOptions, + ): TypedContainer, [T, ...TAncestors]>; +} + +type Bind = < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, +>( + serviceIdentifier: TKey, +) => interfaces.BindingToSyntax; + +type Rebind = Bind; + +type RebindAsync = < + TBound extends ContainerBinding, + TKey extends MappedServiceIdentifier = any, +>( + serviceIdentifier: TKey, +) => Promise>; + +type Unbind = < + TKey extends MappedServiceIdentifier, +>( + serviceIdentifier: TKey, +) => void; + +type UnbindAsync = < + TKey extends MappedServiceIdentifier, +>( + serviceIdentifier: TKey, +) => Promise; + +type IsBound = < + TKey extends MappedServiceIdentifier, +>( + serviceIdentifier: TKey, +) => boolean; + +export type TypedContainer< + T extends BindingMap = any, + TAncestors extends BindingMap[] = any[], +> = ContainerOverrides & + Omit; + +// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unsafe-assignment +export const TypedContainer: { + new ( + ...args: ConstructorParameters + ): TypedContainer; +} = Container as any; diff --git a/packages/container/libraries/strongly-typed/src/index.ts b/packages/container/libraries/strongly-typed/src/index.ts new file mode 100644 index 0000000..15c2a89 --- /dev/null +++ b/packages/container/libraries/strongly-typed/src/index.ts @@ -0,0 +1 @@ +export { TypedContainer } from './container'; diff --git a/packages/container/libraries/strongly-typed/tsconfig.cjs.json b/packages/container/libraries/strongly-typed/tsconfig.cjs.json new file mode 100644 index 0000000..72630fb --- /dev/null +++ b/packages/container/libraries/strongly-typed/tsconfig.cjs.json @@ -0,0 +1,10 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "@inversifyjs/foundation-typescript-config/tsconfig.base.cjs.json", + "compilerOptions": { + "outDir": "./lib/cjs", + "rootDir": "./src", + "tsBuildInfoFile": "tsconfig.cjs.tsbuildinfo" + }, + "include": ["src"] +} diff --git a/packages/container/libraries/strongly-typed/tsconfig.esm.json b/packages/container/libraries/strongly-typed/tsconfig.esm.json new file mode 100644 index 0000000..e597177 --- /dev/null +++ b/packages/container/libraries/strongly-typed/tsconfig.esm.json @@ -0,0 +1,10 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "@inversifyjs/foundation-typescript-config/tsconfig.base.esm.json", + "compilerOptions": { + "outDir": "./lib/esm", + "rootDir": "./src", + "tsBuildInfoFile": "tsconfig.esm.tsbuildinfo" + }, + "include": ["src"] +} diff --git a/packages/container/libraries/strongly-typed/tsconfig.json b/packages/container/libraries/strongly-typed/tsconfig.json new file mode 100644 index 0000000..04a10c9 --- /dev/null +++ b/packages/container/libraries/strongly-typed/tsconfig.json @@ -0,0 +1,4 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "./tsconfig.esm.json" +} diff --git a/packages/container/libraries/strongly-typed/webpack.config.mjs b/packages/container/libraries/strongly-typed/webpack.config.mjs new file mode 100644 index 0000000..e796384 --- /dev/null +++ b/packages/container/libraries/strongly-typed/webpack.config.mjs @@ -0,0 +1,12 @@ +// @ts-check + +import path from 'node:path'; + +import buildWebpackConfig from '@inversifyjs/foundation-webpack-config'; + +const outputPath = path.resolve(import.meta.dirname, 'lib/esm'); + +/** @type {!import("webpack").Configuration} */ +export default { + ...buildWebpackConfig(outputPath), +};