reactuse icon indicating copy to clipboard operation
reactuse copied to clipboard

[doc]: Добавить возможность копипаста реализации хуков из доки

Open loonlylokly opened this issue 1 year ago • 6 comments

Иногда не хочется тянуть отдельный пакет с хуками ради одного или двух хуков. Многие хуки вполне самодостаточны и их можно запихнуть в 1-2 небольших файла. А значит можно сделать реализацию на подобие shadcn/ui, где есть "ручная(manual)" установка. И нужно только скопировать код и вставить. Ну и установить что-то сторонние, если в хуке такое нужно. Хотя это определённо снизит количество скачиваний npm пакета((

loonlylokly avatar Jul 28 '24 20:07 loonlylokly

https://github.com/novajslabs/cli/blob/main/src/commands/add.ts cli можно добавиь на ряду с этим, вообще я считаю, что это уже золотой стандарт

debabin avatar Jul 29 '24 07:07 debabin

  • [ ] cli
  • [ ] транспиляция из ts в js для cli

debabin avatar Jul 29 '24 07:07 debabin

Попробую сделать.

zeroqs avatar Jul 29 '24 12:07 zeroqs

@zeroqs хорошо, сразу скажу пару вводных, в mock-config-server есть схожее и это очень легко сделать на самом деле

  1. Надо научиться превращать ts в читаймый js
  2. Надо создать папку bin и в ней реализовать скрипт похожий https://github.com/novajslabs/cli/blob/main/src/commands/add.ts

debabin avatar Jul 29 '24 14:07 debabin

@zeroqs хорошо, сразу скажу пару вводных, в mock-config-server есть схожее и это очень легко сделать на самом деле

  1. Надо научиться превращать ts в читаймый js
  2. Надо создать папку bin и в ней реализовать скрипт похожий https://github.com/novajslabs/cli/blob/main/src/commands/add.ts

Вот либы https://github.com/elyx-code/typescript-to-js https://github.com/ritz078/transform/tree/master ( Web - https://transform.tools/typescript-to-javascript )

https://github.com/jerosoler/ts2js - вроде прикольно но юзает monaco-editor ( https://www.npmjs.com/package/monaco-editor ) не знаю на сколько ок его сюда тащить

Но как я понял без babel никак, но он оч сильно раздует бандл ( Тогда можно вынести в отдельный "пакет" как в shadcn - https://github.com/shadcn-ui/ui/tree/main/packages)

И еще момент со сборкой, если я помещу папку bin на один и тот же уровень с папкой src, то он не окажется в сборке, как фиксануть ?

Просто щас я создал ее внутри src и получается cli есть и на cjs и на esm модулях, хотя я думаю это не оч правильно. Постарался в конфиг роллапа, зашел в core пакет увидел что output опций только два как раз на cjs и esm

На счет сборки, можно вынести в отдельный "пакет" как в shadcn - https://github.com/shadcn-ui/ui/tree/main/packages Просто я сейчас захотел использовать ora - https://www.npmjs.com/package/ora, а там падает ошибка когда я использую spinner - ReferenceError: navigator is not defined, ну я вроде понял почему, но не уверен.

UPD:

Сделал в отдельной директории и думаю проблем с babel не будет уже, сделал в отдельном потому что если делать в основном то будут тянутся не нужные зависимости если юзер скачает хуки npm пакетом

Осталось проблема в скачивании хука если он имеет зависимость от импортируемого типа или чего либо еще. Я пока додумался только на проверку присутствует ли импорт который начинается с @/ и если да то скачивать его тоже

zeroqs avatar Jul 31 '24 19:07 zeroqs

И я не совсем понимаю cli это минимальный вариант, а в самой доке реализация для копипаста, это идеал или наоборот?))

А почему нельзя бабелем транспиляцию сделать? Вроде должно остаться читабельным. Что-то типо этого использовать в конфиге:

"presets": [
    "@babel/preset-typescript",
    ["@babel/preset-env", { "targets": { "node": "current" } }]
  ]

А синтаксис подсвечивать легкой https://prismjs.com/ (в doka используется она, других не знаю))) В shadcn кстати вообще только ts

loonlylokly avatar Aug 01 '24 14:08 loonlylokly

@debabin

Вообщем-с апдейт по cli

Эта версия написана с использованием API гитхаба в следствие чего есть лимит по использованию. Я решил пойти и узнать как там в shadcn это сделано ( фетч хука, как ? откуда ? и тп )

Как это в shadcn ?

Есть такой основной реестр который формируется скриптом отсюда

 import { registry } from "../registry"

 const result = registrySchema.safeParse(registry)
 
 await buildRegistry(result.data)

Импорт под-реестра который формирует основной реестр вот тут, нам ток ui интересен

import { ui } from "@/registry/registry-ui"

export const registry = {
  name: "shadcn/ui",
  homepage: "https://ui.shadcn.com",
  items: [
    ...ui,
    ...blocks,
    ...charts,
    ...lib,
    ...hooks,
    ...themes,

    // Internal use only.
    ...internal,
    ...examples,
  ],
} 

Ну и вот он и получается он в ручную описан ? ( Я вот этого не понял )

Дальше имеем вот такой json реестра который хостится тут - https://ui.shadcn.com/registry/index.json и к которому делают запросы при добавлении компонента ( там происходит анализ нужен ли компоненту другой компонент, и тп )

const baseUrl

registryIndex = await getRegistryIndex()

вот тут get реестра getRegistryIndex()

вот тут фетч реестра fetchRegistry()

const baseUrl = process.env.COMPONENTS_REGISTRY_URL ?? "https://ui.shadcn.com"

const registryIndex = await getRegistryIndex() 

export async function getRegistryIndex() {
  try {
    const [result] = await fetchRegistry(["index.json"])

    return registryIndexSchema.parse(result)
  } catch (error) {
    throw new Error(`Failed to fetch components from registry.`)
  }
}

async function fetchRegistry(paths: string[]) {
  try {
    const results = await Promise.all(
      paths.map(async (path) => {
        const response = await fetch(`${baseUrl}/registry/${path}`, {
          agent,
        })
        return await response.json()
      })
    )

    return results
  } catch (error) {
    console.log(error)
    throw new Error(`Failed to fetch registry from ${baseUrl}.`)
  }
}

Что придумал сделать

Сделать скрипт формирование реестра который будет в себя включать 1 запрос на весь список хуков потом они будут записаны в реестр с их зависимостями что то типо такого и потом при добавлении хука командой add будет фетч в наш реестр хуков и получается скачивание хука, если есть зависимости то скачать их тоже.

Может возникнуть вопрос что за localDependency, я так обозначил вот например как тут я про constants, но возник вопрос нужны ли нам localDependency потому что я посмотрел и эти constants нужны для демки, вообщем имеет ли смысл localDependency

Вопрос Как анализировать использует ли хук другие хуки или функции из utils ? Я додумался только до регулярки

     const registry = [
     {
         name: hookName,
         localDependency: [],
         hookDependency: [],
         utilsDependency: []
     },
      ...
     ]

И будет что то типо

     const registry = [
     {
         name: useActiveElement,
         localDependency: [],
         hookDependency: ["useMutationObserver"],
         utilsDependency: []
     },
     {
         name: useDebounceCallback,
         localDependency: [],
         hookDependency: ["useEvent"],
         utilsDependency: ["debounce "]
     },
      ...
     ]

А как я буду качать хуки?

Вот так - https://raw.githubusercontent.com/siberiacancode/reactuse/main/src/hooks/useAsync/useAsync.ts

Ну то есть проходится по всему реестру и просто качать + анализировать если ли зависимости и если есть качать их тоже

Вроде как ничего не упустил, было сложно так как вообще первый раз занимаюсь прям таким изучением чужих исходников ( я про опен сорс и либы в частности ) но интересно, вот вообщем все, что думаешь ?

Надеюсь ничего не упустил 👉👈

UPD: raw.githubusercontent.com - Ограна по api не имеет потому что это не апишка ( удивительно :) ), но тк это запрос к статическому файлу, то там могут быть свои ограны, так что надо будет наверное все таки качать себе на сервак или чет такое

Также вместо регулярок для поиска импорта можно использовать acorn с плагином для поддержки ts Вот репка я уже начал - https://github.com/zeroqs/hook-imports-analyzer

zeroqs avatar Feb 02 '25 06:02 zeroqs

Импорт под-реестра который формирует основной реестр вот тут, нам ток ui интересен

А почему нам интересен только ui? Там вроде хуки тоже есть. (или я затупил и это про названия их репозитория?)))

loonlylokly avatar Feb 17 '25 05:02 loonlylokly

Как анализировать использует ли хук другие хуки или функции из utils ? Я додумался только до регулярки

А типы будут учитываться как локальные зависимоти, да? useParallax

Надеюсь ничего не упустил 👉👈

А что по поводу конфигурации у пользователя. Куда будем устанавливать и что уже установленно из зависимостей. Я так понимаю нужен какой-то аналог "components.json" вот такой только видимо reactuse.json (для универсальности лучше, чем просто hooks.json) А также возможно стоит предусмотреть флаг изменения имени хука в cli команде для установки. (Ну мало ли, вдруг мне нужно две разных реализации одного хука или какой-нибудь shadcn использует свой хук, а с новым хуком он сломается)

так что надо будет наверное все таки качать себе на сервак

Ну и статискику использования можно будет собирать) Или она и так как-то будет учитываться при использовании cli?

loonlylokly avatar Feb 17 '25 05:02 loonlylokly

@debabin наверно можно закрывать

zeroqs avatar Mar 07 '25 20:03 zeroqs