@owlmeans/web-client 0.1.18-rc.9 → 0.1.18

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.
Files changed (118) hide show
  1. package/README.md +247 -43
  2. package/agent-meta/manifest.json +3 -3
  3. package/agent-meta/skills/web-client/SKILL.md +62 -73
  4. package/build/components/dispatcher/component.d.ts.map +1 -1
  5. package/build/components/dispatcher/component.js +55 -9
  6. package/build/components/dispatcher/component.js.map +1 -1
  7. package/build/components/dispatcher/parametrise.d.ts.map +1 -1
  8. package/build/components/dispatcher/parametrise.js +0 -3
  9. package/build/components/dispatcher/parametrise.js.map +1 -1
  10. package/build/components/dispatcher/types.d.ts +2 -2
  11. package/build/components/dispatcher/types.d.ts.map +1 -1
  12. package/build/context.d.ts.map +1 -1
  13. package/build/context.js +0 -1
  14. package/build/context.js.map +1 -1
  15. package/build/entrypoints.d.ts +16 -0
  16. package/build/entrypoints.d.ts.map +1 -0
  17. package/build/entrypoints.js +20 -0
  18. package/build/entrypoints.js.map +1 -0
  19. package/build/exports.d.ts +3 -2
  20. package/build/exports.d.ts.map +1 -1
  21. package/build/exports.js +2 -2
  22. package/build/exports.js.map +1 -1
  23. package/build/i18n/auth-be.json +32 -0
  24. package/build/i18n/auth-de.json +32 -0
  25. package/build/i18n/auth-en.json +32 -0
  26. package/build/i18n/auth-es.json +32 -0
  27. package/build/i18n/auth-fr.json +38 -0
  28. package/build/i18n/auth-pl.json +32 -0
  29. package/build/i18n/auth-ru.json +32 -0
  30. package/build/i18n/auth-uk.json +32 -0
  31. package/build/i18n.js +10 -8
  32. package/build/i18n.js.map +1 -1
  33. package/build/index.d.ts +1 -1
  34. package/build/index.d.ts.map +1 -1
  35. package/build/index.js +1 -1
  36. package/build/index.js.map +1 -1
  37. package/build/login/consts.d.ts +36 -0
  38. package/build/login/consts.d.ts.map +1 -1
  39. package/build/login/consts.js +38 -0
  40. package/build/login/consts.js.map +1 -1
  41. package/build/login/consts.local.d.ts +22 -0
  42. package/build/login/consts.local.d.ts.map +1 -0
  43. package/build/login/consts.local.js +48 -0
  44. package/build/login/consts.local.js.map +1 -0
  45. package/build/login/index.d.ts +4 -0
  46. package/build/login/index.d.ts.map +1 -1
  47. package/build/login/index.js +3 -0
  48. package/build/login/index.js.map +1 -1
  49. package/build/login/pump.d.ts +20 -0
  50. package/build/login/pump.d.ts.map +1 -0
  51. package/build/login/pump.js +46 -0
  52. package/build/login/pump.js.map +1 -0
  53. package/build/login/redirect.d.ts.map +1 -1
  54. package/build/login/redirect.js +17 -1
  55. package/build/login/redirect.js.map +1 -1
  56. package/build/login/screen.d.ts +19 -0
  57. package/build/login/screen.d.ts.map +1 -0
  58. package/build/login/screen.js +119 -0
  59. package/build/login/screen.js.map +1 -0
  60. package/build/login/surrogate.d.ts +16 -0
  61. package/build/login/surrogate.d.ts.map +1 -1
  62. package/build/login/surrogate.js +139 -71
  63. package/build/login/surrogate.js.map +1 -1
  64. package/build/login/types.d.ts +10 -0
  65. package/build/login/types.d.ts.map +1 -0
  66. package/build/login/types.js +2 -0
  67. package/build/login/types.js.map +1 -0
  68. package/build/login/view.d.ts +4 -0
  69. package/build/login/view.d.ts.map +1 -0
  70. package/build/login/view.js +12 -0
  71. package/build/login/view.js.map +1 -0
  72. package/build/main.d.ts +9 -1
  73. package/build/main.d.ts.map +1 -1
  74. package/build/main.js +18 -5
  75. package/build/main.js.map +1 -1
  76. package/build/middleware.d.ts +1 -1
  77. package/build/middleware.d.ts.map +1 -1
  78. package/build/middleware.js +7 -6
  79. package/build/middleware.js.map +1 -1
  80. package/build/service.js +1 -1
  81. package/build/service.js.map +1 -1
  82. package/build/types.local.d.ts +5 -0
  83. package/build/types.local.d.ts.map +1 -0
  84. package/build/types.local.js +2 -0
  85. package/build/types.local.js.map +1 -0
  86. package/package.json +22 -21
  87. package/src/components/dispatcher/component.tsx +71 -8
  88. package/src/components/dispatcher/parametrise.tsx +0 -3
  89. package/src/components/dispatcher/types.ts +2 -2
  90. package/src/context.ts +0 -2
  91. package/src/entrypoints.ts +20 -0
  92. package/src/exports.ts +7 -2
  93. package/src/i18n/auth-be.json +32 -0
  94. package/src/i18n/auth-de.json +32 -0
  95. package/src/i18n/auth-en.json +32 -0
  96. package/src/i18n/auth-es.json +32 -0
  97. package/src/i18n/auth-fr.json +38 -0
  98. package/src/i18n/auth-pl.json +32 -0
  99. package/src/i18n/auth-ru.json +32 -0
  100. package/src/i18n/auth-uk.json +32 -0
  101. package/src/i18n.ts +10 -8
  102. package/src/index.ts +1 -1
  103. package/src/login/consts.local.ts +52 -0
  104. package/src/login/consts.ts +38 -0
  105. package/src/login/index.ts +4 -0
  106. package/src/login/pump.ts +53 -0
  107. package/src/login/redirect.ts +23 -2
  108. package/src/login/screen.tsx +141 -0
  109. package/src/login/surrogate.ts +170 -86
  110. package/src/login/types.ts +10 -0
  111. package/src/login/view.tsx +22 -0
  112. package/src/main.tsx +19 -6
  113. package/src/middleware.ts +9 -12
  114. package/src/service.ts +1 -1
  115. package/src/types.local.ts +5 -0
  116. package/tests/surrogate.spec.ts +74 -0
  117. package/tsconfig.json +1 -1
  118. package/src/modules.ts +0 -9
@@ -1,16 +1,32 @@
1
1
  import { DispatcherHOC } from '@owlmeans/client-auth'
2
- import { useEffect } from 'react'
2
+ import { useEffect, useState } from 'react'
3
3
  import { useI18nLib } from '@owlmeans/client-i18n'
4
4
  import { AUTH_QUERY } from '@owlmeans/auth'
5
+ import { FallbackLoginScreen, LoginIntent, LoginOutcome, ResumeAction, loginResumeHelper } from '@owlmeans/client-auth/login'
6
+ import { LoginSurrogateView } from '../../login/view.js'
7
+ import { SurrogateStage } from '../../login/consts.js'
5
8
  import { useContext } from '../../context.js'
6
9
 
7
- export const Dispatcher = DispatcherHOC(({ provideToken }) => {
10
+ export const Dispatcher = DispatcherHOC(({ provideToken, navigate }) => {
8
11
  const context = useContext()
9
12
  const [query] = context.router().useSearchParams()
10
13
 
11
14
  const t = useI18nLib('auth', 'dispatcher')
15
+ const tAuth = useI18nLib('auth')
16
+
17
+ // Read in the component body, not in the effect: `window.name` is set by `window.open` before
18
+ // this document loads and `sessionStorage` carries the marker across the provider round trip, so
19
+ // the answer is already correct at first paint — and a first paint that showed the application
20
+ // before an effect corrected it is the defect this exists to prevent.
21
+ const [env] = useState(() => context.login().env())
22
+ const [outcome, setOutcome] = useState<LoginOutcome | null>(null)
23
+ // Nothing to return from and nobody signed in: offer the choice rather than starting a flow.
24
+ const [choose, setChoose] = useState(false)
12
25
 
13
26
  useEffect(() => {
27
+ // First statement of the effect on purpose: everything below can navigate this window away.
28
+ context.login().enter()
29
+
14
30
  const token = query.get(AUTH_QUERY)
15
31
  if (token != null) {
16
32
  const params: Record<string, string> = {}
@@ -21,15 +37,62 @@ export const Dispatcher = DispatcherHOC(({ provideToken }) => {
21
37
  })
22
38
 
23
39
  provideToken({ token }, params)
24
- } else {
25
- context.auth().authenticated().then(authzToken => {
26
- if (authzToken == null) {
27
- provideToken({ token: '' }, undefined)
28
- }
29
- })
40
+
41
+ return
30
42
  }
43
+
44
+ void context.auth().authenticated().then(async authzToken => {
45
+ if (authzToken == null || authzToken === '') {
46
+ setChoose(true)
47
+
48
+ return
49
+ }
50
+ // A session already exists in THIS document. Whether it is useful here, or belongs to the
51
+ // window that opened this one, is the plugin's call — the dispatcher reads no environment.
52
+ const settled = await context.login().resume(authzToken)
53
+ switch (loginResumeHelper.resumeAction(settled)) {
54
+ case ResumeAction.Stop:
55
+ return
56
+ case ResumeAction.Render:
57
+ setOutcome(settled)
58
+
59
+ return
60
+ default:
61
+ await navigate()
62
+ }
63
+ })
31
64
  }, [])
32
65
 
66
+ // A surrogate window never renders the application, whatever else is true. Checked ahead of
67
+ // every other return for exactly that reason.
68
+ //
69
+ // `choose` is the one state this must NOT mask, and it is not an exception to the rule: the
70
+ // login chooser is not the application. A login window with nothing to return from and nobody
71
+ // signed in has exactly one thing left that can move it forward, and that is asking which
72
+ // provider. The surrogate URL normally carries `?method=` so the question is already settled,
73
+ // but a window opened from a bare "Log in" — the framed application's own header button — has no
74
+ // method to send. Returning the "working" panel there left the popup on "Signing you in…"
75
+ // permanently, because nothing was ever going to start.
76
+ if (env.surrogate && !choose) {
77
+ return <LoginSurrogateView
78
+ intent={LoginIntent.Login}
79
+ stage={
80
+ outcome === LoginOutcome.Orphaned ? SurrogateStage.Orphaned
81
+ : outcome === LoginOutcome.Failed ? SurrogateStage.Failed
82
+ : outcome === LoginOutcome.Gesture ? SurrogateStage.Gesture
83
+ : SurrogateStage.Working
84
+ }
85
+ onAction={() => window.close()}
86
+ translate={(key, defaultValue) => tAuth(key, { defaultValue })}
87
+ />
88
+ }
89
+
90
+ if (choose) {
91
+ const Screen = context.login().screen() ?? FallbackLoginScreen
92
+
93
+ return <Screen translate={(key, defaultValue) => tAuth(key, { defaultValue })} />
94
+ }
95
+
33
96
  return query.has(AUTH_QUERY) ? <div style={{
34
97
  width: '100%', // Makes the div occupy the full width
35
98
  display: 'flex', // Enables flexbox layout
@@ -6,9 +6,7 @@ import { Dispatcher } from "./component.js"
6
6
  import { ParametrisedProps } from "./types.js"
7
7
 
8
8
  export const parametriseDispatcher = (def: Partial<ParametrisedProps>, Com?: RoutedComponent<DispatcherProps> ) => {
9
- console.log('Parametrising dispatcher with', def)
10
9
  return (props: ParametrisedProps) => {
11
- console.log('Rendering parametrised dispatcher with', props)
12
10
  const _props = useMemo(() => {
13
11
  let payload: FlowPayload | undefined = undefined
14
12
  if (def.payload != null) {
@@ -20,7 +18,6 @@ export const parametriseDispatcher = (def: Partial<ParametrisedProps>, Com?: Rou
20
18
  }
21
19
  return { ...def, ...props, payload }
22
20
  }, [props])
23
- console.log('Computed dispatcher props', _props)
24
21
  Com ??= Dispatcher
25
22
  return <Com {..._props} />
26
23
  }
@@ -1,6 +1,6 @@
1
- import type { ModuleContextParams } from "@owlmeans/client"
1
+ import type { EntrypointContextParams } from "@owlmeans/client"
2
2
  import type { DispatcherProps } from "@owlmeans/client-auth"
3
3
  import type { PropsWithChildren } from "react"
4
4
 
5
- export interface ParametrisedProps extends PropsWithChildren<ModuleContextParams & DispatcherProps> {
5
+ export interface ParametrisedProps extends PropsWithChildren<EntrypointContextParams & DispatcherProps> {
6
6
  }
package/src/context.ts CHANGED
@@ -22,8 +22,6 @@ export const makeContext = <C extends AppConfig = AppConfig, T extends AppContex
22
22
  appendWebRouter<C, T>(context)
23
23
  appendWebLogin<C, T>(context)
24
24
 
25
- context.makeContext = makeContext as typeof context.makeContext
26
-
27
25
  return context
28
26
  }
29
27
 
@@ -0,0 +1,20 @@
1
+ import { authProtocols } from '@owlmeans/auth-common'
2
+ import { entrypoints as authBindings } from '@owlmeans/client-auth'
3
+ import { bindScreen } from '@owlmeans/client-entrypoint'
4
+ import { handler } from '@owlmeans/client'
5
+ import { Dispatcher } from './components/dispatcher/component.js'
6
+ import { SurrogateScreen } from './login/screen.js'
7
+
8
+ /**
9
+ * Bound here rather than in a relying-party package on purpose.
10
+ *
11
+ * The surrogate mechanic is not OIDC-specific — it is "run the login route one window up and hand
12
+ * the result back" — and every web application already spreads this list. Putting the screen here
13
+ * means `web-panel`, `mui-panel` and every generated target gain a working login window with no
14
+ * edit of their own, which is the only way an application that is already deployed can get it.
15
+ */
16
+ export const entrypoints = [
17
+ ...authBindings,
18
+ bindScreen(authProtocols.dispatcher, handler(Dispatcher)),
19
+ bindScreen(authProtocols.surrogate, handler(SurrogateScreen)),
20
+ ]
package/src/exports.ts CHANGED
@@ -1,9 +1,14 @@
1
1
 
2
- export { handler } from '@owlmeans/client'
2
+ export {
3
+ handler, lazyHandler, lazyComponent, lazyRetryHelper, recoverFromChunkError,
4
+ } from '@owlmeans/client'
5
+ export type {
6
+ LazyComponent, LazyComponentOptions, LazyErrorRenderer, LazyHandler, LazyRetryHelper, RetryImportOptions
7
+ } from '@owlmeans/client'
3
8
  export { config } from '@owlmeans/client-context'
4
9
  export { service } from '@owlmeans/config'
5
10
  export { AppType, HOME, ROOT, BASE, GUEST } from '@owlmeans/context'
6
- export { entrypoint, elevate, provideRequest, stab } from '@owlmeans/client-entrypoint'
11
+ export { bind, bindAll, bindScreen, clientRequestHelper, provideRequest, stab } from '@owlmeans/client-entrypoint'
7
12
  export { route, frontend } from '@owlmeans/route'
8
13
  export type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
9
14
  export type { ClientEntrypoint as Module } from '@owlmeans/client-entrypoint'
@@ -2,5 +2,37 @@
2
2
  "dispatcher": {
3
3
  "loading": "Загрузка...",
4
4
  "error": "Не ўдалося прайсці аўтэнтыфікацыю: {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Выконваем уваход…",
9
+ "gesture": {
10
+ "title": "Працягніце, каб увайсці.",
11
+ "action": "Увайсці"
12
+ },
13
+ "handing": "Гатова. Вяртаемся ў праграму…",
14
+ "orphaned": "Уваход выкананы. Можаце закрыць гэтае акно і вярнуцца ў праграму.",
15
+ "failed": "Не ўдалося завяршыць. Закрыйце гэтае акно і паспрабуйце зноў.",
16
+ "standalone": {
17
+ "title": "Гэтая старонка выкарыстоўваецца для ўваходу з іншага акна.",
18
+ "action": "Адкрыць праграму"
19
+ },
20
+ "close": "Закрыць"
21
+ },
22
+ "logout": {
23
+ "working": "Выконваем выхад…",
24
+ "gesture": {
25
+ "title": "Працягніце, каб выйсці.",
26
+ "action": "Выйсці"
27
+ },
28
+ "handing": "Выхад выкананы. Вяртаемся ў праграму…",
29
+ "orphaned": "Выхад выкананы. Можаце закрыць гэтае акно.",
30
+ "failed": "Выхад тут не завершаны. Можаце закрыць гэтае акно.",
31
+ "standalone": {
32
+ "title": "Гэтая старонка выкарыстоўваецца для выхаду з іншага акна.",
33
+ "action": "Адкрыць праграму"
34
+ },
35
+ "close": "Закрыць"
36
+ }
5
37
  }
6
38
  }
@@ -2,5 +2,37 @@
2
2
  "dispatcher": {
3
3
  "loading": "Wird geladen...",
4
4
  "error": "Authentifizierung fehlgeschlagen: {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Anmeldung läuft…",
9
+ "gesture": {
10
+ "title": "Fortfahren, um sich anzumelden.",
11
+ "action": "Anmelden"
12
+ },
13
+ "handing": "Fertig. Zurück zur Anwendung…",
14
+ "orphaned": "Angemeldet. Sie können dieses Fenster schließen und in der Anwendung fortfahren.",
15
+ "failed": "Das wurde nicht abgeschlossen. Schließen Sie dieses Fenster und versuchen Sie es erneut.",
16
+ "standalone": {
17
+ "title": "Diese Seite dient der Anmeldung aus einem anderen Fenster.",
18
+ "action": "Anwendung öffnen"
19
+ },
20
+ "close": "Schließen"
21
+ },
22
+ "logout": {
23
+ "working": "Abmeldung läuft…",
24
+ "gesture": {
25
+ "title": "Fortfahren, um sich abzumelden.",
26
+ "action": "Abmelden"
27
+ },
28
+ "handing": "Abgemeldet. Zurück zur Anwendung…",
29
+ "orphaned": "Abgemeldet. Sie können dieses Fenster schließen.",
30
+ "failed": "Die Abmeldung wurde hier nicht abgeschlossen. Sie können dieses Fenster schließen.",
31
+ "standalone": {
32
+ "title": "Diese Seite dient der Abmeldung aus einem anderen Fenster.",
33
+ "action": "Anwendung öffnen"
34
+ },
35
+ "close": "Schließen"
36
+ }
5
37
  }
6
38
  }
@@ -2,5 +2,37 @@
2
2
  "dispatcher": {
3
3
  "loading": "Loading...",
4
4
  "error": "Authentication failed: {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Signing you in…",
9
+ "gesture": {
10
+ "title": "Continue to sign in.",
11
+ "action": "Sign in"
12
+ },
13
+ "handing": "Done. Returning to the application…",
14
+ "orphaned": "Signed in. You can close this window and continue in the application.",
15
+ "failed": "That did not complete. You can close this window and try again.",
16
+ "standalone": {
17
+ "title": "This page is used to sign in from another window.",
18
+ "action": "Open the application"
19
+ },
20
+ "close": "Close"
21
+ },
22
+ "logout": {
23
+ "working": "Signing you out…",
24
+ "gesture": {
25
+ "title": "Continue to sign out.",
26
+ "action": "Sign out"
27
+ },
28
+ "handing": "Signed out. Returning to the application…",
29
+ "orphaned": "Signed out. You can close this window.",
30
+ "failed": "Sign-out did not complete here. You can close this window.",
31
+ "standalone": {
32
+ "title": "This page is used to sign out from another window.",
33
+ "action": "Open the application"
34
+ },
35
+ "close": "Close"
36
+ }
5
37
  }
6
38
  }
@@ -2,5 +2,37 @@
2
2
  "dispatcher": {
3
3
  "loading": "Cargando...",
4
4
  "error": "Error de autenticación: {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Iniciando sesión…",
9
+ "gesture": {
10
+ "title": "Continúa para iniciar sesión.",
11
+ "action": "Iniciar sesión"
12
+ },
13
+ "handing": "Listo. Volviendo a la aplicación…",
14
+ "orphaned": "Sesión iniciada. Puedes cerrar esta ventana y continuar en la aplicación.",
15
+ "failed": "No se completó. Cierra esta ventana e inténtalo de nuevo.",
16
+ "standalone": {
17
+ "title": "Esta página se usa para iniciar sesión desde otra ventana.",
18
+ "action": "Abrir la aplicación"
19
+ },
20
+ "close": "Cerrar"
21
+ },
22
+ "logout": {
23
+ "working": "Cerrando sesión…",
24
+ "gesture": {
25
+ "title": "Continúa para cerrar sesión.",
26
+ "action": "Cerrar sesión"
27
+ },
28
+ "handing": "Sesión cerrada. Volviendo a la aplicación…",
29
+ "orphaned": "Sesión cerrada. Puedes cerrar esta ventana.",
30
+ "failed": "El cierre de sesión no se completó aquí. Puedes cerrar esta ventana.",
31
+ "standalone": {
32
+ "title": "Esta página se usa para cerrar sesión desde otra ventana.",
33
+ "action": "Abrir la aplicación"
34
+ },
35
+ "close": "Cerrar"
36
+ }
5
37
  }
6
38
  }
@@ -0,0 +1,38 @@
1
+ {
2
+ "dispatcher": {
3
+ "loading": "Chargement…",
4
+ "error": "Échec de l’authentification : {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Connexion en cours…",
9
+ "gesture": {
10
+ "title": "Continuez pour vous connecter.",
11
+ "action": "Se connecter"
12
+ },
13
+ "handing": "Terminé. Retour à l’application…",
14
+ "orphaned": "Vous êtes connecté. Vous pouvez fermer cette fenêtre et continuer dans l’application.",
15
+ "failed": "Cela n’a pas abouti. Vous pouvez fermer cette fenêtre et réessayer.",
16
+ "standalone": {
17
+ "title": "Cette page sert à vous connecter depuis une autre fenêtre.",
18
+ "action": "Ouvrir l’application"
19
+ },
20
+ "close": "Fermer"
21
+ },
22
+ "logout": {
23
+ "working": "Déconnexion en cours…",
24
+ "gesture": {
25
+ "title": "Continuez pour vous déconnecter.",
26
+ "action": "Se déconnecter"
27
+ },
28
+ "handing": "Déconnecté. Retour à l’application…",
29
+ "orphaned": "Vous êtes déconnecté. Vous pouvez fermer cette fenêtre.",
30
+ "failed": "La déconnexion n’a pas abouti ici. Vous pouvez fermer cette fenêtre.",
31
+ "standalone": {
32
+ "title": "Cette page sert à vous déconnecter depuis une autre fenêtre.",
33
+ "action": "Ouvrir l’application"
34
+ },
35
+ "close": "Fermer"
36
+ }
37
+ }
38
+ }
@@ -2,5 +2,37 @@
2
2
  "dispatcher": {
3
3
  "loading": "Ładowanie...",
4
4
  "error": "Uwierzytelnianie nie powiodło się: {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Trwa logowanie…",
9
+ "gesture": {
10
+ "title": "Kontynuuj, aby się zalogować.",
11
+ "action": "Zaloguj się"
12
+ },
13
+ "handing": "Gotowe. Wracamy do aplikacji…",
14
+ "orphaned": "Zalogowano. Możesz zamknąć to okno i kontynuować w aplikacji.",
15
+ "failed": "Nie udało się ukończyć. Zamknij to okno i spróbuj ponownie.",
16
+ "standalone": {
17
+ "title": "Ta strona służy do logowania z innego okna.",
18
+ "action": "Otwórz aplikację"
19
+ },
20
+ "close": "Zamknij"
21
+ },
22
+ "logout": {
23
+ "working": "Trwa wylogowywanie…",
24
+ "gesture": {
25
+ "title": "Kontynuuj, aby się wylogować.",
26
+ "action": "Wyloguj się"
27
+ },
28
+ "handing": "Wylogowano. Wracamy do aplikacji…",
29
+ "orphaned": "Wylogowano. Możesz zamknąć to okno.",
30
+ "failed": "Wylogowanie nie zostało tu ukończone. Możesz zamknąć to okno.",
31
+ "standalone": {
32
+ "title": "Ta strona służy do wylogowania z innego okna.",
33
+ "action": "Otwórz aplikację"
34
+ },
35
+ "close": "Zamknij"
36
+ }
5
37
  }
6
38
  }
@@ -2,5 +2,37 @@
2
2
  "dispatcher": {
3
3
  "loading": "Загрузка...",
4
4
  "error": "Не удалось выполнить аутентификацию: {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Выполняем вход…",
9
+ "gesture": {
10
+ "title": "Продолжите, чтобы войти.",
11
+ "action": "Войти"
12
+ },
13
+ "handing": "Готово. Возвращаемся в приложение…",
14
+ "orphaned": "Вход выполнен. Можете закрыть это окно и вернуться в приложение.",
15
+ "failed": "Не удалось завершить. Закройте это окно и попробуйте снова.",
16
+ "standalone": {
17
+ "title": "Эта страница используется для входа из другого окна.",
18
+ "action": "Открыть приложение"
19
+ },
20
+ "close": "Закрыть"
21
+ },
22
+ "logout": {
23
+ "working": "Выполняем выход…",
24
+ "gesture": {
25
+ "title": "Продолжите, чтобы выйти.",
26
+ "action": "Выйти"
27
+ },
28
+ "handing": "Выход выполнен. Возвращаемся в приложение…",
29
+ "orphaned": "Выход выполнен. Можете закрыть это окно.",
30
+ "failed": "Выход здесь не завершён. Можете закрыть это окно.",
31
+ "standalone": {
32
+ "title": "Эта страница используется для выхода из другого окна.",
33
+ "action": "Открыть приложение"
34
+ },
35
+ "close": "Закрыть"
36
+ }
5
37
  }
6
38
  }
@@ -2,5 +2,37 @@
2
2
  "dispatcher": {
3
3
  "loading": "Завантаження...",
4
4
  "error": "Не вдалося пройти автентифікацію: {{error}}"
5
+ },
6
+ "surrogate": {
7
+ "login": {
8
+ "working": "Виконуємо вхід…",
9
+ "gesture": {
10
+ "title": "Продовжте, щоб увійти.",
11
+ "action": "Увійти"
12
+ },
13
+ "handing": "Готово. Повертаємось до застосунку…",
14
+ "orphaned": "Вхід виконано. Можете закрити це вікно й повернутися до застосунку.",
15
+ "failed": "Не вдалося завершити. Закрийте це вікно та спробуйте ще раз.",
16
+ "standalone": {
17
+ "title": "Ця сторінка використовується для входу з іншого вікна.",
18
+ "action": "Відкрити застосунок"
19
+ },
20
+ "close": "Закрити"
21
+ },
22
+ "logout": {
23
+ "working": "Виконуємо вихід…",
24
+ "gesture": {
25
+ "title": "Продовжте, щоб вийти.",
26
+ "action": "Вийти"
27
+ },
28
+ "handing": "Вихід виконано. Повертаємось до застосунку…",
29
+ "orphaned": "Вихід виконано. Можете закрити це вікно.",
30
+ "failed": "Вихід тут не завершено. Можете закрити це вікно.",
31
+ "standalone": {
32
+ "title": "Ця сторінка використовується для виходу з іншого вікна.",
33
+ "action": "Відкрити застосунок"
34
+ },
35
+ "close": "Закрити"
36
+ }
5
37
  }
6
38
  }
package/src/i18n.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { addI18nLib } from '@owlmeans/i18n'
1
+ import { i18nHelper } from '@owlmeans/i18n'
2
2
 
3
3
  import authEn from './i18n/auth-en.json' with { type: 'json' }
4
4
  import authPl from './i18n/auth-pl.json' with { type: 'json' }
@@ -7,11 +7,13 @@ import authBe from './i18n/auth-be.json' with { type: 'json' }
7
7
  import authUk from './i18n/auth-uk.json' with { type: 'json' }
8
8
  import authEs from './i18n/auth-es.json' with { type: 'json' }
9
9
  import authDe from './i18n/auth-de.json' with { type: 'json' }
10
+ import authFr from './i18n/auth-fr.json' with { type: 'json' }
10
11
 
11
- addI18nLib('en', 'auth', authEn)
12
- addI18nLib('pl', 'auth', authPl)
13
- addI18nLib('ru', 'auth', authRu)
14
- addI18nLib('be', 'auth', authBe)
15
- addI18nLib('uk', 'auth', authUk)
16
- addI18nLib('es', 'auth', authEs)
17
- addI18nLib('de', 'auth', authDe)
12
+ i18nHelper.addI18nLib('en', 'auth', authEn)
13
+ i18nHelper.addI18nLib('pl', 'auth', authPl)
14
+ i18nHelper.addI18nLib('ru', 'auth', authRu)
15
+ i18nHelper.addI18nLib('be', 'auth', authBe)
16
+ i18nHelper.addI18nLib('uk', 'auth', authUk)
17
+ i18nHelper.addI18nLib('es', 'auth', authEs)
18
+ i18nHelper.addI18nLib('de', 'auth', authDe)
19
+ i18nHelper.addI18nLib('fr', 'auth', authFr)
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ export * from './types.js'
4
4
  export * from './main.js'
5
5
  export * from './router.js'
6
6
  export * from './components/index.js'
7
- export * from './modules.js'
7
+ export * from './entrypoints.js'
8
8
  export * from './exports.js'
9
9
  export * from './context.js'
10
10
  export * from './helper.js'
@@ -0,0 +1,52 @@
1
+ import type { CSSProperties } from 'react'
2
+ import { SurrogateStage } from './consts.js'
3
+
4
+ /**
5
+ * The whole of what a login window shows.
6
+ *
7
+ * Plain elements and inline styles on purpose. This renders in a popup opened by a `web-panel` app,
8
+ * a `mui-panel` app and a generated Tailwind app alike, and none of their stylesheets is loaded
9
+ * here — a class name would simply do nothing. It is also the reason this component carries no
10
+ * dependency on a UI family at all.
11
+ */
12
+ export const box: CSSProperties = {
13
+ maxWidth: '22rem', margin: '15vh auto', padding: '1.5rem', textAlign: 'center',
14
+ fontFamily: 'system-ui, sans-serif', lineHeight: 1.5,
15
+ }
16
+
17
+ export const action: CSSProperties = {
18
+ marginTop: '1rem', padding: '.625rem 1.25rem', fontSize: '1rem',
19
+ cursor: 'pointer', borderRadius: '.375rem', border: '1px solid currentColor',
20
+ }
21
+
22
+ export const COPY: Record<SurrogateStage, { key: string, en: string, action?: [string, string] }> = {
23
+ [SurrogateStage.Working]: { key: 'working', en: 'Signing you in…' },
24
+ [SurrogateStage.Gesture]: {
25
+ key: 'gesture.title', en: 'Continue to sign in.', action: ['gesture.action', 'Sign in'],
26
+ },
27
+ [SurrogateStage.Handing]: { key: 'handing', en: 'Done. Returning to the application…' },
28
+ [SurrogateStage.Orphaned]: {
29
+ key: 'orphaned', en: 'Signed in. You can close this window and continue in the application.',
30
+ action: ['close', 'Close'],
31
+ },
32
+ [SurrogateStage.Failed]: {
33
+ key: 'failed', en: 'That did not complete. You can close this window and try again.',
34
+ action: ['close', 'Close'],
35
+ },
36
+ [SurrogateStage.Standalone]: {
37
+ key: 'standalone.title', en: 'This page is used to sign in from another window.',
38
+ action: ['standalone.action', 'Open the application'],
39
+ },
40
+ }
41
+
42
+ export const LOGOUT_COPY: Partial<Record<SurrogateStage, { key: string, en: string }>> = {
43
+ [SurrogateStage.Working]: { key: 'working', en: 'Signing you out…' },
44
+ [SurrogateStage.Gesture]: { key: 'gesture.title', en: 'Continue to sign out.' },
45
+ [SurrogateStage.Handing]: { key: 'handing', en: 'Signed out. Returning to the application…' },
46
+ [SurrogateStage.Orphaned]: {
47
+ key: 'orphaned', en: 'Signed out. You can close this window.',
48
+ },
49
+ [SurrogateStage.Failed]: {
50
+ key: 'failed', en: 'Sign-out did not complete here. You can close this window.',
51
+ },
52
+ }
@@ -10,3 +10,41 @@ export const SURROGATE_LOGIN = 'owlmeans-surrogate-login'
10
10
  * ordinary tab.
11
11
  */
12
12
  export const SURROGATE_LOGIN_PRIORITY = 100
13
+
14
+ /** What the surrogate window is doing, from the point of view of the person watching it. */
15
+ export enum SurrogateStage {
16
+ /** Working. No control — there is nothing for the user to do but wait. */
17
+ Working = 'working',
18
+ /** Needs a click: the flow cannot continue without a fresh gesture. */
19
+ Gesture = 'gesture',
20
+ /** Done here; handing the result back and closing. */
21
+ Handing = 'handing',
22
+ /** Acted, but with no channel back to the window that asked. */
23
+ Orphaned = 'orphaned',
24
+ /** Ended with nothing. */
25
+ Failed = 'failed',
26
+ /** Not a surrogate at all — someone opened this address directly. */
27
+ Standalone = 'standalone',
28
+ }
29
+
30
+ /**
31
+ * The login window an embedded application opens one level up.
32
+ *
33
+ * It is NOT wrapped in `DispatcherHOC`, and that is the point: the HOC's continuation navigates to
34
+ * `HOME` when it has nothing else to do, which is how a popup ended up rendering the whole
35
+ * application, with its navigation, inside itself. This screen has no continuation at all — it
36
+ * either hands something back and closes, or it says what it is waiting for.
37
+ *
38
+ * It also never runs the authorization machine itself: it forwards to the dispatcher (`next`),
39
+ * which owns that flow, and hands back what the dispatcher issued — see {@link surrogateLoginStep}
40
+ * for why a session already stored in this window is not simply handed back.
41
+ */
42
+ /** What a surrogate window opened to SIGN IN does with the session it may already hold. */
43
+ export enum SurrogateLoginStep {
44
+ /** Drop the stored session and authenticate afresh through the dispatcher. */
45
+ Forget = 'forget',
46
+ /** Hand the stored session to the opener — there is no dispatcher to authenticate through. */
47
+ Resume = 'resume',
48
+ /** Nothing stored: authenticate through the dispatcher. */
49
+ Authenticate = 'authenticate',
50
+ }
@@ -1,4 +1,8 @@
1
1
  export * from './consts.js'
2
+ export * from './pump.js'
2
3
  export * from './redirect.js'
3
4
  export * from './surrogate.js'
5
+ export * from './view.js'
6
+ export type * from './types.js'
7
+ export * from './screen.js'
4
8
  export * from './service.js'