react-generic-user 0.0.0-stage → 0.0.1-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/dist/type.d.ts ADDED
@@ -0,0 +1,152 @@
1
+ import type { ComponentType, Context, Provider, ReactNode } from 'react';
2
+ import type { TextInputTypes } from 'react-input-material';
3
+ import type { UnknownAction } from 'redux';
4
+ import type { Action, AsyncThunk, AsyncThunkPayloadCreator, Dispatch as BaseDispatch, Slice } from '@reduxjs/toolkit';
5
+ import type { ButtonProps } from '@rmwc/button';
6
+ import type { SliceCaseReducers } from '@reduxjs/toolkit';
7
+ export type Dispatch<A extends Action = UnknownAction> = BaseDispatch<A>;
8
+ export interface AsyncThunkConfig {
9
+ state?: unknown;
10
+ dispatch?: Dispatch;
11
+ extra?: unknown;
12
+ rejectValue?: unknown;
13
+ serializedErrorType?: unknown;
14
+ pendingMeta?: unknown;
15
+ fulfilledMeta?: unknown;
16
+ rejectedMeta?: unknown;
17
+ }
18
+ /**
19
+ * Minimal location representation to stay independent of a concrete routing
20
+ * library (e.g. "react-router" locations are compatible).
21
+ */
22
+ export interface Location {
23
+ hash?: string;
24
+ pathname: string;
25
+ search?: string;
26
+ state?: unknown;
27
+ }
28
+ export type To = Partial<Location> | string;
29
+ export interface RedirectProperties {
30
+ replace?: boolean;
31
+ state?: {
32
+ from: Location;
33
+ };
34
+ to: To;
35
+ }
36
+ /**
37
+ * Integration of the used routing library.
38
+ * Using "react-router" for example: "{Redirect: Navigate, useLocation}".
39
+ */
40
+ export interface Routing {
41
+ Redirect: ComponentType<RedirectProperties>;
42
+ useLocation: () => Location;
43
+ }
44
+ export interface BaseLoginData {
45
+ login: null | string;
46
+ password: null | string;
47
+ }
48
+ export interface BaseUserContext {
49
+ name: string;
50
+ roles?: Array<string>;
51
+ }
52
+ export interface BaseUserSession<UserContext extends BaseUserContext> {
53
+ authenticated: boolean | null;
54
+ authenticating: unknown;
55
+ deauthenticating: unknown;
56
+ initialRequestedLocation?: null | Location;
57
+ userContext?: UserContext;
58
+ }
59
+ export interface User<LoginData extends BaseLoginData = BaseLoginData, UserContext extends BaseUserContext = BaseUserContext, SessionType extends BaseUserSession<UserContext> = BaseUserSession<UserContext>> {
60
+ authenticate: () => void;
61
+ login: (data: LoginData) => Promise<boolean> | undefined;
62
+ logout: () => void;
63
+ session: SessionType;
64
+ }
65
+ export type RenderAuthenticated = <LoginData extends BaseLoginData, UserContext extends BaseUserContext, SessionType extends BaseUserSession<UserContext>>(context: {
66
+ fallbackLocation?: To;
67
+ location: Location;
68
+ user: User<LoginData, UserContext, SessionType>;
69
+ }) => ReactNode;
70
+ export interface AuthenticatedProperties {
71
+ fallbackLocation?: To;
72
+ children: ReactNode | RenderAuthenticated;
73
+ loadingFallback: ReactNode;
74
+ }
75
+ export interface AuthenticatedProps {
76
+ fallbackLocation?: AuthenticatedProperties['fallbackLocation'];
77
+ children: AuthenticatedProperties['children'];
78
+ loadingFallback?: AuthenticatedProperties['loadingFallback'];
79
+ }
80
+ export interface LoginFormState {
81
+ sent: boolean;
82
+ submitted: boolean;
83
+ pending: boolean;
84
+ authenticated: boolean;
85
+ loginInput: TextInputTypes.Props<string>;
86
+ passwordInput: TextInputTypes.Props<string>;
87
+ }
88
+ export type RenderStatus = (state: LoginFormState) => ReactNode;
89
+ export interface LoginProperties<LoginData extends BaseLoginData, UserContext extends BaseUserContext, SessionType extends BaseUserSession<UserContext>> {
90
+ buttonProperties?: ButtonProps;
91
+ inputProperties?: TextInputTypes.Props<string>;
92
+ loginProperties?: TextInputTypes.Props<string>;
93
+ passwordProperties?: TextInputTypes.Props<string>;
94
+ children?: ReactNode | RenderStatus;
95
+ onSubmitted?: (login: null | string, password: null | string) => boolean | undefined;
96
+ onSuccess?: (user: User<LoginData, UserContext, SessionType>) => void;
97
+ }
98
+ export type LoginProps<LoginData extends BaseLoginData, UserContext extends BaseUserContext, SessionType extends BaseUserSession<UserContext>> = Partial<LoginProperties<LoginData, UserContext, SessionType>>;
99
+ export type HasRoleHook = (role: Array<string> | string) => boolean;
100
+ export type IsAdminHook = () => boolean;
101
+ export interface ContextUserSession<UserContext extends BaseUserContext> extends BaseUserSession<UserContext> {
102
+ authenticating: Promise<UserContext> | null;
103
+ deauthenticating: Promise<boolean> | null;
104
+ }
105
+ export interface SessionCallbacks<UserContext extends BaseUserContext> {
106
+ onAuthenticate: (context: UserContext) => void;
107
+ onDeauthenticate: (context?: UserContext) => void;
108
+ }
109
+ export interface ProviderProps<UserContext extends BaseUserContext> {
110
+ children: ReactNode;
111
+ options?: Partial<SessionCallbacks<UserContext>>;
112
+ }
113
+ export type ContextUserHook<LoginData extends BaseLoginData, UserContext extends BaseUserContext, SessionType extends BaseUserSession<UserContext>> = () => User<LoginData, UserContext, SessionType>;
114
+ export interface SessionTools<LoginData extends BaseLoginData, UserContext extends BaseUserContext, SessionType extends BaseUserSession<UserContext>> {
115
+ UserProvider: (props: ProviderProps<UserContext>) => ReturnType<Provider<User<LoginData, UserContext, SessionType>>>;
116
+ userContext: Context<User<LoginData, UserContext, SessionType> | undefined>;
117
+ useHasRole: HasRoleHook;
118
+ useIsAdmin: IsAdminHook;
119
+ useUser: ContextUserHook<LoginData, UserContext, SessionType>;
120
+ useUserState: (options?: Partial<SessionCallbacks<UserContext>>) => User<LoginData, UserContext, SessionType>;
121
+ }
122
+ export interface ContextSessionHandler<LoginData extends BaseLoginData, UserContext extends BaseUserContext> {
123
+ authenticate: (session: ContextUserSession<UserContext>) => Promise<UserContext>;
124
+ login: (data: LoginData) => Promise<UserContext>;
125
+ logout: (session: ContextUserSession<UserContext>) => Promise<boolean>;
126
+ }
127
+ export interface ReduxUserSession<UserContext extends BaseUserContext = BaseUserContext> extends BaseUserSession<UserContext> {
128
+ authenticating: boolean;
129
+ deauthenticating: boolean;
130
+ }
131
+ export type Selectors<UserContext extends BaseUserContext> = {
132
+ selectUser: (user: ReduxUserSession<UserContext>) => ReduxUserSession<UserContext>;
133
+ };
134
+ export declare const ACTION_NAME_PREFIX = "user";
135
+ export type ReduxUserHook<LoginData extends BaseLoginData = BaseLoginData, UserContext extends BaseUserContext = BaseUserContext, SessionType extends BaseUserSession<UserContext> = BaseUserSession<UserContext>> = (data?: Partial<LoginData>, isLoginLocation?: (location: Location) => boolean) => User<LoginData, UserContext, SessionType>;
136
+ export interface ReduxSessionService<LoginData extends BaseLoginData, UserContext extends BaseUserContext, SessionType extends BaseUserSession<UserContext>, AsyncThunkOptions extends AsyncThunkConfig> {
137
+ authenticateThunk: AsyncThunk<null | UserContext, Partial<LoginData>, AsyncThunkOptions>;
138
+ loginThunk: AsyncThunk<null | UserContext, LoginData, AsyncThunkOptions>;
139
+ logoutThunk: AsyncThunk<boolean, Partial<LoginData>, AsyncThunkOptions>;
140
+ slice: Slice<ReduxUserSession<UserContext>, SliceCaseReducers<ReduxUserSession<UserContext>>, typeof ACTION_NAME_PREFIX, typeof ACTION_NAME_PREFIX, Selectors<UserContext>>;
141
+ useHasRole: HasRoleHook;
142
+ useIsAdmin: IsAdminHook;
143
+ useUser: ReduxUserHook<LoginData, UserContext, SessionType>;
144
+ }
145
+ export interface ReduxSessionOptions {
146
+ useLocation?: () => Location | null;
147
+ }
148
+ export interface ReduxSessionHandler<LoginData extends BaseLoginData, UserContext extends BaseUserContext, AsyncThunkOptions extends AsyncThunkConfig> {
149
+ authenticate: AsyncThunkPayloadCreator<null | UserContext, Partial<LoginData>, AsyncThunkOptions>;
150
+ login: AsyncThunkPayloadCreator<null | UserContext, Partial<LoginData>, AsyncThunkOptions>;
151
+ logout: AsyncThunkPayloadCreator<boolean, Partial<LoginData>, AsyncThunkOptions>;
152
+ }
package/dist/type.js ADDED
@@ -0,0 +1,41 @@
1
+ if(typeof window==='undefined'||window===null)var window=(typeof globalThis==='undefined'||globalThis===null)?{}:globalThis;// -*- coding: utf-8 -*-
2
+ /** @module type *//* !
3
+ region header
4
+ [Project page](https://tsickert.com/react-generic-user)
5
+
6
+ Copyright Torben Sickert (info["~at~"]tsickert.com) 16.12.2012
7
+
8
+ License
9
+ -------
10
+
11
+ This library written by Torben Sickert stands under a creative commons
12
+ naming 3.0 unported license.
13
+ See https://creativecommons.org/licenses/by/3.0/deed.de
14
+ endregion
15
+ */// region imports
16
+ // endregion
17
+ // NOTE: Has to be redeclared since it is not exported by "@reduxjs/toolkit".
18
+ // region exports
19
+ /// region routing
20
+ /**
21
+ * Minimal location representation to stay independent of a concrete routing
22
+ * library (e.g. "react-router" locations are compatible).
23
+ *//**
24
+ * Integration of the used routing library.
25
+ * Using "react-router" for example: "{Redirect: Navigate, useLocation}".
26
+ *//// endregion
27
+ /// region universal
28
+ //// region hooks
29
+ //// endregion
30
+ /// endregion
31
+ /// region context
32
+ //// region expected given integration by library's usage
33
+ //// endregion
34
+ /// endregion
35
+ /// region redux
36
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
37
+ var ACTION_NAME_PREFIX="user";//// region expected given integration by library's usage
38
+ //// endregion
39
+ /// endregion
40
+ // endregion
41
+ export { ACTION_NAME_PREFIX };
package/package.json CHANGED
@@ -1,6 +1,308 @@
1
1
  {
2
2
  "name": "react-generic-user",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.0.1-1",
4
+ "description": "Generic user session handling (redux or react context based) and login components.",
5
+ "keywords": [
6
+ "authentication",
7
+ "login",
8
+ "react",
9
+ "redux",
10
+ "session",
11
+ "user"
12
+ ],
13
+ "homepage": "https://tsickert.com/react-generic-user",
14
+ "bugs": {
15
+ "email": "info@tsickert.com",
16
+ "url": "https://github.com/thaibault/react-generic-user/issues"
17
+ },
18
+ "license": "CC-BY-3.0",
19
+ "author": {
20
+ "email": "info@tsickert.com",
21
+ "name": "Torben Sickert",
22
+ "url": "https://tsickert.com"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/thaibault/react-generic-user.git"
27
+ },
28
+ "type": "module",
29
+ "exports": {
30
+ ".": "./dist/index.js",
31
+ "./components": "./dist/components.js",
32
+ "./components.css": {
33
+ "style": "./dist/components.css"
34
+ },
35
+ "./components.js": "./dist/components.js",
36
+ "./context": "./dist/context.js",
37
+ "./context.js": "./dist/context.js",
38
+ "./harness": "./dist/harness.js",
39
+ "./harness.js": "./dist/harness.js",
40
+ "./index.css": {
41
+ "style": "./dist/index.css"
42
+ },
43
+ "./redux": "./dist/redux.js",
44
+ "./redux.js": "./dist/redux.js",
45
+ "./type": "./dist/type.js",
46
+ "./type.js": "./dist/type.js"
47
+ },
48
+ "main": "dist/index.js",
49
+ "typesVersions": {
50
+ "*": {
51
+ "*": [
52
+ "./dist/*"
53
+ ]
54
+ }
55
+ },
56
+ "files": [
57
+ "dist"
58
+ ],
59
+ "sideEffects": [
60
+ "*.css"
61
+ ],
62
+ "scripts": {
63
+ "build": "yarn build:types && yarn build:plain",
64
+ "build:plain": "weboptimizer build",
65
+ "build:types": "weboptimizer build:types",
66
+ "check": "yarn check:types && yarn lint",
67
+ "check:types": "weboptimizer check:types",
68
+ "clear": "weboptimizer clear",
69
+ "document": "weboptimizer document",
70
+ "lint": "weboptimizer lint",
71
+ "prepare": "yarn build",
72
+ "serve": "weboptimizer serve",
73
+ "start": "yarn serve",
74
+ "test": "weboptimizer test",
75
+ "test:browser": "weboptimizer test:browser",
76
+ "test:coverage": "weboptimizer test:coverage",
77
+ "test:coverage:report": "weboptimizer test:coverage:report",
78
+ "update:documentation": "web-documentation",
79
+ "watch": "weboptimizer build --watch"
80
+ },
81
+ "devDependencies": {
82
+ "@babel/eslint-parser": "^8.0.7",
83
+ "@babel/preset-react": "^8.0.1",
84
+ "@eslint/js": "^10.0.1",
85
+ "@playwright/test": "^1.65.0",
86
+ "@reduxjs/toolkit": "^2.14.0",
87
+ "@rmwc/button": "^14.3.5",
88
+ "@rmwc/circular-progress": "^14.3.5",
89
+ "@rmwc/icon": "^14.3.5",
90
+ "@rmwc/icon-button": "^14.3.5",
91
+ "@rmwc/menu": "^14.3.5",
92
+ "@rmwc/select": "^14.3.5",
93
+ "@rmwc/textfield": "^14.3.5",
94
+ "@rmwc/theme": "^14.3.5",
95
+ "@rmwc/touch-target": "^14.3.5",
96
+ "@rmwc/typography": "^14.3.5",
97
+ "@stylistic/eslint-plugin": "^5.10.0",
98
+ "@teamsupercell/typings-for-css-modules-loader": "^2.5.2",
99
+ "@types/jsdom": "^30.0.0",
100
+ "@types/node": "^26.6.6",
101
+ "@types/prop-types": "^15.7.15",
102
+ "@types/react": "^18.3.31",
103
+ "@types/react-dom": "^18.3.7",
104
+ "@types/webpack-env": "^1.18.8",
105
+ "@typescript-eslint/eslint-plugin": "^8.72.1",
106
+ "@typescript-eslint/parser": "^8.72.1",
107
+ "clientnode": "^4.0.1531",
108
+ "css-loader": "^7.1.5",
109
+ "cssnano": "^9.9.0",
110
+ "eslint": "^10.14.0",
111
+ "eslint-config-google": "^0.14.0",
112
+ "eslint-plugin-jsdoc": "^65.4.5",
113
+ "identity-obj-proxy": "^3.0.0",
114
+ "jest": "^30.5.2",
115
+ "jsdoc": "^4.0.5",
116
+ "material-components-web": "^14.0.0",
117
+ "mini-css-extract-plugin": "^2.10.2",
118
+ "playwright-core": "^1.65.0",
119
+ "postcss": "8.5.32",
120
+ "postcss-import": "^17.0.1",
121
+ "postcss-loader": "^8.2.1",
122
+ "postcss-nested": "^9.0.1",
123
+ "postcss-preset-env": "^11.6.2",
124
+ "postcss-scss": "^4.0.9",
125
+ "prop-types": "^15.8.1",
126
+ "react": "^18.3.1",
127
+ "react-dom": "^18.3.1",
128
+ "react-generic-animate": "^0.0.141",
129
+ "react-generic-dummy": "^0.0.141",
130
+ "react-generic-tools": "^0.0.138",
131
+ "react-input-material": "^0.0.855",
132
+ "react-redux": "^9.3.1",
133
+ "react-transition-group": "^4.4.5",
134
+ "react-useanimations": "^3.1.1",
135
+ "redux": "^5.0.1",
136
+ "style-loader": "^4.0.0",
137
+ "stylelint": "^18.0.0",
138
+ "stylelint-config-standard": "^41.0.0",
139
+ "tslib": "^2.9.1",
140
+ "typescript-eslint": "^8.72.1",
141
+ "typescript-plugin-css-modules": "^5.3.0",
142
+ "web-documentation": "^1.0.74",
143
+ "weboptimizer": "^4.0.109",
144
+ "webpack-dev-server": "^6.1.0"
145
+ },
146
+ "peerDependencies": {
147
+ "@babel/preset-react": "*",
148
+ "@reduxjs/toolkit": "*",
149
+ "@rmwc/button": "*",
150
+ "@types/react": "*",
151
+ "@types/react-dom": "*",
152
+ "clientnode": "*",
153
+ "playwright-core": "*",
154
+ "react": "*",
155
+ "react-dom": "*",
156
+ "react-generic-tools": "*",
157
+ "react-input-material": "*",
158
+ "react-redux": "*",
159
+ "tslib": "*"
160
+ },
161
+ "peerDependenciesMeta": {
162
+ "@babel/preset-react": {
163
+ "optional": true
164
+ },
165
+ "@reduxjs/toolkit": {
166
+ "optional": true
167
+ },
168
+ "@rmwc/button": {
169
+ "optional": true
170
+ },
171
+ "@types/react": {
172
+ "optional": true
173
+ },
174
+ "@types/react-dom": {
175
+ "optional": true
176
+ },
177
+ "playwright-core": {
178
+ "optional": true
179
+ },
180
+ "react-dom": {
181
+ "optional": true
182
+ },
183
+ "react-input-material": {
184
+ "optional": true
185
+ },
186
+ "react-redux": {
187
+ "optional": true
188
+ }
189
+ },
190
+ "resolutions": {
191
+ "globals@npm:^11.1.0": "patch:globals@npm%3A11.12.0#~/.yarn/patches/globals-npm-11.12.0-1fa7f41a6c.patch",
192
+ "globals@npm:^14.0.0": "patch:globals@npm%3A11.12.0#~/.yarn/patches/globals-npm-11.12.0-1fa7f41a6c.patch",
193
+ "globals@npm:^9.18.0": "patch:globals@npm%3A11.12.0#~/.yarn/patches/globals-npm-11.12.0-1fa7f41a6c.patch"
194
+ },
195
+ "engines": {
196
+ "node": ">=26",
197
+ "npm": ">=12",
198
+ "yarn": ">=4"
199
+ },
200
+ "webDocumentation": {
201
+ "languages": [
202
+ "deDE",
203
+ "enUS"
204
+ ],
205
+ "tagline": "Generic user sessions and login components.<!--deDE:Generische Benutzersitzungen und Login-Komponenten.-->"
206
+ },
207
+ "webOptimizer": {
208
+ "commandLine": {
209
+ "test": {
210
+ "environments": [
211
+ "jsdom"
212
+ ]
213
+ }
214
+ },
215
+ "generic": {
216
+ "entry": {
217
+ "components": [
218
+ "./style.module.css",
219
+ "./components"
220
+ ],
221
+ "context": "./context",
222
+ "harness": "./harness",
223
+ "index": "./index.ts",
224
+ "redux": "./redux",
225
+ "type": "./type"
226
+ },
227
+ "supportedBrowsers": [
228
+ "IE >= 11",
229
+ "last 2 versions",
230
+ "> 5%"
231
+ ]
232
+ },
233
+ "module": {
234
+ "optimizer": {
235
+ "terser": {
236
+ "terserOptions": {
237
+ "compress": {
238
+ "#": "To provide a logging output we need to exclude this feature.",
239
+ "drop_console": {
240
+ "__evaluate__": "false"
241
+ },
242
+ "drop_debugger": {
243
+ "__evaluate__": "false"
244
+ }
245
+ }
246
+ }
247
+ }
248
+ },
249
+ "preprocessor": {
250
+ "javaScript": {
251
+ "options": {
252
+ "overrides": {
253
+ "__evaluate__": "[{test: /\\.(jsx|tsx)$/u, presets: [['@babel/preset-react', {development: self.debug}]]}]"
254
+ },
255
+ "presets": {
256
+ "#": "NOTE: We disable module export/import transformation to allow tree shaking by the final (minimizer).",
257
+ "__evaluate__": "[['@babel/preset-env', {targets: self.generic.isWeb ? {browsers: self.generic.supportedBrowsers, node: packageConfiguration.engines.node.replace(/>?=?([0-9]+)/, '$1')} : {node: packageConfiguration.engines.node.replace(/>?=?([0-9]+)/, '$1')}}], '@babel/preset-typescript']"
258
+ }
259
+ }
260
+ },
261
+ "cascadingStyleSheet": {
262
+ "additional": {
263
+ "plugins": {
264
+ "pre": {
265
+ "__append__": "module.optionalImport('postcss-nested').then((module) => module?.default)"
266
+ }
267
+ }
268
+ }
269
+ }
270
+ },
271
+ "cascadingStyleSheet": {
272
+ "exclude": false,
273
+ "options": {
274
+ "import": {
275
+ "filter": {
276
+ "__evaluate__": "(url) => !url.includes('.css')"
277
+ }
278
+ }
279
+ }
280
+ }
281
+ },
282
+ "path": {
283
+ "source": {
284
+ "base": "src/"
285
+ },
286
+ "target": {
287
+ "base": "dist/"
288
+ }
289
+ },
290
+ "injection": {
291
+ "entry": {
292
+ "__evaluate__": "2 < self.givenCommandLineArguments.length && self.givenCommandLineArguments[2].startsWith('test') ? {testBundle: './test'} : self.generic.entry"
293
+ },
294
+ "external": {
295
+ "implicit": {
296
+ "pattern": {
297
+ "include": {
298
+ "__append__": {
299
+ "__evaluate__": "/(?:^|\\/)playwright(?:-core)?(?:$|\\/)/"
300
+ }
301
+ }
302
+ }
303
+ }
304
+ }
305
+ }
306
+ },
307
+ "packageManager": "yarn@4.18.1+sha512.b2e1e7524f654f2749d32b4ebcb4622473cb5bcbc485df2007e12a154e50162a4d795526768bc5f5b8f81717bfd79deb2472813d86fb5ae2eb551fa9c872b08f"
308
+ }
package/readme.md ADDED
@@ -0,0 +1,136 @@
1
+ <!-- !/usr/bin/env markdown
2
+ -*- coding: utf-8 -*-
3
+ region header
4
+ Copyright Torben Sickert (info["~at~"]tsickert.com) 16.12.2012
5
+
6
+ License
7
+ -------
8
+
9
+ This library written by Torben Sickert stands under a creative commons naming
10
+ 3.0 unported license. See https://creativecommons.org/licenses/by/3.0/deed.de
11
+ endregion -->
12
+
13
+ <!--|deDE:Projektstatus-->
14
+ Project status
15
+ --------------
16
+
17
+ [![npm](https://img.shields.io/npm/v/react-generic-user?color=%23d55e5d&label=npm%20package%20version&logoColor=%23d55e5d&style=for-the-badge)](https://www.npmjs.com/package/react-generic-user)
18
+ [![npm downloads](https://img.shields.io/npm/dy/react-generic-user.svg?style=for-the-badge)](https://www.npmjs.com/package/react-generic-user)
19
+
20
+ [![build](https://img.shields.io/github/actions/workflow/status/thaibault/react-generic-user/build.yaml?style=for-the-badge)](https://github.com/thaibault/react-generic-user/actions/workflows/build.yaml)
21
+ [![build push package](https://img.shields.io/github/actions/workflow/status/thaibault/react-generic-user/build-package-and-push.yaml?label=build%20push%20package&style=for-the-badge)](https://github.com/thaibault/react-generic-user/actions/workflows/build-package-and-push.yaml)
22
+
23
+ [![check types](https://img.shields.io/github/actions/workflow/status/thaibault/react-generic-user/check-types.yaml?label=check%20types&style=for-the-badge)](https://github.com/thaibault/react-generic-user/actions/workflows/check-types.yaml)
24
+ [![lint](https://img.shields.io/github/actions/workflow/status/thaibault/react-generic-user/lint.yaml?label=lint&style=for-the-badge)](https://github.com/thaibault/react-generic-user/actions/workflows/lint.yaml)
25
+
26
+ [![deploy web documentation](https://img.shields.io/github/actions/workflow/status/thaibault/react-generic-user/deploy-web-documentation.yaml?label=deploy%20web%20documentation&style=for-the-badge)](https://github.com/thaibault/react-generic-user/actions/workflows/deploy-web-documentation.yaml)
27
+ [![web documentation](https://img.shields.io/website-up-down-green-red/https/tsickert.com/react-generic-user.svg?label=web-documentation&style=for-the-badge)](https://tsickert.com/react-generic-user)
28
+
29
+ <!--|deDE:Verwendung-->
30
+ Use case
31
+ --------
32
+
33
+ Generic user session handling based on redux or a react context together with
34
+ components to protect content and to log in. The library is independent of a
35
+ concrete routing library.
36
+ <!--deDE:
37
+ Generische Verwaltung von Benutzersitzungen auf Basis von Redux oder eines
38
+ React-Kontexts sowie Komponenten zum Schutz von Inhalten und zur Anmeldung.
39
+ Die Bibliothek ist unabhängig von einer konkreten Routing-Bibliothek.
40
+ -->
41
+
42
+ Installation
43
+ ------------
44
+
45
+ You can install via package manager or simply download the compiled version as
46
+ zip file here and inject:
47
+ <!--deDE:
48
+ Sie können das Paket über den Paketmanager installieren oder einfach die
49
+ kompilierte Version als ZIP-Datei hier herunterladen und einbinden:
50
+ -->
51
+
52
+ ```bash
53
+ npm install react-generic-user
54
+ ```
55
+
56
+ <!--|deDE:Beispiel-->
57
+ Example
58
+ -------
59
+
60
+ Create a redux based session by providing how to authenticate, log in and log
61
+ out:
62
+ <!--deDE:
63
+ Erstellen Sie eine Redux-basierte Sitzung, indem Sie angeben, wie
64
+ authentifiziert, an- und abgemeldet wird:
65
+ -->
66
+
67
+ ```TypeScript
68
+ import {useLocation} from 'react-router'
69
+ import sessionFactory from 'react-generic-user/redux'
70
+
71
+ export const {slice, useIsAdmin, useUser} = sessionFactory(
72
+ {
73
+ authenticate: async () => (await api.getSession()).user,
74
+ login: async ({login, password}) => await api.login(login, password),
75
+ logout: async () => (await api.logout()).ok
76
+ },
77
+ // Optional: Remembers initially requested locations.
78
+ {useLocation}
79
+ )
80
+
81
+ const store = configureStore({reducer: {user: slice.reducer}})
82
+ ```
83
+
84
+ Alternatively a react context based session can be used:
85
+ <!--deDE:Alternativ kann eine Sitzung auf Basis eines React-Kontexts genutzt
86
+ werden:-->
87
+
88
+ ```TypeScript
89
+ import sessionFactory from 'react-generic-user/context'
90
+
91
+ const {UserProvider, useUser} = sessionFactory({authenticate, login, logout})
92
+ ```
93
+
94
+ Create components to protect content and to log in by integrating your routing
95
+ library:
96
+ <!--deDE:
97
+ Erstellen Sie Komponenten zum Schutz von Inhalten und zur Anmeldung, indem
98
+ Sie Ihre Routing-Bibliothek integrieren:
99
+ -->
100
+
101
+ ```TypeScript
102
+ import {Navigate, useLocation} from 'react-router'
103
+ import componentFactory from 'react-generic-user/components'
104
+ import 'react-generic-user/components.css'
105
+
106
+ const {Authenticated, Login} =
107
+ componentFactory(useUser, {Redirect: Navigate, useLocation})
108
+
109
+ const Application = () => <Routes>
110
+ <Route path="/login" element={<Login onSuccess={redirectBack} />} />
111
+ <Route
112
+ path="*"
113
+ element={
114
+ <Authenticated fallbackLocation="/login">
115
+ <Protected />
116
+ </Authenticated>
117
+ }
118
+ />
119
+ </Routes>
120
+ ```
121
+
122
+ End-to-end tests can interact with the login form via its harness:
123
+ <!--deDE:
124
+ End-to-End-Tests können über das Harness mit dem Anmeldeformular
125
+ interagieren:
126
+ -->
127
+
128
+ ```TypeScript
129
+ import loginHarness from 'react-generic-user/harness'
130
+
131
+ const {stable: {loginButton, nameInput, passwordInput}} = loginHarness(page)
132
+
133
+ await nameInput.fill('name')
134
+ await passwordInput.fill('password')
135
+ await loginButton.main.click()
136
+ ```
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.