@clicktap/state 0.1.1 → 0.1.3
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/index.js +729 -0
- package/package.json +6 -3
- package/src/auth/AuthProvider.d.ts +49 -0
- package/src/auth/auth.d.ts +52 -0
- package/src/toast/ToastProvider.d.ts +17 -0
- package/src/toast/timer.d.ts +26 -0
- package/src/toast/toast.d.ts +46 -0
- package/.eslintrc.json +0 -40
- package/jest.config.ts +0 -10
- package/project.json +0 -40
- package/src/auth/AuthProvider.tsx +0 -97
- package/src/auth/auth.spec.ts +0 -7
- package/src/auth/auth.ts +0 -408
- package/src/toast/ToastProvider.tsx +0 -44
- package/src/toast/timer.ts +0 -109
- package/src/toast/toast.spec.ts +0 -7
- package/src/toast/toast.ts +0 -222
- package/tsconfig.json +0 -24
- package/tsconfig.lib.json +0 -10
- package/tsconfig.spec.json +0 -14
- /package/src/{index.ts → index.d.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clicktap/state",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Clicktap",
|
|
6
6
|
"description": "A state management library for Clicktap reference frontend.",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
14
|
-
"type": "
|
|
14
|
+
"type": "module",
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"cookie": "^0.5.0"
|
|
17
17
|
},
|
|
@@ -26,5 +26,8 @@
|
|
|
26
26
|
"@xstate/immer": "^0.3.3",
|
|
27
27
|
"@xstate/inspect": "^0.8.0",
|
|
28
28
|
"@xstate/react": "^3.2.2"
|
|
29
|
-
}
|
|
29
|
+
},
|
|
30
|
+
"module": "./index.js",
|
|
31
|
+
"main": "./index.js",
|
|
32
|
+
"types": "./src/index.d.ts"
|
|
30
33
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { InterpreterFrom } from 'xstate';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { NextPageContext } from 'next';
|
|
4
|
+
import { authMachine } from './auth';
|
|
5
|
+
export declare const AuthContext: import("react").Context<import("xstate").Interpreter<import("./auth").AuthMachineContext, any, import("./auth").AuthMachineEvents, {
|
|
6
|
+
value: any;
|
|
7
|
+
context: import("./auth").AuthMachineContext;
|
|
8
|
+
}, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, import("./auth").AuthMachineEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>>;
|
|
9
|
+
export declare const useAuth: () => import("xstate").Interpreter<import("./auth").AuthMachineContext, any, import("./auth").AuthMachineEvents, {
|
|
10
|
+
value: any;
|
|
11
|
+
context: import("./auth").AuthMachineContext;
|
|
12
|
+
}, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, import("./auth").AuthMachineEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>;
|
|
13
|
+
export declare const useUser: () => {
|
|
14
|
+
email: string;
|
|
15
|
+
username: string;
|
|
16
|
+
firstName: string;
|
|
17
|
+
lastName: string;
|
|
18
|
+
birthdate?: Date | undefined;
|
|
19
|
+
gender?: string | undefined;
|
|
20
|
+
createdAt: Date;
|
|
21
|
+
updatedAt: Date;
|
|
22
|
+
role?: string | undefined;
|
|
23
|
+
locked: boolean;
|
|
24
|
+
affiliateId: string;
|
|
25
|
+
stripeId: string;
|
|
26
|
+
} | null;
|
|
27
|
+
type AuthOptions = {
|
|
28
|
+
devTools: boolean;
|
|
29
|
+
endpoints: {
|
|
30
|
+
login: string;
|
|
31
|
+
logout: string;
|
|
32
|
+
refresh: string;
|
|
33
|
+
ssrRefresh: string;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* this will run on the server side as part of app.getInitialProps
|
|
38
|
+
* @todo is it possible to share state from client to server? headers? cookies?
|
|
39
|
+
*/
|
|
40
|
+
export declare const getAuth: (context: NextPageContext, options: AuthOptions) => Promise<import("xstate").Interpreter<import("./auth").AuthMachineContext, any, import("./auth").AuthMachineEvents, {
|
|
41
|
+
value: any;
|
|
42
|
+
context: import("./auth").AuthMachineContext;
|
|
43
|
+
}, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, import("./auth").AuthMachineEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>>;
|
|
44
|
+
type Props = {
|
|
45
|
+
children: ReactNode;
|
|
46
|
+
service: InterpreterFrom<typeof authMachine>;
|
|
47
|
+
};
|
|
48
|
+
export declare function AuthProvider({ children, service, }: Props): JSX.Element;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { DoneInvokeEvent } from 'xstate';
|
|
2
|
+
export interface AuthMachineContext {
|
|
3
|
+
user: {
|
|
4
|
+
email: string;
|
|
5
|
+
username: string;
|
|
6
|
+
firstName: string;
|
|
7
|
+
lastName: string;
|
|
8
|
+
birthdate?: Date;
|
|
9
|
+
gender?: string /** @todo use enum? */;
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
updatedAt: Date;
|
|
12
|
+
role?: string /** @todo use enum? */;
|
|
13
|
+
locked: boolean;
|
|
14
|
+
affiliateId: string;
|
|
15
|
+
stripeId: string;
|
|
16
|
+
} | null;
|
|
17
|
+
accessToken: string;
|
|
18
|
+
refreshToken: string;
|
|
19
|
+
ignoreRefreshToken: boolean;
|
|
20
|
+
endpoints: {
|
|
21
|
+
login: string;
|
|
22
|
+
logout: string;
|
|
23
|
+
refresh: string;
|
|
24
|
+
ssrRefresh: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export interface RefreshTokenEvent {
|
|
28
|
+
type: 'REFRESH_TOKEN';
|
|
29
|
+
accessToken: AuthMachineContext['accessToken'];
|
|
30
|
+
}
|
|
31
|
+
export interface LoginEvent {
|
|
32
|
+
type: 'LOGIN';
|
|
33
|
+
username: string;
|
|
34
|
+
password: string;
|
|
35
|
+
}
|
|
36
|
+
export interface LogoutEvent {
|
|
37
|
+
type: 'LOGOUT';
|
|
38
|
+
}
|
|
39
|
+
export interface AuthenticateSuccessEvent {
|
|
40
|
+
type: 'AUTHENTICATE_SUCCESS';
|
|
41
|
+
user: AuthMachineContext['user'];
|
|
42
|
+
accessToken: AuthMachineContext['accessToken'];
|
|
43
|
+
}
|
|
44
|
+
export interface RefreshTokenSuccessEvent {
|
|
45
|
+
type: 'REFRESH_TOKEN_SUCCESS';
|
|
46
|
+
accessToken: AuthMachineContext['accessToken'];
|
|
47
|
+
}
|
|
48
|
+
export type AuthMachineEvents = RefreshTokenEvent | LoginEvent | LogoutEvent | DoneInvokeEvent<AuthenticateSuccessEvent> | DoneInvokeEvent<RefreshTokenSuccessEvent>;
|
|
49
|
+
export declare const authMachine: import("xstate").StateMachine<AuthMachineContext, any, AuthMachineEvents, {
|
|
50
|
+
value: any;
|
|
51
|
+
context: AuthMachineContext;
|
|
52
|
+
}, import("xstate").BaseActionObject, import("xstate").ServiceMap, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, AuthMachineEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { InterpreterFrom } from 'xstate';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import { toastMachine } from './toast';
|
|
4
|
+
export declare const ToastContext: import("react").Context<import("xstate").Interpreter<import("./toast").ToastMachineContext, any, import("./toast").ToastMachineEvents, {
|
|
5
|
+
value: any;
|
|
6
|
+
context: import("./toast").ToastMachineContext;
|
|
7
|
+
}, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, import("./toast").ToastMachineEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>>;
|
|
8
|
+
export declare const useToast: () => import("xstate").Interpreter<import("./toast").ToastMachineContext, any, import("./toast").ToastMachineEvents, {
|
|
9
|
+
value: any;
|
|
10
|
+
context: import("./toast").ToastMachineContext;
|
|
11
|
+
}, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, import("./toast").ToastMachineEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>;
|
|
12
|
+
type Props = {
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
service: InterpreterFrom<typeof toastMachine>;
|
|
15
|
+
};
|
|
16
|
+
export declare function ToastProvider({ children, service, }: Props): JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export interface TimerContext {
|
|
3
|
+
elapsed: number;
|
|
4
|
+
duration: number;
|
|
5
|
+
interval: number;
|
|
6
|
+
intervalId: NodeJS.Timer | null;
|
|
7
|
+
}
|
|
8
|
+
export type TimerEvents = {
|
|
9
|
+
type: 'START_TIMER';
|
|
10
|
+
} | {
|
|
11
|
+
type: 'RESUME_TIMER';
|
|
12
|
+
} | {
|
|
13
|
+
type: 'PAUSE_TIMER';
|
|
14
|
+
} | {
|
|
15
|
+
type: 'TICK';
|
|
16
|
+
} | {
|
|
17
|
+
type: 'DURATION.UPDATE';
|
|
18
|
+
value: number;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'RESET_TIMER';
|
|
21
|
+
};
|
|
22
|
+
export declare const timerMachine: import("xstate").StateMachine<TimerContext, any, TimerEvents, {
|
|
23
|
+
value: any;
|
|
24
|
+
context: TimerContext;
|
|
25
|
+
}, import("xstate").BaseActionObject, import("xstate").ServiceMap, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, TimerEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>;
|
|
26
|
+
export default timerMachine;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import type { ReactElement } from 'react';
|
|
3
|
+
/** @todo figure out TS here */
|
|
4
|
+
export type ToastItem = {
|
|
5
|
+
id: string | null;
|
|
6
|
+
duration: number;
|
|
7
|
+
element: ReactNode;
|
|
8
|
+
};
|
|
9
|
+
export interface ToastMachineContext {
|
|
10
|
+
/** @todo create proper type for Array items */
|
|
11
|
+
items: Array<ToastItem>;
|
|
12
|
+
order: 'asc' | 'desc';
|
|
13
|
+
duration: number;
|
|
14
|
+
activeItem: string | null;
|
|
15
|
+
}
|
|
16
|
+
export interface AddItemEvent {
|
|
17
|
+
type: 'ADD_ITEM';
|
|
18
|
+
item: ReactElement;
|
|
19
|
+
duration?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface RemoveItemEvent {
|
|
22
|
+
type: 'REMOVE_ITEM';
|
|
23
|
+
}
|
|
24
|
+
export interface SetIdleEvent {
|
|
25
|
+
type: 'SET_IDLE';
|
|
26
|
+
}
|
|
27
|
+
export interface SetActiveEvent {
|
|
28
|
+
type: 'SET_ACTIVE';
|
|
29
|
+
}
|
|
30
|
+
export interface ResumeTimerEvent {
|
|
31
|
+
type: 'RESUME_TIMER';
|
|
32
|
+
}
|
|
33
|
+
export interface PauseTimerEvent {
|
|
34
|
+
type: 'PAUSE_TIMER';
|
|
35
|
+
}
|
|
36
|
+
export interface TimeoutEvent {
|
|
37
|
+
type: 'xstate.after(ITEM_TIMEOUT)#toast.active';
|
|
38
|
+
}
|
|
39
|
+
export interface TimerDoneEvent {
|
|
40
|
+
type: 'done.invoke.timer';
|
|
41
|
+
}
|
|
42
|
+
export type ToastMachineEvents = AddItemEvent | RemoveItemEvent | SetIdleEvent | SetActiveEvent | TimeoutEvent | ResumeTimerEvent | PauseTimerEvent | TimerDoneEvent;
|
|
43
|
+
export declare const toastMachine: import("xstate").StateMachine<ToastMachineContext, any, ToastMachineEvents, {
|
|
44
|
+
value: any;
|
|
45
|
+
context: ToastMachineContext;
|
|
46
|
+
}, import("xstate").BaseActionObject, import("xstate").ServiceMap, import("xstate").ResolveTypegenMeta<import("xstate").TypegenDisabled, ToastMachineEvents, import("xstate").BaseActionObject, import("xstate").ServiceMap>>;
|
package/.eslintrc.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": [
|
|
3
|
-
"../../.eslintrc.json"
|
|
4
|
-
],
|
|
5
|
-
"ignorePatterns": [
|
|
6
|
-
"!**/*",
|
|
7
|
-
"jest.config.ts",
|
|
8
|
-
"*.spec.ts"
|
|
9
|
-
],
|
|
10
|
-
"overrides": [
|
|
11
|
-
{
|
|
12
|
-
"files": [
|
|
13
|
-
"*.ts",
|
|
14
|
-
"*.tsx",
|
|
15
|
-
"*.js",
|
|
16
|
-
"*.jsx"
|
|
17
|
-
],
|
|
18
|
-
"rules": {}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"files": [
|
|
22
|
-
"*.ts",
|
|
23
|
-
"*.tsx"
|
|
24
|
-
],
|
|
25
|
-
"rules": {},
|
|
26
|
-
"parserOptions": {
|
|
27
|
-
"project": [
|
|
28
|
-
"libs/state/tsconfig.lib.json"
|
|
29
|
-
]
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
"files": [
|
|
34
|
-
"*.js",
|
|
35
|
-
"*.jsx"
|
|
36
|
-
],
|
|
37
|
-
"rules": {}
|
|
38
|
-
}
|
|
39
|
-
]
|
|
40
|
-
}
|
package/jest.config.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
export default {
|
|
3
|
-
displayName: 'state',
|
|
4
|
-
preset: '../../jest.preset.js',
|
|
5
|
-
transform: {
|
|
6
|
-
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
|
|
7
|
-
},
|
|
8
|
-
moduleFileExtensions: ['ts', 'js', 'html'],
|
|
9
|
-
coverageDirectory: '../../coverage/libs/state',
|
|
10
|
-
};
|
package/project.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "state",
|
|
3
|
-
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "libs/state/src",
|
|
5
|
-
"projectType": "library",
|
|
6
|
-
"targets": {
|
|
7
|
-
"build": {
|
|
8
|
-
"executor": "@nx/js:tsc",
|
|
9
|
-
"outputs": ["{options.outputPath}"],
|
|
10
|
-
"options": {
|
|
11
|
-
"outputPath": "dist/libs/state",
|
|
12
|
-
"main": "libs/state/src/index.ts",
|
|
13
|
-
"tsConfig": "libs/state/tsconfig.lib.json",
|
|
14
|
-
"assets": ["libs/state/*.md"]
|
|
15
|
-
}
|
|
16
|
-
},
|
|
17
|
-
"lint": {
|
|
18
|
-
"executor": "@nx/linter:eslint",
|
|
19
|
-
"outputs": ["{options.outputFile}"],
|
|
20
|
-
"options": {
|
|
21
|
-
"lintFilePatterns": ["libs/state/**/*.ts"]
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"test": {
|
|
25
|
-
"executor": "@nx/jest:jest",
|
|
26
|
-
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
|
27
|
-
"options": {
|
|
28
|
-
"jestConfig": "libs/state/jest.config.ts",
|
|
29
|
-
"passWithNoTests": true
|
|
30
|
-
},
|
|
31
|
-
"configurations": {
|
|
32
|
-
"ci": {
|
|
33
|
-
"ci": true,
|
|
34
|
-
"codeCoverage": true
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
"tags": []
|
|
40
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import { createContext, useContext } from 'react';
|
|
2
|
-
import { interpret } from 'xstate';
|
|
3
|
-
import type { InterpreterFrom } from 'xstate';
|
|
4
|
-
import cookie from 'cookie';
|
|
5
|
-
import type { ReactNode } from 'react';
|
|
6
|
-
import type { NextPageContext } from 'next';
|
|
7
|
-
import { authMachine } from './auth';
|
|
8
|
-
|
|
9
|
-
// removing dependencies on next, this should work regardless of platform
|
|
10
|
-
// import type { NextPageContext } from 'next';
|
|
11
|
-
// import { useRouter } from 'next/router';
|
|
12
|
-
|
|
13
|
-
export const AuthContext = createContext(
|
|
14
|
-
{} as InterpreterFrom<typeof authMachine>
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
export const useAuth = () => {
|
|
18
|
-
// console.log('useAuth');
|
|
19
|
-
// console.log(useContext(AuthContext).getSnapshot().context);
|
|
20
|
-
return useContext(AuthContext);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const useUser = () => {
|
|
24
|
-
return useContext(AuthContext).getSnapshot().context.user;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type AuthOptions = {
|
|
28
|
-
devTools: boolean;
|
|
29
|
-
endpoints: {
|
|
30
|
-
login: string;
|
|
31
|
-
logout: string;
|
|
32
|
-
refresh: string;
|
|
33
|
-
ssrRefresh: string;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* this will run on the server side as part of app.getInitialProps
|
|
39
|
-
* @todo is it possible to share state from client to server? headers? cookies?
|
|
40
|
-
*/
|
|
41
|
-
export const getAuth = async (
|
|
42
|
-
context: NextPageContext,
|
|
43
|
-
options: AuthOptions
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
45
|
-
) => {
|
|
46
|
-
if (typeof window !== 'undefined') {
|
|
47
|
-
// eslint-disable-next-line no-console
|
|
48
|
-
console.warn(
|
|
49
|
-
'App.getInitialProps::getAuth should not be run on the frontend. You are probably missing getServerSideProps in your page.'
|
|
50
|
-
);
|
|
51
|
-
return interpret(authMachine, { devTools: options.devTools }).start();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const cookies = cookie.parse(
|
|
55
|
-
context?.req?.headers && context.req.headers.cookie
|
|
56
|
-
? context.req.headers.cookie
|
|
57
|
-
: ''
|
|
58
|
-
);
|
|
59
|
-
if (typeof cookies['refresh_token'] !== 'undefined') {
|
|
60
|
-
const authContext = {
|
|
61
|
-
...authMachine.initialState.context,
|
|
62
|
-
refreshToken: cookies['refresh_token'],
|
|
63
|
-
endpoints: { ...options.endpoints },
|
|
64
|
-
};
|
|
65
|
-
return interpret(authMachine.withContext(authContext), {
|
|
66
|
-
devTools: options.devTools,
|
|
67
|
-
}).start();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return interpret(authMachine, { devTools: options.devTools }).start();
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
type Props = {
|
|
74
|
-
children: ReactNode;
|
|
75
|
-
service: InterpreterFrom<typeof authMachine>;
|
|
76
|
-
// options: {
|
|
77
|
-
// devTools: boolean;
|
|
78
|
-
// };
|
|
79
|
-
// state: StateConfig<AuthMachineContext, AuthMachineEvents>;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export function AuthProvider({
|
|
83
|
-
children,
|
|
84
|
-
service,
|
|
85
|
-
}: // options = { devTools: false },
|
|
86
|
-
// state
|
|
87
|
-
Props) {
|
|
88
|
-
// console.log('AuthProvider::state');
|
|
89
|
-
// console.log(state.context);
|
|
90
|
-
// let authService = interpret(authMachine, { devTools: options.devTools }).start(state);
|
|
91
|
-
// console.log('AuthProvider::authService');
|
|
92
|
-
// console.log(authService.getSnapshot().context);
|
|
93
|
-
|
|
94
|
-
return (
|
|
95
|
-
<AuthContext.Provider value={service}>{children}</AuthContext.Provider>
|
|
96
|
-
);
|
|
97
|
-
}
|