Repository: ieedan/jsrepo
Branch: main
Commit: aa1753d4a043
Files: 459
Total size: 1.1 MB
Directory structure:
gitextract__1f43wdr/
├── .changeset/
│ └── config.json
├── .github/
│ └── workflows/
│ ├── build-example-registries.yml
│ ├── bundle-analyze.yml
│ ├── ci.yml
│ ├── cli-preview.yml
│ ├── publish.yml
│ └── test-external-projects.yml
├── .gitignore
├── .vscode/
│ └── settings.json
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── apps/
│ └── docs/
│ ├── .gitignore
│ ├── README.md
│ ├── biome.json
│ ├── cli.json
│ ├── content/
│ │ └── docs/
│ │ ├── cli/
│ │ │ ├── add.mdx
│ │ │ ├── auth.mdx
│ │ │ ├── build.mdx
│ │ │ ├── config/
│ │ │ │ ├── language.mdx
│ │ │ │ ├── mcp.mdx
│ │ │ │ ├── meta.json
│ │ │ │ ├── provider.mdx
│ │ │ │ └── transform.mdx
│ │ │ ├── meta.json
│ │ │ ├── publish.mdx
│ │ │ └── update.mdx
│ │ ├── create-a-registry.mdx
│ │ ├── index.mdx
│ │ ├── jsrepo-com.mdx
│ │ ├── jsrepo-config.mdx
│ │ ├── languages/
│ │ │ ├── css.mdx
│ │ │ ├── html.mdx
│ │ │ ├── index.mdx
│ │ │ ├── js.mdx
│ │ │ ├── svelte.mdx
│ │ │ └── vue.mdx
│ │ ├── legacy.mdx
│ │ ├── mcp.mdx
│ │ ├── migrate.mdx
│ │ ├── outputs/
│ │ │ ├── distributed.mdx
│ │ │ ├── index.mdx
│ │ │ ├── repository.mdx
│ │ │ └── shadcn.mdx
│ │ ├── providers/
│ │ │ ├── azure.mdx
│ │ │ ├── bitbucket.mdx
│ │ │ ├── fs.mdx
│ │ │ ├── github.mdx
│ │ │ ├── gitlab.mdx
│ │ │ ├── http.mdx
│ │ │ ├── index.mdx
│ │ │ ├── jsrepo.mdx
│ │ │ └── shadcn.mdx
│ │ └── transforms/
│ │ ├── biome.mdx
│ │ ├── filecasing.mdx
│ │ ├── index.mdx
│ │ ├── javascript.mdx
│ │ ├── oxfmt.mdx
│ │ └── prettier.mdx
│ ├── instrumentation-client.js
│ ├── jsrepo.config.mts
│ ├── middleware.ts
│ ├── next.config.mjs
│ ├── og-image.d.ts
│ ├── package.json
│ ├── postcss.config.mjs
│ ├── source.config.ts
│ ├── src/
│ │ ├── app/
│ │ │ ├── (home)/
│ │ │ │ ├── code-block.tsx
│ │ │ │ ├── layout.tsx
│ │ │ │ ├── page.tsx
│ │ │ │ └── providers-section.tsx
│ │ │ ├── api/
│ │ │ │ └── search/
│ │ │ │ └── route.ts
│ │ │ ├── app-client.tsx
│ │ │ ├── docs/
│ │ │ │ ├── [[...slug]]/
│ │ │ │ │ └── page.tsx
│ │ │ │ └── layout.tsx
│ │ │ ├── global.css
│ │ │ ├── layout.tsx
│ │ │ ├── llms-full.txt/
│ │ │ │ └── route.ts
│ │ │ ├── llms.mdx/
│ │ │ │ └── [[...slug]]/
│ │ │ │ └── route.ts
│ │ │ ├── og/
│ │ │ │ ├── docs/
│ │ │ │ │ └── [...slug]/
│ │ │ │ │ └── route.tsx
│ │ │ │ └── route.tsx
│ │ │ └── robots.txt
│ │ ├── components/
│ │ │ ├── PrismaticBurst.tsx
│ │ │ ├── badges-table.tsx
│ │ │ ├── feature-tabs.tsx
│ │ │ ├── files.tsx
│ │ │ ├── language-toggle.tsx
│ │ │ ├── layout/
│ │ │ │ ├── home/
│ │ │ │ │ ├── client.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ └── shared/
│ │ │ │ ├── client.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── logos/
│ │ │ │ ├── antigravity.tsx
│ │ │ │ ├── azure-devops.tsx
│ │ │ │ ├── biome.tsx
│ │ │ │ ├── bitbucket.tsx
│ │ │ │ ├── claude.tsx
│ │ │ │ ├── css.tsx
│ │ │ │ ├── cursor.tsx
│ │ │ │ ├── github.tsx
│ │ │ │ ├── gitlab.tsx
│ │ │ │ ├── html.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── javascript.tsx
│ │ │ │ ├── jsrepo-com.tsx
│ │ │ │ ├── npm.tsx
│ │ │ │ ├── openai.tsx
│ │ │ │ ├── oxfmt.tsx
│ │ │ │ ├── prettier.tsx
│ │ │ │ ├── registry-kit.tsx
│ │ │ │ ├── shadcn.tsx
│ │ │ │ ├── svelte.tsx
│ │ │ │ ├── typescript.tsx
│ │ │ │ ├── vscode.tsx
│ │ │ │ └── vue.tsx
│ │ │ ├── navigation-menu.tsx
│ │ │ ├── page-actions.tsx
│ │ │ ├── registry-index.tsx
│ │ │ ├── registry-kit/
│ │ │ │ ├── demo-example.tsx
│ │ │ │ └── demo.tsx
│ │ │ ├── search-toggle.tsx
│ │ │ ├── sidebar.tsx
│ │ │ ├── theme-toggle.tsx
│ │ │ └── ui/
│ │ │ ├── accordion.tsx
│ │ │ ├── animated-beam.tsx
│ │ │ ├── badge.tsx
│ │ │ ├── button.tsx
│ │ │ ├── collapsible.tsx
│ │ │ ├── field.tsx
│ │ │ ├── github-button.tsx
│ │ │ ├── index.ts
│ │ │ ├── input-group.tsx
│ │ │ ├── input.tsx
│ │ │ ├── item.tsx
│ │ │ ├── label.tsx
│ │ │ ├── popover.tsx
│ │ │ ├── scroll-area.tsx
│ │ │ ├── separator.tsx
│ │ │ ├── sonner.tsx
│ │ │ ├── table.tsx
│ │ │ ├── tabs.tsx
│ │ │ ├── terminal.tsx
│ │ │ ├── textarea.tsx
│ │ │ ├── tooltip.tsx
│ │ │ └── underline-tabs.tsx
│ │ ├── hooks/
│ │ │ ├── use-copy-to-clipboard.tsx
│ │ │ └── use-scroll-to-top.tsx
│ │ ├── lib/
│ │ │ ├── cn.ts
│ │ │ ├── is-active.ts
│ │ │ ├── layout.shared.tsx
│ │ │ ├── og.ts
│ │ │ ├── source.ts
│ │ │ └── utils.ts
│ │ └── mdx-components.tsx
│ └── tsconfig.json
├── biome.json
├── examples/
│ ├── react/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── jsrepo.config.mts
│ │ ├── next.config.ts
│ │ ├── package.json
│ │ ├── postcss.config.mjs
│ │ ├── public/
│ │ │ └── r/
│ │ │ ├── button.json
│ │ │ ├── registry.json
│ │ │ ├── shadcn/
│ │ │ │ ├── button.json
│ │ │ │ ├── registry.json
│ │ │ │ └── utils.json
│ │ │ └── utils.json
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── demos/
│ │ │ │ │ └── button-demo/
│ │ │ │ │ └── page.tsx
│ │ │ │ ├── globals.css
│ │ │ │ ├── layout.tsx
│ │ │ │ └── page.tsx
│ │ │ └── registry/
│ │ │ ├── lib/
│ │ │ │ └── utils.ts
│ │ │ └── ui/
│ │ │ └── button.tsx
│ │ └── tsconfig.json
│ └── svelte/
│ ├── .gitignore
│ ├── .npmrc
│ ├── README.md
│ ├── biome.json
│ ├── jsrepo.config.ts
│ ├── package.json
│ ├── src/
│ │ ├── app.css
│ │ ├── app.d.ts
│ │ ├── app.html
│ │ ├── lib/
│ │ │ └── registry/
│ │ │ ├── lib/
│ │ │ │ └── utils.ts
│ │ │ └── ui/
│ │ │ └── button/
│ │ │ ├── button.svelte
│ │ │ └── index.ts
│ │ └── routes/
│ │ ├── +layout.svelte
│ │ ├── +page.svelte
│ │ └── demos/
│ │ └── button-demo/
│ │ └── +page.svelte
│ ├── static/
│ │ ├── r/
│ │ │ ├── button.json
│ │ │ ├── registry.json
│ │ │ └── utils.json
│ │ └── robots.txt
│ ├── svelte.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
├── package.json
├── packages/
│ ├── bun/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── workspace.ts
│ │ ├── tests/
│ │ │ ├── bun.test.ts
│ │ │ └── fixtures/
│ │ │ ├── bun-workspace/
│ │ │ │ ├── package.json
│ │ │ │ └── packages/
│ │ │ │ ├── bar/
│ │ │ │ │ └── package.json
│ │ │ │ └── foo/
│ │ │ │ └── package.json
│ │ │ └── bun-workspace-object/
│ │ │ ├── package.json
│ │ │ └── packages/
│ │ │ └── baz/
│ │ │ └── package.json
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── jsrepo/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── api/
│ │ │ │ ├── config.ts
│ │ │ │ ├── errors.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── langs/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── js.ts
│ │ │ │ ├── outputs.ts
│ │ │ │ ├── providers.ts
│ │ │ │ ├── utils.ts
│ │ │ │ └── warnings.ts
│ │ │ ├── bin.ts
│ │ │ ├── cli.ts
│ │ │ ├── commands/
│ │ │ │ ├── add.ts
│ │ │ │ ├── auth.ts
│ │ │ │ ├── build.ts
│ │ │ │ ├── config/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── language.ts
│ │ │ │ │ ├── mcp.ts
│ │ │ │ │ ├── provider.ts
│ │ │ │ │ └── transform.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── init.ts
│ │ │ │ ├── publish.ts
│ │ │ │ ├── update.ts
│ │ │ │ └── utils.ts
│ │ │ ├── langs/
│ │ │ │ ├── css.ts
│ │ │ │ ├── html.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── js.ts
│ │ │ │ ├── svelte.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── vue.ts
│ │ │ ├── outputs/
│ │ │ │ ├── distributed.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── repository.ts
│ │ │ │ └── types.ts
│ │ │ ├── providers/
│ │ │ │ ├── azure.ts
│ │ │ │ ├── bitbucket.ts
│ │ │ │ ├── fs.ts
│ │ │ │ ├── github.ts
│ │ │ │ ├── gitlab.ts
│ │ │ │ ├── http.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jsrepo.ts
│ │ │ │ └── types.ts
│ │ │ └── utils/
│ │ │ ├── add.ts
│ │ │ ├── build.ts
│ │ │ ├── casing.ts
│ │ │ ├── compat/
│ │ │ │ └── shadcn.ts
│ │ │ ├── config/
│ │ │ │ ├── index.ts
│ │ │ │ ├── mods/
│ │ │ │ │ ├── add-plugins.ts
│ │ │ │ │ ├── add-registries.ts
│ │ │ │ │ └── update-paths.ts
│ │ │ │ └── utils.ts
│ │ │ ├── diff.ts
│ │ │ ├── env.ts
│ │ │ ├── errors.ts
│ │ │ ├── fs.ts
│ │ │ ├── glob.ts
│ │ │ ├── hooks.ts
│ │ │ ├── json.ts
│ │ │ ├── lines.ts
│ │ │ ├── package.ts
│ │ │ ├── pad.ts
│ │ │ ├── parse-package-name.ts
│ │ │ ├── path.ts
│ │ │ ├── persisted.ts
│ │ │ ├── prompts.ts
│ │ │ ├── roles.ts
│ │ │ ├── strings.ts
│ │ │ ├── token-manager.ts
│ │ │ ├── tsconfig.ts
│ │ │ ├── types.ts
│ │ │ ├── url.ts
│ │ │ ├── utils.ts
│ │ │ ├── validate-npm-package-name.ts
│ │ │ ├── warnings.ts
│ │ │ └── zod.ts
│ │ ├── tests/
│ │ │ ├── __mocks__/
│ │ │ │ ├── fs/
│ │ │ │ │ └── promises.cjs
│ │ │ │ └── fs.cjs
│ │ │ ├── build.test.ts
│ │ │ ├── config.test.ts
│ │ │ ├── fixtures/
│ │ │ │ ├── build/
│ │ │ │ │ ├── .npmignore
│ │ │ │ │ ├── .npmrc
│ │ │ │ │ ├── jsrepo.config.ts
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── src/
│ │ │ │ │ ├── components/
│ │ │ │ │ │ └── ui/
│ │ │ │ │ │ ├── button.tsx
│ │ │ │ │ │ ├── counter.svelte
│ │ │ │ │ │ ├── empty/
│ │ │ │ │ │ │ ├── empty-content.svelte
│ │ │ │ │ │ │ ├── empty.svelte
│ │ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ └── lanyard/
│ │ │ │ │ │ ├── Lanyard.tsx
│ │ │ │ │ │ └── card.glb
│ │ │ │ │ ├── routes/
│ │ │ │ │ │ ├── demo/
│ │ │ │ │ │ │ ├── +page.server.ts
│ │ │ │ │ │ │ └── +page.svelte
│ │ │ │ │ │ └── demos/
│ │ │ │ │ │ ├── button-default.tsx
│ │ │ │ │ │ ├── button-loading.tsx
│ │ │ │ │ │ └── subdir/
│ │ │ │ │ │ ├── button-subdir.tsx
│ │ │ │ │ │ └── nested/
│ │ │ │ │ │ └── button-nested.tsx
│ │ │ │ │ ├── utils/
│ │ │ │ │ │ ├── math/
│ │ │ │ │ │ │ ├── add.test.ts
│ │ │ │ │ │ │ ├── add.ts
│ │ │ │ │ │ │ ├── answer-format.test.ts
│ │ │ │ │ │ │ └── answer-format.ts
│ │ │ │ │ │ ├── shiki.ts
│ │ │ │ │ │ └── stdout.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── config/
│ │ │ │ │ ├── basic/
│ │ │ │ │ │ └── jsrepo.config.ts
│ │ │ │ │ ├── mts/
│ │ │ │ │ │ └── jsrepo.config.mts
│ │ │ │ │ └── nested/
│ │ │ │ │ └── jsrepo.config.ts
│ │ │ │ └── langs/
│ │ │ │ ├── js/
│ │ │ │ │ ├── logger.ts
│ │ │ │ │ ├── math/
│ │ │ │ │ │ ├── add.ts
│ │ │ │ │ │ └── subtract.ts
│ │ │ │ │ ├── print-answer.ts
│ │ │ │ │ └── stdout.ts
│ │ │ │ ├── js-arbitrary-extensions/
│ │ │ │ │ ├── component.svelte
│ │ │ │ │ ├── config.json
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── svelte-entry.ts
│ │ │ │ ├── js-baseurl-bare-imports/
│ │ │ │ │ ├── package.json
│ │ │ │ │ ├── tsconfig.json
│ │ │ │ │ └── types.ts
│ │ │ │ ├── js-subpath-imports/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── package.json
│ │ │ │ │ └── src/
│ │ │ │ │ ├── meta.ts
│ │ │ │ │ └── utils/
│ │ │ │ │ └── print.ts
│ │ │ │ └── svelte/
│ │ │ │ └── page.svelte
│ │ │ ├── langs/
│ │ │ │ ├── js.test.ts
│ │ │ │ └── svelte.test.ts
│ │ │ ├── providers/
│ │ │ │ ├── azure.test.ts
│ │ │ │ ├── bitbucket.test.ts
│ │ │ │ ├── fs.test.ts
│ │ │ │ ├── github.test.ts
│ │ │ │ ├── gitlab.test.ts
│ │ │ │ └── http.test.ts
│ │ │ └── utils/
│ │ │ ├── add-plugins-to-config.test.ts
│ │ │ ├── add-registries.test.ts
│ │ │ ├── add.test.ts
│ │ │ ├── casing.test.ts
│ │ │ ├── config-mcp.test.ts
│ │ │ ├── config-utils.test.ts
│ │ │ ├── env.test.ts
│ │ │ ├── package.test.ts
│ │ │ ├── parse-package-name.test.ts
│ │ │ ├── roles.test.ts
│ │ │ ├── update-paths.test.ts
│ │ │ └── zod.test.ts
│ │ ├── tsconfig.json
│ │ ├── tsdown.config.ts
│ │ └── vitest.config.ts
│ ├── mcp/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ ├── server.ts
│ │ │ └── utils.ts
│ │ ├── tests/
│ │ │ └── mcp.test.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── migrate/
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── bin.ts
│ │ │ ├── cli.ts
│ │ │ ├── commands/
│ │ │ │ ├── index.ts
│ │ │ │ ├── utils.ts
│ │ │ │ └── v3.ts
│ │ │ └── utils/
│ │ │ ├── errors.ts
│ │ │ ├── fs.ts
│ │ │ ├── json.ts
│ │ │ ├── package.ts
│ │ │ ├── parse-package-name.ts
│ │ │ ├── path.ts
│ │ │ ├── prompts.ts
│ │ │ ├── strings.ts
│ │ │ ├── types.ts
│ │ │ ├── v2/
│ │ │ │ └── config.ts
│ │ │ └── zod.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── pnpm/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── catalog.ts
│ │ │ ├── index.ts
│ │ │ └── workspace.ts
│ │ ├── tests/
│ │ │ ├── fixtures/
│ │ │ │ └── pnpm-workspace/
│ │ │ │ ├── packages/
│ │ │ │ │ ├── pkg-a/
│ │ │ │ │ │ └── package.json
│ │ │ │ │ ├── pkg-b/
│ │ │ │ │ │ └── package.json
│ │ │ │ │ └── pkg-c/
│ │ │ │ │ └── package.json
│ │ │ │ └── pnpm-workspace.yaml
│ │ │ └── pnpm.test.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── shadcn/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ ├── output.ts
│ │ │ ├── provider.ts
│ │ │ └── utils.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── transform-biome/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── transform-filecasing/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── filecasing.test.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── transform-javascript/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── strip-types.test.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ ├── transform-oxfmt/
│ │ ├── CHANGELOG.md
│ │ ├── README.md
│ │ ├── biome.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ └── tsdown.config.ts
│ └── transform-prettier/
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── biome.json
│ ├── package.json
│ ├── src/
│ │ └── index.ts
│ ├── tsconfig.json
│ └── tsdown.config.ts
├── pnpm-workspace.yaml
└── task.config.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .changeset/config.json
================================================
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": ["@svitejs/changesets-changelog-github-compact", { "repo": "jsrepojs/jsrepo" }],
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@jsrepo/docs", "@example/react", "@example/svelte"],
"prettier": false
}
================================================
FILE: .github/workflows/build-example-registries.yml
================================================
name: build-example-registries
on:
pull_request:
branches: [main]
jobs:
build-example-registries:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Build example registries
run: pnpm build:example-registries
================================================
FILE: .github/workflows/bundle-analyze.yml
================================================
name: Bundle Analyze
on:
pull_request:
branches: [next, main]
jobs:
bundle-analyze:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Build packages
run: pnpm build:packages
- name: Bundle Analyze
run: |
pnpm bundle-analyze
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
pull_request:
branches: [main]
jobs:
CI:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Check Types
run: pnpm check
- name: Test
run: pnpm test
================================================
FILE: .github/workflows/cli-preview.yml
================================================
name: Package Previews
on:
pull_request:
branches: [main]
paths:
- 'pnpm-lock.yaml'
- 'packages/**'
jobs:
release-previews:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: pnpm
- name: Install dependencies
run: pnpm install # packages automatically built on postinstall
- name: publish preview
run: pnpm pkg-pr-new publish --pnpm './packages/jsrepo' './packages/mcp' './packages/transform-prettier' './packages/transform-biome' './packages/transform-javascript' './packages/migrate' './packages/transform-oxfmt' './packages/transform-filecasing' --packageManager=pnpm
================================================
FILE: .github/workflows/publish.yml
================================================
name: Publish
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
permissions:
contents: write # to create release (changesets/action)
pull-requests: write # to create pull request (changesets/action)
id-token: write # Required for OIDC
name: Build & Publish Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: 'pnpm'
- run: npm install -g npm@latest
- name: Install dependencies
run: pnpm install
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
commit: "chore(release): version package"
title: "chore(release): version package"
publish: pnpm ci:release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_CONFIG_PROVENANCE: true
================================================
FILE: .github/workflows/test-external-projects.yml
================================================
name: Test External Projects
on:
pull_request:
branches: [main]
jobs:
test-external-projects:
runs-on: ubuntu-latest
strategy:
matrix:
project:
- name: shadcn-svelte-extras
repo: ieedan/shadcn-svelte-extras
pm: pnpm
build: pnpm registry:build
- name: react-bits
repo: DavidHDev/react-bits
pm: npm
build: npm run registry:build
steps:
- name: Checkout jsrepo
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: pnpm
- name: Install jsrepo dependencies
run: pnpm install
- name: Build jsrepo
run: pnpm build:packages
- name: Pack jsrepo
id: pack
run: |
cd packages/jsrepo && pnpm pack
TARBALL="$(ls jsrepo-*.tgz)"
echo "tarball_path=${{ github.workspace }}/packages/jsrepo/$TARBALL" >> $GITHUB_OUTPUT
- name: Clone ${{ matrix.project.name }}
uses: actions/checkout@v4
with:
repository: ${{ matrix.project.repo }}
path: external-project
- name: Cache ${{ matrix.project.name }} dependencies
uses: actions/cache@v4
with:
path: external-project/node_modules
key: ${{ matrix.project.name }}-deps-${{ hashFiles('external-project/package-lock.json', 'external-project/pnpm-lock.yaml') }}
- name: Install local jsrepo in ${{ matrix.project.name }}
working-directory: external-project
env:
TARBALL: ${{ steps.pack.outputs.tarball_path }}
run: |
if [ "${{ matrix.project.pm }}" = "pnpm" ]; then
pnpm add "jsrepo@file:$TARBALL"
else
npm install "jsrepo@file:$TARBALL"
fi
- name: Build ${{ matrix.project.name }} registry
working-directory: external-project
run: ${{ matrix.project.build }}
================================================
FILE: .gitignore
================================================
node_modules
# out
dist
# testing
temp-test
**/tests/fixtures/**/node_modules
**/tests/fixtures/**/package-lock.json
**/tests/fixtures/**/pnpm-lock.yaml
.DS_Store
# ralphex progress logs
progress*.txt
================================================
FILE: .vscode/settings.json
================================================
{
"cSpell.words": ["fuzzysort", "onwarn", "packlist"]
}
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to jsrepo
Looking to contribute to jsrepo? Great! You're in the right place. This guide will help you get started.
## AI Assistance Notice
> [!IMPORTANT]
>
> If you are using **any kind of AI assistance** to contribute to jsrepo,
> it must be disclosed in the pull request.
If you are using any kind of AI assistance while contributing to jsrepo,
**this must be disclosed in the pull request**, along with the extent to
which AI assistance was used (e.g. docs only vs. code generation).
If PR responses are being generated by an AI, disclose that as well.
As a small exception, trivial tab-completion doesn't need to be disclosed,
so long as it is limited to single keywords or short phrases.
An example disclosure:
> This PR was written primarily by Claude Code.
Or a more detailed disclosure:
> I consulted ChatGPT to understand the codebase but the solution
> was fully authored manually by myself.
Failure to disclose this is first and foremost rude to the human operators
on the other end of the pull request, but it also makes it difficult to
determine how much scrutiny to apply to the contribution.
When using AI assistance, we expect contributors to understand the code
that is produced and be able to answer critical questions about it. It
isn't a maintainers job to review a PR so broken that it requires
significant rework to be acceptable.
Please be respectful to maintainers and disclose AI assistance.
## Development
First install dependencies:
```sh
pnpm install
```
Then run the dev script:
```sh
pnpm dev
```
This will start the development server and watch for changes to packages.
The docs are available at [http://localhost:3000](http://localhost:3000).
To run the tests, run the following command:
```sh
pnpm test
```
To test jsrepo manually you can use the playground projects in the [`playground/`](./playground/) directory.
### Project Structure
- `packages/jsrepo` - jsrepo CLI
- `packages/mcp` - MCP server for jsrepo
- `playground/` - Playground projects to manually test jsrepo
- `apps/docs` - Contains the documentation hosted at [https://jsrepo.dev](https://jsrepo.dev).
## Before opening a PR
### Open an issue
If your PR is more than a one line fix please open an issue first to discuss the changes you want to make.
### Checklist
- Run `pnpm format`
- Run `pnpm lint` (Ensure passing)
- Run `pnpm check` (Ensure passing)
- Run `pnpm test` (Ensure passing)
- Run `pnpm changeset` and add a changeset for your changes if it effects any of the released packages (under packages/*)
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2025 jsrepo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
[](https://npmjs.com/package/jsrepo)
[](https://npmjs.com/package/jsrepo)
# jsrepo
The modern registry toolchain. Distribute your code in any language anywhere with one CLI.
## Get Started
```sh
npx jsrepo init
```
================================================
FILE: apps/docs/.gitignore
================================================
# deps
/node_modules
# generated content
.contentlayer
.content-collections
.source
# test & build
/coverage
/.next/
/out/
/build
*.tsbuildinfo
# misc
.DS_Store
*.pem
/.pnp
.pnp.js
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# others
.env*.local
.vercel
next-env.d.ts
public/registry-kit
================================================
FILE: apps/docs/README.md
================================================
# docs
This is a Next.js application generated with
[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
Run development server:
```bash
npm run dev
# or
pnpm dev
# or
yarn dev
```
Open http://localhost:3000 with your browser to see the result.
## Explore
In the project, you can see:
- `lib/source.ts`: Code for content source adapter, [`loader()`](https://fumadocs.dev/docs/headless/source-api) provides the interface to access your content.
- `lib/layout.shared.tsx`: Shared options for layouts, optional but preferred to keep.
| Route | Description |
| ------------------------- | ------------------------------------------------------ |
| `app/(home)` | The route group for your landing page and other pages. |
| `app/docs` | The documentation layout and pages. |
| `app/api/search/route.ts` | The Route Handler for search. |
### Fumadocs MDX
A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
Read the [Introduction](https://fumadocs.dev/docs/mdx) for further details.
## Learn More
To learn more about Next.js and Fumadocs, take a look at the following
resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
- [Fumadocs](https://fumadocs.dev) - learn about Fumadocs
================================================
FILE: apps/docs/biome.json
================================================
{
"root": false,
"extends": "//",
"files": {
"includes": []
}
}
================================================
FILE: apps/docs/cli.json
================================================
{
"aliases": {
"uiDir": "./components/ui",
"componentsDir": "./components",
"blockDir": "./components",
"cssDir": "./styles",
"libDir": "./lib"
},
"baseDir": "src",
"commands": {}
}
================================================
FILE: apps/docs/content/docs/cli/add.mdx
================================================
---
title: add
description: Add items from registries to your project.
---
```sh
jsrepo add
```
## Usage
Add an item from the registries in your `jsrepo.config` file:
```sh
jsrepo add button
```
If the item exists in multiple registries you will be prompted to select which one you want to add:
```
◆ Multiple registries contain button. Please select one:
│ ● button (@ieedan/shadcn-svelte-extras)
│ ○ button (@ai/elements)
└
```
Add an item from a specific registry:
```sh
jsrepo add @ieedan/shadcn-svelte-extras/button
```
Add all items from a specific registry:
```sh
jsrepo add @ieedan/shadcn-svelte-extras --all
```
Add all items from every registry in your `jsrepo.config` file:
```sh
jsrepo add --all
```
## Options
### `--all`
Add all items from every registry:
```sh
jsrepo add --all
```
### `--cwd`
The current working directory:
```sh
jsrepo add button --cwd ./my-project
```
### `--expand`
Expands the diff so you see the entire file:
```sh
jsrepo add button --expand
```
### `--max-unchanged`
Maximum unchanged lines that will show without being collapsed:
```sh
jsrepo add button --max-unchanged 20
```
### `--overwrite`
Overwrite files without prompting:
```sh
jsrepo add button --overwrite
```
### `--registry`
The registry to add items from:
```sh
jsrepo add button --registry @ieedan/shadcn-svelte-extras
```
### `--verbose`
Include debug logs:
```sh
jsrepo add button --verbose
```
### `--with`
Include files with the given roles:
```sh
jsrepo add --with example test storybook
```
### `--with-docs` (Deprecated)
Use `--with doc`:
```sh
jsrepo add --with-docs
```
### `--with-examples` (Deprecated)
Use `--with example`:
```sh
jsrepo add --with-examples
```
### `--with-tests` (Deprecated)
Use `--with test`:
```sh
jsrepo add --with-tests
```
### `--yes`
Skip the confirmation prompt:
```sh
jsrepo add button --yes
```
================================================
FILE: apps/docs/content/docs/cli/auth.mdx
================================================
---
title: auth
description: Authenticate to a provider or registry.
---
```sh
jsrepo auth
```
## Usage
Authenticate to a provider. You will be prompted to select a provider if multiple are available:
```sh
jsrepo auth
```
Authenticate to a specific provider:
```sh
jsrepo auth github
```
If the provider requires registry-specific authentication, you will be prompted to select a registry:
```
◆ Select a registry to authenticate to.
│ ● @ieedan/shadcn-svelte-extras
│ ○ @ai/elements
│ ○ Other
└
```
Logout from a provider:
```sh
jsrepo auth github --logout
```
If the provider uses registry-specific tokens, you will be prompted to select which registry to logout from:
```
◆ Select a registry to logout of.
│ ● @ieedan/shadcn-svelte-extras
│ ○ @ai/elements
└
```
Authenticate using a token directly:
```sh
jsrepo auth github --token
```
Authenticate non-interactively for a specific registry:
```sh
jsrepo auth --registry https://private-registry.example.com --token
```
## Options
### `--cwd`
The current working directory:
```sh
jsrepo auth --cwd ./my-project
```
### `--logout`
Execute the logout flow:
```sh
jsrepo auth github --logout
```
### `--registry`
The registry to authenticate to. This is especially useful in non-interactive environments where prompts are unavailable:
```sh
jsrepo auth --registry https://private-registry.example.com --token
```
### `--token`
The token to use for authenticating to this provider:
```sh
jsrepo auth github --token
```
### `--verbose`
Include debug logs:
```sh
jsrepo auth github --verbose
```
================================================
FILE: apps/docs/content/docs/cli/build.mdx
================================================
---
title: build
description: Build your registry.
---
```sh
jsrepo build
```
## Usage
Build all blocks from the registries in your `jsrepo.config` file:
```sh
jsrepo build
```
Build blocks and watch for changes:
```sh
jsrepo build --watch
```
## Options
### `--cwd`
The current working directory:
```sh
jsrepo build --cwd ./my-project
```
### `--debounce`, `-d`
How long to wait before building again after a change is detected (watch mode only):
```sh
jsrepo build --watch --debounce 200
```
### `--watch`, `-w`
Watch for changes and rebuild automatically:
```sh
jsrepo build --watch
```
================================================
FILE: apps/docs/content/docs/cli/config/language.mdx
================================================
---
title: language
description: Add a language to your config.
---
```sh
jsrepo config language
```
## Usage
Add a language to your config. You will be prompted to install dependencies after adding:
```sh
jsrepo config language jsrepo-language-go
```
Add multiple languages at once:
```sh
jsrepo config language jsrepo-language-go jsrepo-language-rust
```
## Options
### `--cwd`
The current working directory:
```sh
jsrepo config language jsrepo-language-go --cwd ./my-project
```
### `--yes`
Skip the confirmation prompt:
```sh
jsrepo config language jsrepo-language-go --yes
```
================================================
FILE: apps/docs/content/docs/cli/config/mcp.mdx
================================================
---
title: mcp
description: Configure the jsrepo MCP server for your environment.
---
```sh
jsrepo config mcp
```
## Usage
Configure the jsrepo MCP server. You will be prompted to select which clients to configure:
```sh
jsrepo config mcp
```
You will be prompted to select which clients you want to configure:
```
◆ Which clients would you like to configure?
│ ■ Cursor
│ □ Claude Code
│ □ VS Code
│ □ Codex
└
```
Configure a specific client:
```sh
jsrepo config mcp --client cursor
```
Configure multiple clients:
```sh
jsrepo config mcp --client cursor vscode
```
Configure all supported MCP clients:
```sh
jsrepo config mcp --all
```
## Options
### `--all`
Configure all supported MCP clients:
```sh
jsrepo config mcp --all
```
### `--client`
The MCP client(s) to configure. Supported clients: `cursor`, `claude`, `vscode`, `codex`:
```sh
jsrepo config mcp --client cursor
```
Configure multiple clients:
```sh
jsrepo config mcp --client cursor vscode
```
### `--cwd`
The current working directory:
```sh
jsrepo config mcp --cwd ./my-project
```
================================================
FILE: apps/docs/content/docs/cli/config/meta.json
================================================
{
"title": "config"
}
================================================
FILE: apps/docs/content/docs/cli/config/provider.mdx
================================================
---
title: provider
description: Add a provider to your config.
---
```sh
jsrepo config provider
```
## Usage
Add a provider to your config. You will be prompted to install dependencies after adding:
```sh
jsrepo config provider jsrepo-provider-jsr
```
Add multiple providers at once:
```sh
jsrepo config provider jsrepo-provider-jsr jsrepo-provider-npm
```
## Options
### `--cwd`
The current working directory:
```sh
jsrepo config provider jsrepo-provider-jsr --cwd ./my-project
```
### `--yes`
Skip the confirmation prompt:
```sh
jsrepo config provider jsrepo-provider-jsr --yes
```
================================================
FILE: apps/docs/content/docs/cli/config/transform.mdx
================================================
---
title: transform
description: Add a transform to your config.
---
```sh
jsrepo config transform
```
## Usage
Add a transform to your config. You will be prompted to install dependencies after adding:
```sh
jsrepo config transform @jsrepo/transform-prettier
```
Add multiple transforms at once:
```sh
jsrepo config transform @jsrepo/transform-prettier @jsrepo/transform-biome
```
## Options
### `--cwd`
The current working directory:
```sh
jsrepo config transform @jsrepo/transform-prettier --cwd ./my-project
```
### `--yes`
Skip the confirmation prompt:
```sh
jsrepo config transform @jsrepo/transform-prettier --yes
```
================================================
FILE: apps/docs/content/docs/cli/meta.json
================================================
{
"title": "CLI"
}
================================================
FILE: apps/docs/content/docs/cli/publish.mdx
================================================
---
title: publish
description: Publish your registry to jsrepo.com.
---
```sh
jsrepo publish
```
## Usage
Publish all registries in your `jsrepo.config` file:
```sh
jsrepo publish
```
Publish a specific registry:
```sh
jsrepo publish @jsrepo/playground
```
Publish in dry run mode:
```sh
jsrepo publish --dry-run
```
## Options
### `--cwd`
The current working directory:
```sh
jsrepo build --cwd ./my-project
```
### `--dry-run`
Publish in dry run mode. This will check with jsrepo.com to see if the registry can be published in it's current state:
```sh
jsrepo publish --dry-run
```
### `--verbose`
Include debug logs:
```sh
jsrepo publish --verbose
```
================================================
FILE: apps/docs/content/docs/cli/update.mdx
================================================
---
title: update
description: Update items in your project.
---
```sh
jsrepo update
```
## Usage
Update an item in your project:
```sh
jsrepo update button
```
Select which items from your project that you want to update:
```sh
jsrepo update
```
```
◆ Which items would you like to update?
│ ■ button
│ □ math
│ □ logger
└
```
Update an item from a specific registry:
```sh
jsrepo update @ieedan/shadcn-svelte-extras/button
```
Update all items in your project:
```sh
jsrepo update --all
```
## Options
### `--all`
Update all items in your project:
```sh
jsrepo update --all
```
### `--cwd`
The current working directory:
```sh
jsrepo update button --cwd ./my-project
```
### `--expand`
Expands the diff so you see the entire file:
```sh
jsrepo update button --expand
```
### `--max-unchanged`
Maximum unchanged lines that will show without being collapsed:
```sh
jsrepo update button --max-unchanged 20
```
### `--overwrite`
Overwrite files without prompting:
```sh
jsrepo update button --overwrite
```
### `--registry`
The registry to update items from:
```sh
jsrepo update button --registry @ieedan/shadcn-svelte-extras
```
### `--verbose`
Include debug logs:
```sh
jsrepo update button --verbose
```
### `--with`
Include files with the given roles:
```sh
jsrepo update --with example test storybook
```
### `--with-docs` (Deprecated)
Use `--with doc`:
```sh
jsrepo update --with-docs
```
### `--with-examples` (Deprecated)
Use `--with example`:
```sh
jsrepo update --with-examples
```
### `--with-tests` (Deprecated)
Use `--with test`:
```sh
jsrepo update --with-tests
```
### `--yes`
Skip the confirmation prompt:
```sh
jsrepo update button --yes
```
================================================
FILE: apps/docs/content/docs/create-a-registry.mdx
================================================
---
title: Create a registry
description: A complete guide to creating your own registry with jsrepo.
---
In this guide we will show you how to setup a registry with **jsrepo**.
## Creating a registry
To create a registry start by running:
```npm
npx jsrepo init
```
This will initialize a blank config in your project and install **jsrepo** as a dev dependency.
Before we continue let's create some items for our registry.
```ts tab="src/stdout.ts"
export function print(msg: string) {
console.log(msg);
}
```
```ts tab="src/logger.ts"
import { print } from './stdout';
export function createLogger() {
return {
log: print,
}
}
```
Next we can configure the registry with the `registry` key.
Let's start by giving the registry a name:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
name: 'my-first-registry', // [!code ++]
},
});
```
Next let's add the items we just created to the registry:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
// ...
items: [ // [!code ++]
{ // [!code ++]
name: 'logger', // [!code ++]
type: 'utils', // [!code ++]
files: [ // [!code ++]
{ // [!code ++]
path: 'src/logger.ts', // [!code ++]
}, // [!code ++]
] // [!code ++]
}, // [!code ++]
{ // [!code ++]
name: 'stdout', // [!code ++]
type: 'utils', // [!code ++]
add: 'when-needed', // [!code ++] this will prevent the item from being listed by the `add` command
files: [ // [!code ++]
{ // [!code ++]
path: 'src/stdout.ts', // [!code ++]
}, // [!code ++]
] // [!code ++]
} // [!code ++]
], // [!code ++]
}
});
```
For now we will use the `repository` output for our registry so let's add it to our config:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
registry: {
// ...
outputs: [repository()], // [!code ++]
},
});
```
Now we can build our registry with the `jsrepo build` command:
```sh
jsrepo build
```
This will create a `registry.json` file at the root of our project that contains everything we need to start adding items from our registry to other projects.
### Testing the registry
To test our registry locally we can use the `fs` provider. Let's add it to our config:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs";
import { fs } from "jsrepo/providers"; // [!code ++]
export default defineConfig({
// ...
providers: [fs()], // [!code ++]
});
```
Now let's initialize our registry with the `jsrepo init` command:
```sh
jsrepo init fs://./
```
This will add the registry to the `registries` key in our config file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs";
import { fs } from "jsrepo/providers";
export default defineConfig({
// ...
registries: ["fs://./"], // [!code ++]
});
```
Now we can run `jsrepo add` to add an item to our project:
```sh
jsrepo add logger
```
## Deploying your registry
This is the end of the basic guide.
Now that you have a working registry you can deploy it wherever you want! Take a look at the [providers](/docs/providers) docs for the full list of hosting options.
For more advanced usage you can continue reading below...
## Advanced Usage
Now that we have covered the basics of creating a registry we can start to explore some of the features that make **jsrepo** so powerful.
### Resolving Dependencies
**jsrepo** automatically resolves dependencies both to other items in the registry and to remote packages. This ensures that when building your registry it will work out of the box for end users.
#### Excluding dependencies
Many times you may not want certain dependencies to be installed with your registry items. For instance if you import `useState` from `react` you probably don't want to force users to install `react` with your registry.
For this you can use the `excludeDeps` key of your registry config.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
// ...
excludeDeps: ["react"], // [!code ++]
},
});
```
It's good practice to put your framework in the `excludeDeps` list whether that be `react`, `vue`, `svelte` etc.
#### Opting out of automatic dependency resolution
Occasionally you may want to opt out of automatic dependency resolution for a particular item or file.
To do this you can set the `dependencyResolution` key to `manual` on the item or on specific files within the item:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
// ...
dependencyResolution: "manual", // [!code ++]
}
]
},
});
```
#### Resolving `workspace:` and `catalog:` dependencies
By default `workspace:` and `catalog:` dependencies won't be handled by **jsrepo**, however if you are using `pnpm` or `bun` you can use the `@jsrepo/pnpm` or `@jsrepo/bun` packages to automatically resolve these dependencies.
pnpm:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { pnpm } from "@jsrepo/pnpm"; // [!code ++]
export default defineConfig({
// ...
build: {
remoteDependencyResolver: pnpm(), // [!code ++]
},
});
```
bun:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { bun } from "@jsrepo/bun"; // [!code ++]
export default defineConfig({
// ...
build: {
remoteDependencyResolver: bun(), // [!code ++]
},
});
```
Now when you build your registry the `workspace:` and `catalog:` dependencies will be resolved to concrete versions.
### Files
We showed you how to include files in the registry earlier by referencing them by their path but there's much more to know!
#### File types
Files can have any type that an item can. If you don't provide a type the file will simply inherit the type from the parent item.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
// ...
files: [
{
path: "src/example.ts",
type: "utils", // [!code ++]
}
]
}
]
}
});
```
#### File dependencies
Just like items you can set the `dependencyResolution` to `manual` and manually specify the dependencies of a file.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
// ...
files: [
{
path: "src/example.ts",
dependencyResolution: "manual", // [!code ++]
dependencies: ["chalk"], // [!code ++]
}
]
}
]
}
});
```
#### File roles
File roles classify files into different categories that can be optionally installed by the user. The built-in roles are:
- `file` - The default (always installed)
- `example` - An example file
- `doc` - A documentation file
- `test` - A test file
- Custom roles - Any other role you want to give files in your registry
By default only files with the `file` role are included.
Users can include files with specific roles using the `--with ` flag:
```sh
jsrepo add --with story doc
```
These files are also made available to LLMs when using the `@jsrepo/mcp` server.
You can specify the role of a file when you define it on an item:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
// ...
items: [
{
// ...
files: [
{
path: "src/example.ts",
role: "example", // [!code ++]
},
],
}
]
},
});
```
Files with any non-`file` role will only install their dependencies when the file is included.
For example if you have a file with `role: "test"` that depends on `vitest`. `vitest` will only be installed to the user's project when the user provides `--with test`.
Similarly if that same file was to depend on another item in the registry. Then that item will only be installed to the user's project when the test file is added.
This allows you to add **documentation**, **examples**, **tests**, or any other optional role to your registry without forcing the user to install them.
#### Folders
When using frameworks like **Svelte** you are forced to define *one component per file* which will require you to bundle all your files into a folder. In cases like this you need to be able to include folders in your registry.
Doing this is intuitive in **jsrepo**.
Let's take for example, this **Empty** component:
import { Files, Folder, File } from "@/components/files";
We can simply reference the folder path and **jsrepo** will automatically include all the files in the folder:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
name: 'empty',
type: 'ui',
files: [
{
path: 'src/components/ui/empty', // [!code ++]
},
],
},
],
},
});
```
All the files in the folder will be included in the registry automatically and when users add them they will be added together under the `empty` folder.
If you need to configure the files that are included in a folder you can use the `files` key on folder. This is also useful if you need to change properties like the `role` or `dependencyResolution` of a particular file.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
// ...
files: [
{
path: 'src/components/ui/empty', // [!code ++]
files: [ // [!code ++]
{ // [!code ++]
// file paths are relative to the parent folder path so this turns into `src/components/ui/empty/empty-content.svelte` // [!code ++]
path: 'empty-content.svelte', // [!code ++]
// you can also configure other properties like the `role` or `dependencyResolution` of a particular file. // [!code ++]
dependencyResolution: 'manual', // [!code ++]
}, // [!code ++]
{ // [!code ++]
path: 'empty-description.svelte', // [!code ++]
}, // [!code ++]
{ // [!code ++]
path: 'empty-header.svelte', // [!code ++]
}, // [!code ++]
{ // [!code ++]
path: 'empty-media.svelte', // [!code ++]
}, // [!code ++]
{ // [!code ++]
path: 'empty-title.svelte', // [!code ++]
}, // [!code ++]
{ // [!code ++]
path: 'empty.svelte', // [!code ++]
}, // [!code ++]
{ // [!code ++]
path: 'index.ts', // [!code ++]
}, // [!code ++]
], // [!code ++]
},
],
},
],
});
});
```
#### Glob patterns in file paths
You can also use glob patterns in file paths to include all files that match the pattern.
For example lets say I want to include all my demos for the button component as examples:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
name: 'button',
type: 'ui',
files: [
{
path: 'src/lib/components/button',
},
{
path: "src/lib/demos/button-*.svelte", // [!code ++]
role: 'example',
dependencyResolution: 'manual',
},
],
},
],
});
});
```
This will match all files that match the pattern `button-*.svelte` in the `src/lib/demos` directory.
**Recursive glob patterns:**
Match files in subdirectories while preserving the directory structure:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
name: 'button',
type: 'ui',
files: [
{
path: 'src/lib/components/button',
},
{
path: "src/lib/demos/**/button-*.svelte", // [!code ++]
role: 'example',
},
],
},
],
});
});
```
This will match all files (including those in subdirectories) that match the pattern `button-*.svelte` while maintaining the directory structure.
For instance:
| Source Path | Path Relative to Item |
|-------------|----------------------|
| `src/lib/demos/button-default.svelte` | `button-default.svelte` |
| `src/lib/demos/variants/button-outlined.svelte` | `variants/button-outlined.svelte` |
| `src/lib/demos/variants/themes/button-dark.svelte` | `variants/themes/button-dark.svelte` |
### Configure when an item is added
We mentioned this briefly above but you can configure when an item is added in the user's project by setting the `add` key an item.
- `"on-init"` - Added on registry init or when it's needed by another item
- `"optionally-on-init"` - Users are prompted to add the item when initializing the registry
- `"when-needed"` - Not listed and only added when another item is added that depends on it
- `"when-added"` - Added when the user selects it to be added
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
// ...
add: "when-added", // [!code ++]
}
]
},
});
```
### Configuring the user's project
There are a few common things you may want to automatically configure in the user's project when they first initialize your registry.
#### Default Paths
Default paths are just that, the default locations for which items types or specific items should be added to in the user's project.
You can configure the `defaultPaths` key of your registry config to configure the default paths for items or item types to be added to in the user's project.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
// ...
defaultPaths: { // [!code ++]
component: "src/components/ui", // [!code ++]
// you can of course also configure a specific item by referencing it by `/` // [!code ++]
"ui/button": "src/components/ui/button", // [!code ++]
}, // [!code ++]
},
});
```
#### Plugins
You can configure the `plugins` key to automatically install plugins to the user's project when they initialize your registry.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
plugins: {
languages: [{ package: "jsrepo-language-go" }], // [!code ++]
// by setting the optional key to true the user will be prompted to install the plugin if it is not already installed. // [!code ++]
transforms: [{ package: "@jsrepo/transform-prettier", optional: true }], // [!code ++]
},
},
});
```
### Environment Variables
Sometimes your registry items may require environment variables to work.
For this you can define the `envVars` key of that particular item:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
// ...
items: [
// ...
{
// ...
name: 'db',
type: 'lib',
files: [
{
path: 'src/db.ts',
}
],
envVars: { // [!code ++]
DATABASE_URL: "https://example.com/database", // [!code ++]
DATABASE_SECRET_TOKEN: "", // [!code ++]
}, // [!code ++]
}
]
},
});
```
Environment variables will be added to the users `.env.local` or `.env` file.
If you leave an environment variable blank the user will be prompted to add a value for it.
Values you configure here will ***never*** overwrite existing values in the user's env file.
### Distributing multiple registries
It's become common to distribute multiple registries to allow users to optionally use different variants of your registry for example JavaScript or TypeScript.
However until now there wasn't an easy way to do this.
**jsrepo** solves this by allowing you to define multiple registries in the same config:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: [
{
name: '@my-registry/typescript',
// ...
},
{
name: '@my-registry/javascript',
// ...
}
]
});
```
You can then use the `outputs` api to define where each registry should be output to:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { distributed } from "jsrepo/outputs";
export default defineConfig({
registry: [
{
name: '@my-registry/vanilla',
outputs: [distributed({ dir: "./public/r/v" })], // [!code ++]
// ...
},
{
name: '@my-registry/tailwind',
outputs: [distributed({ dir: "./public/r/tw" })], // [!code ++]
// ...
}
]
});
```
### Dynamically generating registries
You don't always want to have to manually define your entire registry in your config file.
AI has made this less cumbersome but it's still annoying to have a 1k LOC file just to define your registry.
In **jsrepo v2** we automatically generated your registry based on a bunch of complicated options and this wasn't the best experience.
In **jsrepo v3** we are giving the control back to you allowing you to write your own code to generate your registry.
To do this simply pass a function to the `registry` key that returns a registry config:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
// define your own custom function
import { getItems } from "./getItems";
export default defineConfig({
registry: ({ cwd }) => {
return {
name: 'my-registry',
items: getItems(cwd)
}
}
});
```
Oh and of course you can also pass an array of functions:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
// define your own custom function
import { getItems } from "./getItems";
export default defineConfig({
registry: [
({ cwd }) => {
return {
name: '@my-registry/typescript',
items: getItems(path.join(cwd, 'src/registry/ts'))
}
},
({ cwd }) => {
return {
name: '@my-registry/javascript',
items: getItems(path.join(cwd, 'src/registry/js'))
}
}
]
});
```
Dynamically generated registries will still work with the `--watch` flag.
### Supporting JavaScript and TypeScript
Thanks to the **jsrepo** transforms API it's extremely straightforward to allow your users to choose between JavaScript and TypeScript when using your registry.
Users can simply initialize your registry with the `--js` flag to use JavaScript:
```sh
jsrepo init @example/registry --js
# or add the javascript plugin at any time
jsrepo config transform javascript
```
Or add the `@jsrepo/transform-javascript` transform to their config manually:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import javascript from "@jsrepo/transform-javascript"; // [!code ++]
export default defineConfig({
transforms: [javascript()], // [!code ++]
});
```
This will automatically strip the types from TypeScript files and rename them to JavaScript files. You can see the full documentation for the `@jsrepo/transform-javascript` transform [here](/docs/transforms/javascript).
This only works for [erasable syntax](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html#the---erasablesyntaxonly-option) if you are expecting for your users to use TypeScript ensure you are using the `--erasableSyntaxOnly` option when writing your TypeScript code.
### Depending on items from other registries
Often times you may want to depend on items from other registries. In `shadcn/ui` you would add the registry URL to the item you are dependent on.
**jsrepo** doesn't support this for a few reasons:
1. You may have made changes to the component in your project that are not tracked by the upstream registry. This can break the users code or cause it to function incorrectly.
2. It's possible that the author of the upstream registry may make changes to the component that break your code in users projects.
For this reason **jsrepo** doesn't support depending on items from other registries. The alternative is to simply copy the components from the upstream registry into your own registry and serve them from your own registry.
We recommend when you do this to follow a few best practices:
1. Credit the upstream registry in some way so users know where those items came from.
2. Ensure to set `add: "when-needed"` on items from external registries to prevent them from being listed by the `add` command.
### Modifying items in your registry before build
Sometimes you may want to modify the content of registry items before they are built to an output.
For example you may want to build multiple different types of your registry for each style you offer.
You can do this with the `build.transforms` option:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
build: {
transforms: [
{
transform: async (content, opts) => {
return { content: content.replaceAll('{{PROJECT_NAME}}', 'jsrepo') };
},
}
],
},
});
```
This will run the transform on the content of each file in your registry before it's added to the output. This way you can easily modify the content at build time without needing to write another registry to the filesystem.
================================================
FILE: apps/docs/content/docs/index.mdx
================================================
---
title: Introduction
description: Why we built jsrepo.
---
import Link from "next/link";
[shadcn/ui](https://ui.shadcn.com) proved that distributing code in a way that allows consumers to own the source is an extremely powerful pattern. Since then registries have become a common way to distribute reusable components.
As more and more registries start to emerge it became clear that there was a need for a more powerful toolchain to help manage and distribute these registries. That's where **jsrepo** comes in...
**jsrepo** is a toolchain for distributing your code. It gives powerful tools to both registry owners and consumers.
**Registry owners...**
- Don't want to have to write their own CLI and build system to distribute their code
- Want to be able to test and verify that their registry will work for their users before they publish it
- Want to be able to host their registries privately without having to write their own hosting solution
**Registry consumers...**
- Want to quickly add items from a registry to their project and start using them without having to even look at the code
- Want to be able to easily update their items with visibility to what as changed
- Want to be able to install and manage code from multiple registries in a single project
- Want an easy way to authenticate to private registries
**jsrepo...**
- Provides a powerful CLI for building and distributing your registry
- Prevents you from publishing broken or unusable registries
- Provides provider adapters to allow you to host your registry publicly or privately anywhere you want
- Automatically resolves dependencies to other items so your items always come ready to use
- Provides an interactive update command to easily update your items with visibility to what as changed
- Allows you to authenticate to private registries with `jsrepo auth`
Is this trying to replace npm?
No, **jsrepo** won't replace npm, but it's perfect for distributing code like leftPad that probably shouldn't
be a package but also shouldn't have to be rewritten every time.
Is this shadcn compatible?
Yes **jsrepo** is fully shadcn compatible. You can add and update items from **shadcn** with zero configuration needed.
================================================
FILE: apps/docs/content/docs/jsrepo-com.mdx
================================================
---
title: jsrepo.com
description: A registry for your registries.
---
import { BadgesTable } from "@/components/badges-table";
[jsrepo.com](https://jsrepo.com) is a centralized source registry for registries. Much like npm is for packages, **jsrepo.com** is for registries.
Like npm, you publish your registry to [jsrepo.com](https://jsrepo.com) with the `jsrepo publish` command and then other developers can add your code to their projects with the `jsrepo add` command.
## The benefits of jsrepo.com
- Semver support - You can publish multiple versions of the same registry (including pre-release versions) just like you would on npm.
- Easy installation - You can add your registry to your project with the simple `@/` syntax.
- Private registries - You can easily publish private registries and share them with your team for free.
- Marketplace - You can monetize your registry by selling it on the marketplace.
- Discoverability - Your registry will be discoverable through the **jsrepo.com** website and the jsrepo mcp server.
## Publishing your registry
If you already have a registry that can be built with **jsrepo** then there are only a few steps to publishing it to **jsrepo.com**. If not then checkout the [create a registry](/docs/create-a-registry) guide to get started.
### Create an account
Go to [jsrepo.com](https://jsrepo.com) and create an account.
### Claim a scope
Once you have an account navigate to `/account/scopes/new` to [claim a scope](https://www.jsrepo.com/account/scopes/new).
Scopes are used to group your registries together and are required to publish your registry.
When users add your registry the scope will be the first part of the registry name: `@/`.
### Authenticate with jsrepo.com
Run the following command to authenticate with jsrepo.com:
```sh
jsrepo auth jsrepo
```
You will be prompted to finish the sign in in your browser and then you will be authenticated.
### Prepare your registry
Decide on a name for your registry and add it to your `jsrepo.config.ts` file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
name: "@my-scope/my-registry", // [!code ++]
// ...
},
});
```
Next you need to provide the version or your registry that will be published. If you want **jsrepo** to pull from the version in your `package.json` file just provide `package` as the version:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
name: "@my-scope/my-registry",
version: "1.0.0", // [!code ++]
// or take the version from the `package.json` file
version: "package", // [!code ++]
// ...
},
});
```
(Optional) Now is also a good time to add any other metadata you want to your registry:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
name: "@my-scope/my-registry",
description: "My first registry", // [!code ++]
homepage: "https://my-registry.com", // [!code ++]
repository: "https://github.com/my-scope/my-registry", // [!code ++]
bugs: "https://github.com/my-scope/my-registry/issues", // [!code ++]
authors: ["Aidan Bleser"], // [!code ++]
tags: ["first-registry"], // [!code ++]
// ...
},
});
```
(Optional) By default your registry will be published as public so anyone can see and use it. You can change the access level to `"private"` or `"marketplace"` by setting the `access` property:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
name: "@my-scope/my-registry",
access: "private", // [!code ++]
},
});
```
### Publish your registry
Run the following command to publish your registry:
```sh
jsrepo publish
```
### Start adding items to your project
Run the following command to add items to your project:
```sh
jsrepo add --registry @my-scope/my-registry
# or
jsrepo init @my-scope/my-registry
```
## Badges
================================================
FILE: apps/docs/content/docs/jsrepo-config.mdx
================================================
---
title: jsrepo.config
description: The configuration file for jsrepo.
---
The `jsrepo.config.(ts|js|mts|mjs)` file is used to configure **jsrepo** projects and registries.
Having a js based config allows you far more flexibility when configuring your project or registry allowing you to abstract out the reusable parts of your config.
## Creating a config
To create a new config in your project you can run the following command or copy the code below:
```sh
jsrepo init
```
This will initialize a blank config in your project.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
// configure where stuff comes from here
registries: [],
// configure where stuff goes here
paths: {},
});
```
We default to `.mts` to prevent errors when you don't have `"type": "module"` in your `package.json`. But you can
rename this to `.ts` if you prefer.
### Create with a registry
To create your config with a registry you can run the following command:
```sh
jsrepo init [registry]
```
Let's look at an example...
You might run:
```sh
jsrepo init https://example.com/registry
```
First you will be prompted to install any plugins specified by the registry author:
```plaintext
┌ jsrepo
│
◆ Would you like to add the @jsrepo/transform-prettier transform plugin?
│ ● Yes / ○ No
```
Next you can configure the paths for the items you want to add. (These are the types of the items you can add from the registry)
```plaintext
◆ Which paths would you like to configure?
│ ◻ block (Default: src/components)
│ ◻ component
│ ◻ lib
└
```
Once you have configured the paths any items that were specified by the registry author to add upon initialization will be added to your project. And the resulting config should look like this:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import prettier from "@jsrepo/transform-prettier";
export default defineConfig({
registries: ["https://example.com/registry"],
transforms: [prettier()],
paths: {
block: "src/components",
component: "src/components/ui",
lib: "src/lib",
},
});
```
## Adding plugins
Plugins are a big part of what makes jsrepo so powerful but having to manually add them to your config kinda sucks. So we've added a way to automatically install and add plugins to your config.
To add a plugin run the following command:
```sh
# add a transform plugin
jsrepo config transform @jsrepo/transform-prettier
# add a provider plugin
jsrepo config provider jsrepo-provider-
# add a language plugin
jsrepo config language jsrepo-language-
```
This will automatically install the plugin and add it to your config:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import prettier from "@jsrepo/transform-prettier"; // [!code ++]
export default defineConfig({
registries: ["https://example.com/registry"],
transforms: [prettier()], // [!code ++]
paths: {
block: "src/components",
component: "src/components/ui",
lib: "src/lib",
},
});
```
As your config grows this will continue to work (so long as you don't use some really contrived syntax for your config).
## Options
### languages
Languages are how **jsrepo** knows how to parse and transform code. You can read more about the supported languages [here](/docs/languages).
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { js } from "jsrepo/languages";
export default defineConfig({
languages: [js()], // [!code highlight]
});
```
### paths
Paths are how **jsrepo** knows where to put items in your project. Paths can either reference a type of item or a specific item.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
paths: { // [!code highlight]
block: "src/components", // [!code highlight]
// control where a specific item goes by referencing it by `/` // [!code highlight]
"ui/button": "src/components/ui/button", // [!code highlight]
}, // [!code highlight]
});
```
### providers
Providers are how **jsrepo** knows where to fetch items from. You can read more about providers [here](/docs/providers).
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { fs } from "jsrepo/providers";
export default defineConfig({
providers: [fs()], // [!code highlight]
});
```
### registries
Registries are the default locations that items will be fetched from when you run **jsrepo** commands.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registries: ["https://example.com/registry"], // [!code highlight]
});
```
### registry
The `registry` option allows you to define your own registry or registries. You can learn more about creating your own registry [here](/docs/create-a-registry).
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: ..., // [!code highlight]
});
```
### transforms
Transforms allow you to make modifications to code before it is added to your project this is where you might add formatting, and other code modifications. You can read more about transforms [here](/docs/transforms).
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import prettier from "@jsrepo/transform-prettier";
export default defineConfig({
transforms: [prettier()], // [!code highlight]
});
```
### onwarn
**Deprecated:** The top-level `onwarn` option is deprecated. Use [`build.onwarn`](#buildonwarn) instead.
### build.onwarn
The `build.onwarn` option allows you to customize how warnings are handled during the build process. You can suppress specific warnings, transform them, or use the default logging behavior.
The handler receives two arguments:
- `warning`: The warning instance (extends the base `Warning` class)
- `handler`: A function to log the warning using the default format
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { InvalidImportWarning, LanguageNotFoundWarning } from "jsrepo/warnings";
export default defineConfig({
// ...
build: {
onwarn: (warning, handler) => { // [!code highlight]
// Suppress warnings for SvelteKit internal imports
if (warning instanceof InvalidImportWarning) { // [!code highlight]
if (['$app/server', '$app/navigation'].includes(warning.specifier)) { // [!code highlight]
return; // Don't log this warning // [!code highlight]
}
}
// Suppress language warnings for specific file types
if (warning instanceof LanguageNotFoundWarning) { // [!code highlight]
if (warning.path.endsWith('.glb') || warning.path.endsWith('.png')) { // [!code highlight]
return; // Don't log this warning // [!code highlight]
}
}
// Log all other warnings using the default handler
handler(warning); // [!code highlight]
},
},
});
```
Available warning types:
- `InvalidImportWarning`: Triggered when an import is skipped because it's not a valid package name or path alias
- `LanguageNotFoundWarning`: Triggered when a language cannot be found to resolve dependencies for a file
- `UnresolvableDynamicImportWarning`: Triggered when a dynamic import cannot be resolved due to unresolvable syntax
All warnings extend the base `Warning` class which has a `message` property. Each specific warning type includes additional properties relevant to that warning type.
### build.remoteDependencyResolver
The `build.remoteDependencyResolver` option lets you rewrite each detected remote dependency before it is added to the built registry output.
This is useful when your source `package.json` uses version protocols like `workspace:*` or `catalog:` and you want to replace them with concrete versions during build.
For pnpm workspaces (workspace and catalog protocols), use `@jsrepo/pnpm`:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { pnpm } from "@jsrepo/pnpm";
export default defineConfig({
build: {
remoteDependencyResolver: pnpm(),
},
});
```
For bun workspaces, use `@jsrepo/bun`:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { bun } from "@jsrepo/bun";
export default defineConfig({
build: {
remoteDependencyResolver: bun(),
},
});
```
Or implement a custom resolver:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
build: {
remoteDependencyResolver: async (dep) => {
if (dep.version === "workspace:*") {
return { ...dep, version: "1.2.3" };
}
if (dep.version === "catalog:") {
return { ...dep, version: "^4.0.0" };
}
return dep;
},
},
});
```
### build.transforms
The `build.transforms` option allows you to transform the content of files before they are added to your project.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
build: {
transforms: [
{
transform: async (content, opts) => {
return { content: content.replaceAll('{{PROJECT_NAME}}', 'jsrepo') };
},
}
],
},
});
```
### hooks
Hooks allow you to run custom logic before and after CLI commands.
- `before` hooks run before the command executes.
- `after` hooks run after the command completes.
Hooks can be a function, a shell command string, or an array of either.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
hooks: {
before: ({ command }) => {
console.log(`Running ${command}...`);
},
after: "echo done",
},
});
```
Function hooks receive typed arguments with a `command` discriminant. Use it to narrow and access command-specific data:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
hooks: {
after: (args) => {
if (args.command === "add") {
console.log(`Added ${args.result.items.length} items`);
}
},
},
});
```
You can also use an array of hooks:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
hooks: {
before: [
({ command }) => console.log(`Starting ${command}...`),
"echo 'before hook done'",
],
},
});
```
================================================
FILE: apps/docs/content/docs/languages/css.mdx
================================================
---
title: css
description: CSS language support for jsrepo.
---
The `css` language plugin supports dependency resolution for CSS, SCSS, and Sass files as well as installing dependencies with `ecosystem: "js"`.
## Supported syntax
The CSS plugin uses the [css-dependency](https://www.npmjs.com/package/css-dependency) library under the hood to detect dependencies. So it supports all the following syntax:
- `@import` statements
- `@plugin` statements (if `allowTailwindDirectives` is `true`)
- `@config` statements (if `allowTailwindDirectives` is `true`)
- `@reference` statements (if `allowTailwindDirectives` is `true`)
By default `allowTailwindDirectives` is `true` so it will also detect Tailwind directives as imports. To opt out of this behavior you can set `allowTailwindDirectives` to `false`.
```ts
import { defineConfig } from "jsrepo";
import { css } from "jsrepo/langs";
export default defineConfig({
languages: [css({ allowTailwindDirectives: false })], // [!code ++]
});
```
## Supported File Extensions
The CSS language plugin supports the following file extensions:
| Extension |
| --------- |
| `.css` |
| `.scss` |
| `.sass` |
================================================
FILE: apps/docs/content/docs/languages/html.mdx
================================================
---
title: html
description: HTML language support for jsrepo.
---
The `html` language plugin supports dependency resolution for HTML files as well as installing dependencies with `ecosystem: "js"`.
## Supported syntax
The HTML plugin will detect dependencies from the following syntax:
- `script` tags with `src` attributes
- `script` tags with inline code
- `link` tags with `href` attributes
For example the following code:
```html
```
Will result in the following dependencies:
- `./app.css` - From `link` tag
- `@/utils/stdout` - From `script` tag with inline code
## Supported File Extensions
The HTML language plugin supports the following file extensions:
| Extension |
| --------- |
| `.html` |
================================================
FILE: apps/docs/content/docs/languages/index.mdx
================================================
---
title: Languages
description: Language support for jsrepo.
---
**jsrepo** uses languages to determine the dependencies of registry items when you run the `build` command and also how to add and install dependencies.
**jsrepo** can distribute code of any language or file type but these are the languages that support [dependency
resolution](#what-is-dependency-resolution).
## Available Languages
By default **jsrepo** supports the following languages:
} title="JavaScript">
Support for `*.js`, `*.ts`, `*.jsx`, `*.tsx`, `*.mjs`, `*.mts` files.
} title="Svelte">
Support for `*.svelte` files.
} title="Vue">
Support for `*.vue` files.
} title="CSS">
Support for `*.css`, `*.scss`, `*.sass` files.
} title="HTML">
Support for `*.html` files.
## What is dependency resolution?
Dependency resolution is the process of determining the dependencies of a registry item. This process ensures that when you add a registry item that all of it's dependencies are also added.
Without dependency resolution you need to manually specify dependencies of a registry item which is cumbersome and error prone.
### How to manually specify dependencies
If your language of choice doesn't support dependency resolution or your registry items have dependencies that cannot be automatically detected you can manually specify them like so:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { js } from "jsrepo/langs";
export default defineConfig({
registry: {
items: [
{
name: "button",
type: "component",
files: [
{
path: "src/components/button.tsx",
},
],
registryDependencies: ["utils"], // [!code ++]
dependencies: [
// [!code ++]
{
// [!code ++]
ecosystem: "js", // [!code ++]
name: "radix-ui", // [!code ++]
version: "1.4.3", // [!code ++]
}, // [!code ++]
], // [!code ++]
},
],
},
});
```
### How to prevent automatic dependency resolution
If you want to opt out of automatic dependency resolution you can do so by setting the `dependencyResolution` option to `manual` on the registry item or on the file itself.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { js } from "jsrepo/langs";
export default defineConfig({
registry: {
items: [
{
name: "button",
type: "component",
// for the entire item
dependencyResolution: "manual", // [!code ++]
files: [
{
path: "src/components/button.tsx",
// for individual files
dependencyResolution: "manual", // [!code ++]
},
],
},
],
},
});
```
### Strict mode
By default **jsrepo** will error if it cannot resolve all dependencies of a registry item. You can opt out of this behavior by setting the `strict` option to `false`.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { js } from "jsrepo/langs";
export default defineConfig({
registry: {
items: [
{
name: "button",
type: "component",
strict: false, // [!code ++]
},
],
},
});
```
================================================
FILE: apps/docs/content/docs/languages/js.mdx
================================================
---
title: js
description: JavaScript language support for jsrepo.
---
The `js` language plugin supports dependency resolution for both JavaScript and TypeScript files as well as installing dependencies with `ecosystem: "js"`.
## Supported syntax
The JavaScript plugin will detect dependencies from the following syntax:
- Static imports
- Dynamic imports
- Export from statements
For example the following code:
```ts
import 'dotenv/config';
import { print } from "@/utils/stdout";
async function printDynamic() {
const data = await import("./data.json", { with: { type: "json" } });
print(data.message);
}
export { logger } from "@/utils/logger";
```
Will result in the following dependencies:
- `dotenv` - From side effect import
- `@/utils/stdout` - From static import
- `./data.json` - From dynamic import
- `@/utils/logger` - From export from statement
## Supported File Extensions
The JavaScript language plugin supports the following file extensions:
| Extension |
| --------- |
| `.js` |
| `.ts` |
| `.jsx` |
| `.tsx` |
| `.mjs` |
| `.mts` |
================================================
FILE: apps/docs/content/docs/languages/svelte.mdx
================================================
---
title: svelte
description: Svelte language support for jsrepo.
---
The `svelte` language plugin supports dependency resolution for Svelte files as well as installing dependencies with `ecosystem: "js"`.
This language plugin requires `svelte` to be installed in your project.
## Supported syntax
The Svelte plugin parses all script tags and passes the code to the [JavaScript plugin](/docs/languages/js) to resolve dependencies so all the same syntax is supported.
## Supported File Extensions
The JavaScript language plugin supports the following file extensions:
| Extension |
| --------- |
| `.svelte` |
================================================
FILE: apps/docs/content/docs/languages/vue.mdx
================================================
---
title: vue
description: Vue language support for jsrepo.
---
The `vue` language plugin supports dependency resolution for Vue files as well as installing dependencies with `ecosystem: "js"`.
This language plugin requires `vue` to be installed in your project.
## Supported syntax
The Vue plugin parses all script tags and passes the code to the [JavaScript plugin](/docs/languages/js) to resolve dependencies so all the same syntax is supported.
## Supported File Extensions
The Vue language plugin supports the following file extensions:
| Extension |
| --------- |
| `.vue` |
================================================
FILE: apps/docs/content/docs/legacy.mdx
================================================
---
title: Legacy Docs
description: Legacy documentation for jsrepo.
---
All documentation for older versions of **jsrepo** can be found below:
} title="jsrepo v2">
Legacy documentation for jsrepo v2.
================================================
FILE: apps/docs/content/docs/mcp.mdx
================================================
---
title: MCP Server
description: The jsrepo MCP server.
---
The **jsrepo** MCP server has been built alongside the **jsrepo** CLI to ensure agents have first class support for interacting with jsrepo registries.
The **jsrepo** MCP ships separate to the **jsrepo** CLI to reduce the overall size of the CLI and can be found on npm as `@jsrepo/mcp`.
All **jsrepo** registries are supported out of the box by the MCP server, including registries hosted on custom providers (provided the custom provider is present in your `jsrepo.config`).
## Configuration
Cursor Claude Code VS Code Codex Antigravity
You can quickly configure the MCP server for Cursor by running the following command:
```sh
jsrepo config mcp --client cursor
```
This will automatically configure the MCP server for Cursor in the correct file:
```json title=".cursor/mcp.json"
{
"mcpServers": {
"jsrepo": {
"command": "npx",
"args": ["@jsrepo/mcp"]
}
}
}
```
You can quickly configure the MCP server for Claude Code by running the following command:
```sh
jsrepo config mcp --client claude
```
This will automatically configure the MCP server for Claude Code in the correct file:
```json title=".mcp.json"
{
"mcpServers": {
"jsrepo": {
"command": "npx",
"args": ["@jsrepo/mcp"]
}
}
}
```
You can quickly configure the MCP server for VSCode by running the following command:
```sh
jsrepo config mcp --client vscode
```
This will automatically configure the MCP server for VSCode in the correct file:
```json title=".vscode/mcp.json"
{
"servers": {
"jsrepo": {
"command": "npx",
"args": ["@jsrepo/mcp"]
}
}
}
```
You can quickly configure the MCP server for Codex by running the following command:
```sh
jsrepo config mcp --client codex
```
This will automatically configure the MCP server for Codex in the correct file:
```toml title="~/.codex/config.toml"
[mcp_servers.jsrepo]
command = "npx"
args = ["@jsrepo/mcp"]
```
You can quickly configure the MCP server for Antigravity by running the following command:
```sh
jsrepo config mcp --client antigravity
```
This will automatically configure the MCP server for Antigravity in the correct file:
```json title="~/.gemini/antigravity/mcp_config.json"
{
"mcpServers": {
"jsrepo": {
"command": "npx",
"args": ["@jsrepo/mcp"]
}
}
}
```
## Tools
The jsrepo MCP server provides the following tools:
| Tool | Description |
|------|-------------|
| `add_item_to_project` | Add a registry item or items directly to the users project |
| `view_registry_item` | View the code and information about a registry item |
| `list_items_in_registry` | List registry items in one or more registries and optionally fuzzy search |
## Registry Authors
Your registry will automatically be compatible with the **jsrepo** MCP server, but here are a few tips to improve the agents usage of your registry:
- include all the registry metadata in your `jsrepo.config` to allow agents to find your registry more easily when searching
- include a `description` with each item in your registry
- include files with `role: "example"` that show how to use each item
- include files with `role: "doc"` that document each item
================================================
FILE: apps/docs/content/docs/migrate.mdx
================================================
---
title: Migration
description: Migrate from jsrepo v2 to jsrepo v3.
---
**jsrepo** v3 is a complete rewrite of the **jsrepo** CLI and we haven't been shy about making breaking changes.
If you're coming from **jsrepo** v2 and want to quickly get started with **jsrepo** v3 you can run the following command in your existing **jsrepo** project:
```sh
pnpm dlx @jsrepo/migrate v3
```
The migration tool will:
- Migrate your `jsrepo-build-config.json` and `jsrepo.json` files into the new `jsrepo.config.ts` file.
- Install `jsrepo` and the correct formatting transform (if you were using one)
- Build your registry using both v2 and v3 to ensure compatibility
You can put this in your upgrade guide for your users.
## Breaking changes
### 1. A new js based config
In **jsrepo** v2 you used a `jsrepo-build-config.json` file to configure your registry and a `jsrepo.json` file to configure your project. This wasn't great for obvious reasons.
In **jsrepo** v3 we use a `jsrepo.config.ts` file to configure your registry and project:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
// ...
});
```
This affords us more flexibility and allows us to support plugins.
If you're like me you may be worried about having to automatically make modifications to a js based config. Not to worry! The blood, sweat, and (mostly) tears have been shed to make it as seamless as possible.
### 2. No more categories
In **jsrepo** v2 we had item categories. This allowed you to group items together and add them by running `jsrepo add /`.
In **jsrepo** v3 you can add items by running `jsrepo add `.
"categories" are now the `type` of the item. The type of an item is used to determine the path that the item will be added to in the user's project:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
name: "button",
type: "component", // instead of category now it's type // [!code highlight]
files: [
{
path: "src/components/button.tsx",
},
],
},
],
},
});
```
### 3. No backwards compatibility with v2 registries
You probably could've guessed this by some of the changes we have already mentioned but unfortunately we don't support adding items from v2 registries from the v3 CLI.
If you still want to use a v2 registry you can of course continue to use the v2 CLI to add items to your project:
```sh
pnpm dlx jsrepo@2 add ui/button
```
### 4. Deprecated commands
The following commands have been deprecated in **jsrepo** v3:
- `jsrepo test`
- `jsrepo execute`
- `jsrepo tokens` - Now all auth functions are handled by the `jsrepo auth` command.
- `jsrepo mcp` - The MCP server has been moved to the `@jsrepo/mcp` package.
### 5. No more `Update with AI`
While we were excited by the `Update with AI` feature it didn't feel worth the added bundle cost. We'll likely explore ways to improve the workflow of updating items with AI without the added bundle cost.
### 6. Formatting functionality has been externalized
In **jsrepo** v2 you could format code before it was added to your project by configuring the formatter in your `jsrepo.json` file.
With **jsrepo** v3 we introduced the concept of "transforms" and in so doing we realized that the formatting functionality should be externalized to reduce the bundle size of the CLI and allow for more flexibility for users.
You can now configure formatting for your project by adding one of the officially supported transforms to your config:
```sh
# prettier
jsrepo config transform prettier
# biome
jsrepo config transform biome
```
### 7. Output configuration changes
In **jsrepo** v2, registries could specify an `outputDir` in their build config. In **jsrepo** v3, this has been replaced with output plugins:
- Registries that had an `outputDir` are migrated to use the [distributed](/docs/outputs/distributed) output
- Registries without an `outputDir` use the [repository](/docs/outputs/repository) output by default
### 8. Removed peer dependencies
Right now this is just a choice to reduce API surface for language plugins. If this becomes something the community wants we can add it back in the future.
## The wins
Now let's talk about the reasons we are so excited to break everyone's code for **jsrepo** v3.
### Plugins
In **jsrepo** v3 we have introduced plugins. There are currently three types of plugins:
- [Languages](/docs/languages) - Extend jsrepo dependency resolution support to include additional languages.
- [Outputs](/docs/outputs) - Customize the way your registry is distributed.
- [Providers](/docs/providers) - Allow users to install items from a custom source.
- [Transforms](/docs/transforms) - Modify code before it's added to your project.
### Shadcn compatibility
**jsrepo** v3 is now **shadcn** compatible. You can now add and update items from **shadcn** meaning **jsrepo** now has access to an entire ecosystem of **shadcn** registries.
Try it out by running:
```sh
pnpm jsrepo add --registry https://ui.shadcn.com/r/styles/new-york-v4
```
### Greatly improved MCP responses
Thanks to adopting the more manual approach for defining a registry it's now possible to add metadata to your registry items greatly improving the responses you will get when using the **jsrepo** MCP server.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
export default defineConfig({
registry: {
items: [
{
name: "button",
title: "Button", // [!code ++]
description: "A button component", // [!code ++]
files: [
{
path: "src/components/button.tsx",
},
// add examples for LLMs to use
{ // [!code ++]
path: 'src/demos/button-demo.tsx', // [!code ++]
role: 'example', // [!code ++]
} // [!code ++]
]
},
],
},
});
```
================================================
FILE: apps/docs/content/docs/outputs/distributed.mdx
================================================
---
title: Distributed
description: Output your registry as json files in a directory.
---
import { Files, Folder, File } from "@/components/files";
The `distributed` output is used for maximizing performance when serving your registry as a static asset.
## Usage
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { distributed } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
registry: {
outputs: [distributed({ dir: "./public/r" })], // [!code ++]
},
});
```
Now running `jsrepo build` will output your registry to the `./public/r` directory.
Unlike the `repository` output, the `distributed` output will output each item as a separate json file. For example:
Since each item file contains all the code for all the files required for that item this is much more performant, and portable than the `repository` output.
================================================
FILE: apps/docs/content/docs/outputs/index.mdx
================================================
---
title: Outputs
description: Output your registry however you want.
---
Outputs allow you to customize the way your registry is distributed, or (more generally) what to do with the registry after it's built.
This isn't limited into building your registry into a format that **jsrepo** can understand you could use it to output documentation or a manifest for your own CLI application.
By default **jsrepo** ships with two output types:
- [Distributed](/docs/outputs/distributed) - Output your registry as json files in a directory.
- [Repository](/docs/outputs/repository) - Output your registry as a single json file in the root of your repository.
Here are all the officially available outputs:
} title="Distributed">
Output your registry as json files in a directory.
} title="Repository">
Output your registry as a single json file in the root of your repository.
} title="shadcn">
Output your registry as a shadcn registry.
## Creating a custom output
You can create your own output either inline in your config file or as a standalone package.
For this example we will create a standalone package that outputs your registry as a markdown file called `REGISTRY.md`.
Let's create our `output.ts` file and import the `Output` type from `jsrepo/outputs`:
```ts
import type { Output } from "jsrepo/outputs";
export function output(): Output {
return {
}
}
```
Next let's define the `output` key to define how the registry should be output:
```ts title="src/output.ts"
import type { Output } from "jsrepo/outputs";
export const OUTPUT_FILE = "REGISTRY.md";
export function output(): Output {
return {
output: async (buildResult, { cwd }) => { // [!code ++]
let content = `# ${buildResult.name}\n\n`; // [!code ++]
// [!code ++]
for (const item of buildResult.items) { // [!code ++]
content += `## ${item.name}\n\n${item.description}\n\n`; // [!code ++]
} // [!code ++]
// [!code ++]
fs.writeFileSync(path.join(cwd, OUTPUT_FILE), content); // [!code ++]
}, // [!code ++]
}
}
```
The `buildResult` object contains a bunch of useful information about the registry. You can find the full type [here](https://github.com/jsrepojs/jsrepo/blob/next/packages/jsrepo/src/utils/build.ts#L31).
Finally we can define the `clean` key to define how to remove the output file before the next build:
```ts title="src/output.ts"
import type { Output } from "jsrepo/outputs";
export const OUTPUT_FILE = "REGISTRY.md";
export function output(): Output {
return {
output: async (buildResult, { cwd }) => {
let content = `# ${buildResult.name}\n\n`;
for (const item of buildResult.items) {
content += `## ${item.name}\n\n${item.description}\n\n`;
}
fs.writeFileSync(path.join(cwd, OUTPUT_FILE), content);
},
clean: async ({ cwd }) => { // [!code ++]
const manifestPath = path.join(cwd, OUTPUT_FILE); // [!code ++]
if (!fs.existsSync(manifestPath)) return; // [!code ++]
fs.rmSync(manifestPath); // [!code ++]
}, // [!code ++]
}
}
```
Now we can use the output in our config file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { output } from "./src/output";
export default defineConfig({
registry: {
name: "my-registry",
outputs: [output()],
// ...
}
});
```
And the result should look like this:
```markdown title="REGISTRY.md"
# my-registry
## button
A button component.
```
================================================
FILE: apps/docs/content/docs/outputs/repository.mdx
================================================
---
title: Repository
description: Output your registry as a single json file in the root of your repository.
---
The `repository` output is used when you are serving your registry from a repository and want to minimize code duplication and tracked files.
## Usage
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
registry: {
outputs: [repository()], // [!code ++]
},
});
```
Now running `jsrepo build` will output a `registry.json` file to the root of your repository.
================================================
FILE: apps/docs/content/docs/outputs/shadcn.mdx
================================================
---
title: shadcn
description: Output your registry as a shadcn registry.
---
The `@jsrepo/shadcn` is a package that helps you distribute your jsrepo registry as a shadcn registry.
## Usage
To get started install the package:
```npm
npm install @jsrepo/shadcn -D
```
Next let's add the output to our config file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { output } from "@jsrepo/shadcn/output";
export default defineConfig({
registry: {
// ...
outputs: [output({ dir: "./public/r/shadcn" })], // [!code ++]
},
});
```
Now running `jsrepo build` will output a **shadcn** registry to the `./public/r/shadcn` directory.
## defineShadcnRegistry
**shadcn** registries are defined a bit differently than **jsrepo** registries, generally this plugin should correctly resolve those differences or warn you if it is unable to.
However if you are only distributing your registry as a **shadcn** registry and don't care about the other features of **jsrepo** you can use the `defineShadcnRegistry` function to define your registry the *"shadcn"* way.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { defineShadcnRegistry, output } from "@jsrepo/shadcn";
export default defineConfig({
registry: defineShadcnRegistry({
// make sure you still include the output
outputs: [output({ dir: "./public/r/shadcn" })],
}),
});
```
When using the `defineShadcnRegistry` function it's be possible to just paste the contents of the **shadcn** `registry.json` file into your config file and start building your registry with **jsrepo**.
## Outputting jsrepo registries alongside shadcn registries
Currently the **jsrepo** and **shadcn** outputs are not compatible to be used in the same directory. Because of this you will need to serve each registry from a different URL.
The preferred way to avoid this conflict would be to publish your registry to [jsrepo.com](https://jsrepo.com) (which also has it's own benefits).
In absence of that, the easiest way to do this and our recommendation is to postfix the **shadcn** registry output `dir` option with `/shadcn`.
For example:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { distributed } from "jsrepo/outputs";
import { output } from "@jsrepo/shadcn/output";
export default defineConfig({
registry: {
outputs: [
distributed({ dir: "./public/r" }),
output({ dir: "./public/r" }) // [!code --]
output({ dir: "./public/r/shadcn" }) // [!code ++]
],
},
});
```
================================================
FILE: apps/docs/content/docs/providers/azure.mdx
================================================
---
title: azure
description: Download and add registry items from an Azure DevOps repository.
---
## Usage
To start adding registry items from an Azure DevOps repository you can run the following command:
```sh
jsrepo add azure///
```
The Azure provider understands refs as either branches or tags:
```sh
jsrepo add azure////heads/
jsrepo add azure////tags/
```
### Custom base urls
By default the Azure provider will use `https://dev.azure.com` as the base url. You can configure this behavior by configuring `azure` in your `jsrepo.config` file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { azure } from "jsrepo/providers";
export default defineConfig({
providers: [azure({ baseUrl: "https://dev.azure.com" })], // [!code highlight]
});
```
Alternatively you can use the `azure:https://` shorthand to use a custom base url without having to touch your config file:
```sh
jsrepo add azure:https://dev.azure.com////heads/
```
This syntax tells the Azure provider that it can resolve this URL as an Azure DevOps repository.
## Deploying your registry to Azure DevOps
When deploying your registry to Azure DevOps you will want to use the `repository` output type:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
registry: {
// ...
outputs: [repository()], // [!code ++]
},
});
```
This will create a `registry.json` file that will contain everything users need to use your registry.
The `registry.json` file must be at the **root** of your repository otherwise users won't be able to use your registry.
## Authentication
To authenticate with Azure DevOps you can run the following command:
```sh
jsrepo auth azure
```
You can logout of your account by running:
```sh
jsrepo auth azure --logout
```
### Environment Variable
If you prefer to use an environment variable or are in an environment where you can't use the `jsrepo auth` command you can provide the token via the `AZURE_TOKEN` environment variable.
```sh
AZURE_TOKEN=... jsrepo add
```
## Options
================================================
FILE: apps/docs/content/docs/providers/bitbucket.mdx
================================================
---
title: bitbucket
description: Download and add registry items from a Bitbucket repository.
---
## Usage
To start adding registry items from a Bitbucket repository you can run the following command:
```sh
jsrepo add https://bitbucket.org///
```
The Bitbucket provider can parse Bitbucket URLs so that you can just copy and paste a link to a Bitbucket repository and it will just work:
```sh
jsrepo add https://bitbucket.org///
jsrepo add https://bitbucket.org///src/
```
### The `bitbucket/` shorthand
You can also just use the `bitbucket/` shorthand in place of `https://bitbucket.org/`.
```sh
jsrepo add bitbucket///
jsrepo add bitbucket///src/
```
If you configured a custom `baseUrl` in your `jsrepo.config` file then using the `bitbucket/` shorthand will use your
custom base url instead of `https://bitbucket.org/`.
### Custom base urls
By default the Bitbucket provider will use `https://bitbucket.org` as the base url for the `bitbucket/` shorthand. You can configure this behavior by configuring `bitbucket` in your `jsrepo.config` file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { bitbucket } from "jsrepo/providers";
export default defineConfig({
providers: [bitbucket()], // [!code ++]
});
```
Alternatively you can use the `bitbucket:https://` shorthand to use a custom base url without having to touch your config file:
```sh
jsrepo add bitbucket:https://bitbucket.org///src/
```
This syntax tells the Bitbucket provider that it can resolve this URL as a Bitbucket repository.
## Deploying your registry to Bitbucket
When deploying your registry to Bitbucket you will want to use the `repository` output type:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
registry: {
// ...
outputs: [repository()], // [!code ++]
},
});
```
This will create a `registry.json` file that will contain everything users need to use your registry.
The `registry.json` file must be at the **root** of your repository otherwise users won't be able to use your registry.
## Authentication
To authenticate with Bitbucket you can run the following command:
```sh
jsrepo auth bitbucket
```
You can logout of your account by running:
```sh
jsrepo auth bitbucket --logout
```
### Environment Variable
If you prefer to use an environment variable or are in an environment where you can't use the `jsrepo auth` command you can provide the token via the `BITBUCKET_TOKEN` environment variable.
```sh
BITBUCKET_TOKEN=... jsrepo add
```
## Options
================================================
FILE: apps/docs/content/docs/providers/fs.mdx
================================================
---
title: fs
description: Download and add registry items from your local filesystem.
---
The `fs` provider allows you to distribute code from your local filesystem. This is useful when you want to test out how your registries behave without having to deploy them somewhere first.
## Usage
To start adding registry items from your local filesystem you first need to configure the provider in your `jsrepo.config` file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { fs } from "jsrepo/providers"; // [!code ++]
export default defineConfig({
providers: [fs()], // [!code ++]
});
```
Now you can start adding registry items from your local filesystem:
```sh
jsrepo add fs://../registries/my-registry
```
You may also want to supply a base directory to the provider:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { fs } from "jsrepo/providers";
export default defineConfig({
providers: [fs({ baseDir: "../registries" })], // [!code highlight]
});
```
Now your commands will be relative to the base directory you defined:
```sh
jsrepo add fs://./my-registry
```
## Options
================================================
FILE: apps/docs/content/docs/providers/github.mdx
================================================
---
title: github
description: Download and add registry items from a GitHub repository.
---
## Usage
To start adding registry items from a GitHub repository you can run the following command:
```sh
jsrepo add https://github.com///
```
The GitHub provider can parse GitHub URLs so that you can just copy and paste a link to a GitHub repository and it will just work:
```sh
jsrepo add https://github.com///
jsrepo add https://github.com///tree/
```
### The `github/` shorthand
You can also just use the `github/` shorthand in place of `https://github.com/`.
```sh
jsrepo add github///
jsrepo add github///tree/
```
If you configured a custom `baseUrl` in your `jsrepo.config` file then using the `github/` shorthand will use your
custom base url instead of `https://github.com/`.
### Custom base urls
By default the GitHub provider will use `https://github.com` as the base url for the `github/` shorthand. You can configure this behavior by configuring `github` in your `jsrepo.config` file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { github } from "jsrepo/providers";
export default defineConfig({
providers: [github({ baseUrl: "https://my-github-instance.com" })], // [!code highlight]
});
```
Alternatively you can use the `github:https://` shorthand to use a custom base url without having to touch your config file:
```sh
jsrepo add github:https://my-github-instance.com///
```
This syntax tells the GitHub provider that it can resolve this URL as a GitHub repository.
## Authentication
To authenticate with GitHub you can run the following command:
```sh
jsrepo auth github
```
You can logout of your account by running:
```sh
jsrepo auth github --logout
```
### Environment Variable
If you prefer to use an environment variable or are in an environment where you can't use the `jsrepo auth` command you can provide the token via the `GITHUB_TOKEN` environment variable.
```sh
GITHUB_TOKEN=... jsrepo add
```
## Deploying your registry to GitHub
When deploying your registry to GitHub you will want to use the `repository` output type:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
registry: {
// ...
outputs: [repository()], // [!code ++]
},
});
```
This will create a `registry.json` file that will contain everything users need to use your registry.
The `registry.json` file must be at the **root** of your repository otherwise users won't be able to use your registry.
### Workflow
If you want to use GitHub Actions to automatically build your registry when you push changes you can use this workflow:
```yml title=".github/workflows/build-registry.yml"
name: build-registry
on:
push:
branches:
- main
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm install
- name: Build registry.json
run: jsrepo build
- name: Create pull request with changes
uses: peter-evans/create-pull-request@v7
with:
title: 'chore: update `registry.json`'
body: |
- Update `registry.json`
---
This PR was auto generated
branch: build-registry
commit-message: build `registry.json`
```
## Options
================================================
FILE: apps/docs/content/docs/providers/gitlab.mdx
================================================
---
title: gitlab
description: Download and add registry items from a GitLab repository.
---
## Usage
To start adding registry items from a GitLab repository you can run the following command:
```sh
jsrepo add https://gitlab.com///
```
The GitLab provider can parse GitLab URLs so that you can just copy and paste a link to a GitLab repository and it will just work:
```sh
jsrepo add https://gitlab.com///
jsrepo add https://gitlab.com///-/tree/
```
### The `gitlab/` shorthand
You can also just use the `gitlab/` shorthand in place of `https://gitlab.com/`.
```sh
jsrepo add gitlab///
jsrepo add gitlab////-/tree/
```
If you configured a custom `baseUrl` in your `jsrepo.config` file then using the `gitlab/` shorthand will use your
custom base url instead of `https://gitlab.com/`.
### Custom base urls
By default the GitLab provider will use `https://gitlab.com` as the base url for the `gitlab/` shorthand. You can configure this behavior by configuring `gitlab` in your `jsrepo.config` file:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { gitlab } from "jsrepo/providers";
export default defineConfig({
providers: [gitlab({ baseUrl: "https://my-gitlab-instance.com" })], // [!code highlight]
});
```
Alternatively you can use the `gitlab:https://` shorthand to use a custom base url without having to touch your config file:
```sh
jsrepo add gitlab:https://my-gitlab-instance.com///
```
This syntax tells the GitLab provider that it can resolve this URL as a GitLab repository.
## Deploying your registry to GitLab
When deploying your registry to GitLab you will want to use the `repository` output type:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { repository } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
registry: {
// ...
outputs: [repository()], // [!code ++]
},
});
```
This will create a `registry.json` file that will contain everything users need to use your registry.
The `registry.json` file must be at the **root** of your repository otherwise users won't be able to use your registry.
## Authentication
To authenticate with GitLab you can run the following command:
```sh
jsrepo auth gitlab
```
You can logout of your account by running:
```sh
jsrepo auth gitlab --logout
```
### Environment Variable
If you prefer to use an environment variable or are in an environment where you can't use the `jsrepo auth` command you can provide the token via the `GITLAB_TOKEN` environment variable.
```sh
GITLAB_TOKEN=... jsrepo add
```
## Options
================================================
FILE: apps/docs/content/docs/providers/http.mdx
================================================
---
title: http
description: Download and add registry items from an arbitrary HTTP endpoint.
---
import { Files, Folder, File } from "@/components/files";
The http provider is the simplest provider by far. To add registry items simply provide the base url of the `registry.json` file:
```sh
jsrepo add https://example.com/registry
```
**jsrepo** will then find the `registry.json` file from `https://example.com/registry/registry.json`.
## Deploying a registry to your own website
When deploying a registry to your own website you will want to use the `distributed` output type:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { distributed } from "jsrepo/outputs"; // [!code ++]
export default defineConfig({
// `dir` is the directory to output the files to
outputs: [distributed({ dir: "./public/r" })], // [!code ++]
});
```
This will output your registry to the `public/r` directory which might look something like this:
Users will then be able to add registry items to their project by running:
```sh
jsrepo add https://your-website.com/r
```
## Authentication
To authenticate with the http provider you can run the following command:
```sh
jsrepo auth http
```
You will then be prompted to select or enter the name of a registry to authenticate to.
Once authenticated that token will continue to be used for that registry until you logout.
You can logout of your account by running:
```sh
jsrepo auth http --logout
```
## Options
### `baseUrl`
The `baseUrl` option allows you to configure what registries this provider will match.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { http } from "jsrepo/providers";
export default defineConfig({
// only use this provider for registries starting with https://myregistry.com
providers: [
http({
baseUrl: "https://myregistry.com" // [!code ++]
})
],
});
```
### `authHeader`
The `authHeader` function allows you to set headers for every request using the provided token. This is useful for when you need to authenticate to a registry that doesn't support the Bearer token format.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { http } from "jsrepo/providers";
export default defineConfig({
providers: [
http({
// set your custom headers here
authHeader: (token) => ({ 'X-API-Key': token }) // [!code ++]
})
],
});
```
### `headers`
You can set custom headers on every request by providing the `headers` option:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { http } from "jsrepo/providers";
export default defineConfig({
providers: [
http({
headers: { // [!code ++]
'X-Custom-Header': 'custom value' // [!code ++]
} // [!code ++]
})
],
});
```
One way you might use headers is by providing an authorization token via an environment variable:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { http } from "jsrepo/providers";
export default defineConfig({
providers: [
http({
baseUrl: "https://myregistry.com", // [!code ++]
headers: { // [!code ++]
Authorization: `Bearer ${process.env.MYREGISTRY_TOKEN}` // [!code ++]
} // [!code ++]
})
],
});
```
Now anyone running `jsrepo add` will have the `Authorization` header set to the value of the `MYREGISTRY_TOKEN` environment variable when making requests to `https://myregistry.com/registry`.
================================================
FILE: apps/docs/content/docs/providers/index.mdx
================================================
---
title: Providers
description: Host your code anywhere with jsrepo.
---
Providers are how **jsrepo** knows where to find registry items. When you provide a registry identifier to a **jsrepo** command the provider is responsible for resolving that to a usable URL.
For example you might run the following command:
```sh
jsrepo init github/ieedan/std
```
In this case the `github` provider will be used to resolve the path to the `registry.json` file which might look something like this:
```plaintext
https://api.github.com/repos/ieedan/std/contents/registry.json?ref=main
```
This makes **jsrepo** more flexible than any other registry because you can host your registry anywhere.
## Available providers
} title="jsrepo">
Download and add registry items from jsrepo.com
} title="GitHub">
Download and add registry items from a GitHub repository.
} title="GitLab">
Download and add registry items from a GitLab repository.
} title="Bitbucket">
Download and add registry items from a Bitbucket repository.
} title="AzureDevops">
Download and add registry items from an Azure DevOps repository.
} title="Your Website">
Download and add registry items from your own website.
} title="Local Filesystem">
Download and add registry items from your local filesystem.
You can customize the providers that **jsrepo** uses by adding them to your `jsrepo.config` file.
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import { github } from "jsrepo/providers"; // [!code ++]
export default defineConfig({
providers: [github()], // [!code ++]
});
```
## Provider plugins
Provider plugins are a way to add support for additional providers to **jsrepo**.
### Adding provider plugins
You can add provider plugins by running the following command:
```sh
jsrepo config provider
```
This will automatically install the plugin and add it to your config file:
```ts title="jsrepo.config.ts"
import { defineConfig, DEFAULT_PROVIDERS } from "jsrepo"; // [!code ++]
import myProvider from "jsrepo-provider-myprovider"; // [!code ++]
export default defineConfig({
providers: [...DEFAULT_PROVIDERS, myProvider()], // [!code ++]
});
```
You will notice the addition of the `DEFAULT_PROVIDERS` object in the example above. This way you can continue to
use all other providers alongside your provider plugin.
================================================
FILE: apps/docs/content/docs/providers/jsrepo.mdx
================================================
---
title: jsrepo
description: Download and add registry items from jsrepo.com
---
**jsrepo.com** is a centralized source registry for registries. Much like npm is for packages, **jsrepo.com** is for registries.
**jsrepo.com** comes with a few added benefits over other registry providers:
- Semver support
- First class support for private registries with the `jsrepo auth` command
- Discoverability of your registry through the **jsrepo.com** website (also by the jsrepo mcp agent)
- Easier installation for your users with simple `@/` syntax
## Usage
To start adding registry items from **jsrepo.com** you can run the following command:
```sh
jsrepo add @/
```
You can also add registries at a specific version:
```sh
jsrepo add @/@1.0.0
```
## Authentication
To authenticate with jsrepo.com you can run the following command:
```sh
jsrepo auth jsrepo
```
Once authenticated you will have access to all registries associated with your account public and private as well as the ability to publish registries.
You can logout of your account by running:
```sh
jsrepo auth jsrepo --logout
```
### Environment Variable
If you prefer to use an environment variable or are in an environment where you can't use the `jsrepo auth` command you can provide the token via the `JSREPO_TOKEN` environment variable.
```sh
JSREPO_TOKEN=... jsrepo publish
```
## Publishing your registry to jsrepo.com
Once you have authenticated you can publish your registry with the `publish` command:
```sh
jsrepo publish
```
For a more detailed guide on publishing your registry to jsrepo.com checkout the guide [here](/docs/jsrepo-com#publishing-your-registry).
================================================
FILE: apps/docs/content/docs/providers/shadcn.mdx
================================================
---
title: shadcn
description: Download and add items from the shadcn registry index.
---
import { RegistryDirectory } from "@/components/registry-index";
## Usage
The **shadcn** registry index is a nice way to shorten shadcn registry urls. If you are making use of shadcn registries in your project you can use this provider to use registries by their shortened name.
Since this doesn't come by default you will need to add it to your `jsrepo.config.ts` file. You can do this with a command:
```sh
jsrepo config provider @jsrepo/shadcn
```
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import shadcn from "@jsrepo/shadcn"; // [!code ++]
export default defineConfig({
providers: [shadcn()], // [!code ++]
});
```
Now you can simply use the `shadcn:` prefix followed by the registry namespace:
```sh
jsrepo add --registry shadcn:@react-bits
```
## Options
## Registry Directory
All of these registries are available to use with the **shadcn** provider.
================================================
FILE: apps/docs/content/docs/transforms/biome.mdx
================================================
---
title: Biome
description: Format code before it's added to your project using Biome.
---
The [@jsrepo/transform-biome](https://npmjs.com/package/@jsrepo/transform-biome) package is a transform plugin for **jsrepo** that formats code using your local biome configuration before it's added to your project using [Biome](https://biomejs.dev).
This is especially useful when you are making use of the `jsrepo update` command as it will format the code the same way as it is in your project preventing any formatting changes from being shown in the diff.
## Installation
To add the **@jsrepo/transform-biome** transform to your config run the following command:
```sh
jsrepo config transform biome
```
This will automatically install the transform and add it to your config:
```ts
import { defineConfig } from "jsrepo";
import biome from "@jsrepo/transform-biome"; // [!code ++]
export default defineConfig({
transforms: [biome()], // [!code ++]
});
```
================================================
FILE: apps/docs/content/docs/transforms/filecasing.mdx
================================================
---
title: File Casing
description: Transform file and folder names to different case formats before adding them to your project.
---
The [@jsrepo/transform-filecasing](https://npmjs.com/package/@jsrepo/transform-filecasing) package is a transform plugin for **jsrepo** that transforms file and folder names to different case formats before adding them to your project.
This is useful when your project follows a specific file or folder naming convention and you want registry items to automatically conform to it.
The transform only affects the item's relative path, not the base path configured in your jsrepo.config. For example, if your config specifies `src/lib/components/ui` as the path for components, and you add a button component, only the part after that base path is transformed: `button/index.ts` → `Button/Index.ts`, resulting in `src/lib/components/ui/Button/Index.ts`.
## Installation
To add the **@jsrepo/transform-filecasing** transform to your config run the following command:
```sh
jsrepo config transform filecasing
```
This will automatically install the transform and add it to your config:
```ts
import { defineConfig } from "jsrepo";
import fileCasing from "@jsrepo/transform-filecasing"; // [!code ++]
export default defineConfig({
transforms: [fileCasing({ to: "camel" })], // [!code ++]
});
```
Now when a file is added to your project its file and folder names will be transformed to the target case format. Note that only the item's relative path is transformed, not the base path from your config:
```ts title="Config path: 'src/lib/components/ui', Item: 'button/index.ts' → Result: 'src/lib/components/ui/Button/Index.ts'"
// Config path: 'src/lib/components/ui'
// Item path: 'button/index.ts'
// Result: 'src/lib/components/ui/Button/Index.ts'
```
## Configuration
The transform accepts an options object with the following properties:
| Option | Type | Description |
|--------|------|-------------|
| `to` | `"kebab" \| "camel" \| "snake" \| "pascal"` | The target case format for file and folder names |
| `transformDirectories` | `boolean` | Whether to transform directory segments in the path. When `false`, only the filename baseName is transformed. Defaults to `true` |
### Transform Directories and Filenames (Default)
By default, both directory segments and filenames are transformed:
```ts
import { defineConfig } from "jsrepo";
import fileCasing from "@jsrepo/transform-filecasing";
export default defineConfig({
// Config path: 'src/lib/components/ui'
transforms: [fileCasing({ to: "pascal" })],
});
```
This will transform the item's relative path:
- Item: `button/index.ts` → Result: `src/lib/components/ui/Button/Index.ts`
- Item: `my-components/use-hook.ts` → Result: `src/lib/components/ui/MyComponents/UseHook.ts`
Note that the config path (`src/lib/components/ui`) is never transformed.
### Transform Only Filenames
To preserve directory names and only transform filenames, set `transformDirectories` to `false`:
```ts
import { defineConfig } from "jsrepo";
import fileCasing from "@jsrepo/transform-filecasing";
export default defineConfig({
transforms: [fileCasing({ to: "camel", transformDirectories: false })],
});
```
This will transform only the filename in the item's relative path:
- Item: `my-components/use-hook.ts` → Result: `src/lib/components/ui/my-components/useHook.ts`
- Item: `button/index.ts` → Result: `src/lib/components/ui/button/index.ts`
Note that directory names in the item path are preserved, and the config path is never transformed.
This only transforms directories and files within added items and will never rename existing files or directories in your project.
================================================
FILE: apps/docs/content/docs/transforms/index.mdx
================================================
---
title: Transforms
description: Modify code before it is added to your project.
---
Transforms are a way to modify code before it's added to your project. You can use transforms to format code, add comments, or any other code modification you can think of.
Transforms are also pluggable so you can create your own and share them with the community. Here are a few of the officially supported transforms:
} title="@jsrepo/transform-prettier">
Format code before it's added to your project using **Prettier**.
} title="@jsrepo/transform-biome">
Format code before it's added to your project using **Biome**.
} title="@jsrepo/transform-oxfmt">
Format code before it's added to your project using **oxfmt**.
} title="@jsrepo/transform-javascript">
Transform TypeScript registry items into JavaScript before adding them to your project.
Transform file and folder names to different case formats before adding them to your project.
## Adding transforms
You can add transforms to your config by running the following command:
```sh
jsrepo config transform jsrepo-transform-my-transform
```
This will automatically install the transform and add it to your config:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import myTransform from "jsrepo-transform-my-transform"; // [!code ++]
export default defineConfig({
transforms: [myTransform()], // [!code ++]
});
```
## Transform authors
When creating transforms we recommend you follow a few rules:
1. Name your transform package with the following naming convention: `jsrepo-transform-` or `@/jsrepo-transform-`
2. Export the transform as the `default` export
The name of your transform in the config will be the name of your package without the `jsrepo-transform-` prefix converted to camel case.
For example:
```plaintext
jsrepo-transform-my-transform -> myTransform
@my-org/jsrepo-transform-my-transform -> myTransform
```
Official plugins are an exception to this rule to prevent having to name packages like `@jsrepo/jsrepo-transform-prettier`.
For instance:
```plaintext
@jsrepo/transform-prettier -> prettier
@jsrepo/transform-faster-prettier -> fasterPrettier
```
## Creating your own transform
To demonstrate the power of transforms let's create a simple transform that adds a comment at the top of each file letting the user know what registry the item was added from.
```ts title="src/transform.ts"
import type { Transform } from "jsrepo";
export default function(): Transform {
return {
transform: async (code, fileName, { registryUrl }) => {
if (fileName.endsWith('.ts') || fileName.endsWith('.js')) {
return { code: `// Added from ${registryUrl}\n\n${code}` };
}
// return nothing since no changes were made
return { };
},
};
}
```
Now we can use the transform in our config:
```ts title="jsrepo.config.ts"
import { defineConfig } from "jsrepo";
import addComment from "./src/transform"; // [!code ++]
export default defineConfig({
transforms: [addComment()], // [!code ++]
});
```
Now when users add items from the registry they will include the comment at the top of the file letting them know what registry the item was added from:
```ts title="src/math/add.ts"
// Added from https://example.com/registry // [!code highlight]
export function add(a: number, b: number): number {
return a + b;
}
```
================================================
FILE: apps/docs/content/docs/transforms/javascript.mdx
================================================
---
title: JavaScript
description: Transform TypeScript registry items into JavaScript before adding them to your project.
---
The [@jsrepo/transform-javascript](https://npmjs.com/package/@jsrepo/transform-javascript) package is a transform plugin for **jsrepo** that converts TypeScript registry items into JavaScript before adding them to your project.
This only works for [erasable syntax](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html#the---erasablesyntaxonly-option).
## Installation
```sh
jsrepo config transform javascript
# or initialize any jsrepo project with the --js flag
jsrepo init @ieedan/std --js
```
This will automatically install the transform and add it to your config:
```ts
import { defineConfig } from "jsrepo";
import javascript from "@jsrepo/transform-javascript"; // [!code ++]
export default defineConfig({
// ...
transforms: [javascript()], // [!code ++]
});
```
This plugin will then transform any registry items written in TypeScript into JavaScript before adding them to your project.
**Before:**
```ts title="math/add.ts"
export function add(a: number, b: number): number {
return a + b;
}
```
**After:**
```ts title="math/add.js"
export function add(a: number, b: number): number { // [!code --]
export function add(a, b) { // [!code ++]
return a + b;
}
```
## Supported Languages
If your language of choice is not supported here feel free to contribute it!
- ✅ Full support
- ⚠️ Partial support
- ❌ No support
| Language | Support |
|------------|---------|
| TypeScript | ✅ |
| Svelte | ✅ |
================================================
FILE: apps/docs/content/docs/transforms/oxfmt.mdx
================================================
---
title: oxfmt
description: Format code before it's added to your project using oxfmt.
---
The [@jsrepo/transform-oxfmt](https://npmjs.com/package/@jsrepo/transform-oxfmt) package is a transform plugin for **jsrepo** that formats code using [oxfmt](https://github.com/oxc-project/oxfmt) before it's added to your project.
This is especially useful when you are making use of the `jsrepo update` command as it will format the code the same way as it is in your project preventing any formatting changes from being shown in the diff.
## Installation
To add the **@jsrepo/transform-oxfmt** transform to your config run the following command:
```sh
jsrepo config transform oxfmt
```
This will automatically install the transform and add it to your config:
```ts
import { defineConfig } from "jsrepo";
import oxfmt from "@jsrepo/transform-oxfmt"; // [!code ++]
export default defineConfig({
transforms: [oxfmt()], // [!code ++]
});
```
================================================
FILE: apps/docs/content/docs/transforms/prettier.mdx
================================================
---
title: Prettier
description: Format code before it's added to your project using Prettier.
---
The [@jsrepo/transform-prettier](https://npmjs.com/package/@jsrepo/transform-prettier) package is a transform plugin for **jsrepo** that formats code using your local Prettier configuration before it's added to your project using [Prettier](https://prettier.io).
This is especially useful when you are making use of the `jsrepo update` command as it will format the code the same way as it is in your project preventing any formatting changes from being shown in the diff.
## Installation
To add the **@jsrepo/transform-prettier** transform to your config run the following command:
```sh
jsrepo config transform prettier
```
This will automatically install the transform and add it to your config:
```ts
import { defineConfig } from "jsrepo";
import prettier from "@jsrepo/transform-prettier"; // [!code ++]
export default defineConfig({
transforms: [prettier()], // [!code ++]
});
```
================================================
FILE: apps/docs/instrumentation-client.js
================================================
import posthog from "posthog-js";
if (process.env.NODE_ENV === 'production') {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
defaults: "2025-05-24"
});
}
================================================
FILE: apps/docs/jsrepo.config.mts
================================================
import { defineConfig, DEFAULT_PROVIDERS } from "jsrepo";
import shadcn from '@jsrepo/shadcn';
export default defineConfig({
registries: ["https://reactbits.dev/r", "https://magicui.design/r", "https://ui.shadcn.com/r/styles/new-york-v4"],
paths: {
component: '@/components',
util: '@/lib/utils',
ui: '@/components/ui',
lib: '@/lib',
hook: '@/hooks',
},
providers: [...DEFAULT_PROVIDERS, shadcn()]
});
================================================
FILE: apps/docs/middleware.ts
================================================
import { NextRequest, NextResponse } from "next/server";
import { isMarkdownPreferred, rewritePath } from "fumadocs-core/negotiation";
const { rewrite: rewriteLLM } = rewritePath("/docs/*path", "/llms.mdx/*path");
export function middleware(request: NextRequest) {
if (isMarkdownPreferred(request)) {
const result = rewriteLLM(request.nextUrl.pathname);
if (result) {
return NextResponse.rewrite(new URL(result, request.nextUrl));
}
}
return NextResponse.next();
}
================================================
FILE: apps/docs/next.config.mjs
================================================
import { createMDX } from "fumadocs-mdx/next";
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
reactStrictMode: true,
async rewrites() {
return [
{
source: "/docs/:path*.mdx",
destination: "/llms.mdx/:path*",
},
];
},
};
export default withMDX(config);
================================================
FILE: apps/docs/og-image.d.ts
================================================
/**
* Type declarations for @vercel/og ImageResponse.
* The `tw` prop allows Tailwind-style class names for OG image generation.
* @see https://vercel.com/docs/og-image-generation
*/
export {};
declare module "react" {
interface HTMLAttributes {
tw?: string;
}
}
================================================
FILE: apps/docs/package.json
================================================
{
"name": "@jsrepo/docs",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "next build",
"dev": "next dev --turbo",
"start": "next start",
"postinstall": "fumadocs-mdx"
},
"dependencies": {
"@gsap/react": "^2.1.2",
"@radix-ui/react-accordion": "^1.2.12",
"@radix-ui/react-collapsible": "^1.1.12",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-navigation-menu": "^1.2.14",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-presence": "^1.1.5",
"@radix-ui/react-scroll-area": "^1.2.10",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@shikijs/transformers": "3.14.0",
"@tanstack/react-query": "^5.90.21",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"fumadocs-core": "16.0.7",
"fumadocs-mdx": "13.0.5",
"fumadocs-ui": "16.0.7",
"gsap": "^3.13.0",
"lucide-react": "^0.575.0",
"next": "16.1.6",
"next-themes": "^0.4.6",
"ogl": "^1.0.11",
"react": "19.2.4",
"react-dom": "19.2.4",
"sonner": "^2.0.7",
"tailwind-merge": "^3.5.0"
},
"devDependencies": {
"@jsrepo/shadcn": "workspace:*",
"@tailwindcss/postcss": "^4.2.0",
"@types/mdx": "^2.0.13",
"@types/node": "25.3.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"fuzzysort": "^3.1.0",
"jsrepo": "workspace:*",
"motion": "^12.34.3",
"postcss": "^8.5.6",
"posthog-js": "^1.352.0",
"tailwindcss": "^4.2.0",
"tw-animate-css": "^1.4.0",
"typescript": "^5.9.3",
"zod": "catalog:"
}
}
================================================
FILE: apps/docs/postcss.config.mjs
================================================
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
================================================
FILE: apps/docs/source.config.ts
================================================
import { defineConfig, defineDocs, frontmatterSchema, metaSchema } from "fumadocs-mdx/config";
import { remarkMdxFiles } from "fumadocs-core/mdx-plugins";
// You can customize Zod schemas for frontmatter and `meta.json` here
// see https://fumadocs.dev/docs/mdx/collections
export const docs = defineDocs({
docs: {
schema: frontmatterSchema,
postprocess: {
includeProcessedMarkdown: true,
},
},
meta: {
schema: metaSchema,
},
});
export default defineConfig({
mdxOptions: {
remarkPlugins: [remarkMdxFiles],
},
});
================================================
FILE: apps/docs/src/app/(home)/code-block.tsx
================================================
import * as Base from "fumadocs-ui/components/codeblock";
import { highlight } from "fumadocs-core/highlight";
import { type HTMLAttributes } from "react";
import { transformerNotationDiff, transformerNotationHighlight } from "@shikijs/transformers";
import { cn } from "@/lib/utils";
export async function CodeBlock({
code,
lang,
className,
...rest
}: HTMLAttributes & {
code: string;
lang: string;
}) {
const rendered = await highlight(code, {
lang,
components: {
pre: (props) => ,
},
transformers: [transformerNotationDiff(), transformerNotationHighlight()],
});
return (
{rendered}
);
}
================================================
FILE: apps/docs/src/app/(home)/layout.tsx
================================================
import { HomeLayout } from "@/components/layout/home";
import { baseOptions } from "@/lib/layout.shared";
export default function Layout({ children }: LayoutProps<"/">) {
return (
Docs>,
url: "/docs",
},
]}
>
{children}
);
}
================================================
FILE: apps/docs/src/app/(home)/page.tsx
================================================
import Link from "next/link";
import type { Metadata } from "next";
import { Button } from "@/components/ui/button";
import { FeatureTabs, FeatureTabsList, FeatureTabsTrigger, FeatureTabsContent } from "@/components/feature-tabs";
import { AnimatedSpan, Terminal, TypingAnimation } from "@/components/ui/terminal";
import { CodeBlock } from "./code-block";
import { ProvidersSection } from "./providers-section";
import { cn } from "@/lib/utils";
import PrismaticBurst from "@/components/PrismaticBurst";
import { ExternalLinkIcon } from "lucide-react";
export const metadata: Metadata = {
title: "jsrepo.dev - The modern registry toolchain",
description: "jsrepo - The modern registry toolchain",
openGraph: {
title: "jsrepo.dev",
description: "jsrepo - The modern registry toolchain",
type: "website",
siteName: "jsrepo.dev",
images: [
{
url: "/og",
width: 1200,
height: 630,
},
],
},
twitter: {
card: "summary_large_image",
title: "jsrepo.dev",
description: "jsrepo - The modern registry toolchain",
images: [
{
url: "/og",
width: 1200,
height: 630,
},
],
},
metadataBase: new URL("https://jsrepo.dev"),
};
export default function HomePage() {
return (
<>
Ready to level up your registry?
>
);
}
function HeroSection() {
return (
The modern registry toolchain
jsrepo handles the hard parts of registries so you can focus on building.
);
}
function PluginsSection() {
return (
Customize your experience with plugins
With a js based config the sky is the limit.
);
}
function RestEasySection() {
return (
Rest easy
If your registry builds with jsrepo, it will work for your users.
);
}
function LLMsSection() {
return (
Built for LLMs
jsrepo is optimized for LLMs by giving them demos and documentation alongside registry items.
);
}
function ShadcnCompatibilitySection() {
return (
Shadcn compatible
Add and update items seamlessly from shadcn registries.
> jsrepo add shadcn:@react-bits/AnimatedContent-TS-TW
✔ Fetched manifest from shadcn:@react-bits/AnimatedContent-TS-TW
✔ Fetched AnimatedContent-TS-TW.Added AnimatedContent-TS-TW to your project.Updated 1 file.
);
}
function FeatureAccordionSection() {
return (
Configure
Build
Add
Update
> jsrepo init✔ Wrote config to jsrepo.config.ts✔ Installed dependencies.✔ Initialization complete.> jsrepo build --watch✔ Finished in 10.49ms
@ieedan/std: Created 1 output in 10.12ms with 3 items and 4 files.
Watching for changes...> jsrepo add button
✔ Fetched manifest from @ieedan/shadcn-svelte-extras
✔ Fetched button.Added button, utils to your project.Updated 2 files.> jsrepo update button
✔ Fetched manifest from @ieedan/shadcn-svelte-extras
✔ Fetched button.