![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
@fullerstack/agx-store
Advanced tools
A simple flat state/store that helps implementing lite-redux patterns
A simple flat state/store that helps implementing lite-redux patterns
This library helps implementing a flat redux
state store, with simplicity and performance in mind.
@fullerstack/agx-store attempts to simplify the reactive implementation of your browser application, through minimal redux
patterns, while promoting DRY DRY.
npm i @fullerstack/agx-store |OR| yarn add @fullerstack/agx-store
// auth.model.ts
import { DeepReadonly } from 'ts-essentials';
// define the shape of the auth state
export interface AuthState {
userId: string;
isAnonymous: boolean;
isLoggedIn: boolean;
isSigningUp: boolean;
isAuthenticating: boolean;
hasError: boolean;
token: string;
}
// create an immutable default state
export const DefaultAuthState: DeepReadonly<AuthState> = {
userId: null,
isAnonymous: false,
isLoggedIn: false,
isSigningUp: false,
isAuthenticating: false,
hasError: false,
token: null,
};
import { DeepReadonly } from 'ts-essentials';
import { Subscription } from 'rxjs';
import { Store, StoreStateType } from '@fullerstack/agx-store';
// auth service
export class AuthService<T = StoreStateType> {
// state slice name to be reserved for the auth service
private nameSpace = 'AUTH';
// claim ID of the slice is stored post registration
// read-access to auth state is open to all
// write-access to auth state is only open to those with a valid claimId
private claimId: string;
// holds our local state (if we need to compare `prev` vs. `next`)
// a local deep clone copy of our state, which is also immutable
// to allow others read-access, without the ability to mutate our local state
state: DeepReadonly<AuthState> = DefaultAuthState;
// auth state subscription, so we can unsubscribe on cleanup
readonly stateSub$: Subscription;
// we need to create an instance of the store here
// alternatively, an app-level store could be used if available
private store: StoreState;
// tell the store to stay immutable or not
// for performance gain, immutable can be set to false, post development.
// this way all the issues are found prior to releasing the application
// deep clone vs. freeze analysis, pointed this project to accepting
// the ownership of the incoming state data, and freezing it in-place
// as such leaving the state immutable is highly recommended
immutable = true; // alternatively (production ? false: true)
constructor() {
// instantiate a new local store
this.store = new StoreState<T>({} as T, this.immutable);
// reserve our AUTH slice from the full state
// we choose console.log as our slice/state logger
// alternatively a custom logger implementing the console api can be chosen
this.claimId = this.store.claimSlice(sliceName, console.log);
// subscribe to state changes for auth
this.stateSub$ = this.store.select$<AuthState>(this.nameSpace).subscribe({
next: (newState) => {
const prevState = cloneDeep(this.state);
this.state = { ...DefaultAuthState, ...newState };
if (this.state.isLoggedIn && !prevState.isLoggedIn) {
console.log(`You are logged in now!`);
}
// do other stuff, if you may!
},
});
}
loginRequest(input: AuthUserCredentialsInput) {
// set auth state to authenticating
// loading started ...
this.store.setState(
this.claimId, // provide write-access claimId
{
...this.state,
isAuthenticating: true,
},
'AUTH_LOGIN_REQ_SENT' // action name (optional)
);
// make login request (e.g. `doFetch()` is your way of communicating with your server)
const resp = doFetch('/login', input);
if (resp.ok) {
// set auth state to authenticated
// loading ended ...
this.store.setState(
this.claimId,
{
...DefaultAuthState,
isLoggedIn: true,
token: resp.token,
userId: resp.userId,
},
'AUTH_LOGIN_REQ_SUCCESS' // action
);
} else {
// set auth state to authentication failed
// loading ended ...
this.store.setState(
this.claimId,
{
...DefaultAuthState,
hasError: true,
message: resp.message,
},
'AUTH_LOGIN_REQ_FAILED' // action
);
}
}
// clean up and free up resources prior to class instance `destroy`
cleanUp() {
this.stateSub$.unsubscribe();
this.store.releaseSlice(this.claimId);
this.store = undefined;
}
}
// console.log ...
[STORE][PREV][AUTH_LOGIN_REQ_SENT] ↠ {AUTH: {…}}
[STORE][NEXT][AUTH_LOGIN_REQ_SENT] ↠ {AUTH: {…}}
[AUTH] Login request sent ...
[INTERCEPT][SUCCESS][userSelf] Http Request took 17 ms!
[STORE][PREV][AUTH_LOGIN_REQ_SUCCESS] ↠ {AUTH: {…}}
[STORE][NEXT][AUTH_LOGIN_REQ_SUCCESS] ↠ {AUTH: {…}}
[AUTH] Login request success ...
// Call signature of:
// setState<K = any>(claimId: string, updater: K, action?: string): K {}
// State can be passed in, along with claimId, skipping the action type
// If a logger is passed in, the action will be missing from state change logs
this.store.setState(this.claimId, {
isAuthenticating: true,
});
// State can be passed in, along with claimId, as well as an action type
// If a logger is passed in, the action will in the state change logs
this.store.setState(this.claimId, {
isAuthenticating: true,
}, 'AUTH_LOGIN_REQ_SENT');
// Call signature of:
// setState<K = any>(claimId: string, updater: StoreStateReducer<T, K>, action?: string): K;
// Where StoreStateReducer is:
// export type StoreStateReducer<T = any, K = any> = (fullState: T) => K;
// State reducer function can be passed in, along with claimId and action type
// If a logger is passed in, the action will be missing from state change logs
this.store.setState(this.claimId, (fullStoreState) => {
if (fullStoreState['app'].private) {
return {
...fullStoreState[this.sliceName],
isAuthenticating: true,
},
}
return {
// no login is required
...DefaultAuthState,
isAnonymous: true
}
}, 'AUTH_LOGIN_REQ_SENT');
Released under a (MIT) license.
X.Y.Z Version
`MAJOR` version -- making incompatible API changes
`MINOR` version -- adding functionality in a backwards-compatible manner
`PATCH` version -- making backwards-compatible bug fixes
FAQs
A simple flat state/store that helps implementing lite-redux patterns
The npm package @fullerstack/agx-store receives a total of 1 weekly downloads. As such, @fullerstack/agx-store popularity was classified as not popular.
We found that @fullerstack/agx-store demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.