jsrepo.config

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:

jsrepo init

This will initialize a blank config in your project.

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:

jsrepo init [registry]

Let's look at an example...

You might run:

jsrepo init https://example.com/registry

First you will be prompted to install any plugins specified by the registry author:

┌   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)

◆  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:

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:

# add a transform plugin
jsrepo config transform @jsrepo/transform-prettier
# add a provider plugin
jsrepo config provider jsrepo-provider-<provider>
# add a language plugin
jsrepo config language jsrepo-language-<language>

This will automatically install the plugin and add it to your config:

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",
	},
});

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.

jsrepo.config.ts
import { defineConfig } from "jsrepo";
import { js } from "jsrepo/languages";

export default defineConfig({
	languages: [js()], 
});

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.

jsrepo.config.ts
import { defineConfig } from "jsrepo";

export default defineConfig({
	paths: { 
		block: "src/components", 
		// control where a specific item goes by referencing it by `<type>/<name>`
		"ui/button": "src/components/ui/button", 
	}, 
});

providers

Providers are how jsrepo knows where to fetch items from. You can read more about providers here.

jsrepo.config.ts
import { defineConfig } from "jsrepo";
import { fs } from "jsrepo/providers";

export default defineConfig({
	providers: [fs()], 
});

registries

Registries are the default locations that items will be fetched from when you run jsrepo commands.

jsrepo.config.ts
import { defineConfig } from "jsrepo";

export default defineConfig({
	registries: ["https://example.com/registry"], 
});

registry

The registry option allows you to define your own registry or registries. You can learn more about creating your own registry here.

jsrepo.config.ts
import { defineConfig } from "jsrepo";

export default defineConfig({
	registry: ..., 
});

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.

jsrepo.config.ts
import { defineConfig } from "jsrepo";
import prettier from "@jsrepo/transform-prettier";

export default defineConfig({
	transforms: [prettier()], 
});

onwarn

Deprecated: The top-level onwarn option is deprecated. Use build.onwarn 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
jsrepo.config.ts
import { defineConfig } from "jsrepo";
import { InvalidImportWarning, LanguageNotFoundWarning } from "jsrepo/warnings";

export default defineConfig({
	// ...
	build: {
		onwarn: (warning, handler) => { 
			// Suppress warnings for SvelteKit internal imports
			if (warning instanceof InvalidImportWarning) { 
				if (['$app/server', '$app/navigation'].includes(warning.specifier)) { 
					return; // Don't log this warning
				}
			}
			// Suppress language warnings for specific file types
			if (warning instanceof LanguageNotFoundWarning) { 
				if (warning.path.endsWith('.glb') || warning.path.endsWith('.png')) { 
					return; // Don't log this warning
				}
			}
			// Log all other warnings using the default handler
			handler(warning); 
		},
	},
});

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:

jsrepo.config.ts
import { defineConfig } from "jsrepo";
import { pnpm } from "@jsrepo/pnpm";

export default defineConfig({
	build: {
		remoteDependencyResolver: pnpm(),
	},
});

For bun workspaces, use @jsrepo/bun:

jsrepo.config.ts
import { defineConfig } from "jsrepo";
import { bun } from "@jsrepo/bun";

export default defineConfig({
	build: {
		remoteDependencyResolver: bun(),
	},
});

Or implement a custom resolver:

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;
		},
	},
});

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.

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:

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:

jsrepo.config.ts
import { defineConfig } from "jsrepo";

export default defineConfig({
	hooks: {
		before: [
			({ command }) => console.log(`Starting ${command}...`),
			"echo 'before hook done'",
		],
	},
});