feat: Phase 2 — layout · auth · shell are real
@gsc/web-kit v0.2.0. Three modules turn from stubs into the working
surface apps need to render a chrome-wrapped Next.js page with one
import per concern.
auth/server:
- createAuth({ keycloak: { clientId, clientSecret, issuer } }) factory
returns { handlers, signIn, signOut, auth, requireAuth, signInPath }.
Canonical SessionUser shape (id, keycloakId, tenantId, email,
displayName, givenName, familyName, roles, accessToken, idToken)
baked into the session callback. Apps drop their hand-rolled
src/auth.ts (~80 lines) for a 6-line factory call.
- requireAuth() — server-only. await it at the top of an RSC layout
or page; redirects to signInPath if no session.
auth/middleware:
- createAuthMiddleware({ publicRoutes? }) returns a Next.js middleware
that redirects unauth'd requests to /api/auth/signin/keycloak with
?callbackUrl=<original>. Bypasses /api/auth/*, /_next/*, /images/*,
favicon, robots.txt always.
auth (client):
- signInRedirect(callbackUrl?) — hard-nav from any client component.
shell/server:
- fetchShellConfig({ appKey, accessToken, apiUrl?, timeoutMs? }).
Server-only fetcher. 3s default timeout. Graceful fallback config
on any error — shell-api outages can't blank-screen a host app.
shell (client):
- <ShellProvider> + useShell() — read the resolved config from any
descendant of <AppLayout>.
layout:
- <AppLayout config currentPath translate onSignOut navbarExtras>.
Renders the chronos-style Bootstrap-Layout-3 chrome (navbar-static,
sidebar-light sidebar-main with collapse + persistence in
localStorage, navbar-footer). Wraps children with the kit's
ShellProvider so useShell() works.
devDep: @types/node for the server-side process.env read.
All 14 sub-exports still resolve under dist/. Phase 3 (data + forms)
and the gscCRM pilot cutover come next.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
22
package-lock.json
generated
22
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@gsc/web-kit",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@gsc/web-kit",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@limitless/ui": "file:../limitless-ui",
|
||||
@@ -15,6 +15,7 @@
|
||||
"zod": "^3.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/react": "^19.0.0",
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"typescript": "^5.4.0"
|
||||
@@ -1297,6 +1298,16 @@
|
||||
"@swc/counter": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.19.40",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.40.tgz",
|
||||
"integrity": "sha512-xxx6M2IpSTnnKcR0cMvIiohkiCx20/oRPtWGbenFygKCGl3zqUzdNjQ/1V4solq1LU+dgv0nQzeGOuqkqZGg0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "19.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
|
||||
@@ -1879,6 +1890,13 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/use-intl": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.11.1.tgz",
|
||||
|
||||
Reference in New Issue
Block a user