• Модуль магазина как отдельный сервис. Хорошая ли идея и если да, то какие есть решения?

    @romaro
    Еще не совсем понятно: как у вас на данный момент реализован учет товарных остатков вашего мерча? Видимо, никак. Тогда можно присмотреться к интеграции "МойСклад" и стороннего сервиса интернет-магазина. Это все равно будет проще и быстрее, чем писать свою платформу. Пусть даже придется с какими-то костылями мириться.
  • Модуль магазина как отдельный сервис. Хорошая ли идея и если да, то какие есть решения?

    @romaro
    GizzaProger, как человек, который в еком логистике почти 10 лет, скажу, что да, сложности есть... Вам по-хорошему нужен либо бекендер с опытом в екоммерс (обычно у таких по умолчанию хороший беграунд в базах данных и навыки бизнес-аналитика), который согласует с вашим фронтом API и реализует всю логику под ваш фронтенд. Это тот путь, по которому мы в свое время пошли и он не сильно быстрый.

    Второй вариант вы сами назвали. Если не найдете готового решения, то почему бы не управлять готовым сервисом вроде InSales, у которого уже есть API, в том числе для управления состоянием каталога, заказами и т.д.
  • Модуль магазина как отдельный сервис. Хорошая ли идея и если да, то какие есть решения?

    @romaro
    Вы, видимо, хотите shop backend as a service? Пульнул метод "Обновить остатки" и там само все как-то обновилось, а вы по другой апишке получаете актуальное состояние склада? Или передал заказ по адресу /orders/create и потом знай только статусы обновляй по тому же api через свой gui?

    Просто делали нечто подобное для внутренних нужд в свое время, т.к. готовых решений найти не удалось.
  • Не является ли создание глобального контекста антипаттерном?

    @romaro Автор вопроса
    Поскольку у меня веб-серверное приложение и оно используется для обработки запросов, получается, что глобальный контекст (g) действительно часто используется (передается в конструкторы классов) вместе с контекстом самого запроса (ctx). Однако разницу между этими двумя сущностями я вижу в их жизненном цикле: глобальный контекст не меняется за все время работы приложения. Т.е. вне зависимости от пользовательских запросов, состояние условного мейлера или работа пула соединений с БД, неизменно.

    В существовании контекста уровня приложения вряд ли есть что-то плохое. Вопрос в реализации. Если я оказываюсь от инкапсуляции этого контекста в объектную переменную g, которая затем передается во все конструкторы "рабочих" классов, то нужно как-то по-другому сделать это состояние доступным, над чем я и ломаю голову :)

    Условный мейлер я могу вынести в микросервис. Но сама переменная g выглядит удобным транспортным контейнером, который позволяет, при необходимости, быстро внедрить любой сервис во все приложение, сделав его частью общего состояния.
  • Не является ли создание глобального контекста антипаттерном?

    @romaro Автор вопроса
    WbICHA, ну почему? Контекст, который я создаю, можно сделать инстансом класса (у меня вначале так и было). Этот класс не имеет собственного функционала, а является лишь транспортным контейнером для экземпляров "рабочих" классов.

    Мне хочется понять, как грамотно внедрять зависимости, которые представляют собой не сами классы, а их экземпляры с состоянием, которое не меняется за время работы приложения.

    Наверное, что-то вроде DI-фреймворков, которые активно используются в андроид-разработке. Но и там некоторые советуют ограничиться созданием класса для хранения глобального состояние приложения.
  • Как использовать типизацию только из tsconfig["lib"]?

    @romaro
    Я правильно понял, что вас смутил переход в @types/node из подсказки в IDE? Но ведь это же не имеет отношение к работе компилятора TypeScript. То есть вы можете вообще писать на JS, подсказки все равно будут подтягиваться из деклараций. И да, когда вы даунгрейдили типы для node, IDE перестала отображать подсказки для более нового синтаксиса.
  • Как не удалять директорию во время компиляции?

    @romaro
    А компиляцию запускаете через tsc или nest-cli?
  • Как правильно организовать экспорт/импорт деклараций внутри проекта?

    @romaro Автор вопроса
    WbICHA, я похоже понял, в чем моя ошибка: в использовании import. TS переводит файл в модульный режим и его приходится импортировать. Но если объявить тип без использования экспорта, то включается "скриптовый режим" и все декларации оказываются в общей области видимости. Соответственно, декларации из таких файлов не нужно импортировать. То есть мне нужно разобраться с областью видимости и declare (в том числе declare module и declare namespace)
  • Как правильно написать дженерик вместо наследования?

    @romaro Автор вопроса
    Код действительно получается сложнее, чем с наследованием. Вы бы тоже решали через наследование?
  • Как замапить массив?

    @romaro
    Алексей Уколов, нашел в документации и разобрался.

    WbICHA, с каждым днем все лучше))
  • Как замапить массив?

    @romaro
    WbICHA, Алексей Уколов, поскольку я плохо знаком с синтаксисом Реакта (а вопрос имеет два тега, один из которых относится к чистому JS), то с ходу и не сообразил, что в пропс key сразу передается объект и фигурные скобки в записи {...obj.pizzas} означают банальную переупаковку, а не метку шаблонизатора. В таком случае (если нужно, чтобы title оказался на первом месте), проще, наверное, записать так:
    key={ pizza.title, ...pizza }
  • Как замапить массив?

    @romaro
    Алексей Уколов, это только у объектов, для которых реализован [Symbol.iterator]. Не получится без него: https://playcode.io/903033
  • Как найти все дочерние компоненты родителя?

    @romaro Автор вопроса
    Да, подсветит все дочерние компоненты. Было бы удобно, если я меняю один компонент на другой, видеть, где нужно выполнить замены. Можно конечно заняться рефакторингом и внутри основного компонента, но бывает, что компонент уже готов и просто нужно заменить.
  • У кого-нибудь есть опыт подобной архитектуры с Postgres?

    @romaro Автор вопроса
    Можно ли как-то с вами связаться для платных консультаций?
  • Как типизировать зависимость вывода функции от типа аргумента?

    @romaro Автор вопроса
    Тут наверное лучше наследоваться от типа, чтобы каждый раз не указывать очевидный тип перед вызовом функции:
    type F = <T extends string | number>(p: T) => T;
    const f: F = (p) => p;
    f(55);
  • Возможно ли функцией next(); передать переменные?

    @romaro
    Никита Савченко, locals — это всего лишь рекомендация по именованию объекта, которым вы расширяете req. Можете назвать req.ctx, не принципиально. Просто нужно понять, что middleware выполняются одна за другой (т.е. синхронно). Затем подумать, а что, собственно, следующая middleware знает о предыдущей? Очевидно, только объекты Request (req) и Response (res), ведь именно они передаются в параметры каждой middleware. Соответственно, чтобы передать данные из одного обработичка в другой, вам нужно как-то поместить их в один из этих объектов. Обычно для этого расширяют объект Response и вы это сделали, но не в том месте. Перепишите вот так, если вам удобно работать с контекстом

    app.post("/register", urlencodedParser, async(req, res, next) => {
        req.locals = {
          name: req.body.username,
          email: req.body.email,
          password: req.body.password
        }
        // ...


    Но вы можете вообще никакой locals не объявлять, а достать данные из body:
    app.post('/email-verification', async(req, res) => {
        if (req.body.code === code) {
            const post = {
                    name: req.body.name,
                    email: req.body.email,
                    password: req.body.password


    Конечно, можно использовать app.locals и при каждом запросе перезаписывать глобальные переменные, но это совсем не тот юзеркейс, для которого предназначено указанное API
  • Возможно ли функцией next(); передать переменные?

    @romaro
    Никита Савченко, в этом нет ничего удивительного, ведь в документации по API Экспресса прямо указывается, что свойство app.locals для глобальных переменных уровня инстанса приложения.

    Вам же требуется сохранить контекст конкретного запроса. Попробуйте объявить объект до условной логики:
    app.post("/register", urlencodedParser, async(req, res, next) => {
        // Создаете объект до ветвлений if, назвать можно как угодно
        req.locals = {};
        ...
    });


    У вас ошибка, видимо, связана с тем, что if-ветка с render() не отрабатывает, а объект создавался именно в ней. Соответственно, следующий обработчик объекта не увидит
  • Возможно ли функцией next(); передать переменные?

    @romaro
    Попробуйте сначала добавить locals в req
  • У кого-нибудь есть опыт подобной архитектуры с Postgres?

    @romaro Автор вопроса
    mayton2019, если говорить в терминах Оракла, то там подключаемые БД (pluggable database) наиболее близки к этому. Кажется, с версии 12 он их поддерживает.