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/LICENSE +121 -0
- package/dist/components.css +2 -0
- package/dist/components.d.ts +17 -0
- package/dist/components.js +167 -0
- package/dist/context.d.ts +3 -0
- package/dist/context.js +115 -0
- package/dist/harness.d.ts +40 -0
- package/dist/harness.js +28 -0
- package/dist/index.css +2 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +340 -0
- package/dist/redux.d.ts +11 -0
- package/dist/redux.js +179 -0
- package/dist/test/components.d.ts +1 -0
- package/dist/test/context.d.ts +1 -0
- package/dist/test/helper.d.ts +11 -0
- package/dist/test/redux.d.ts +1 -0
- package/dist/type.d.ts +152 -0
- package/dist/type.js +41 -0
- package/package.json +306 -4
- package/readme.md +136 -0
- package/README.md +0 -3
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.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
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
|
+
[](https://www.npmjs.com/package/react-generic-user)
|
|
18
|
+
[](https://www.npmjs.com/package/react-generic-user)
|
|
19
|
+
|
|
20
|
+
[](https://github.com/thaibault/react-generic-user/actions/workflows/build.yaml)
|
|
21
|
+
[](https://github.com/thaibault/react-generic-user/actions/workflows/build-package-and-push.yaml)
|
|
22
|
+
|
|
23
|
+
[](https://github.com/thaibault/react-generic-user/actions/workflows/check-types.yaml)
|
|
24
|
+
[](https://github.com/thaibault/react-generic-user/actions/workflows/lint.yaml)
|
|
25
|
+
|
|
26
|
+
[](https://github.com/thaibault/react-generic-user/actions/workflows/deploy-web-documentation.yaml)
|
|
27
|
+
[](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