Migrate from 0.1

Move a 0.1 registry and installer to 0.3.

Registry

The output format changed

A 0.3 installer cannot read a 0.1 registry, and vice versa. Publish the new registry output and your CLI together.

Split Components into Entries & Rules

components only names the entry files, and files holds the rules for installing them.

registry.ts
export const registry: Registry = {
  name: "acme-ui",
  dir,
  components: [
    {
      name: "button",
      title: "Button",
      files: [{ type: "ui", path: "src/button.tsx", target: "<dir>/primitives/button.tsx" }],
    },
  ],
};
0.10.3
components[].name, title, etc.Key and info of components.
components[].files[]entry of the component, and a rule in files. One glob rule can cover many files.
Files imported by a listed fileNeed a matching rule, or to be exported by your package.
dir as the repository rootdir is the source directory, usually src. It must belong to a package.

Remove Compile Hooks

compile() only accepts root.

0.10.3
onUnknownFile returning a fileAdd a rule to files.
onUnknownFile / isExternal for packagesAutomatic: imports of files exported by your package become package imports.
isExternal for files the consumer ownsexternal of Registry.
onParseReferencealias to point a file to another, preserve to prefer the package import.
beforeTransform, afterTransformRemoved. Transform on install with a plugin.

This can reveal broken imports of 0.1

0.1 trusted the specifier returned by onParseReference. 0.3 checks each imported name against the exports of your package, so a mapping that was never satisfied now fails the compilation.

If the compilation reports an import that is not a public export, either export it from your package or add a rule matching the file. See Errors.

Update Registry Options

0.10.3
packageJsonRemoved, the nearest package.json of dir is used.
tsconfigPathRemoved, the nearest tsconfig.json of each file is used.
dependenciesUnchanged: override the version of a dependency, null for the latest.
devDependenciesRemoved. @types/* packages are detected from your package.json.
subComponentsRemoved. Import the file instead, across registries too, or list the entries in one component like all. References to registries over HTTP are not supported.
meta, content of a fileRemoved.

Route Handlers

Describe the route in a rule, the macro itself is unchanged.

const files: Registry["files"] = {
  "post-route.ts": { type: "route-handler", route: "api/posts/[id]" },
};

Serve the New Output

writeRegistry() has the same signature, but writes a manifest and raw files instead of one JSON per component:

registry/
  _registry.json
  files/button.tsx

Serve the whole directory.

  • The output now contains source files. When it is written into your app (e.g. public/registry), exclude it from tsconfig.json and your linter.
  • Pass cleanDir: true once to remove the JSON files of 0.1.

If you validated the output yourself, fuma-cli/registry/schema now exports types and assertManifest() instead of Zod schemas.

Installer

Options

0.10.3
io.onFileDownloaded(file)io.onFileWritten(file)
io.onWarnRemoved.
options.path in iofile.output, the absolute output path.
install(name, subRegistry)Unchanged. It is now a shorthand of plan() & apply().

confirmFileOverride is only asked for the overwrite status. Files of tree-shaken sources are merged without asking.

Listing Components

connector.fetchRegistryInfo() is replaced by the manifest:

const manifest = await installer.fetchManifest(); // or fetchManifest("sub-registry")

for (const item of manifest.components) {
  if (item.unlisted) continue;
  console.log(item.name, item.title, item.description);
}

A custom RegistryConnector now implements fetchManifest(registry?) and fetchFile(file, registry?).

Plugins

Plugins need a name, and hooks are called with a context as this.

0.10.3
transform(code, context)transform(code, file)
transformImportresolveId: decide where a file is installed, or mark it external to reuse a file of the consumer.
beforeInstall, afterDownloadRemoved. Inspect or filter plan.files between plan() and apply().
beforeDownloadRemoved. Put auth and logging in your connector.
(new)writeBundle, after files are written.

@fuma-cli/interactive

The API of FumadocsComponentInstaller is unchanged, upgrade it together with fuma-cli.

Last updated on

On this page