# The Uniform redirect file converter

> This section provides information on how to use the file converter to convert a redirect into a file format for use with other tools.

Source: https://docs.uniform.app/docs/guides/composition/url-management/redirects/file-converter

The redirect file converter is a Node.js script designed to help export redirects into a file format destined for other platforms to perform the redirects.

## ENV

The recommended approach is to use a `.env` file with the following properties:

```properties
UNIFORM_API_KEY=<YOUR API KEY>
UNIFORM_PROJECT_ID=<YOUR PROJECT ID>
```

### Usage

Import

```js
import { RedirectFileConverter } from '@uniformdev/redirect'
```

This contains a function used to convert Uniform redirects to another format.

```js
RedirectFileConverter({
  client, // Redirect SDK client, automatically provisioned if using the env file from above
  redirectEntryObject, // Function to convert a Uniform redirect object into your desired format
  wildcardConverter, // Function to convert the format of wildcards from the Uniform format :wildcard to the desired format
  writeFile, // Function that writes out to a file, or processes the resulting converted output
})
```

### redirectEntryObject

Convert a Uniform defined redirect into another format

Inputs

- **redirect**: singular redirect object

Outputs

- object representing the new format for the redirect

```js
const redirectEntryObject = (r) => ({
  source: r.redirect.sourceUrl,
  destination: r.redirect.targetUrl,
  permanent: r.redirect.targetStatusCode === 301,
})
```

### wildcardConverter

Different platforms require different formats for wildcards, use this converter to adjust your wildcards. Here is an example for converting Uniform wildcards `/:wildcard` -> `/:wildcard` to those used by Cloudflare `/*` -> `/$1`.

**Inputs**

- **sourceUrl**: source URL as defined by Uniform
- **sourceWildcards**: array of defined wildcards, each having a `pathSegment`, the text value of wildcard and `index` where it occurs in the source URL
- **targetUrl**: target URL as defined by Uniform
- **targetWildcards**: array of defined wildcards, each having a `pathSegment`, the text value of wildcard and `index` where it occurs in the target URL

**Outputs**

- **sourceUrl**: source URL with wildcards converted into a new form
- **targetUrl**: target URL with wildcards converted into a new form

```js
const wildcardConverter = ({
  sourceUrl,
  sourceWildcards,
  targetUrl,
  targetWildcards,
}) => {
  const wildcardPosition = new Map()
  let count = 1
  sourceWildcards.forEach((w) => {
    if (w.pathSegment === '*') return
    wildcardPosition.set(w.pathSegment, count++)
    sourceUrl = sourceUrl.replace(w.pathSegment, '*')
  })
  if (
    sourceWildcards.length &&
    sourceWildcards[sourceWildcards.length - 1].pathSegment === '*'
  ) {
    wildcardPosition.set(':splat', count)
  }
  targetWildcards.forEach((w) => {
    targetUrl = targetUrl.replace(
      w.pathSegment,
      `$${wildcardPosition.get(w.pathSegment)}`
    )
  })
  return { sourceUrl, targetUrl }
}
```

### writeFile

Take the converted Uniform objects to be processed.

Input

- **redirects**: array of converted objects.

```js
function writeFile(redirects) {
  if (!fs.existsSync('out')) {
    fs.mkdirSync('out')
  }
  fs.writeFile(
    'out/nextJsRedirects.json',
    JSON.stringify(redirects, undefined, ' '),
    (e) => {
      if (e) {
        // eslint-disable-next-line no-console
        console.log(e)
      }
    }
  )
}
```

### Examples

**Nextjs**

Convert Uniform to Next.js redirect format

```js
RedirectFileConverter({
  redirectEntryObject: (r) => ({
    source: r.redirect.sourceUrl,
    destination: r.redirect.targetUrl,
    permanent: r.redirect.targetStatusCode === 301,
  }),
  writeFile(redirects) {
    fs.writeFile(
      'out/nextJsRedirects.json',
      JSON.stringify(redirects, null, 4),
      (e) => {
        if (e) {
          console.log(e)
        }
      }
    )
  },
})
```

**Netlify toml**

Convert Uniform to a netlify toml file format for redirects

```js
RedirectFileConverter <
  NetlifyTomlRedirect >
  {
    redirectEntryObject: (r) => ({
      lines: [
        '[[redirects]]',
        `from = "${r.redirect.sourceUrl}"`,
        `to = "${r.redirect.targetUrl}"`,
        `status = ${r.redirect.targetStatusCode}`,
      ],
    }),
    writeFile(redirects) {
      if (!fs.existsSync('out')) {
        fs.mkdirSync('out')
      }
      fs.writeFile(
        'out/netlifyTomlRedirects.toml',
        redirects.reduce((cur, o) => {
          return `${cur}${o.lines.join('\n\t')}\n\n`
        }, ''),
        (e) => {
          if (e) {
            console.log(e)
          }
        }
      )
    },
  }
```

**Netlify redirects**

Convert Uniform to Netlify _redirects file

```js
const convertUniformToNetlify_redirects = async () => {
  let slen = 0
  let tlen = 0
  const pad = (maxLen: number, curlen: number) => {
    const ret: string[] = []
    for (let i = curlen; i < maxLen; i++) {
      ret.push(' ')
    }
    return ret.join('')
  }
  RedirectFileConverter <
    NetlifyRedirect >
    {
      redirectEntryObject: (r) => {
        slen =
          slen < r.redirect.sourceUrl.length
            ? r.redirect.sourceUrl.length
            : slen
        tlen =
          tlen < r.redirect.targetUrl.length
            ? r.redirect.targetUrl.length
            : tlen
        return {
          source: r.redirect.sourceUrl,
          target: r.redirect.targetUrl,
          statusCode: r.redirect.targetStatusCode,
        }
      },
      writeFile(redirects) {
        if (!fs.existsSync('out')) {
          fs.mkdirSync('out')
        }
        fs.writeFile(
          'out/netlify_redirects',
          redirects.reduce((cur, o) => {
            return `${cur}${o.source} ${pad(slen, o.source.length)} ${
              o.target
            } ${pad(tlen, o.target.length)} ${o.statusCode}\n`
          }, ''),
          (e) => {
            if (e) {
              console.log(e)
            }
          }
        )
      },
    }
}
convertUniformToNetlify_redirects()
```

**Cloudflare Single**

Convert Uniform to a single Cloudflare redirect item.

```js
RedirectFileConverter<CloudflareSingleRedirect>({
    redirectEntryObject: (r) => ({
      expression: `http.request.uri.path eq "${r.redirect.sourceUrl}"`,
      description: `Uniform redirect ${r.redirect.sourceUrl} to ${r.redirect.targetUrl}`,
      action: 'redirect',
      action_parameters: {
        from_value: { target_url: r.redirect.targetUrl },
        status_code: r.redirect.targetStatusCode,
        preserve_query_string: Boolean(r.redirect.sourceRetainQuerystring),
      },
    }),
    wildcardConverter: ({ sourceUrl, sourceWildcards, targetUrl, targetWildcards }) => {
      const wildcardPosition = new Map<string, number>();
      let count = 1;
      sourceWildcards.forEach((w) => {
        if (w.pathSegment === '*') return;
        wildcardPosition.set(w.pathSegment, count++);
        sourceUrl = sourceUrl.replace(w.pathSegment, '*');
      });
      if (sourceWildcards.length && sourceWildcards[sourceWildcards.length - 1].pathSegment === '*') {
        wildcardPosition.set(':splat', count);
      }
      targetWildcards.forEach((w) => {
        targetUrl = targetUrl.replace(w.pathSegment, `$${wildcardPosition.get(w.pathSegment)}`);
      });
      return { sourceUrl, targetUrl };
    },
    writeFile(redirects) {
      if (!fs.existsSync('out')) {
        fs.mkdirSync('out');
      }
      fs.writeFile(
        'out/cloudflareRedirects.json',
        JSON.stringify(
          {
            name: 'Uniform Redirect Rules',
            kind: 'zone',
            phase: 'http_request_dynamic_redirect',
            rules: redirects,
          },
          undefined,
          ' '
        ),
        (e) => {
          if (e) {
            console.log(e);
          }
        }
      );
    },
  });
```

**Cloudflare List**

Convert Uniform to Cloudflare List item that can be used to source redirects.

```js
  RedirectFileConverter<CloudflareListRedirect>({
    redirectEntryObject: (r) => ({
      redirect: {
        source_url: r.redirect.sourceUrl,
        target_url: r.redirect.targetUrl,
        status_code: r.redirect.targetStatusCode,
        preserve_query_string: Boolean(r.redirect.sourceRetainQuerystring),
      },
    }),
    wildcardConverter: ({ sourceUrl, sourceWildcards, targetUrl, targetWildcards }) => {
      const wildcardPosition = new Map<string, number>();
      let count = 1;
      sourceWildcards.forEach((w) => {
        if (w.pathSegment === '*') return;
        wildcardPosition.set(w.pathSegment, count++);
        sourceUrl = sourceUrl.replace(w.pathSegment, '*');
      });
      if (sourceWildcards.length && sourceWildcards[sourceWildcards.length - 1].pathSegment === '*') {
        wildcardPosition.set(':splat', count);
      }
      targetWildcards.forEach((w) => {
        targetUrl = targetUrl.replace(w.pathSegment, `$${wildcardPosition.get(w.pathSegment)}`);
      });
      return { sourceUrl, targetUrl };
    },
    writeFile(redirects) {
      if (!fs.existsSync('out')) {
        fs.mkdirSync('out');
      }
      fs.writeFile('out/cloudflareList.json', JSON.stringify(redirects, undefined, ' '), (e) => {
        if (e) {
          console.log(e);
        }
      });
    },
  });
```
