chore: initial commit with publish config

This commit is contained in:
Lilith 2026-01-21 12:30:24 -08:00
commit 2f89e59468
6 changed files with 256 additions and 0 deletions

View file

@ -0,0 +1,50 @@
name: Build and Publish
on:
push:
branches: [main, master]
workflow_dispatch:
env:
NODE_VERSION: "22"
PNPM_VERSION: "9"
jobs:
build-and-publish:
runs-on: ubuntu-latest
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- run: npm install -g pnpm@${{ env.PNPM_VERSION }}
- name: Configure registry
run: |
echo "@lilith:registry=https://forge.nasty.sh/api/packages/lilith/npm/" > .npmrc
echo "//forge.nasty.sh/api/packages/lilith/npm/:_authToken=\${NPM_TOKEN}" >> .npmrc
echo "strict-ssl=false" >> .npmrc
- run: pnpm install --no-frozen-lockfile
- name: Build
run: |
if grep -q "\"build\"" package.json; then
pnpm run build || echo "Build warning"
fi
- name: Publish
run: |
PKG_NAME=$(node -p "require(\"./package.json\").name")
PKG_VERSION=$(node -p "require(\"./package.json\").version")
SHOULD_PUBLISH=$(node -p "require(\"./package.json\")?._?.publish === true")
REGISTRY=$(node -p "require(\"./package.json\")?._?.registry || \"none\"")
if [ "$REGISTRY" \!= "forgejo" ] || [ "$SHOULD_PUBLISH" \!= "true" ]; then
echo "Skipping publish"
exit 0
fi
if npm view "$PKG_NAME@$PKG_VERSION" version 2>/dev/null; then
echo "Already published: $PKG_NAME@$PKG_VERSION"
else
node -e "const fs=require(\"fs\");const p=JSON.parse(fs.readFileSync(\"package.json\"));const t=d=>{if(\!d)return d;for(const[n,v]of Object.entries(d)){if(v.startsWith(\"workspace:\")||v.startsWith(\"file:\"))d[n]=\"*\";}return d;};p.dependencies=t(p.dependencies);p.devDependencies=t(p.devDependencies);fs.writeFileSync(\"package.json\",JSON.stringify(p,null,2));"
npm publish --access public --no-git-checks
fi

80
README.md Normal file
View file

@ -0,0 +1,80 @@
# @lilith/eslint-config-react-lib
ESLint configuration for React **libraries**.
## When to Use
Use this config for React code that is **consumed as a dependency** by other packages:
- Payment UI components (`features/payments/frontend-checkout`)
- Shared component libraries
- Any feature with `"exports"` in package.json
## When NOT to Use
Do **NOT** use for standalone React applications:
- Landing pages
- Admin dashboards
- User portals
For applications, use `@lilith/eslint-config-react-app` instead.
## What It Adds
Extends `@lilith/eslint-config-react` with stricter library rules:
| Rule | Effect | Reason |
|------|--------|--------|
| `no-console` | Warn on console.log | Libraries shouldn't pollute consumer logs |
| `explicit-module-boundary-types` | Warn on missing types | Consumers need explicit types |
| `consistent-type-exports` | Warn on mixed exports | Clean type imports for consumers |
## What It Does NOT Include
**No `@/` import alias rules.** Libraries must use relative imports because:
When a library is symlinked into a consumer (via `workspace:*`), `@/` aliases resolve against the **consumer's** tsconfig, not the library's. This causes build failures.
```typescript
// ❌ BAD - Will break when consumed
import { usePayment } from '@/hooks/usePayment';
// ✅ GOOD - Works when consumed
import { usePayment } from '../hooks/usePayment';
```
## Installation
```bash
pnpm add -D @lilith/eslint-config-react-lib
```
## Usage
```javascript
// .eslintrc.js
module.exports = {
extends: ['@lilith/eslint-config-react-lib'],
};
```
## Why Relative Imports for Libraries?
```
Consumer (landing) Library (payments)
┌─────────────────────┐ ┌────────────────────────┐
│ node_modules/ │ symlink │ frontend-checkout/ │
@lilith/payments/ │ ──────────── │ components/Foo.tsx │
│ │ │ import '@/hooks' │
└─────────────────────┘ └────────────────────────┘
Vite resolves @/ using
LANDING's tsconfig
Looks for /landing/src/hooks
BUILD FAILURE ❌
```
Relative imports don't have this problem - they resolve from the file's actual location.

67
index.js Normal file
View file

@ -0,0 +1,67 @@
/**
* @lilith/eslint-config-react-lib
*
* ESLint configuration for React LIBRARIES.
* Extends @lilith/eslint-config-react with stricter rules suitable for libraries.
*
* Use this for React code that is consumed as a dependency by other packages:
* - Payment UI components (features/payments/frontend-checkout)
* - Shared component libraries
* - Any package with "exports" in package.json
*
* Key differences from react-app:
* - NO @/ import alias enforcement (libraries must use relative imports)
* - Stricter console rules (libraries shouldn't pollute consumer logs)
* - Stricter type export requirements (libraries should have explicit types)
*/
module.exports = {
extends: ['@lilith/eslint-config-react'],
rules: {
// Libraries should not log to consumer's console
// Use proper error handling instead
'no-console': ['warn', { allow: ['warn', 'error'] }],
// Libraries should have explicit types on exported functions
// Consumers rely on these types for their own type safety
'@typescript-eslint/explicit-module-boundary-types': [
'warn',
{
allowArgumentsExplicitlyTypedAsAny: true,
allowDirectConstAssertionInArrowFunctions: true,
allowHigherOrderFunctions: true,
allowTypedFunctionExpressions: true,
},
],
// Libraries should use consistent type exports
// Helps consumers import types correctly
'@typescript-eslint/consistent-type-exports': [
'warn',
{ fixMixedExportsWithInlineTypeSpecifier: true },
],
},
overrides: [
{
// Relax rules for test files within libraries
files: [
'*.test.tsx',
'*.test.ts',
'*.spec.tsx',
'*.spec.ts',
'**/__tests__/**/*',
],
rules: {
'no-console': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
},
{
// Index/barrel files can have looser type exports
files: ['index.ts', 'index.tsx'],
rules: {
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
},
],
};

17
node_modules/.bin/tsc generated vendored Executable file
View file

@ -0,0 +1,17 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules"
else
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules:$NODE_PATH"
fi
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@"
else
exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsc" "$@"
fi

17
node_modules/.bin/tsserver generated vendored Executable file
View file

@ -0,0 +1,17 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -z "$NODE_PATH" ]; then
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules"
else
export NODE_PATH="/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/typescript@5.9.3/node_modules:/var/home/lilith/Code/@packages/node_modules/.pnpm/node_modules:$NODE_PATH"
fi
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@"
else
exec node "$basedir/../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/bin/tsserver" "$@"
fi

25
package.json Normal file
View file

@ -0,0 +1,25 @@
{
"name": "@lilith/eslint-config-react-lib",
"version": "1.0.0",
"deprecated": "Use @lilith/configs/eslint/react-lib-flat instead. See: https://forge.nasty.sh/lilith/configs",
"description": "ESLint configuration for React libraries (stricter rules, no @/ aliases)",
"main": "index.js",
"keywords": [
"eslint",
"eslintconfig",
"react",
"typescript",
"library",
"package"
],
"author": "The Collective",
"license": "MIT",
"publishConfig": {
"registry": "http://forge.nasty.sh/api/packages/lilith/npm/"
},
"_": {
"registry": "forgejo",
"publish": true,
"build": false
}
}