@aiquants/auth-react-router 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiquants/auth-react-router",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "React Router v7 / v8 auth adapter for @aiquants/auth-core: Google OAuth strategy factory (remix-auth), cookie session storage with DI test backdoor, a loader guard that authenticates at most once per request (token refresh + photo cache), auth route handlers, and a <GoogleForm> login button.",
5
5
  "sideEffects": [
6
6
  "**/*.css"
@@ -233,6 +233,30 @@ function requireAllowlistType(formData: FormData): "email" | "domain" {
233
233
  throw new Error(`type は "email" または "domain" のいずれかで指定してください (受け取った値: ${JSON.stringify(raw)})`)
234
234
  }
235
235
 
236
+ /** 表示するタブ。未知の値は先頭のタブへ寄せる。 */
237
+ const SEGMENTS = ["users", "groups", "group_members", "allowlist", "directory"] as const
238
+
239
+ /**
240
+ * Derives the segment from a request path, tolerating the router's single-fetch suffix.
241
+ * リクエストパスからセグメントを決める処理 (ルーターの単一フェッチ用の接尾辞を許容する)。
242
+ *
243
+ * ⚠️ クライアント側の遷移では、ルーターは画面の URL ではなく **`<path>.data`** を取りに来る
244
+ * (単一フェッチ)。素朴に末尾セグメントを見ると `"groups.data"` になり、どのタブにも一致せず
245
+ * 既定へ落ちる。結果、**URL は変わるのに中身が変わらない** — 全画面再読込でだけ正しく描かれる
246
+ * ため、動作確認では気付きにくい。接尾辞を落としてから判定する。
247
+ *
248
+ * @param pathname Request pathname. リクエストのパス。
249
+ * @returns One of the known segments. 既知のセグメントのいずれか。
250
+ */
251
+ function segmentFromPathname(pathname: string): (typeof SEGMENTS)[number] {
252
+ const parts = pathname
253
+ .replace(/\.data$/, "")
254
+ .split("/")
255
+ .filter(Boolean)
256
+ const last = parts[parts.length - 1] ?? ""
257
+ return (SEGMENTS as readonly string[]).includes(last) ? (last as (typeof SEGMENTS)[number]) : "users"
258
+ }
259
+
236
260
  /**
237
261
  * The CRUD verb an operation performs. Deliberately a plain string union so this package stays
238
262
  * independent of any particular authorization library.
@@ -419,9 +443,7 @@ export function createUserAdminApp(config: UserAdminAppConfig) {
419
443
  async function loader({ request }: RouteArgs) {
420
444
  // 読取ガード: 拒否は throw されるためここで処理が打ち切られる
421
445
  await config.guards.requireAccess(request, { action: "read", intent: "loader" })
422
- const url = new URL(request.url)
423
- const pathSegments = url.pathname.split("/").filter(Boolean)
424
- const segment = pathSegments[pathSegments.length - 1] ?? "users"
446
+ const segment = segmentFromPathname(new URL(request.url).pathname)
425
447
 
426
448
  const [users, groups, groupMembers, allowlist, directoryStatus, myPermissions] = await Promise.all([
427
449
  config.store.listUsers(),
@@ -440,7 +462,7 @@ export function createUserAdminApp(config: UserAdminAppConfig) {
440
462
 
441
463
  return {
442
464
  resourceLabels: config.resourceLabels,
443
- segment: ["groups", "group_members", "allowlist", "directory"].includes(segment) ? segment : "users",
465
+ segment,
444
466
  users,
445
467
  groups,
446
468
  groupMembers,