Skip to content
Merged
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
67 changes: 0 additions & 67 deletions .eslintrc.cjs

This file was deleted.

5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ updates:
groups:
actions:
patterns: ['*']
update-types: [minor, patch]

- package-ecosystem: npm
directory: /
schedule:
interval: weekly
# Minor and patch updates are grouped; each major update comes as its
# own pull request, since it may need code or configuration changes.
groups:
dev-dependencies:
dependency-type: development
update-types: [minor, patch]
dependencies:
dependency-type: production
update-types: [minor, patch]
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Read-only token: the lint and CI workflows called below need nothing more.
permissions:
contents: read

jobs:
lint:
name: Lint
uses: grokify/.github/.github/workflows/ts-lint-pnpm.yaml@v0.4.0
with:
node-version: '20.x'
node-version: '26.x'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
pnpm-version: '9'
lint-script: 'lint'
format-check-script: 'format:check'
Expand All @@ -24,7 +28,7 @@ jobs:
name: CI
uses: grokify/.github/.github/workflows/ts-ci-pnpm.yaml@v0.4.0
with:
node-versions: '["20.x"]'
node-versions: '["24.x", "26.x"]'
pnpm-version: '9'
test-script: 'test'
build-script: 'build'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '20'
node-version: '26'
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'

Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ function CheckoutPage() {

## Development

Building this repository needs Node.js 24.15 or later (CI runs 24 and 26) and
pnpm 9.

```bash
# Install dependencies
pnpm install
Expand Down
3 changes: 2 additions & 1 deletion docs/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

## Prerequisites

- Node.js 20+
- A supported Node.js LTS release (24.15 or later) for your build tools; the
packages themselves run in the browser
- pnpm 9+ (recommended) or npm

## Install Packages
Expand Down
62 changes: 62 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// ESLint flat config for every package. ESLint finds it from each linted
// file's directory, so `eslint src/` in a package uses it too.
import js from '@eslint/js';
import eslintReact from '@eslint-react/eslint-plugin';
import prettier from 'eslint-config-prettier';
import reactHooks from 'eslint-plugin-react-hooks';
import globals from 'globals';
import tseslint from 'typescript-eslint';

export default tseslint.config(
{
ignores: ['**/node_modules/', '**/dist/', '**/*.js', '**/*.cjs', '**/*.mjs'],
},
js.configs.recommended,
tseslint.configs.recommended,
eslintReact.configs['recommended-typescript'],
reactHooks.configs.flat.recommended,
prettier,
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: { ...globals.browser, ...globals.node },
},
rules: {
// TypeScript handles these
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],

// Allow explicit any in some cases
'@typescript-eslint/no-explicit-any': 'warn',

// React 19 style suggestions. Some packages still support React 18,
// and the rest gain nothing from rewriting working code.
'@eslint-react/no-forward-ref': 'off',
'@eslint-react/no-context-provider': 'off',
'@eslint-react/no-use-context': 'off',
'@eslint-react/naming-convention-ref-name': 'off',
'@eslint-react/use-state': 'off',
// eslint-plugin-react-hooks checks hooks; don't report twice.
'@eslint-react/exhaustive-deps': 'off',
'@eslint-react/rules-of-hooks': 'off',

// Hooks rules
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',

// General
'no-console': ['warn', { allow: ['warn', 'error'] }],
'prefer-const': 'error',
'no-var': 'error',
},
}
);
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,28 @@
},
"devDependencies": {
"@changesets/cli": "^3.0.3",
"@eslint-react/eslint-plugin": "^5.28.8",
"@eslint/js": "^10.0.1",
"@testing-library/dom": "^10.0.0",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^16.0.0",
"@types/node": "^26.6.6",
"@typescript-eslint/eslint-plugin": "^8.58.1",
"@typescript-eslint/parser": "^8.58.1",
"@types/node": "^24.19.2",
"@vitejs/plugin-react": "^6.0.1",
"eslint": "^10.14.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.1.1",
"globals": "^17.14.0",
"jsdom": "^30.1.3",
"prettier": "^3.8.1",
"turbo": "^2.0.0",
"typescript": "^7.0.2",
"typescript": "^6.0.3",
"typescript-eslint": "^8.72.1",
"vite": "^8.3.5",
"vitest": "^5.0.5"
},
"packageManager": "pnpm@9.0.0",
"engines": {
"node": ">=20.0.0",
"node": ">=24.15.0",
"pnpm": ">=9.0.0"
}
}
2 changes: 1 addition & 1 deletion packages/api-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"devDependencies": {
"@types/react": "^19.0.0",
"tsup": "^9.0.0",
"typescript": "^7.0.2"
"typescript": "^6.0.3"
},
"keywords": [
"systemforge",
Expand Down
2 changes: 1 addition & 1 deletion packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tsup": "^9.0.0",
"typescript": "^7.0.2",
"typescript": "^6.0.3",
"vitest": "^5.0.5"
},
"repository": {
Expand Down
49 changes: 34 additions & 15 deletions packages/auth/src/session/SessionProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {
createContext,
type ReactNode,
useCallback,
useContext,
useEffect,
useLayoutEffect,
useMemo,
useRef,
useState,
type ReactNode,
} from 'react';
import { endLoginSession, type SystemAuthSignOut } from '../signout';
import { SessionClient, type SignInOptions } from './client';
Expand Down Expand Up @@ -75,27 +76,45 @@ export function SessionProvider({
const [error, setError] = useState<Error | undefined>();
const wasAuthenticated = useRef(false);
const onUnauthorizedRef = useRef(onUnauthorized);
onUnauthorizedRef.current = onUnauthorized;
// A layout effect, so a session read that settles right after a render
// calls the callback that render committed.
useLayoutEffect(() => {
onUnauthorizedRef.current = onUnauthorized;
});

const apply = useCallback((s: Session) => {
setSession(s);
setError(undefined);
setStatus(s.authenticated ? 'authenticated' : 'unauthenticated');
if (wasAuthenticated.current && !s.authenticated) {
onUnauthorizedRef.current?.();
}
wasAuthenticated.current = s.authenticated;
}, []);

const fail = useCallback((err: unknown) => {
setError(err instanceof Error ? err : new Error(String(err)));
setStatus('error');
}, []);

const refresh = useCallback(async () => {
try {
const s = await bff.getSession();
setSession(s);
setError(undefined);
setStatus(s.authenticated ? 'authenticated' : 'unauthenticated');
if (wasAuthenticated.current && !s.authenticated) {
onUnauthorizedRef.current?.();
}
wasAuthenticated.current = s.authenticated;
apply(await bff.getSession());
} catch (err) {
setError(err instanceof Error ? err : new Error(String(err)));
setStatus('error');
fail(err);
}
}, [bff]);
}, [bff, apply, fail]);

useEffect(() => {
void refresh();
}, [refresh]);
let live = true;
bff.getSession().then(
(s) => live && apply(s),
(err: unknown) => live && fail(err)
);
return () => {
live = false;
};
}, [bff, apply, fail]);

useEffect(() => {
if (!refreshOnFocus || typeof window === 'undefined') return undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tsup": "^9.0.0",
"typescript": "^7.0.2"
"typescript": "^6.0.3"
},
"keywords": [
"react",
Expand Down
Loading
Loading