Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Package checks

on:
pull_request:
branches:
- main
paths:
- package.json
- pnpm-lock.yaml
- tsconfig.json
- tsup.config.ts
- src/**
- scripts/**
- .github/workflows/package.yml
- PUBLISHING.md
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

jobs:
package:
name: Node.js ${{ matrix.node-version }} package
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
node-version:
- 22.x
- 24.x

steps:
- uses: actions/checkout@v6.0.2

- uses: actions/setup-node@v6.4.0
with:
node-version: ${{ matrix.node-version }}

- name: Enable pnpm
run: |
corepack enable
corepack prepare pnpm@10.26.2 --activate

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build package
run: pnpm build

- name: Verify package dist
run: pnpm verify:package

- name: Verify packed consumer install
run: pnpm verify:consumer
68 changes: 68 additions & 0 deletions PUBLISHING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Publishing `@api7/better-auth-ui`

This fork is published as `@api7/better-auth-ui` so API7 projects can depend on
a prebuilt npm package instead of rebuilding this repository during consumer
installation.

## Versioning

Use the upstream version plus an API7 suffix:

```text
3.3.15-api7.0
3.3.15-api7.1
3.4.0-api7.0
```

Increment the API7 suffix for fork-only fixes. Move the upstream base version
when rebasing onto a newer upstream release.

## Release Checks

Run these commands before publishing:

```bash
pnpm install --frozen-lockfile
pnpm build
pnpm verify:package
pnpm verify:consumer
npm pack --dry-run
```

`pnpm verify:package` checks that:

- the package is named `@api7/better-auth-ui`
- `prepare` is not used for consumer installs
- `dist/index.js` preserves `"use client"`
- the public type exports used by API7 Developer Portal exist
- server-side view path exports exist
- all package export targets point to files included in `dist`

`pnpm verify:consumer` packs the package, installs the tarball in a temporary
consumer project, type-checks common imports, and verifies runtime exports.

## Publish

Make sure you are logged in with permission to publish under the `@api7` scope:

```bash
npm whoami
npm publish --access public
```

Do not restore a `prepare` script for this package. Consumers should install the
prebuilt npm tarball rather than rebuilding the GitHub repository during their
own install step.

## Portal Dependency

API7 Developer Portal can keep existing source imports while installing the API7
package through an npm alias:

```json
{
"dependencies": {
"@daveyplate/better-auth-ui": "npm:@api7/better-auth-ui@3.3.15-api7.0"
}
}
```
20 changes: 14 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
{
"name": "@daveyplate/better-auth-ui",
"name": "@api7/better-auth-ui",
"homepage": "https://better-auth-ui.com",
"version": "3.3.15",
"version": "3.3.15-api7.0",
"description": "Plug & play shadcn/ui components for better-auth",
"scripts": {
"build": "tsup --clean --dts && cp src/style.css dist/style.css",
"prepare": "pnpm build",
"dev": "tsc-watch",
"prepublishOnly": "rm -rf dist && turbo build",
"prepack": "pnpm build && pnpm verify:package",
"prepublishOnly": "pnpm build && pnpm verify:package",
"verify:package": "node scripts/verify-package.mjs",
"verify:consumer": "node scripts/verify-consumer.mjs",
"pack:dry-run": "npm pack --dry-run",
"lint": "biome check",
"lint:fix": "biome check --write"
},
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
"./css": "./dist/style.css",
".": {
Expand Down Expand Up @@ -68,8 +72,9 @@
}
},
"files": [
"src",
"dist"
"dist",
"README.md",
"LICENSE"
],
"keywords": [
"typescript",
Expand Down Expand Up @@ -161,5 +166,8 @@
"vaul": "^1.1.2"
},
"packageManager": "pnpm@10.26.2",
"publishConfig": {
"access": "public"
},
"overrides": {}
}
120 changes: 120 additions & 0 deletions scripts/verify-consumer.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { execFileSync } from "node:child_process"
import {
existsSync,
mkdirSync,
mkdtempSync,
readdirSync,
rmSync,
writeFileSync
} from "node:fs"
import { tmpdir } from "node:os"
import path from "node:path"
import { fileURLToPath } from "node:url"

const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
const workDir = mkdtempSync(
path.join(tmpdir(), "api7-better-auth-ui-consumer-")
)
const packDir = path.join(workDir, "pack")
const appDir = path.join(workDir, "app")

function run(command, args, options = {}) {
execFileSync(command, args, {
stdio: "inherit",
...options
})
}

try {
mkdirSync(packDir, { recursive: true })
run("npm", ["pack", "--pack-destination", packDir], { cwd: root })

const tarball = readdirSync(packDir)
.filter((file) => file.endsWith(".tgz"))
.map((file) => path.join(packDir, file))[0]

if (!tarball || !existsSync(tarball)) {
throw new Error("npm pack did not produce a tarball")
}

mkdirSync(appDir, { recursive: true })
writeFileSync(
path.join(appDir, "package.json"),
JSON.stringify({ private: true, type: "module" }, null, 2)
)
writeFileSync(
path.join(appDir, "tsconfig.json"),
JSON.stringify(
{
compilerOptions: {
jsx: "react-jsx",
lib: ["dom", "dom.iterable", "esnext"],
module: "esnext",
moduleResolution: "bundler",
noEmit: true,
skipLibCheck: true,
strict: true,
target: "es2022"
},
include: ["src"]
},
null,
2
)
)

const sourceDir = path.join(appDir, "src")
mkdirSync(sourceDir, { recursive: true })
writeFileSync(
path.join(sourceDir, "index.tsx"),
`import { AuthUIProvider, AuthView, OrganizationSwitcher, UserButton, UserInvitationsCard, type Provider } from "@api7/better-auth-ui"
import { accountViewPaths, organizationViewPaths } from "@api7/better-auth-ui/server"

const provider: Provider = { provider: "api7", name: "API7" }
const refs = [
AuthUIProvider,
AuthView,
OrganizationSwitcher,
UserButton,
UserInvitationsCard,
accountViewPaths.SETTINGS,
organizationViewPaths.MEMBERS,
provider.name
]

console.log(refs.length)
`
)

run(
"npm",
[
"install",
"--silent",
tarball,
"typescript@5.9.3",
"react@18.3.1",
"react-dom@18.3.1",
"@types/react@18.3.3",
"@types/react-dom@18.3.0"
],
{ cwd: appDir }
)
run("npx", ["tsc", "--noEmit"], { cwd: appDir })

const runtimeCheck = `const ui = await import("@api7/better-auth-ui")
const server = await import("@api7/better-auth-ui/server")
for (const name of ["AuthUIProvider", "AuthView", "OrganizationView", "OrganizationSwitcher", "UserButton", "UserInvitationsCard"]) {
if (!(name in ui)) throw new Error("Missing runtime export: " + name)
}
for (const name of ["accountViewPaths", "organizationViewPaths"]) {
if (!(name in server)) throw new Error("Missing server runtime export: " + name)
}
`
writeFileSync(path.join(appDir, "runtime-check.mjs"), runtimeCheck)
run("node", ["runtime-check.mjs"], { cwd: appDir })

console.log("Consumer verification passed")
} finally {
rmSync(workDir, { recursive: true, force: true })
}
Loading