molszanski / iti

~1kB Dependency Injection Library for Typescript and React with a unique support of async flow
https://itijs.org
MIT License
129 stars 6 forks source link

fix: commonjs compatibility, nodenext type resolution #43

Open jacoobes opened 1 year ago

jacoobes commented 1 year ago

this SHOULD resolve #38 #37 Here was the issue with iti's resolution

https://arethetypeswrong.github.io/?p=iti%400.6.0

Changes

I tested my package with applications in the follow pairs (module system, module resolution) : (commonjs, node) (commonjs, nodenext) (esm, nodenext), (esm, node)

DDDKnightmare commented 11 months ago

after building it, I had to patch it, add the extensions to index.d.ts to the imports. (I'm using nodenext type resolution)

jacoobes commented 11 months ago

after building it, I had to patch it, add the extensions to index.d.ts to the imports. (I'm using nodenext type resolution)

Could you show the diff as to what u changed? i can perhaps add the change to this pr

DDDKnightmare commented 11 months ago

I had to add .js extension to the imports on index.d.ts, so they were mapped correctly. I didn't look into the build process, but adding the extension to the .ts file imports might solve it. e.g.:

import ... from `<tsFile>.ts`
jacoobes commented 11 months ago

I had to add .js extension to the imports on index.d.ts, so they were mapped correctly. I didn't look into the build process, but adding the extension to the .ts file imports might solve it. e.g.:

import ... from `<tsFile>.ts`

cool, ill play around with it this week and add it to the pr. Ill update you

jacoobes commented 10 months ago

hey, been busy with work. this is still not stale, will update when i can

jacoobes commented 10 months ago

I had to add .js extension to the imports on index.d.ts, so they were mapped correctly. I didn't look into the build process, but adding the extension to the .ts file imports might solve it. e.g.:

import ... from `<tsFile>.ts`

Everything seemed to work fine without manual changes to the index.js. i didn't have to add .js extensions and i could import all of the utlitity types and whatnot

{
    "compilerOptions": {
        "resolveJsonModule": true,
        "target": "ESNext",
        "module": "commonjs",
        "moduleResolution": "bundler",
        "outDir": "dist",
        "rootDir": "src",
        "strict": true,
        "esModuleInterop": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
    }
}

this was my tsconfig.

jacoobes commented 10 months ago

@molszanski check this out :eyes: will help solve some of the issues in this repo

molszanski commented 10 months ago

Thanks @jacoobes, @oliveirarle, @DDDKnightmare for the input! Will check it out!

DDDKnightmare commented 8 months ago

This is the patch I used to be able to use it without problems (types being inferred correctly, and the imports working correctly, when applied on iti@0.6.0):

diff --git a/dist/src/_utils.d.ts b/dist/_utils.d.ts
similarity index 100%
rename from dist/src/_utils.d.ts
rename to dist/_utils.d.ts
diff --git a/dist/src/errors.d.ts b/dist/errors.d.ts
similarity index 100%
rename from dist/src/errors.d.ts
rename to dist/errors.d.ts
diff --git a/dist/iti.cjs b/dist/index.cjs
similarity index 99%
rename from dist/iti.cjs
rename to dist/index.cjs
index 614cf926346efaa0b579d229e46a7ca33f71c9eb..99beb8941fa0a2ce03f0ad4b16336fd4ddc25156 100644
--- a/dist/iti.cjs
+++ b/dist/index.cjs
@@ -1,2 +1,2 @@
 function t(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,n(t,e)}function e(t){return e=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},e(t)}function n(t,e){return n=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},n(t,e)}function r(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(t){return!1}}function o(t,e,i){return o=r()?Reflect.construct:function(t,e,r){var o=[null];o.push.apply(o,e);var i=new(Function.bind.apply(t,o));return r&&n(i,r.prototype),i},o.apply(null,arguments)}function i(t){var r="function"==typeof Map?new Map:void 0;return i=function(t){if(null===t||-1===Function.toString.call(t).indexOf("[native code]"))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==r){if(r.has(t))return r.get(t);r.set(t,i)}function i(){return o(t,arguments,e(this).constructor)}return i.prototype=Object.create(t.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),n(i,t)},i(t)}function c(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}function u(t,e){var n=Object.keys(e).filter(function(e){return e in t});if(0!==n.length)return n.join("', '")}var s=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return t(n,e),n}(/*#__PURE__*/i(Error)),a=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return t(n,e),n}(s),f=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return t(n,e),n}(s);function h(t,e){try{var n=t()}catch(t){return e(t)}return n&&n.then?n.then(void 0,e):n}var l=/*#__PURE__*/function(e){function n(){return e.call(this)||this}t(n,e);var r,o,i=n.prototype;return i.upsert=function(t){var e="function"==typeof t?t(this.items,this):t;return this._updateContext(e),this},i.add=function(t){var e="function"==typeof t?t(this.items,this):t,n=u(e,this.getTokens());if(n)throw new f("Tokens already exist: ['"+n+"']");return this.upsert(e)},i.addDisposer=function(t){var e="function"==typeof t?t(this.items,this):t,n=u(e,this._disposeCtx);if(n)throw new f("Tokens already exist: ['"+n+"']");for(var r=0,o=Object.entries(e);r<o.length;r++){var i=o[r];this._disposeCtx[i[0]]=i[1]}return this},i._extractTokens=function(t){return"function"==typeof t?t(this.getTokens()):t},i.subscribeToContainerSet=function(t,e){var n=this,r=this._extractTokens(t),o=this.ee.on("containerUpserted",function(t){try{var o=function(){if(r.includes(t.key)){var o=h(function(){return Promise.resolve(n.getContainerSet(r)).then(function(t){e(null,t)})},function(t){e(t,void 0)});if(o&&o.then)return o.then(function(){})}}();return Promise.resolve(o&&o.then?o.then(function(){}):void 0)}catch(t){return Promise.reject(t)}}),i=this.ee.on("containerDeleted",function(t){try{return r.includes(t.key)&&e({containerRemoved:t.key},void 0),Promise.resolve()}catch(t){return Promise.reject(t)}});return function(){o(),i()}},i.getContainerSet=function(t){try{for(var e,n=this,r=n._extractTokens(t),o=[],i=[],u=function(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(n)return(n=n.call(t)).next.bind(n);if(Array.isArray(t)||(n=function(t,e){if(t){if("string"==typeof t)return c(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?c(t,e):void 0}}(t))){n&&(t=n);var r=0;return function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(r);!(e=u()).done;){var s=e.value;n.items[s]instanceof Promise&&(o.push(s),i.push(n.items[s]))}var a={};return r.forEach(function(t){a[t]=n.items[t]}),Promise.resolve(Promise.all(i)).then(function(t){return o.forEach(function(e,n){a[e]=t[n]}),a})}catch(t){return Promise.reject(t)}},r=n,(o=[{key:"containers",get:function(){return this.items}},{key:"items",get:function(){var t=this,e={},n=function(n){!function(t,e,n){Object.defineProperty(t,e,{get:function(){return n()},enumerable:!0})}(e,n,function(){return t.get(n)})};for(var r in this.getTokens())n(r);return e}}])&&function(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}(r.prototype,o),Object.defineProperty(r,"prototype",{writable:!1}),n}(/*#__PURE__*/function(e){t(r,e);var n=r.prototype;function r(){var t;return(t=e.call(this)||this)._cache={},t._context={},t._disposeCtx={},t.ee=void 0,t.ee={events:{},emit:function(t){var e=arguments;(this.events[t]||[]).forEach(function(t){return t.apply(void 0,[].slice.call(e,1))})},on:function(t,e){var n=this;return(this.events[t]=this.events[t]||[]).push(e),function(){return n.events[t]=(n.events[t]||[]).filter(function(t){return t!==e})}}},t}return n.on=function(t,e){return this.ee.on(t,e)},n.get=function(t){var e=this;if(t in this._context){if(t in this._cache)return this._cache[t];var n=function(t,n){e._cache[t]=n,e.ee.emit("containerUpserted",{key:t,newContainer:n})},r=this._context[t];if("function"==typeof r){var o=r();return n(t,o),o}return n(t,r),r}throw new a("Can't find token '"+String(t)+"' value")},n.delete=function(t){return delete this._context[t],delete this._cache[t],delete this._disposeCtx[t],this.ee.emit("containerDeleted",{key:t}),this},n.dispose=function(t){try{var e=this;if(!(t in e._disposeCtx)||!(t in e._cache))return Promise.resolve();var n=e._disposeCtx[t];return Promise.resolve(function(){if("function"==typeof n)return Promise.resolve(Promise.resolve(e._cache[t])).then(function(r){var o=n(r),i=function(){delete e._cache[t],e.ee.emit("containerDisposed",{key:t})};return o instanceof Promise?o.then(i):i(),o})}())}catch(t){return Promise.reject(t)}},n.disposeAll=function(){try{var t=this,e=Object.keys(t._disposeCtx).map(function(e){return t.dispose(e)});return Promise.resolve(Promise.all(e)).then(function(){})}catch(t){return Promise.reject(t)}},n._updateContext=function(t){for(var e=0,n=Object.entries(t);e<n.length;e++){var r=n[e],o=r[0],i=r[1];o in this._context&&this.ee.emit("containerUpdated",{key:o,newContainer:i}),this._context[o]=i,delete this._cache[o],this.ee.emit("containerUpserted",{key:o,newContainer:i})}},n.subscribeToContainer=function(t,e){var n=this,r=this.ee.on("containerUpserted",function(r){try{var o=function(){if(t===r.key){var o=h(function(){return Promise.resolve(n.get(t)).then(function(t){e(null,t)})},function(t){e(t,void 0)});if(o&&o.then)return o.then(function(){})}}();return Promise.resolve(o&&o.then?o.then(function(){}):void 0)}catch(t){return Promise.reject(t)}}),o=this.ee.on("containerDeleted",function(n){try{return t===n.key&&e({containerRemoved:t},void 0),Promise.resolve()}catch(t){return Promise.reject(t)}});return function(){r(),o()}},n.getTokens=function(){return Object.fromEntries(Object.keys(this._context).map(function(t){return[t,t]}))},r}(function(){}));function p(){return new l}exports.Container=l,exports.createContainer=p,exports.makeRoot=p;
-//# sourceMappingURL=iti.cjs.map
+//# sourceMappingURL=index.cjs.map
diff --git a/dist/index.cjs.map b/dist/index.cjs.map
new file mode 100644
index 0000000000000000000000000000000000000000..247cbc7073ffba36dcbf8063d5a266def3f173bc
--- /dev/null
+++ b/dist/index.cjs.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.cjs","sources":["../src/_utils.ts","../src/errors.ts","../src/iti.ts","../src/nanoevents.ts"],"sourcesContent":["export type UnPromisify<T> = T extends Promise<infer U> ? U : T\n\nexport type GetContainerFormat<ProviderFunction extends (...args: any) => any> =\n  UnPromisify<ReturnType<ProviderFunction>>\n\nexport function addGetter(object, key, fn: any) {\n  Object.defineProperty(object, key, {\n    get() {\n      return fn()\n    },\n    enumerable: true,\n  })\n}\n\nexport type Assign<OldContext extends object, NewContext extends object> = {\n  [Token in keyof ({\n    [K in keyof OldContext]: OldContext[K]\n  } & {\n    [K in keyof NewContext]: NewContext[K]\n  })]: Token extends keyof NewContext\n    ? NewContext[Token]\n    : Token extends keyof OldContext\n    ? OldContext[Token]\n    : never\n}\n\nexport type Prettify<T> = T extends infer U ? { [K in keyof U]: U[K] } : never\n\nexport type UnpackFunction<T> = T extends (...args: any) => infer U ? U : T\nexport type UnpackObject<T> = {\n  [K in keyof T]: UnpackFunction<T[K]>\n}\n\nexport type UnpromisifyObject<T> = {\n  [K in keyof T]: UnPromisify<T[K]>\n}\n// keep\n// type AssignAndUnpackObjects<O1 extends {}, O2 extends {}> = UnpromisifyObject<\n//   UnpackObject<Assign4<O1, O2>>\n// >\n\nexport type FullyUnpackObject<T extends {}> = UnpromisifyObject<UnpackObject<T>>\n\nexport type KeysOrCb<Context extends {}> =\n  | Array<keyof Context>\n  | ((t: { [K in keyof Context]: K }) => Array<keyof Context>)\n\nexport type MyRecord<O extends {}, T> = {\n  [K in keyof O]: T\n}\nexport type ContextGetter<Context extends {}> = {\n  [CK in keyof Context]: UnpackFunction<Context[CK]>\n}\n\nexport type UnpackFunctionReturn<T> = T extends (arg: T) => infer U ? U : T\nexport type ContextGetterWithCache<Context extends {}> = {\n  [CK in keyof Context]: UnpackFunctionReturn<Context[CK]>\n}\n\nexport function _intersectionKeys(\n  needle: { [key: string]: any },\n  haystack: { [key: string]: any },\n) {\n  let haystackKeys = Object.keys(haystack)\n  let duplicates = haystackKeys.filter((x) => x in needle)\n  if (duplicates.length === 0) {\n    return undefined\n  }\n  return duplicates.join(\"', '\")\n}\n","export class ItiError extends Error {}\nexport class ItiResolveError extends ItiError {}\nexport class ItiTokenError extends ItiError {}\n","import { Intersection } from \"utility-types\"\nimport { createNanoEvents, Emitter } from \"./nanoevents\"\nimport {\n  addGetter,\n  Prettify,\n  Assign,\n  KeysOrCb,\n  ContextGetter,\n  UnpackFunction,\n  MyRecord,\n  FullyUnpackObject,\n  _intersectionKeys,\n  UnPromisify,\n  UnpackFunctionReturn,\n} from \"./_utils\"\nimport { ItiResolveError, ItiTokenError } from \"./errors\"\n\nabstract class AbstractNode<Context extends {}> {\n  public abstract get<T extends keyof Context>(\n    token: T,\n  ): UnpackFunction<Context[T]>\n\n  public abstract getTokens<T extends keyof Context>(): { [M in T]: T }\n}\n\ntype Events<Context> = {\n  // Used only in tests for now\n  containerUpdated: (payload: {\n    key: keyof Context\n    newContainer: Context[keyof Context]\n  }) => void\n  containerUpserted: (payload: {\n    key: keyof Context\n    newContainer: Context[keyof Context] | null\n  }) => void\n  containerDeleted: (payload: { key: keyof Context }) => void\n  containerDisposed: (payload: { key: keyof Context }) => void\n\n  // Older events\n  // containerCreated: (payload: {\n  //   key: keyof Context\n  //   newContainer: Context[keyof Context]\n  // }) => void\n  // containerRemoved: (payload: { key: keyof Context }) => void\n  // containerRequested: (payload: { key: keyof Context }) => void\n}\n\nclass Node<\n  Context extends {},\n  DisposeContext extends {},\n> extends AbstractNode<Context> {\n  /**\n   * When we create a new class instance or function, we cache the output\n   */\n  private _cache: { [K in keyof Context]?: any } = {}\n\n  /**\n   * Holds key:value factories in a form token:factory\n   */\n  public _context: Context = <Context>{}\n\n  /**\n   * Here we hold references to \"disposers\".\n   * A disposer is a function assigned to a token that will be called when\n   * `dispose` call is made.\n   */\n  public _disposeCtx: { [K in keyof DisposeContext]?: any } = {}\n\n  /**\n   * EventEmitter Logic\n   */\n  protected ee: Emitter<Events<Context>>\n  // public on = this.ee.on\n  on<E extends keyof Events<Context>>(event: E, callback: Events<Context>[E]) {\n    return this.ee.on(event, callback)\n  }\n\n  constructor() {\n    super()\n    this.ee = createNanoEvents<Events<Context>>()\n  }\n  public get<SearchToken extends keyof Context>(\n    token: SearchToken,\n  ): UnpackFunction<Context[SearchToken]> {\n    /**\n     * FLOW A: We have this is in a current context\n     */\n    if (token in this._context) {\n      // Case 1: If this token was a function / provider it might be in a cache\n      if (token in this._cache) {\n        const cachedValue = this._cache[token]\n        return cachedValue\n      }\n\n      const storeInCache = (token: SearchToken, v: any) => {\n        this._cache[token] = v\n\n        /**\n         * Not remember why this is here.\n         * I think to indicate when we create an instance\n         * or cache a function result\n         */\n        this.ee.emit(\"containerUpserted\", {\n          key: token,\n          newContainer: v,\n        })\n      }\n\n      // Case 2: If this token is a function we must launch and cache it\n      const tokenValue = this._context[token]\n      if (typeof tokenValue === \"function\") {\n        const providedValue = tokenValue()\n        storeInCache(token, providedValue)\n        return providedValue\n      }\n\n      // Case 3: This is a simple literal so we just send it\n      storeInCache(token, tokenValue) // We store it send events too\n      return tokenValue as any\n    }\n\n    throw new ItiResolveError(`Can't find token '${String(token)}' value`)\n  }\n\n  public delete<SearchToken extends keyof Context>(\n    token: SearchToken,\n  ): Container<Omit<Context, SearchToken>, DisposeContext> {\n    delete this._context[token]\n    delete this._cache[token]\n    // There is no need to check for disposer existence, since delete will not throw\n    // @ts-expect-error\n    delete this._disposeCtx[token]\n\n    this.ee.emit(\"containerDeleted\", {\n      key: token as any,\n    })\n\n    return this as any\n  }\n\n  public async dispose<\n    DisposeToken extends keyof DisposeContext & keyof Context,\n  >(token: DisposeToken): Promise<void> {\n    const tokenHasDisposerFn = token in this._disposeCtx\n    const tokenHasBeenResolved = token in this._cache\n\n    if (!tokenHasDisposerFn || !tokenHasBeenResolved) return\n\n    const disposerFn = this._disposeCtx[token]\n\n    if (typeof disposerFn === \"function\") {\n      const cachedValue = this._cache[token]\n      const cachedValueResolved = await Promise.resolve(cachedValue)\n\n      const disposeResult = disposerFn(cachedValueResolved)\n\n      const cleanup = () => {\n        delete this._cache[token]\n        this.ee.emit(\"containerDisposed\", { key: token })\n      }\n      if (disposeResult instanceof Promise) {\n        disposeResult.then(cleanup)\n      } else {\n        cleanup()\n      }\n      return disposeResult\n    }\n  }\n\n  /**\n   * Will naively dispose all the containers in the dispose context.\n   *\n   * It will only dispose values we've touched / created.\n   *\n   * Always async, because disposing is 95% async anyway\n   */\n  public async disposeAll() {\n    const thingsToDispose = Object.keys(this._disposeCtx).map((token) =>\n      this.dispose(token as any),\n    )\n\n    // We wait for all the disposers to finish and clear all cache\n    await Promise.all(thingsToDispose)\n  }\n\n  protected _updateContext(updatedContext: Context) {\n    for (const [token, value] of Object.entries(updatedContext)) {\n      if (token in this._context) {\n        this.ee.emit(\"containerUpdated\", {\n          key: token as any,\n          newContainer: value as any,\n        })\n      }\n      // Save state and clear cache\n      this._context[token] = value\n      delete this._cache[token]\n      this.ee.emit(\"containerUpserted\", {\n        key: token as any,\n        newContainer: value,\n      } as any)\n    }\n  }\n\n  public subscribeToContainer<T extends keyof Context>(\n    token: T,\n    cb: (err: any, container: UnpackFunction<Context[T]>) => void,\n  ): () => void {\n    const upsertUnsubscribe = this.ee.on(\"containerUpserted\", async (ev) => {\n      if (token === ev.key) {\n        try {\n          const data = await this.get(token)\n          cb(null, data)\n        } catch (error) {\n          cb(error, undefined as any)\n        }\n      }\n    })\n    const deleteUnsubscribe = this.ee.on(\"containerDeleted\", async (ev) => {\n      if (token === ev.key) {\n        cb({ containerRemoved: token }, undefined as any)\n      }\n    })\n    return () => {\n      upsertUnsubscribe()\n      deleteUnsubscribe()\n    }\n  }\n\n  public getTokens(): {\n    [T in keyof Context]: T\n  } {\n    let tokens = Object.fromEntries(\n      Object.keys(this._context).map((el) => [el, el]),\n    ) as any\n    return tokens\n  }\n}\n\nexport class Container<\n  Context extends {},\n  DisposeContext extends {},\n> extends Node<Context, DisposeContext> {\n  constructor() {\n    super()\n  }\n\n  // SAVE: NewContext extends {! [T in keyof NewContext]: NewContext[T] }\n  public upsert<NewContext extends {}>(\n    newContext:\n      | NewContext\n      | ((\n          containers: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewContext),\n  ): Container<Prettify<Assign<Context, NewContext>>, DisposeContext> {\n    let nc =\n      typeof newContext === \"function\"\n        ? // @ts-expect-error\n          newContext(this.items, this)\n        : newContext\n    this._updateContext(nc)\n    return this as any\n  }\n\n  public add<\n    // This \"magic\" type gives user an Error in an IDE with a helpful message\n    NewContext extends Intersection<\n      MyRecord<\n        Context,\n        \"You are overwriting this token. It is not safe. Use an unsafe `upsert` method\"\n      >,\n      NewContext\n    >,\n  >(\n    newContextOrCb:\n      | NewContext\n      | ((\n          items: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewContext),\n  ): Container<Prettify<Assign<Context, NewContext>>, DisposeContext> {\n    let newContext =\n      typeof newContextOrCb === \"function\"\n        ? newContextOrCb(this.items, this)\n        : newContextOrCb\n\n    // Step 1: Runtime check for existing tokens in context\n    const duplicates = _intersectionKeys(newContext, this.getTokens())\n    if (duplicates)\n      throw new ItiTokenError(`Tokens already exist: ['${duplicates}']`)\n\n    // Step 2: If everything is fine add a newContext\n    let m = this.upsert(newContext)\n    return m as any\n  }\n  // {! [T in keyof NewContext]: NewContext[T] }\n  public addDisposer<\n    NewDisposerContext extends {\n      [T in keyof Context]?: (\n        cachedValue: UnPromisify<UnpackFunctionReturn<Context[T]>>,\n      ) => any\n    },\n  >(\n    newContextOrCb:\n      | NewDisposerContext\n      | ((\n          items: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewDisposerContext),\n  ): Container<Context, Assign<DisposeContext, NewDisposerContext>> {\n    let newDisposingCtx =\n      typeof newContextOrCb === \"function\"\n        ? newContextOrCb(this.items, this)\n        : newContextOrCb\n\n    // Step 1: Runtime check for existing tokens in a Dispose Context\n    const duplicates = _intersectionKeys(newDisposingCtx, this._disposeCtx)\n    if (duplicates)\n      throw new ItiTokenError(`Tokens already exist: ['${duplicates}']`)\n\n    // Step 2: Add disposer context\n    for (const [token, value] of Object.entries(newDisposingCtx)) {\n      this._disposeCtx[token] = value\n    }\n\n    return this as any\n  }\n\n  public _extractTokens<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n  ): T[] {\n    if (typeof tokensOrCb === \"function\") {\n      return tokensOrCb(this.getTokens()) as any\n    } else {\n      return tokensOrCb as any\n    }\n  }\n\n  public subscribeToContainerSet<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n    cb: (\n      err: any,\n      container: {\n        [K in T]: FullyUnpackObject<Context>[K]\n      },\n    ) => void,\n  ): () => void {\n    let tokens = this._extractTokens(tokensOrCb)\n    const upsertUnsubscribe = this.ee.on(\"containerUpserted\", async (ev) => {\n      if (tokens.includes(ev.key)) {\n        try {\n          const cSet = await this.getContainerSet(tokens)\n          cb(null, cSet)\n        } catch (err) {\n          cb(err, undefined as any)\n        }\n      }\n    })\n    const deleteUnsubscribe = this.ee.on(\"containerDeleted\", async (ev) => {\n      if (tokens.includes(ev.key)) {\n        cb({ containerRemoved: ev.key }, undefined as any)\n      }\n    })\n    return () => {\n      upsertUnsubscribe()\n      deleteUnsubscribe()\n    }\n  }\n\n  // this can be optimized\n  public async getContainerSet<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n  ) {\n    let tokens: T[] = this._extractTokens(tokensOrCb)\n    let promiseTokens: T[] = []\n    let allPromises: any = []\n    for (let token of tokens) {\n      if (this.items[token] instanceof Promise) {\n        promiseTokens.push(token)\n        allPromises.push(this.items[token])\n      }\n    }\n\n    let containerDecoratedMap: {\n      [K in T]: FullyUnpackObject<Context>[K]\n    } = {} as any\n\n    // Step 1: Assign all values\n    tokens.forEach((token) => {\n      containerDecoratedMap[token as any] = this.items[token]\n    })\n\n    // Step 2: Overwrite Promise like values with promise results\n    const rez = await Promise.all(allPromises)\n    promiseTokens.forEach((token, index) => {\n      containerDecoratedMap[token] = rez[index]\n    })\n\n    return containerDecoratedMap\n  }\n\n  /**\n   * This is used to get a container from the context.\n   * It should always return a promise?\n   * But it seems that it is not possible to do that with the current implementation.\n   * @deprecated\n   */\n  public get containers() {\n    return this.items\n  }\n\n  public get items(): ContextGetter<Context> {\n    let itemMap = <ContextGetter<Context>>{}\n    for (let key in this.getTokens()) {\n      addGetter(itemMap, key, () => {\n        return this.get(key as any)\n      })\n    }\n    return itemMap\n  }\n}\n\nexport function createContainer() {\n  return new Container()\n}\n","/**\n * From\n * https://github.com/ai/nanoevents\n *\n * Sadly, can't install it via npm. Some build issue\n */\n\n//////////////////\n\ninterface EventsMap {\n  [event: string]: any\n}\n\ninterface DefaultEvents extends EventsMap {\n  [event: string]: (...args: any) => void\n}\n\nexport interface Unsubscribe {\n  (): void\n}\n\nexport declare class Emitter<Events extends EventsMap = DefaultEvents> {\n  /**\n   * Event names in keys and arrays with listeners in values.\n   *\n   * ```js\n   * emitter1.events = emitter2.events\n   * emitter2.events = { }\n   * ```\n   */\n  events: Partial<{ [E in keyof Events]: Events[E][] }>\n\n  /**\n   * Add a listener for a given event.\n   *\n   * ```js\n   * const unbind = ee.on('tick', (tickType, tickDuration) => {\n   *   count += 1\n   * })\n   *\n   * disable () {\n   *   unbind()\n   * }\n   * ```\n   *\n   * @param event The event name.\n   * @param cb The listener function.\n   * @returns Unbind listener from event.\n   */\n  on<K extends keyof Events>(this: this, event: K, cb: Events[K]): Unsubscribe\n\n  /**\n   * Calls each of the listeners registered for a given event.\n   *\n   * ```js\n   * ee.emit('tick', tickType, tickDuration)\n   * ```\n   *\n   * @param event The event name.\n   * @param args The arguments for listeners.\n   */\n  emit<K extends keyof Events>(\n    this: this,\n    event: K,\n    ...args: Parameters<Events[K]>\n  ): void\n}\n\n/**\n * Create event emitter.\n *\n * ```js\n * import { createNanoEvents } from 'nanoevents'\n *\n * class Ticker {\n *   constructor() {\n *     this.emitter = createNanoEvents()\n *   }\n *   on(...args) {\n *     return this.emitter.on(...args)\n *   }\n *   tick() {\n *     this.emitter.emit('tick')\n *   }\n * }\n * ```\n */\n\nexport function createNanoEvents<\n  Events extends EventsMap = DefaultEvents,\n>(): Emitter<Events> {\n  return {\n    events: {},\n    emit(event, ...args) {\n      // @ts-expect-error\n      ;(this.events[event] || []).forEach((i) => i(...args))\n    },\n    on(event, cb) {\n      // @ts-expect-error\n      ;(this.events[event] = this.events[event] || []).push(cb)\n      return () =>\n        // @ts-expect-error\n        (this.events[event] = (this.events[event] || []).filter(\n          (i) => i !== cb,\n        ))\n    },\n  }\n}\n"],"names":["_intersectionKeys","needle","haystack","duplicates","Object","keys","filter","x","length","join","ItiError","Error","ItiResolveError","ItiTokenError","Container","upsert","newContext","nc","this","items","_updateContext","add","newContextOrCb","getTokens","addDisposer","newDisposingCtx","_disposeCtx","entries","_extractTokens","tokensOrCb","subscribeToContainerSet","cb","tokens","upsertUnsubscribe","ee","on","ev","includes","key","_this8","getContainerSet","cSet","err","undefined","deleteUnsubscribe","containerRemoved","_this10","promiseTokens","allPromises","token","Promise","push","containerDecoratedMap","forEach","all","rez","index","itemMap","object","fn","defineProperty","get","enumerable","addGetter","_this11","_this","_cache","_context","events","emit","event","i","callback","storeInCache","v","_this2","newContainer","tokenValue","providedValue","String","dispose","disposerFn","_this4","resolve","cachedValueResolved","disposeResult","cleanup","then","disposeAll","thingsToDispose","_this6","map","updatedContext","value","subscribeToContainer","_this7","data","error","fromEntries","el","createContainer"],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/src/index.d.ts b/dist/index.d.cts
similarity index 100%
rename from dist/src/index.d.ts
rename to dist/index.d.cts
diff --git a/dist/index.d.ts b/dist/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5d546c5e51c89578213f55b052a51c8ab4b4b1ce
--- /dev/null
+++ b/dist/index.d.ts
@@ -0,0 +1,3 @@
+export { createContainer, createContainer as makeRoot, Container } from "./iti.js";
+export type { GetContainerFormat, UnPromisify, UnpackFunction, Prettify, } from "./_utils.js";
+export type { Emitter } from "./nanoevents.js";
diff --git a/dist/iti.module.js b/dist/index.modern.js
similarity index 99%
rename from dist/iti.module.js
rename to dist/index.modern.js
index e88499582879ffd794c590150f144c89caea0c9e..7a3b303fe8149041ab9db14475195ac9d4eece34 100644
--- a/dist/iti.module.js
+++ b/dist/index.modern.js
@@ -1,2 +1,2 @@
 function t(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,n(t,e)}function e(t){return e=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},e(t)}function n(t,e){return n=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},n(t,e)}function r(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(t){return!1}}function o(t,e,i){return o=r()?Reflect.construct:function(t,e,r){var o=[null];o.push.apply(o,e);var i=new(Function.bind.apply(t,o));return r&&n(i,r.prototype),i},o.apply(null,arguments)}function i(t){var r="function"==typeof Map?new Map:void 0;return i=function(t){if(null===t||-1===Function.toString.call(t).indexOf("[native code]"))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==r){if(r.has(t))return r.get(t);r.set(t,i)}function i(){return o(t,arguments,e(this).constructor)}return i.prototype=Object.create(t.prototype,{constructor:{value:i,enumerable:!1,writable:!0,configurable:!0}}),n(i,t)},i(t)}function c(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}function u(t,e){var n=Object.keys(e).filter(function(e){return e in t});if(0!==n.length)return n.join("', '")}var s=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return t(n,e),n}(/*#__PURE__*/i(Error)),a=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return t(n,e),n}(s),f=/*#__PURE__*/function(e){function n(){return e.apply(this,arguments)||this}return t(n,e),n}(s);function h(t,e){try{var n=t()}catch(t){return e(t)}return n&&n.then?n.then(void 0,e):n}var l=/*#__PURE__*/function(e){function n(){return e.call(this)||this}t(n,e);var r,o,i=n.prototype;return i.upsert=function(t){var e="function"==typeof t?t(this.items,this):t;return this._updateContext(e),this},i.add=function(t){var e="function"==typeof t?t(this.items,this):t,n=u(e,this.getTokens());if(n)throw new f("Tokens already exist: ['"+n+"']");return this.upsert(e)},i.addDisposer=function(t){var e="function"==typeof t?t(this.items,this):t,n=u(e,this._disposeCtx);if(n)throw new f("Tokens already exist: ['"+n+"']");for(var r=0,o=Object.entries(e);r<o.length;r++){var i=o[r];this._disposeCtx[i[0]]=i[1]}return this},i._extractTokens=function(t){return"function"==typeof t?t(this.getTokens()):t},i.subscribeToContainerSet=function(t,e){var n=this,r=this._extractTokens(t),o=this.ee.on("containerUpserted",function(t){try{var o=function(){if(r.includes(t.key)){var o=h(function(){return Promise.resolve(n.getContainerSet(r)).then(function(t){e(null,t)})},function(t){e(t,void 0)});if(o&&o.then)return o.then(function(){})}}();return Promise.resolve(o&&o.then?o.then(function(){}):void 0)}catch(t){return Promise.reject(t)}}),i=this.ee.on("containerDeleted",function(t){try{return r.includes(t.key)&&e({containerRemoved:t.key},void 0),Promise.resolve()}catch(t){return Promise.reject(t)}});return function(){o(),i()}},i.getContainerSet=function(t){try{for(var e,n=this,r=n._extractTokens(t),o=[],i=[],u=function(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(n)return(n=n.call(t)).next.bind(n);if(Array.isArray(t)||(n=function(t,e){if(t){if("string"==typeof t)return c(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?c(t,e):void 0}}(t))){n&&(t=n);var r=0;return function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(r);!(e=u()).done;){var s=e.value;n.items[s]instanceof Promise&&(o.push(s),i.push(n.items[s]))}var a={};return r.forEach(function(t){a[t]=n.items[t]}),Promise.resolve(Promise.all(i)).then(function(t){return o.forEach(function(e,n){a[e]=t[n]}),a})}catch(t){return Promise.reject(t)}},r=n,(o=[{key:"containers",get:function(){return this.items}},{key:"items",get:function(){var t=this,e={},n=function(n){!function(t,e,n){Object.defineProperty(t,e,{get:function(){return n()},enumerable:!0})}(e,n,function(){return t.get(n)})};for(var r in this.getTokens())n(r);return e}}])&&function(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}(r.prototype,o),Object.defineProperty(r,"prototype",{writable:!1}),n}(/*#__PURE__*/function(e){t(r,e);var n=r.prototype;function r(){var t;return(t=e.call(this)||this)._cache={},t._context={},t._disposeCtx={},t.ee=void 0,t.ee={events:{},emit:function(t){var e=arguments;(this.events[t]||[]).forEach(function(t){return t.apply(void 0,[].slice.call(e,1))})},on:function(t,e){var n=this;return(this.events[t]=this.events[t]||[]).push(e),function(){return n.events[t]=(n.events[t]||[]).filter(function(t){return t!==e})}}},t}return n.on=function(t,e){return this.ee.on(t,e)},n.get=function(t){var e=this;if(t in this._context){if(t in this._cache)return this._cache[t];var n=function(t,n){e._cache[t]=n,e.ee.emit("containerUpserted",{key:t,newContainer:n})},r=this._context[t];if("function"==typeof r){var o=r();return n(t,o),o}return n(t,r),r}throw new a("Can't find token '"+String(t)+"' value")},n.delete=function(t){return delete this._context[t],delete this._cache[t],delete this._disposeCtx[t],this.ee.emit("containerDeleted",{key:t}),this},n.dispose=function(t){try{var e=this;if(!(t in e._disposeCtx)||!(t in e._cache))return Promise.resolve();var n=e._disposeCtx[t];return Promise.resolve(function(){if("function"==typeof n)return Promise.resolve(Promise.resolve(e._cache[t])).then(function(r){var o=n(r),i=function(){delete e._cache[t],e.ee.emit("containerDisposed",{key:t})};return o instanceof Promise?o.then(i):i(),o})}())}catch(t){return Promise.reject(t)}},n.disposeAll=function(){try{var t=this,e=Object.keys(t._disposeCtx).map(function(e){return t.dispose(e)});return Promise.resolve(Promise.all(e)).then(function(){})}catch(t){return Promise.reject(t)}},n._updateContext=function(t){for(var e=0,n=Object.entries(t);e<n.length;e++){var r=n[e],o=r[0],i=r[1];o in this._context&&this.ee.emit("containerUpdated",{key:o,newContainer:i}),this._context[o]=i,delete this._cache[o],this.ee.emit("containerUpserted",{key:o,newContainer:i})}},n.subscribeToContainer=function(t,e){var n=this,r=this.ee.on("containerUpserted",function(r){try{var o=function(){if(t===r.key){var o=h(function(){return Promise.resolve(n.get(t)).then(function(t){e(null,t)})},function(t){e(t,void 0)});if(o&&o.then)return o.then(function(){})}}();return Promise.resolve(o&&o.then?o.then(function(){}):void 0)}catch(t){return Promise.reject(t)}}),o=this.ee.on("containerDeleted",function(n){try{return t===n.key&&e({containerRemoved:t},void 0),Promise.resolve()}catch(t){return Promise.reject(t)}});return function(){r(),o()}},n.getTokens=function(){return Object.fromEntries(Object.keys(this._context).map(function(t){return[t,t]}))},r}(function(){}));function p(){return new l}export{l as Container,p as createContainer,p as makeRoot};
-//# sourceMappingURL=iti.module.js.map
+//# sourceMappingURL=index.modern.js.map
diff --git a/dist/index.modern.js.map b/dist/index.modern.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..7c90aecba010df042d3856757b485c4e470cd054
--- /dev/null
+++ b/dist/index.modern.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.modern.js","sources":["../src/_utils.ts","../src/errors.ts","../src/iti.ts","../src/nanoevents.ts"],"sourcesContent":["export type UnPromisify<T> = T extends Promise<infer U> ? U : T\n\nexport type GetContainerFormat<ProviderFunction extends (...args: any) => any> =\n  UnPromisify<ReturnType<ProviderFunction>>\n\nexport function addGetter(object, key, fn: any) {\n  Object.defineProperty(object, key, {\n    get() {\n      return fn()\n    },\n    enumerable: true,\n  })\n}\n\nexport type Assign<OldContext extends object, NewContext extends object> = {\n  [Token in keyof ({\n    [K in keyof OldContext]: OldContext[K]\n  } & {\n    [K in keyof NewContext]: NewContext[K]\n  })]: Token extends keyof NewContext\n    ? NewContext[Token]\n    : Token extends keyof OldContext\n    ? OldContext[Token]\n    : never\n}\n\nexport type Prettify<T> = T extends infer U ? { [K in keyof U]: U[K] } : never\n\nexport type UnpackFunction<T> = T extends (...args: any) => infer U ? U : T\nexport type UnpackObject<T> = {\n  [K in keyof T]: UnpackFunction<T[K]>\n}\n\nexport type UnpromisifyObject<T> = {\n  [K in keyof T]: UnPromisify<T[K]>\n}\n// keep\n// type AssignAndUnpackObjects<O1 extends {}, O2 extends {}> = UnpromisifyObject<\n//   UnpackObject<Assign4<O1, O2>>\n// >\n\nexport type FullyUnpackObject<T extends {}> = UnpromisifyObject<UnpackObject<T>>\n\nexport type KeysOrCb<Context extends {}> =\n  | Array<keyof Context>\n  | ((t: { [K in keyof Context]: K }) => Array<keyof Context>)\n\nexport type MyRecord<O extends {}, T> = {\n  [K in keyof O]: T\n}\nexport type ContextGetter<Context extends {}> = {\n  [CK in keyof Context]: UnpackFunction<Context[CK]>\n}\n\nexport type UnpackFunctionReturn<T> = T extends (arg: T) => infer U ? U : T\nexport type ContextGetterWithCache<Context extends {}> = {\n  [CK in keyof Context]: UnpackFunctionReturn<Context[CK]>\n}\n\nexport function _intersectionKeys(\n  needle: { [key: string]: any },\n  haystack: { [key: string]: any },\n) {\n  let haystackKeys = Object.keys(haystack)\n  let duplicates = haystackKeys.filter((x) => x in needle)\n  if (duplicates.length === 0) {\n    return undefined\n  }\n  return duplicates.join(\"', '\")\n}\n","export class ItiError extends Error {}\nexport class ItiResolveError extends ItiError {}\nexport class ItiTokenError extends ItiError {}\n","import { Intersection } from \"utility-types\"\nimport { createNanoEvents, Emitter } from \"./nanoevents\"\nimport {\n  addGetter,\n  Prettify,\n  Assign,\n  KeysOrCb,\n  ContextGetter,\n  UnpackFunction,\n  MyRecord,\n  FullyUnpackObject,\n  _intersectionKeys,\n  UnPromisify,\n  UnpackFunctionReturn,\n} from \"./_utils\"\nimport { ItiResolveError, ItiTokenError } from \"./errors\"\n\nabstract class AbstractNode<Context extends {}> {\n  public abstract get<T extends keyof Context>(\n    token: T,\n  ): UnpackFunction<Context[T]>\n\n  public abstract getTokens<T extends keyof Context>(): { [M in T]: T }\n}\n\ntype Events<Context> = {\n  // Used only in tests for now\n  containerUpdated: (payload: {\n    key: keyof Context\n    newContainer: Context[keyof Context]\n  }) => void\n  containerUpserted: (payload: {\n    key: keyof Context\n    newContainer: Context[keyof Context] | null\n  }) => void\n  containerDeleted: (payload: { key: keyof Context }) => void\n  containerDisposed: (payload: { key: keyof Context }) => void\n\n  // Older events\n  // containerCreated: (payload: {\n  //   key: keyof Context\n  //   newContainer: Context[keyof Context]\n  // }) => void\n  // containerRemoved: (payload: { key: keyof Context }) => void\n  // containerRequested: (payload: { key: keyof Context }) => void\n}\n\nclass Node<\n  Context extends {},\n  DisposeContext extends {},\n> extends AbstractNode<Context> {\n  /**\n   * When we create a new class instance or function, we cache the output\n   */\n  private _cache: { [K in keyof Context]?: any } = {}\n\n  /**\n   * Holds key:value factories in a form token:factory\n   */\n  public _context: Context = <Context>{}\n\n  /**\n   * Here we hold references to \"disposers\".\n   * A disposer is a function assigned to a token that will be called when\n   * `dispose` call is made.\n   */\n  public _disposeCtx: { [K in keyof DisposeContext]?: any } = {}\n\n  /**\n   * EventEmitter Logic\n   */\n  protected ee: Emitter<Events<Context>>\n  // public on = this.ee.on\n  on<E extends keyof Events<Context>>(event: E, callback: Events<Context>[E]) {\n    return this.ee.on(event, callback)\n  }\n\n  constructor() {\n    super()\n    this.ee = createNanoEvents<Events<Context>>()\n  }\n  public get<SearchToken extends keyof Context>(\n    token: SearchToken,\n  ): UnpackFunction<Context[SearchToken]> {\n    /**\n     * FLOW A: We have this is in a current context\n     */\n    if (token in this._context) {\n      // Case 1: If this token was a function / provider it might be in a cache\n      if (token in this._cache) {\n        const cachedValue = this._cache[token]\n        return cachedValue\n      }\n\n      const storeInCache = (token: SearchToken, v: any) => {\n        this._cache[token] = v\n\n        /**\n         * Not remember why this is here.\n         * I think to indicate when we create an instance\n         * or cache a function result\n         */\n        this.ee.emit(\"containerUpserted\", {\n          key: token,\n          newContainer: v,\n        })\n      }\n\n      // Case 2: If this token is a function we must launch and cache it\n      const tokenValue = this._context[token]\n      if (typeof tokenValue === \"function\") {\n        const providedValue = tokenValue()\n        storeInCache(token, providedValue)\n        return providedValue\n      }\n\n      // Case 3: This is a simple literal so we just send it\n      storeInCache(token, tokenValue) // We store it send events too\n      return tokenValue as any\n    }\n\n    throw new ItiResolveError(`Can't find token '${String(token)}' value`)\n  }\n\n  public delete<SearchToken extends keyof Context>(\n    token: SearchToken,\n  ): Container<Omit<Context, SearchToken>, DisposeContext> {\n    delete this._context[token]\n    delete this._cache[token]\n    // There is no need to check for disposer existence, since delete will not throw\n    // @ts-expect-error\n    delete this._disposeCtx[token]\n\n    this.ee.emit(\"containerDeleted\", {\n      key: token as any,\n    })\n\n    return this as any\n  }\n\n  public async dispose<\n    DisposeToken extends keyof DisposeContext & keyof Context,\n  >(token: DisposeToken): Promise<void> {\n    const tokenHasDisposerFn = token in this._disposeCtx\n    const tokenHasBeenResolved = token in this._cache\n\n    if (!tokenHasDisposerFn || !tokenHasBeenResolved) return\n\n    const disposerFn = this._disposeCtx[token]\n\n    if (typeof disposerFn === \"function\") {\n      const cachedValue = this._cache[token]\n      const cachedValueResolved = await Promise.resolve(cachedValue)\n\n      const disposeResult = disposerFn(cachedValueResolved)\n\n      const cleanup = () => {\n        delete this._cache[token]\n        this.ee.emit(\"containerDisposed\", { key: token })\n      }\n      if (disposeResult instanceof Promise) {\n        disposeResult.then(cleanup)\n      } else {\n        cleanup()\n      }\n      return disposeResult\n    }\n  }\n\n  /**\n   * Will naively dispose all the containers in the dispose context.\n   *\n   * It will only dispose values we've touched / created.\n   *\n   * Always async, because disposing is 95% async anyway\n   */\n  public async disposeAll() {\n    const thingsToDispose = Object.keys(this._disposeCtx).map((token) =>\n      this.dispose(token as any),\n    )\n\n    // We wait for all the disposers to finish and clear all cache\n    await Promise.all(thingsToDispose)\n  }\n\n  protected _updateContext(updatedContext: Context) {\n    for (const [token, value] of Object.entries(updatedContext)) {\n      if (token in this._context) {\n        this.ee.emit(\"containerUpdated\", {\n          key: token as any,\n          newContainer: value as any,\n        })\n      }\n      // Save state and clear cache\n      this._context[token] = value\n      delete this._cache[token]\n      this.ee.emit(\"containerUpserted\", {\n        key: token as any,\n        newContainer: value,\n      } as any)\n    }\n  }\n\n  public subscribeToContainer<T extends keyof Context>(\n    token: T,\n    cb: (err: any, container: UnpackFunction<Context[T]>) => void,\n  ): () => void {\n    const upsertUnsubscribe = this.ee.on(\"containerUpserted\", async (ev) => {\n      if (token === ev.key) {\n        try {\n          const data = await this.get(token)\n          cb(null, data)\n        } catch (error) {\n          cb(error, undefined as any)\n        }\n      }\n    })\n    const deleteUnsubscribe = this.ee.on(\"containerDeleted\", async (ev) => {\n      if (token === ev.key) {\n        cb({ containerRemoved: token }, undefined as any)\n      }\n    })\n    return () => {\n      upsertUnsubscribe()\n      deleteUnsubscribe()\n    }\n  }\n\n  public getTokens(): {\n    [T in keyof Context]: T\n  } {\n    let tokens = Object.fromEntries(\n      Object.keys(this._context).map((el) => [el, el]),\n    ) as any\n    return tokens\n  }\n}\n\nexport class Container<\n  Context extends {},\n  DisposeContext extends {},\n> extends Node<Context, DisposeContext> {\n  constructor() {\n    super()\n  }\n\n  // SAVE: NewContext extends {! [T in keyof NewContext]: NewContext[T] }\n  public upsert<NewContext extends {}>(\n    newContext:\n      | NewContext\n      | ((\n          containers: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewContext),\n  ): Container<Prettify<Assign<Context, NewContext>>, DisposeContext> {\n    let nc =\n      typeof newContext === \"function\"\n        ? // @ts-expect-error\n          newContext(this.items, this)\n        : newContext\n    this._updateContext(nc)\n    return this as any\n  }\n\n  public add<\n    // This \"magic\" type gives user an Error in an IDE with a helpful message\n    NewContext extends Intersection<\n      MyRecord<\n        Context,\n        \"You are overwriting this token. It is not safe. Use an unsafe `upsert` method\"\n      >,\n      NewContext\n    >,\n  >(\n    newContextOrCb:\n      | NewContext\n      | ((\n          items: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewContext),\n  ): Container<Prettify<Assign<Context, NewContext>>, DisposeContext> {\n    let newContext =\n      typeof newContextOrCb === \"function\"\n        ? newContextOrCb(this.items, this)\n        : newContextOrCb\n\n    // Step 1: Runtime check for existing tokens in context\n    const duplicates = _intersectionKeys(newContext, this.getTokens())\n    if (duplicates)\n      throw new ItiTokenError(`Tokens already exist: ['${duplicates}']`)\n\n    // Step 2: If everything is fine add a newContext\n    let m = this.upsert(newContext)\n    return m as any\n  }\n  // {! [T in keyof NewContext]: NewContext[T] }\n  public addDisposer<\n    NewDisposerContext extends {\n      [T in keyof Context]?: (\n        cachedValue: UnPromisify<UnpackFunctionReturn<Context[T]>>,\n      ) => any\n    },\n  >(\n    newContextOrCb:\n      | NewDisposerContext\n      | ((\n          items: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewDisposerContext),\n  ): Container<Context, Assign<DisposeContext, NewDisposerContext>> {\n    let newDisposingCtx =\n      typeof newContextOrCb === \"function\"\n        ? newContextOrCb(this.items, this)\n        : newContextOrCb\n\n    // Step 1: Runtime check for existing tokens in a Dispose Context\n    const duplicates = _intersectionKeys(newDisposingCtx, this._disposeCtx)\n    if (duplicates)\n      throw new ItiTokenError(`Tokens already exist: ['${duplicates}']`)\n\n    // Step 2: Add disposer context\n    for (const [token, value] of Object.entries(newDisposingCtx)) {\n      this._disposeCtx[token] = value\n    }\n\n    return this as any\n  }\n\n  public _extractTokens<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n  ): T[] {\n    if (typeof tokensOrCb === \"function\") {\n      return tokensOrCb(this.getTokens()) as any\n    } else {\n      return tokensOrCb as any\n    }\n  }\n\n  public subscribeToContainerSet<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n    cb: (\n      err: any,\n      container: {\n        [K in T]: FullyUnpackObject<Context>[K]\n      },\n    ) => void,\n  ): () => void {\n    let tokens = this._extractTokens(tokensOrCb)\n    const upsertUnsubscribe = this.ee.on(\"containerUpserted\", async (ev) => {\n      if (tokens.includes(ev.key)) {\n        try {\n          const cSet = await this.getContainerSet(tokens)\n          cb(null, cSet)\n        } catch (err) {\n          cb(err, undefined as any)\n        }\n      }\n    })\n    const deleteUnsubscribe = this.ee.on(\"containerDeleted\", async (ev) => {\n      if (tokens.includes(ev.key)) {\n        cb({ containerRemoved: ev.key }, undefined as any)\n      }\n    })\n    return () => {\n      upsertUnsubscribe()\n      deleteUnsubscribe()\n    }\n  }\n\n  // this can be optimized\n  public async getContainerSet<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n  ) {\n    let tokens: T[] = this._extractTokens(tokensOrCb)\n    let promiseTokens: T[] = []\n    let allPromises: any = []\n    for (let token of tokens) {\n      if (this.items[token] instanceof Promise) {\n        promiseTokens.push(token)\n        allPromises.push(this.items[token])\n      }\n    }\n\n    let containerDecoratedMap: {\n      [K in T]: FullyUnpackObject<Context>[K]\n    } = {} as any\n\n    // Step 1: Assign all values\n    tokens.forEach((token) => {\n      containerDecoratedMap[token as any] = this.items[token]\n    })\n\n    // Step 2: Overwrite Promise like values with promise results\n    const rez = await Promise.all(allPromises)\n    promiseTokens.forEach((token, index) => {\n      containerDecoratedMap[token] = rez[index]\n    })\n\n    return containerDecoratedMap\n  }\n\n  /**\n   * This is used to get a container from the context.\n   * It should always return a promise?\n   * But it seems that it is not possible to do that with the current implementation.\n   * @deprecated\n   */\n  public get containers() {\n    return this.items\n  }\n\n  public get items(): ContextGetter<Context> {\n    let itemMap = <ContextGetter<Context>>{}\n    for (let key in this.getTokens()) {\n      addGetter(itemMap, key, () => {\n        return this.get(key as any)\n      })\n    }\n    return itemMap\n  }\n}\n\nexport function createContainer() {\n  return new Container()\n}\n","/**\n * From\n * https://github.com/ai/nanoevents\n *\n * Sadly, can't install it via npm. Some build issue\n */\n\n//////////////////\n\ninterface EventsMap {\n  [event: string]: any\n}\n\ninterface DefaultEvents extends EventsMap {\n  [event: string]: (...args: any) => void\n}\n\nexport interface Unsubscribe {\n  (): void\n}\n\nexport declare class Emitter<Events extends EventsMap = DefaultEvents> {\n  /**\n   * Event names in keys and arrays with listeners in values.\n   *\n   * ```js\n   * emitter1.events = emitter2.events\n   * emitter2.events = { }\n   * ```\n   */\n  events: Partial<{ [E in keyof Events]: Events[E][] }>\n\n  /**\n   * Add a listener for a given event.\n   *\n   * ```js\n   * const unbind = ee.on('tick', (tickType, tickDuration) => {\n   *   count += 1\n   * })\n   *\n   * disable () {\n   *   unbind()\n   * }\n   * ```\n   *\n   * @param event The event name.\n   * @param cb The listener function.\n   * @returns Unbind listener from event.\n   */\n  on<K extends keyof Events>(this: this, event: K, cb: Events[K]): Unsubscribe\n\n  /**\n   * Calls each of the listeners registered for a given event.\n   *\n   * ```js\n   * ee.emit('tick', tickType, tickDuration)\n   * ```\n   *\n   * @param event The event name.\n   * @param args The arguments for listeners.\n   */\n  emit<K extends keyof Events>(\n    this: this,\n    event: K,\n    ...args: Parameters<Events[K]>\n  ): void\n}\n\n/**\n * Create event emitter.\n *\n * ```js\n * import { createNanoEvents } from 'nanoevents'\n *\n * class Ticker {\n *   constructor() {\n *     this.emitter = createNanoEvents()\n *   }\n *   on(...args) {\n *     return this.emitter.on(...args)\n *   }\n *   tick() {\n *     this.emitter.emit('tick')\n *   }\n * }\n * ```\n */\n\nexport function createNanoEvents<\n  Events extends EventsMap = DefaultEvents,\n>(): Emitter<Events> {\n  return {\n    events: {},\n    emit(event, ...args) {\n      // @ts-expect-error\n      ;(this.events[event] || []).forEach((i) => i(...args))\n    },\n    on(event, cb) {\n      // @ts-expect-error\n      ;(this.events[event] = this.events[event] || []).push(cb)\n      return () =>\n        // @ts-expect-error\n        (this.events[event] = (this.events[event] || []).filter(\n          (i) => i !== cb,\n        ))\n    },\n  }\n}\n"],"names":["_intersectionKeys","needle","haystack","duplicates","Object","keys","filter","x","length","join","ItiError","Error","ItiResolveError","ItiTokenError","Container","upsert","newContext","nc","this","items","_updateContext","add","newContextOrCb","getTokens","addDisposer","newDisposingCtx","_disposeCtx","entries","_extractTokens","tokensOrCb","subscribeToContainerSet","cb","tokens","upsertUnsubscribe","ee","on","ev","includes","key","_this8","getContainerSet","cSet","err","undefined","deleteUnsubscribe","containerRemoved","_this10","promiseTokens","allPromises","token","Promise","push","containerDecoratedMap","forEach","all","rez","index","itemMap","object","fn","defineProperty","get","enumerable","addGetter","_this11","_this","_cache","_context","events","emit","event","i","callback","storeInCache","v","_this2","newContainer","tokenValue","providedValue","String","dispose","disposerFn","_this4","resolve","cachedValueResolved","disposeResult","cleanup","then","disposeAll","thingsToDispose","_this6","map","updatedContext","value","subscribeToContainer","_this7","data","error","fromEntries","el","createContainer"],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/iti.umd.js b/dist/index.umd.js
similarity index 99%
rename from dist/iti.umd.js
rename to dist/index.umd.js
index 979907a5793a9fc0f01e47ace6aaaf8bf40b5fde..21acc5d3d9060e3317331a81e01bcf83ec834712 100644
--- a/dist/iti.umd.js
+++ b/dist/index.umd.js
@@ -1,2 +1,2 @@
 !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t||self).iti={})}(this,function(t){function e(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,r(t,e)}function n(t){return n=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},n(t)}function r(t,e){return r=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},r(t,e)}function o(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(t){return!1}}function i(t,e,n){return i=o()?Reflect.construct:function(t,e,n){var o=[null];o.push.apply(o,e);var i=new(Function.bind.apply(t,o));return n&&r(i,n.prototype),i},i.apply(null,arguments)}function c(t){var e="function"==typeof Map?new Map:void 0;return c=function(t){if(null===t||-1===Function.toString.call(t).indexOf("[native code]"))return t;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,o)}function o(){return i(t,arguments,n(this).constructor)}return o.prototype=Object.create(t.prototype,{constructor:{value:o,enumerable:!1,writable:!0,configurable:!0}}),r(o,t)},c(t)}function u(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}function s(t,e){var n=Object.keys(e).filter(function(e){return e in t});if(0!==n.length)return n.join("', '")}var f=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return e(n,t),n}(/*#__PURE__*/c(Error)),a=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return e(n,t),n}(f),h=/*#__PURE__*/function(t){function n(){return t.apply(this,arguments)||this}return e(n,t),n}(f);function l(t,e){try{var n=t()}catch(t){return e(t)}return n&&n.then?n.then(void 0,e):n}var p=/*#__PURE__*/function(t){e(r,t);var n=r.prototype;function r(){var e;return(e=t.call(this)||this)._cache={},e._context={},e._disposeCtx={},e.ee=void 0,e.ee={events:{},emit:function(t){var e=arguments;(this.events[t]||[]).forEach(function(t){return t.apply(void 0,[].slice.call(e,1))})},on:function(t,e){var n=this;return(this.events[t]=this.events[t]||[]).push(e),function(){return n.events[t]=(n.events[t]||[]).filter(function(t){return t!==e})}}},e}return n.on=function(t,e){return this.ee.on(t,e)},n.get=function(t){var e=this;if(t in this._context){if(t in this._cache)return this._cache[t];var n=function(t,n){e._cache[t]=n,e.ee.emit("containerUpserted",{key:t,newContainer:n})},r=this._context[t];if("function"==typeof r){var o=r();return n(t,o),o}return n(t,r),r}throw new a("Can't find token '"+String(t)+"' value")},n.delete=function(t){return delete this._context[t],delete this._cache[t],delete this._disposeCtx[t],this.ee.emit("containerDeleted",{key:t}),this},n.dispose=function(t){try{var e=this;if(!(t in e._disposeCtx)||!(t in e._cache))return Promise.resolve();var n=e._disposeCtx[t];return Promise.resolve(function(){if("function"==typeof n)return Promise.resolve(Promise.resolve(e._cache[t])).then(function(r){var o=n(r),i=function(){delete e._cache[t],e.ee.emit("containerDisposed",{key:t})};return o instanceof Promise?o.then(i):i(),o})}())}catch(t){return Promise.reject(t)}},n.disposeAll=function(){try{var t=this,e=Object.keys(t._disposeCtx).map(function(e){return t.dispose(e)});return Promise.resolve(Promise.all(e)).then(function(){})}catch(t){return Promise.reject(t)}},n._updateContext=function(t){for(var e=0,n=Object.entries(t);e<n.length;e++){var r=n[e],o=r[0],i=r[1];o in this._context&&this.ee.emit("containerUpdated",{key:o,newContainer:i}),this._context[o]=i,delete this._cache[o],this.ee.emit("containerUpserted",{key:o,newContainer:i})}},n.subscribeToContainer=function(t,e){var n=this,r=this.ee.on("containerUpserted",function(r){try{var o=function(){if(t===r.key){var o=l(function(){return Promise.resolve(n.get(t)).then(function(t){e(null,t)})},function(t){e(t,void 0)});if(o&&o.then)return o.then(function(){})}}();return Promise.resolve(o&&o.then?o.then(function(){}):void 0)}catch(t){return Promise.reject(t)}}),o=this.ee.on("containerDeleted",function(n){try{return t===n.key&&e({containerRemoved:t},void 0),Promise.resolve()}catch(t){return Promise.reject(t)}});return function(){r(),o()}},n.getTokens=function(){return Object.fromEntries(Object.keys(this._context).map(function(t){return[t,t]}))},r}(function(){}),v=/*#__PURE__*/function(t){function n(){return t.call(this)||this}e(n,t);var r,o,i=n.prototype;return i.upsert=function(t){var e="function"==typeof t?t(this.items,this):t;return this._updateContext(e),this},i.add=function(t){var e="function"==typeof t?t(this.items,this):t,n=s(e,this.getTokens());if(n)throw new h("Tokens already exist: ['"+n+"']");return this.upsert(e)},i.addDisposer=function(t){var e="function"==typeof t?t(this.items,this):t,n=s(e,this._disposeCtx);if(n)throw new h("Tokens already exist: ['"+n+"']");for(var r=0,o=Object.entries(e);r<o.length;r++){var i=o[r];this._disposeCtx[i[0]]=i[1]}return this},i._extractTokens=function(t){return"function"==typeof t?t(this.getTokens()):t},i.subscribeToContainerSet=function(t,e){var n=this,r=this._extractTokens(t),o=this.ee.on("containerUpserted",function(t){try{var o=function(){if(r.includes(t.key)){var o=l(function(){return Promise.resolve(n.getContainerSet(r)).then(function(t){e(null,t)})},function(t){e(t,void 0)});if(o&&o.then)return o.then(function(){})}}();return Promise.resolve(o&&o.then?o.then(function(){}):void 0)}catch(t){return Promise.reject(t)}}),i=this.ee.on("containerDeleted",function(t){try{return r.includes(t.key)&&e({containerRemoved:t.key},void 0),Promise.resolve()}catch(t){return Promise.reject(t)}});return function(){o(),i()}},i.getContainerSet=function(t){try{for(var e,n=this,r=n._extractTokens(t),o=[],i=[],c=function(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(n)return(n=n.call(t)).next.bind(n);if(Array.isArray(t)||(n=function(t,e){if(t){if("string"==typeof t)return u(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?u(t,e):void 0}}(t))){n&&(t=n);var r=0;return function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(r);!(e=c()).done;){var s=e.value;n.items[s]instanceof Promise&&(o.push(s),i.push(n.items[s]))}var f={};return r.forEach(function(t){f[t]=n.items[t]}),Promise.resolve(Promise.all(i)).then(function(t){return o.forEach(function(e,n){f[e]=t[n]}),f})}catch(t){return Promise.reject(t)}},r=n,(o=[{key:"containers",get:function(){return this.items}},{key:"items",get:function(){var t=this,e={},n=function(n){!function(t,e,n){Object.defineProperty(t,e,{get:function(){return n()},enumerable:!0})}(e,n,function(){return t.get(n)})};for(var r in this.getTokens())n(r);return e}}])&&function(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}(r.prototype,o),Object.defineProperty(r,"prototype",{writable:!1}),n}(p);function y(){return new v}t.Container=v,t.createContainer=y,t.makeRoot=y});
-//# sourceMappingURL=iti.umd.js.map
+//# sourceMappingURL=index.umd.js.map
diff --git a/dist/index.umd.js.map b/dist/index.umd.js.map
new file mode 100644
index 0000000000000000000000000000000000000000..585cb483515438dfd47417a40ba5467aad0125d4
--- /dev/null
+++ b/dist/index.umd.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.umd.js","sources":["../src/_utils.ts","../src/errors.ts","../src/iti.ts","../src/nanoevents.ts"],"sourcesContent":["export type UnPromisify<T> = T extends Promise<infer U> ? U : T\n\nexport type GetContainerFormat<ProviderFunction extends (...args: any) => any> =\n  UnPromisify<ReturnType<ProviderFunction>>\n\nexport function addGetter(object, key, fn: any) {\n  Object.defineProperty(object, key, {\n    get() {\n      return fn()\n    },\n    enumerable: true,\n  })\n}\n\nexport type Assign<OldContext extends object, NewContext extends object> = {\n  [Token in keyof ({\n    [K in keyof OldContext]: OldContext[K]\n  } & {\n    [K in keyof NewContext]: NewContext[K]\n  })]: Token extends keyof NewContext\n    ? NewContext[Token]\n    : Token extends keyof OldContext\n    ? OldContext[Token]\n    : never\n}\n\nexport type Prettify<T> = T extends infer U ? { [K in keyof U]: U[K] } : never\n\nexport type UnpackFunction<T> = T extends (...args: any) => infer U ? U : T\nexport type UnpackObject<T> = {\n  [K in keyof T]: UnpackFunction<T[K]>\n}\n\nexport type UnpromisifyObject<T> = {\n  [K in keyof T]: UnPromisify<T[K]>\n}\n// keep\n// type AssignAndUnpackObjects<O1 extends {}, O2 extends {}> = UnpromisifyObject<\n//   UnpackObject<Assign4<O1, O2>>\n// >\n\nexport type FullyUnpackObject<T extends {}> = UnpromisifyObject<UnpackObject<T>>\n\nexport type KeysOrCb<Context extends {}> =\n  | Array<keyof Context>\n  | ((t: { [K in keyof Context]: K }) => Array<keyof Context>)\n\nexport type MyRecord<O extends {}, T> = {\n  [K in keyof O]: T\n}\nexport type ContextGetter<Context extends {}> = {\n  [CK in keyof Context]: UnpackFunction<Context[CK]>\n}\n\nexport type UnpackFunctionReturn<T> = T extends (arg: T) => infer U ? U : T\nexport type ContextGetterWithCache<Context extends {}> = {\n  [CK in keyof Context]: UnpackFunctionReturn<Context[CK]>\n}\n\nexport function _intersectionKeys(\n  needle: { [key: string]: any },\n  haystack: { [key: string]: any },\n) {\n  let haystackKeys = Object.keys(haystack)\n  let duplicates = haystackKeys.filter((x) => x in needle)\n  if (duplicates.length === 0) {\n    return undefined\n  }\n  return duplicates.join(\"', '\")\n}\n","export class ItiError extends Error {}\nexport class ItiResolveError extends ItiError {}\nexport class ItiTokenError extends ItiError {}\n","import { Intersection } from \"utility-types\"\nimport { createNanoEvents, Emitter } from \"./nanoevents\"\nimport {\n  addGetter,\n  Prettify,\n  Assign,\n  KeysOrCb,\n  ContextGetter,\n  UnpackFunction,\n  MyRecord,\n  FullyUnpackObject,\n  _intersectionKeys,\n  UnPromisify,\n  UnpackFunctionReturn,\n} from \"./_utils\"\nimport { ItiResolveError, ItiTokenError } from \"./errors\"\n\nabstract class AbstractNode<Context extends {}> {\n  public abstract get<T extends keyof Context>(\n    token: T,\n  ): UnpackFunction<Context[T]>\n\n  public abstract getTokens<T extends keyof Context>(): { [M in T]: T }\n}\n\ntype Events<Context> = {\n  // Used only in tests for now\n  containerUpdated: (payload: {\n    key: keyof Context\n    newContainer: Context[keyof Context]\n  }) => void\n  containerUpserted: (payload: {\n    key: keyof Context\n    newContainer: Context[keyof Context] | null\n  }) => void\n  containerDeleted: (payload: { key: keyof Context }) => void\n  containerDisposed: (payload: { key: keyof Context }) => void\n\n  // Older events\n  // containerCreated: (payload: {\n  //   key: keyof Context\n  //   newContainer: Context[keyof Context]\n  // }) => void\n  // containerRemoved: (payload: { key: keyof Context }) => void\n  // containerRequested: (payload: { key: keyof Context }) => void\n}\n\nclass Node<\n  Context extends {},\n  DisposeContext extends {},\n> extends AbstractNode<Context> {\n  /**\n   * When we create a new class instance or function, we cache the output\n   */\n  private _cache: { [K in keyof Context]?: any } = {}\n\n  /**\n   * Holds key:value factories in a form token:factory\n   */\n  public _context: Context = <Context>{}\n\n  /**\n   * Here we hold references to \"disposers\".\n   * A disposer is a function assigned to a token that will be called when\n   * `dispose` call is made.\n   */\n  public _disposeCtx: { [K in keyof DisposeContext]?: any } = {}\n\n  /**\n   * EventEmitter Logic\n   */\n  protected ee: Emitter<Events<Context>>\n  // public on = this.ee.on\n  on<E extends keyof Events<Context>>(event: E, callback: Events<Context>[E]) {\n    return this.ee.on(event, callback)\n  }\n\n  constructor() {\n    super()\n    this.ee = createNanoEvents<Events<Context>>()\n  }\n  public get<SearchToken extends keyof Context>(\n    token: SearchToken,\n  ): UnpackFunction<Context[SearchToken]> {\n    /**\n     * FLOW A: We have this is in a current context\n     */\n    if (token in this._context) {\n      // Case 1: If this token was a function / provider it might be in a cache\n      if (token in this._cache) {\n        const cachedValue = this._cache[token]\n        return cachedValue\n      }\n\n      const storeInCache = (token: SearchToken, v: any) => {\n        this._cache[token] = v\n\n        /**\n         * Not remember why this is here.\n         * I think to indicate when we create an instance\n         * or cache a function result\n         */\n        this.ee.emit(\"containerUpserted\", {\n          key: token,\n          newContainer: v,\n        })\n      }\n\n      // Case 2: If this token is a function we must launch and cache it\n      const tokenValue = this._context[token]\n      if (typeof tokenValue === \"function\") {\n        const providedValue = tokenValue()\n        storeInCache(token, providedValue)\n        return providedValue\n      }\n\n      // Case 3: This is a simple literal so we just send it\n      storeInCache(token, tokenValue) // We store it send events too\n      return tokenValue as any\n    }\n\n    throw new ItiResolveError(`Can't find token '${String(token)}' value`)\n  }\n\n  public delete<SearchToken extends keyof Context>(\n    token: SearchToken,\n  ): Container<Omit<Context, SearchToken>, DisposeContext> {\n    delete this._context[token]\n    delete this._cache[token]\n    // There is no need to check for disposer existence, since delete will not throw\n    // @ts-expect-error\n    delete this._disposeCtx[token]\n\n    this.ee.emit(\"containerDeleted\", {\n      key: token as any,\n    })\n\n    return this as any\n  }\n\n  public async dispose<\n    DisposeToken extends keyof DisposeContext & keyof Context,\n  >(token: DisposeToken): Promise<void> {\n    const tokenHasDisposerFn = token in this._disposeCtx\n    const tokenHasBeenResolved = token in this._cache\n\n    if (!tokenHasDisposerFn || !tokenHasBeenResolved) return\n\n    const disposerFn = this._disposeCtx[token]\n\n    if (typeof disposerFn === \"function\") {\n      const cachedValue = this._cache[token]\n      const cachedValueResolved = await Promise.resolve(cachedValue)\n\n      const disposeResult = disposerFn(cachedValueResolved)\n\n      const cleanup = () => {\n        delete this._cache[token]\n        this.ee.emit(\"containerDisposed\", { key: token })\n      }\n      if (disposeResult instanceof Promise) {\n        disposeResult.then(cleanup)\n      } else {\n        cleanup()\n      }\n      return disposeResult\n    }\n  }\n\n  /**\n   * Will naively dispose all the containers in the dispose context.\n   *\n   * It will only dispose values we've touched / created.\n   *\n   * Always async, because disposing is 95% async anyway\n   */\n  public async disposeAll() {\n    const thingsToDispose = Object.keys(this._disposeCtx).map((token) =>\n      this.dispose(token as any),\n    )\n\n    // We wait for all the disposers to finish and clear all cache\n    await Promise.all(thingsToDispose)\n  }\n\n  protected _updateContext(updatedContext: Context) {\n    for (const [token, value] of Object.entries(updatedContext)) {\n      if (token in this._context) {\n        this.ee.emit(\"containerUpdated\", {\n          key: token as any,\n          newContainer: value as any,\n        })\n      }\n      // Save state and clear cache\n      this._context[token] = value\n      delete this._cache[token]\n      this.ee.emit(\"containerUpserted\", {\n        key: token as any,\n        newContainer: value,\n      } as any)\n    }\n  }\n\n  public subscribeToContainer<T extends keyof Context>(\n    token: T,\n    cb: (err: any, container: UnpackFunction<Context[T]>) => void,\n  ): () => void {\n    const upsertUnsubscribe = this.ee.on(\"containerUpserted\", async (ev) => {\n      if (token === ev.key) {\n        try {\n          const data = await this.get(token)\n          cb(null, data)\n        } catch (error) {\n          cb(error, undefined as any)\n        }\n      }\n    })\n    const deleteUnsubscribe = this.ee.on(\"containerDeleted\", async (ev) => {\n      if (token === ev.key) {\n        cb({ containerRemoved: token }, undefined as any)\n      }\n    })\n    return () => {\n      upsertUnsubscribe()\n      deleteUnsubscribe()\n    }\n  }\n\n  public getTokens(): {\n    [T in keyof Context]: T\n  } {\n    let tokens = Object.fromEntries(\n      Object.keys(this._context).map((el) => [el, el]),\n    ) as any\n    return tokens\n  }\n}\n\nexport class Container<\n  Context extends {},\n  DisposeContext extends {},\n> extends Node<Context, DisposeContext> {\n  constructor() {\n    super()\n  }\n\n  // SAVE: NewContext extends {! [T in keyof NewContext]: NewContext[T] }\n  public upsert<NewContext extends {}>(\n    newContext:\n      | NewContext\n      | ((\n          containers: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewContext),\n  ): Container<Prettify<Assign<Context, NewContext>>, DisposeContext> {\n    let nc =\n      typeof newContext === \"function\"\n        ? // @ts-expect-error\n          newContext(this.items, this)\n        : newContext\n    this._updateContext(nc)\n    return this as any\n  }\n\n  public add<\n    // This \"magic\" type gives user an Error in an IDE with a helpful message\n    NewContext extends Intersection<\n      MyRecord<\n        Context,\n        \"You are overwriting this token. It is not safe. Use an unsafe `upsert` method\"\n      >,\n      NewContext\n    >,\n  >(\n    newContextOrCb:\n      | NewContext\n      | ((\n          items: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewContext),\n  ): Container<Prettify<Assign<Context, NewContext>>, DisposeContext> {\n    let newContext =\n      typeof newContextOrCb === \"function\"\n        ? newContextOrCb(this.items, this)\n        : newContextOrCb\n\n    // Step 1: Runtime check for existing tokens in context\n    const duplicates = _intersectionKeys(newContext, this.getTokens())\n    if (duplicates)\n      throw new ItiTokenError(`Tokens already exist: ['${duplicates}']`)\n\n    // Step 2: If everything is fine add a newContext\n    let m = this.upsert(newContext)\n    return m as any\n  }\n  // {! [T in keyof NewContext]: NewContext[T] }\n  public addDisposer<\n    NewDisposerContext extends {\n      [T in keyof Context]?: (\n        cachedValue: UnPromisify<UnpackFunctionReturn<Context[T]>>,\n      ) => any\n    },\n  >(\n    newContextOrCb:\n      | NewDisposerContext\n      | ((\n          items: ContextGetter<Context>,\n          self: Container<Context, DisposeContext>,\n        ) => NewDisposerContext),\n  ): Container<Context, Assign<DisposeContext, NewDisposerContext>> {\n    let newDisposingCtx =\n      typeof newContextOrCb === \"function\"\n        ? newContextOrCb(this.items, this)\n        : newContextOrCb\n\n    // Step 1: Runtime check for existing tokens in a Dispose Context\n    const duplicates = _intersectionKeys(newDisposingCtx, this._disposeCtx)\n    if (duplicates)\n      throw new ItiTokenError(`Tokens already exist: ['${duplicates}']`)\n\n    // Step 2: Add disposer context\n    for (const [token, value] of Object.entries(newDisposingCtx)) {\n      this._disposeCtx[token] = value\n    }\n\n    return this as any\n  }\n\n  public _extractTokens<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n  ): T[] {\n    if (typeof tokensOrCb === \"function\") {\n      return tokensOrCb(this.getTokens()) as any\n    } else {\n      return tokensOrCb as any\n    }\n  }\n\n  public subscribeToContainerSet<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n    cb: (\n      err: any,\n      container: {\n        [K in T]: FullyUnpackObject<Context>[K]\n      },\n    ) => void,\n  ): () => void {\n    let tokens = this._extractTokens(tokensOrCb)\n    const upsertUnsubscribe = this.ee.on(\"containerUpserted\", async (ev) => {\n      if (tokens.includes(ev.key)) {\n        try {\n          const cSet = await this.getContainerSet(tokens)\n          cb(null, cSet)\n        } catch (err) {\n          cb(err, undefined as any)\n        }\n      }\n    })\n    const deleteUnsubscribe = this.ee.on(\"containerDeleted\", async (ev) => {\n      if (tokens.includes(ev.key)) {\n        cb({ containerRemoved: ev.key }, undefined as any)\n      }\n    })\n    return () => {\n      upsertUnsubscribe()\n      deleteUnsubscribe()\n    }\n  }\n\n  // this can be optimized\n  public async getContainerSet<T extends keyof Context>(\n    tokensOrCb: KeysOrCb<Context>,\n  ) {\n    let tokens: T[] = this._extractTokens(tokensOrCb)\n    let promiseTokens: T[] = []\n    let allPromises: any = []\n    for (let token of tokens) {\n      if (this.items[token] instanceof Promise) {\n        promiseTokens.push(token)\n        allPromises.push(this.items[token])\n      }\n    }\n\n    let containerDecoratedMap: {\n      [K in T]: FullyUnpackObject<Context>[K]\n    } = {} as any\n\n    // Step 1: Assign all values\n    tokens.forEach((token) => {\n      containerDecoratedMap[token as any] = this.items[token]\n    })\n\n    // Step 2: Overwrite Promise like values with promise results\n    const rez = await Promise.all(allPromises)\n    promiseTokens.forEach((token, index) => {\n      containerDecoratedMap[token] = rez[index]\n    })\n\n    return containerDecoratedMap\n  }\n\n  /**\n   * This is used to get a container from the context.\n   * It should always return a promise?\n   * But it seems that it is not possible to do that with the current implementation.\n   * @deprecated\n   */\n  public get containers() {\n    return this.items\n  }\n\n  public get items(): ContextGetter<Context> {\n    let itemMap = <ContextGetter<Context>>{}\n    for (let key in this.getTokens()) {\n      addGetter(itemMap, key, () => {\n        return this.get(key as any)\n      })\n    }\n    return itemMap\n  }\n}\n\nexport function createContainer() {\n  return new Container()\n}\n","/**\n * From\n * https://github.com/ai/nanoevents\n *\n * Sadly, can't install it via npm. Some build issue\n */\n\n//////////////////\n\ninterface EventsMap {\n  [event: string]: any\n}\n\ninterface DefaultEvents extends EventsMap {\n  [event: string]: (...args: any) => void\n}\n\nexport interface Unsubscribe {\n  (): void\n}\n\nexport declare class Emitter<Events extends EventsMap = DefaultEvents> {\n  /**\n   * Event names in keys and arrays with listeners in values.\n   *\n   * ```js\n   * emitter1.events = emitter2.events\n   * emitter2.events = { }\n   * ```\n   */\n  events: Partial<{ [E in keyof Events]: Events[E][] }>\n\n  /**\n   * Add a listener for a given event.\n   *\n   * ```js\n   * const unbind = ee.on('tick', (tickType, tickDuration) => {\n   *   count += 1\n   * })\n   *\n   * disable () {\n   *   unbind()\n   * }\n   * ```\n   *\n   * @param event The event name.\n   * @param cb The listener function.\n   * @returns Unbind listener from event.\n   */\n  on<K extends keyof Events>(this: this, event: K, cb: Events[K]): Unsubscribe\n\n  /**\n   * Calls each of the listeners registered for a given event.\n   *\n   * ```js\n   * ee.emit('tick', tickType, tickDuration)\n   * ```\n   *\n   * @param event The event name.\n   * @param args The arguments for listeners.\n   */\n  emit<K extends keyof Events>(\n    this: this,\n    event: K,\n    ...args: Parameters<Events[K]>\n  ): void\n}\n\n/**\n * Create event emitter.\n *\n * ```js\n * import { createNanoEvents } from 'nanoevents'\n *\n * class Ticker {\n *   constructor() {\n *     this.emitter = createNanoEvents()\n *   }\n *   on(...args) {\n *     return this.emitter.on(...args)\n *   }\n *   tick() {\n *     this.emitter.emit('tick')\n *   }\n * }\n * ```\n */\n\nexport function createNanoEvents<\n  Events extends EventsMap = DefaultEvents,\n>(): Emitter<Events> {\n  return {\n    events: {},\n    emit(event, ...args) {\n      // @ts-expect-error\n      ;(this.events[event] || []).forEach((i) => i(...args))\n    },\n    on(event, cb) {\n      // @ts-expect-error\n      ;(this.events[event] = this.events[event] || []).push(cb)\n      return () =>\n        // @ts-expect-error\n        (this.events[event] = (this.events[event] || []).filter(\n          (i) => i !== cb,\n        ))\n    },\n  }\n}\n"],"names":["_intersectionKeys","needle","haystack","duplicates","Object","keys","filter","x","length","join","ItiError","Error","ItiResolveError","ItiTokenError","Node","_this","_cache","_context","_disposeCtx","ee","events","emit","event","this","forEach","i","on","cb","push","callback","get","token","storeInCache","v","_this2","key","newContainer","tokenValue","providedValue","String","dispose","disposerFn","_this4","Promise","resolve","cachedValueResolved","disposeResult","cleanup","then","disposeAll","thingsToDispose","_this6","map","all","_updateContext","updatedContext","entries","value","subscribeToContainer","upsertUnsubscribe","ev","_this7","data","error","undefined","deleteUnsubscribe","containerRemoved","getTokens","fromEntries","el","Container","upsert","newContext","nc","items","add","newContextOrCb","addDisposer","newDisposingCtx","_extractTokens","tokensOrCb","subscribeToContainerSet","tokens","includes","_this8","getContainerSet","cSet","err","_this10","promiseTokens","allPromises","containerDecoratedMap","rez","index","itemMap","object","fn","defineProperty","enumerable","addGetter","_this11","createContainer"],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/iti.cjs.map b/dist/iti.cjs.map
deleted file mode 100644
index 146ab6e800678da39399e877c100776159378bda..0000000000000000000000000000000000000000
diff --git a/dist/src/iti.d.ts b/dist/iti.d.ts
similarity index 96%
rename from dist/src/iti.d.ts
rename to dist/iti.d.ts
index 95a6bb294dd34509632085c6593280625d32b9e1..954b806e16078abd28df0898205ea8809116917c 100644
--- a/dist/src/iti.d.ts
+++ b/dist/iti.d.ts
@@ -1,6 +1,6 @@
 import { Intersection } from "utility-types";
-import { Emitter } from "./nanoevents";
-import { Prettify, Assign, KeysOrCb, ContextGetter, UnpackFunction, MyRecord, FullyUnpackObject, UnPromisify, UnpackFunctionReturn } from "./_utils";
+import { Emitter } from "./nanoevents.js";
+import { Prettify, Assign, KeysOrCb, ContextGetter, UnpackFunction, MyRecord, FullyUnpackObject, UnPromisify, UnpackFunctionReturn } from "./_utils.js";
 declare abstract class AbstractNode<Context extends {}> {
     abstract get<T extends keyof Context>(token: T): UnpackFunction<Context[T]>;
     abstract getTokens<T extends keyof Context>(): {
diff --git a/dist/iti.modern.js b/dist/iti.modern.js
deleted file mode 100644
index 54a2d59b2da16ef9aa9fb5eb9c4c8c85c542fa14..0000000000000000000000000000000000000000
diff --git a/dist/iti.modern.js.map b/dist/iti.modern.js.map
deleted file mode 100644
index 35166d5002bd6b7020592452181a957d31c4f129..0000000000000000000000000000000000000000
diff --git a/dist/iti.module.js.map b/dist/iti.module.js.map
deleted file mode 100644
index 419e354850ae2b48fb2aef0119a041f7c5038f0d..0000000000000000000000000000000000000000
diff --git a/dist/iti.umd.js.map b/dist/iti.umd.js.map
deleted file mode 100644
index 8b9c4c7375b10f3b3d792bffc874d52e9cb7c63e..0000000000000000000000000000000000000000
diff --git a/dist/src/nanoevents.d.ts b/dist/nanoevents.d.ts
similarity index 100%
rename from dist/src/nanoevents.d.ts
rename to dist/nanoevents.d.ts
diff --git a/dist/tests/_utils.d.ts b/dist/tests/_utils.d.ts
deleted file mode 100644
index 0e4598b51e6cd6d6c673d3154d4ff7bc4cbabf48..0000000000000000000000000000000000000000
diff --git a/dist/tests/container-get-values.spec.d.ts b/dist/tests/container-get-values.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/container-getter.spec.d.ts b/dist/tests/container-getter.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/container-set.spec.d.ts b/dist/tests/container-set.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/dispose-graph.ts.api.spec.d.ts b/dist/tests/dispose-graph.ts.api.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/dispose.ts.api.spec.d.ts b/dist/tests/dispose.ts.api.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/exotic.spec.d.ts b/dist/tests/exotic.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/getter.spec.d.ts b/dist/tests/getter.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/mock-graph.d.ts b/dist/tests/mock-graph.d.ts
deleted file mode 100644
index 1e0697f4cd2f2a6111312b36147f4bfff5c023d5..0000000000000000000000000000000000000000
diff --git a/dist/tests/mocks/_mock-app-container.d.ts b/dist/tests/mocks/_mock-app-container.d.ts
deleted file mode 100644
index 647708f37ea2ec13bccc26fd5feddc0885067c9d..0000000000000000000000000000000000000000
diff --git a/dist/tests/mocks/container.a.d.ts b/dist/tests/mocks/container.a.d.ts
deleted file mode 100644
index 5a79286d514ad565d032d2227950b0e72cadee31..0000000000000000000000000000000000000000
diff --git a/dist/tests/mocks/container.b.d.ts b/dist/tests/mocks/container.b.d.ts
deleted file mode 100644
index f4e22c7f8a191de8c19e460ac64652d33e67fb7f..0000000000000000000000000000000000000000
diff --git a/dist/tests/mocks/container.c.d.ts b/dist/tests/mocks/container.c.d.ts
deleted file mode 100644
index c03756062d8e45ecdc645b2da5eba40056d4e40a..0000000000000000000000000000000000000000
diff --git a/dist/tests/mocks/store.a.d.ts b/dist/tests/mocks/store.a.d.ts
deleted file mode 100644
index 133d77252a62a6bad14dace03d1635c87c4a3047..0000000000000000000000000000000000000000
diff --git a/dist/tests/mocks/store.b.d.ts b/dist/tests/mocks/store.b.d.ts
deleted file mode 100644
index c9b94e58453f1eadaa2ec5176fbf6d967b2ab83b..0000000000000000000000000000000000000000
diff --git a/dist/tests/mocks/store.c.d.ts b/dist/tests/mocks/store.c.d.ts
deleted file mode 100644
index 81e4645a74bb8952edb986c9fedde4f499cb3038..0000000000000000000000000000000000000000
diff --git a/dist/tests/tsd.container-set-types.spec.d.ts b/dist/tests/tsd.container-set-types.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/tsd.getter.tsd-only.d.ts b/dist/tests/tsd.getter.tsd-only.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/dist/tests/update.api.spec.d.ts b/dist/tests/update.api.spec.d.ts
deleted file mode 100644
index 509db1866f4b5fbb3046d4c04b51ccb638e79c80..0000000000000000000000000000000000000000
diff --git a/package.json b/package.json
index 0faaf4928c686cea69edae1fc91fd7797f22cde4..d43f3181292e9c8e5baad2e89bb867b2f0d6a608 100644
--- a/package.json
+++ b/package.json
@@ -5,19 +5,23 @@
   "type": "module",
   "sideEffects": false,
   "source": "src/index.ts",
+  "main": "./dist/index.cjs",
+  "module": "./dist/index.modern.js",
+  "types": "./dist/index.d.ts",
   "exports": {
-    "require": "./dist/iti.cjs",
-    "default": "./dist/iti.modern.js"
+    "require": { 
+        "default": "./dist/index.cjs",
+        "types": "./dist/index.d.cts"
+    },
+    "import": "./dist/index.modern.js",
+    "types": "./dist/index.d.ts"
   },
-  "main": "./dist/iti.cjs",
-  "module": "./dist/iti.module.js",
-  "typings": "./dist/src/index.d.ts",
   "files": [
     "dist"
   ],
   "scripts": {
     "_build": "rm -rf ./dist && microbundle build -o dist/ && cp -R src/* dist/src",
-    "build": "rm -rf ./dist && microbundle build -o dist/",
+    "build": "rm -rf ./dist && microbundle build && cp dist/index.d.ts dist/index.d.cts",
     "jest": "jest",
     "stryker": "stryker",
     "stryker:run": "stryker run",
@@ -35,9 +39,9 @@
     "@types/jest": "^27.4.1",
     "@types/react": "^18.0.15",
     "jest": "^27.4.7",
-    "stryker-cli": "^1.0.2",
     "microbundle": "^0.15.0",
     "nodemon": "^2.0.19",
+    "stryker-cli": "^1.0.2",
     "ts-jest": "^27.1.3",
     "tsd": "^0.22.0",
     "typescript": "^4.7.4"
loicnestler commented 2 months ago

@molszanski is this PR ready for merging?