# core/factories/certificate.factory.ts

> 30 lines of code and 10 definitions.

Tree: Bane's Lab Build Scripts
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/build-scripts#file-build-scripts-core-factories-certificate-factory-ts
Source text: https://banes-lab.com/source/build-scripts/core/factories/certificate.factory.ts.txt

Listed in [core/factories](https://banes-lab.com/api/source/build-scripts/core/factories.md), after [core/factories/browser.factory.ts](https://banes-lab.com/source/build-scripts/core/factories/browser.factory.ts.md) and before [core/factories/graph.factory.ts](https://banes-lab.com/source/build-scripts/core/factories/graph.factory.ts.md).

## Definitions

- `devCertificate` (lexical_declaration, line 29, exported)
- `writeCertificate` (lexical_declaration, line 19)
- `CERTIFICATE_DIR` (lexical_declaration, line 8)
- `KEY_FILE` (lexical_declaration, line 9)
- `CERT_FILE` (lexical_declaration, line 10)
- `VALIDITY_DAYS` (lexical_declaration, line 11)
- `MS_PER_DAY` (lexical_declaration, line 12)
- `KEY_BITS` (lexical_declaration, line 13)
- `expiry` (lexical_declaration, line 15)
- `pems` (lexical_declaration, line 20)

## Contained in

- [core/factories](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-factories.md)

## Used by

- [core/plugins/server.plugin.ts](https://banes-lab.com/source/build-scripts/core/plugins/server.plugin.ts.md)

## Linked from

- [core/factories](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-factories.md)
- [core/plugins](https://banes-lab.com/anatomy/build-scripts/folder-build-scripts-core-plugins.md)

## Source

```typescript
import { existsSync, mkdirSync, readFileSync } from "node:fs";
import type { DevCertificate } from "#types/certificate.types";
import { absolutePath } from "@ssot/paths";
import { generate } from "selfsigned";
import { join } from "node:path";
import { writeVerbatim } from "@govlab/canonical-write";

const CERTIFICATE_DIR = absolutePath("app.certificates");
const KEY_FILE = join(CERTIFICATE_DIR, "localhost-key.pem");
const CERT_FILE = join(CERTIFICATE_DIR, "localhost-cert.pem");
const VALIDITY_DAYS = 365;
const MS_PER_DAY = 86_400_000;
const KEY_BITS = 2048;

const expiry = function expiry(): Date {
    return new Date(Date.now() + VALIDITY_DAYS * MS_PER_DAY);
};

const writeCertificate = async function writeCertificate(): Promise<void> {
    const pems = await generate([{ name: "commonName", value: "localhost" }], {
        keySize: KEY_BITS,
        notAfterDate: expiry(),
    });
    mkdirSync(CERTIFICATE_DIR, { recursive: true });
    writeVerbatim(KEY_FILE, pems.private);
    writeVerbatim(CERT_FILE, pems.cert);
};

export const devCertificate = async function devCertificate(): Promise<DevCertificate> {
    if (!existsSync(KEY_FILE) || !existsSync(CERT_FILE)) {
        await writeCertificate();
    }
    return { cert: readFileSync(CERT_FILE, "utf8"), key: readFileSync(KEY_FILE, "utf8") };
};
```
