Комментарии 2
В сравнительной таблице DI нет vue :(
Чем вам обычные импорты из barrell-файла не угодили?). Мы обеспечиваем "безопасность" правилами линтер, а не фактом DI-контейнера. Значит мы можем использовать нативные возможности языка, вместо контейнера, который тоже является зависимостью (в данном случае) и может "сменить парадигму или устареть" 😁.
Я не сильно понял тейк о том, как факт контейнера влияет на обеспечение принципа инверсии зависимостей. Для меня достижение принципа происходит с помощью написания некого "адаптера" (wrapper'а) над зависимостью N, предоставляющего свой интерфейс, который контролируется нами...
Признаюсь честно, я не сильно знаком с DDD, так как на фронтенде оно не используется (в чистом виде так уж точно). Как говорил один человек: "Мысль номер 1: никогда не делайте DDD на фронтенде. Это первая заповедь. Как это говорят: есть один человек который сделал DDD на фронтенде, потом его конечно в "психушку" забрали...". Пока за 2е статьи сделал вывод, что если проект не вида "редактор кода", то выглядит это overhead'но.
Папка /features с линтером и правилами превентирования кроссимпортов выглядит проще для понимания...
Но даже так, с нетерпением жду следующих статей, ибо интересно, каким образом мы будем синхронизировать ui-стейт с бизнесовым
Для вашей проблемы есть лучшее решение
Описано в статье
«Инверсия контроля на голом TypeScript без боли» (habr.com/ru/post/541800/), он же лежит в основе $mol.
все зависимости это свойства одного объекта-контекста $. Дочерний контекст — это Object.create(parent) с переопределёнными полями, то есть обычное прототипное наследование. Ваш пример с AuthFacade и PaymentsGateway в таком виде:
namespace $ {
export interface AuthFacade { getAccessToken(): Promise<string | null> }
export let $auth: AuthFacade
export let $payments_gateway: PaymentsGatewayPort
export class $thing {
constructor(readonly $: typeof globalThis.$) {}
}
export class $create_payment extends $thing {
async run() {
const token = await this.$.$auth.getAccessToken()
return this.$.$payments_gateway.charge(token)
}
}
}
// Composition root — просто объект
const app = $.$ambient({ $auth: new CoreAuthFacade(), $payments_gateway: new HttpGateway() })
// Тест — подмена на поддереве, одна строка
const test = app.$ambient({ $auth: { getAccessToken: async () => 'fake' } })
Не нужен Symbol.for , проблема двух копий контрактов в бандле не возникает вообще.
Скоупов нет как отд сущности ( не нужны )
Подмена работает на любом поддереве,
Вес — ноль, плагины не нужны.

DI во фронтенде: от Context API к Composition Root