From a456f199caa1d5d67b0be9b7266fbe7d55674717 Mon Sep 17 00:00:00 2001 From: REllEK-IO Date: Tue, 10 Oct 2023 11:40:02 -0700 Subject: [PATCH] createPayload and selectPayload --- ActionStrategy.md | 2 +- README.md | 2 +- package.json | 2 +- .../appendActionListToDialog.quality.ts | 3 ++- .../appendConceptsToAddQue.quality.ts | 3 ++- .../appendConceptsToRemoveQue.quality.ts | 3 ++- .../axium/qualities/badAction.quality.ts | 3 ++- ...rBadActionTypeFromBadActionList.quality.ts | 3 ++- .../clearBadPlanFromBadPlanList.quality.ts | 3 ++- ...dStrategyTopicFromBadActionList.quality.ts | 3 ++- .../qualities/initializePrinciples.quality.ts | 3 ++- src/concepts/axium/qualities/open.quality.ts | 4 ++- .../qualities/registerSubscriber.quality.ts | 3 ++- .../qualities/setBlockingMode.quality.ts | 3 ++- .../axium/qualities/setDefaultMode.quality.ts | 3 ++- .../qualities/setDefaultModeIndex.quality.ts | 3 ++- .../axium/qualities/setMode.quality.ts | 3 ++- .../axium/strategies/addConcept.strategy.ts | 11 ++++---- .../strategies/initialization.strategy.ts | 13 +++++----- .../strategies/removeConcept.strategy.ts | 7 ++--- .../chain/qualities/prepareChain.quality.ts | 3 ++- .../counter/qualities/setCount.quality.ts | 3 ++- .../qualities/clearPayloadStubs.quality.ts | 3 ++- .../qualities/clearPendingActions.quality.ts | 2 +- .../clearPendingActionsOfStrategy.quality.ts | 3 ++- .../qualities/initializeOwnership.quality.ts | 2 +- .../qualities/resetOwnershipLedger.quality.ts | 2 +- .../strategies/setOwnerShipMode.strategy.ts | 4 +-- src/index.ts | 2 +- src/model/selector.ts | 18 +++++++++++++ src/test/chain.test.ts | 26 ++++++++++++------- src/test/selector.test.ts | 26 ++++++------------- 32 files changed, 105 insertions(+), 69 deletions(-) diff --git a/ActionStrategy.md b/ActionStrategy.md index fc8295f..2cb24fb 100644 --- a/ActionStrategy.md +++ b/ActionStrategy.md @@ -37,7 +37,7 @@ export interface ActionNode { ``` * action - Is an union data pattern to bind the functionality of the ActionNode, ActionStrategy, and Action. This allows for each part to be responsible for itself and to allow for additional functionality at runtime. * actionType - Is merely the type of action to be created at runtime, these should be verbose as to their intended effect as it informs the STRX sentence structure's body. -* payload - Is set to unknown to allow for the explicit typecasting during consumption, reducer, method, or principle. +* payload - Is set to unknown to allow for the explicit typecasting during consumption, reducer, method, or principle. Use createPayload<_Type>(payload: _Type) to ensure type casting in the reducer will be the same type as used in createPayload. This is a logical determination in line with Javascript core functionality. * keyedSelectors - An Array of KeyedSelector that locks some property during the life time of the created action. * semaphore - First is concept's index, second is the quality's index, and the final is the generation of the sets of concepts currently stored on the Axium. *Explicitly setting this value, denotes a primed action without additional look up at runtime.* * agreement - Is time in milliseconds of the lock's expiration time. Default is currently 5000, but such will be reduced upon testing and feedback. diff --git a/README.md b/README.md index 30c92f5..fb6c5de 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ const staged = axium.stage( // Will be ran after both counting strategies conclude. const ownership = selectState(cpts, ownershipName); console.log('Stage 2', ownership.ownershipLedger, ownership.pendingActions); - dispatch(counterSetCount({newCount: 1000}, undefined, 7000), { iterateStep: true}); + dispatch(counterSetCount(createPayload({newCount: 1000}), undefined, 7000), { iterateStep: true}); }, (cpts, dispatch) => { const ownership = selectState(cpts, ownershipName); diff --git a/package.json b/package.json index 1b4a377..88b1d80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@phuire/strx", - "version": "0.0.20", + "version": "0.0.21", "description": "Unified Turing Machine", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/src/concepts/axium/qualities/appendActionListToDialog.quality.ts b/src/concepts/axium/qualities/appendActionListToDialog.quality.ts index 3581eea..4a8b2d5 100644 --- a/src/concepts/axium/qualities/appendActionListToDialog.quality.ts +++ b/src/concepts/axium/qualities/appendActionListToDialog.quality.ts @@ -5,6 +5,7 @@ import { createAction } from '../../../model/action'; import { createQuality } from '../../../model/concept'; import { AxiumState } from '../axium.concept'; import { axiumConcludeType } from './conclude.quality'; +import { selectPayload } from '../../../model/selector'; export const axiumAppendActionListToDialogType: ActionType = 'append Action List to Axium\'s Dialog'; @@ -37,7 +38,7 @@ const createAppendActionListToDialogMethodCreator: MethodCreator = () => { }; export function appendActionListToDialogReducer(state: AxiumState, action: Action) { - const payload = action.payload as AppendActionListToDialogPayload; + const payload = selectPayload(action); let newDialog = ''; if (state.storeDialog) { payload.actionList.forEach(str => {newDialog += str + ' ';}); diff --git a/src/concepts/axium/qualities/appendConceptsToAddQue.quality.ts b/src/concepts/axium/qualities/appendConceptsToAddQue.quality.ts index 90cc6d4..b04c046 100644 --- a/src/concepts/axium/qualities/appendConceptsToAddQue.quality.ts +++ b/src/concepts/axium/qualities/appendConceptsToAddQue.quality.ts @@ -2,6 +2,7 @@ import { Concept, defaultMethodCreator } from '../../../model/concept'; import { AxiumState } from '../axium.concept'; import { Action, ActionType } from '../../../model/action'; import { createQuality } from '../../../model/concept'; +import { selectPayload } from '../../../model/selector'; export const axiumAppendConceptsToAddQueType: ActionType = 'append Concepts to Axium\'s Add Concept Que'; @@ -10,7 +11,7 @@ export type AppendConceptsToAddQuePayload = { } export function appendConceptsToAddQueReducer(state: AxiumState, action: Action) { - const payload = action.payload as AppendConceptsToAddQuePayload; + const payload = selectPayload(action); const addConceptQue = [ ...payload.concepts ]; diff --git a/src/concepts/axium/qualities/appendConceptsToRemoveQue.quality.ts b/src/concepts/axium/qualities/appendConceptsToRemoveQue.quality.ts index 3d9bf33..651c868 100644 --- a/src/concepts/axium/qualities/appendConceptsToRemoveQue.quality.ts +++ b/src/concepts/axium/qualities/appendConceptsToRemoveQue.quality.ts @@ -2,6 +2,7 @@ import { Concept, defaultMethodCreator } from '../../../model/concept'; import { AxiumState } from '../axium.concept'; import { Action, ActionType } from '../../../model/action'; import { createQuality } from '../../../model/concept'; +import { selectPayload } from '../../../model/selector'; export const axiumAppendConceptsToRemoveQueType: ActionType = 'append Concepts to Axium\'s Remove Concept Que'; @@ -10,7 +11,7 @@ export type AppendConceptsToRemoveQuePayload = { } export function appendConceptsToRemoveQueReducer(state: AxiumState, action: Action) { - const payload = action.payload as AppendConceptsToRemoveQuePayload; + const payload = selectPayload(action); let removeQue = state.removeConceptQue; removeQue = [ ...removeQue, diff --git a/src/concepts/axium/qualities/badAction.quality.ts b/src/concepts/axium/qualities/badAction.quality.ts index 039a4c0..582d965 100644 --- a/src/concepts/axium/qualities/badAction.quality.ts +++ b/src/concepts/axium/qualities/badAction.quality.ts @@ -1,12 +1,13 @@ import { Action, ActionType } from '../../../model/action'; import { createQuality } from '../../../model/concept'; +import { selectPayload } from '../../../model/selector'; import { AxiumState } from '../axium.concept'; export const axiumBadActionType: ActionType = 'Axium received a Bad Action'; export type BadActionPayload = Action[]; export function badActionReducer(state: AxiumState, action: Action) { - const payload = action.payload as BadActionPayload; + const payload = selectPayload(action); if (state.logging) { console.log('Axium Received a Bad Action: ', action); } diff --git a/src/concepts/axium/qualities/clearBadActionTypeFromBadActionList.quality.ts b/src/concepts/axium/qualities/clearBadActionTypeFromBadActionList.quality.ts index 18e1cfa..49cc262 100644 --- a/src/concepts/axium/qualities/clearBadActionTypeFromBadActionList.quality.ts +++ b/src/concepts/axium/qualities/clearBadActionTypeFromBadActionList.quality.ts @@ -1,13 +1,14 @@ import { defaultMethodCreator, createQuality } from '../../../model/concept'; import { Action, ActionType, prepareActionCreator } from '../../../model/action'; import { AxiumState } from '../axium.concept'; +import { selectPayload } from '../../../model/selector'; export const axiumClearBadActionTypeFromBadActionListType: ActionType = 'clear ActionType from Axium\'s badAction list'; export const axiumClearBadActionTypeFromBadActionList = prepareActionCreator(axiumClearBadActionTypeFromBadActionListType); export type ClearBadActionTypeFromBadActionListPayload = ActionType; function clearBadActionTypeFromBadActionListReducer(state: AxiumState, action: Action): AxiumState { - const actionType = action.payload as ClearBadActionTypeFromBadActionListPayload; + const actionType = selectPayload(action); return { ...state, badActions: state.badActions.filter(act => act.type !== actionType), diff --git a/src/concepts/axium/qualities/clearBadPlanFromBadPlanList.quality.ts b/src/concepts/axium/qualities/clearBadPlanFromBadPlanList.quality.ts index 05a9ee9..3b7f13d 100644 --- a/src/concepts/axium/qualities/clearBadPlanFromBadPlanList.quality.ts +++ b/src/concepts/axium/qualities/clearBadPlanFromBadPlanList.quality.ts @@ -1,13 +1,14 @@ import { defaultMethodCreator, createQuality } from '../../../model/concept'; import { Action, ActionType, prepareActionCreator } from '../../../model/action'; import { AxiumState } from '../axium.concept'; +import { selectPayload } from '../../../model/selector'; export const axiumClearBadPlanFromBadPlanListType: ActionType = 'clear Plan Topic from Axium\'s badPlan list'; export const axiumClearBadPlanFromBadPlanList = prepareActionCreator(axiumClearBadPlanFromBadPlanListType); export type ClearBadPlanFromBadPlanListPayload = string; function clearBadPlanFromBadPlanListReducer(state: AxiumState, action: Action): AxiumState { - const title = action.payload as ClearBadPlanFromBadPlanListPayload; + const title = selectPayload(action); return { ...state, badPlans: state.badPlans.filter(act => act.title !== title), diff --git a/src/concepts/axium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts b/src/concepts/axium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts index 3b2928e..a04f64d 100644 --- a/src/concepts/axium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts +++ b/src/concepts/axium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts @@ -1,13 +1,14 @@ import { defaultMethodCreator, createQuality } from '../../../model/concept'; import { Action, ActionType, prepareActionCreator } from '../../../model/action'; import { AxiumState } from '../axium.concept'; +import { selectPayload } from '../../../model/selector'; export const axiumClearBadStrategyTopicFromBadActionListType: ActionType = 'clear Strategy Topic from Axium\'s badAction list'; export const axiumClearBadStrategyTopicFromBadActionList = prepareActionCreator(axiumClearBadStrategyTopicFromBadActionListType); export type ClearBadStrategyTopicFromBadActionListPayload = string; function clearBadStrategyTopicFromBadActionListReducer(state: AxiumState, action: Action): AxiumState { - const strategyTopic = action.payload as ClearBadStrategyTopicFromBadActionListPayload; + const strategyTopic = selectPayload(action); const badActions = state.badActions.filter(act => { if (act.strategy && act.strategy.topic !== strategyTopic) { return true; diff --git a/src/concepts/axium/qualities/initializePrinciples.quality.ts b/src/concepts/axium/qualities/initializePrinciples.quality.ts index 9b93b8e..e9ace4a 100644 --- a/src/concepts/axium/qualities/initializePrinciples.quality.ts +++ b/src/concepts/axium/qualities/initializePrinciples.quality.ts @@ -5,6 +5,7 @@ import { Action, ActionType } from '../../../model/action'; import { AxiumState } from '../axium.concept'; import { createQuality } from '../../../model/concept'; import { UnifiedSubject } from '../../../model/unifiedSubject'; +import { selectPayload } from '../../../model/selector'; export const axiumInitializePrinciplesType: ActionType = 'initialize Principles and set new Subscribers to General Subscribers list'; @@ -13,7 +14,7 @@ export type InitializePrinciplesPayload = { } export function initializePrinciplesReducer(state: AxiumState, _action: Action) { - const payload = _action.payload as InitializePrinciplesPayload; + const payload = selectPayload(_action); const concepts = payload.concepts; const action$ = state.action$ as Subject; const subConcepts$ = state.concepts$ as UnifiedSubject; diff --git a/src/concepts/axium/qualities/open.quality.ts b/src/concepts/axium/qualities/open.quality.ts index e031a83..59fef23 100644 --- a/src/concepts/axium/qualities/open.quality.ts +++ b/src/concepts/axium/qualities/open.quality.ts @@ -1,6 +1,7 @@ import { defaultMethodCreator, createQuality } from '../../../model/concept'; import { Action, ActionType, prepareActionCreator } from '../../../model/action'; import { AxiumState } from '../axium.concept'; +import { selectPayload } from '../../../model/selector'; export const axiumOpenType: ActionType = 'Open Axium'; export const axiumOpen = prepareActionCreator(axiumOpenType); @@ -8,8 +9,9 @@ export const axiumOpen = prepareActionCreator(axiumOpenType); export type OpenPayload = { open?: boolean; } | undefined; + export function openReducer(state: AxiumState, action: Action) { - const payload = action.payload as OpenPayload; + const payload = selectPayload(action); return { ...state, open: payload?.open ? payload.open : true diff --git a/src/concepts/axium/qualities/registerSubscriber.quality.ts b/src/concepts/axium/qualities/registerSubscriber.quality.ts index 4de586e..3895646 100644 --- a/src/concepts/axium/qualities/registerSubscriber.quality.ts +++ b/src/concepts/axium/qualities/registerSubscriber.quality.ts @@ -3,6 +3,7 @@ import { defaultMethodCreator } from '../../../model/concept'; import { Action, ActionType } from '../../../model/action'; import { AxiumState } from '../axium.concept'; import { createQuality } from '../../../model/concept'; +import { selectPayload } from '../../../model/selector'; export const axiumRegisterSubscriberType: ActionType = 'register Subscriber to Axium\'s General Subscriber list'; @@ -12,7 +13,7 @@ export type RegisterSubscriberPayload = { } export function registerSubscriberReducer(state: AxiumState, action: Action) { - const payload = action.payload as RegisterSubscriberPayload; + const payload = selectPayload(action); const generalSubscribers = state.generalSubscribers; const subscriber = payload.subscriber; const name = payload.name; diff --git a/src/concepts/axium/qualities/setBlockingMode.quality.ts b/src/concepts/axium/qualities/setBlockingMode.quality.ts index 482bd18..b9d7dab 100644 --- a/src/concepts/axium/qualities/setBlockingMode.quality.ts +++ b/src/concepts/axium/qualities/setBlockingMode.quality.ts @@ -4,6 +4,7 @@ import { Action, ActionType } from '../../../model/action'; import { AxiumState } from '../axium.concept'; import { createQuality } from '../../../model/concept'; import { blockingMethodSubscription } from '../../../model/axium'; +import { selectPayload } from '../../../model/selector'; export const axiumSetBlockingModeType: ActionType = 'set Axium to Blocking Mode'; @@ -16,7 +17,7 @@ export function setBlockingModeReducer(state: AxiumState, _action: Action) { methodSubscribers.forEach(named => named.subscriber.unsubscribe()); methodSubscribers = []; - const payload = _action.payload as SetBlockingModePayload; + const payload = selectPayload(_action); const concepts = payload.concepts; concepts.forEach(concept => { concept.qualities.forEach(quality => { diff --git a/src/concepts/axium/qualities/setDefaultMode.quality.ts b/src/concepts/axium/qualities/setDefaultMode.quality.ts index ede4ed7..2a1af41 100644 --- a/src/concepts/axium/qualities/setDefaultMode.quality.ts +++ b/src/concepts/axium/qualities/setDefaultMode.quality.ts @@ -4,6 +4,7 @@ import { Action, ActionType } from '../../../model/action'; import { AxiumState } from '../axium.concept'; import { createQuality } from '../../../model/concept'; import { defaultMethodSubscription } from '../../../model/axium'; +import { selectPayload } from '../../../model/selector'; export const axiumSetDefaultModeType: ActionType = 'set Axium to its current Default Mode Index'; @@ -15,7 +16,7 @@ export function setDefaultModeReducer(state: AxiumState, _action: Action) { let methodSubscribers = state.methodSubscribers; methodSubscribers.forEach(named => named.subscriber.unsubscribe()); methodSubscribers = []; - const payload = _action.payload as SetDefaultModePayload; + const payload = selectPayload(_action); const concepts = payload.concepts; concepts.forEach(concept => { concept.qualities.forEach(quality => { diff --git a/src/concepts/axium/qualities/setDefaultModeIndex.quality.ts b/src/concepts/axium/qualities/setDefaultModeIndex.quality.ts index 07c446f..ada759f 100644 --- a/src/concepts/axium/qualities/setDefaultModeIndex.quality.ts +++ b/src/concepts/axium/qualities/setDefaultModeIndex.quality.ts @@ -1,6 +1,7 @@ import { defaultMethodCreator, createQuality } from '../../../model/concept'; import { Action, ActionType } from '../../../model/action'; import { AxiumState } from '../axium.concept'; +import { selectPayload } from '../../../model/selector'; export const axiumSetDefaultModeIndexType: ActionType = 'set Axium\'s Default Mode Index'; @@ -9,7 +10,7 @@ export type SetDefaultModeIndexPayload = { }; export function setDefaultModeIndexReducer(state: AxiumState, action: Action) { - const payload = action.payload as SetDefaultModeIndexPayload; + const payload = selectPayload(action); return { ...state, defaultModeIndex: payload.index, diff --git a/src/concepts/axium/qualities/setMode.quality.ts b/src/concepts/axium/qualities/setMode.quality.ts index 20725f9..24efe20 100644 --- a/src/concepts/axium/qualities/setMode.quality.ts +++ b/src/concepts/axium/qualities/setMode.quality.ts @@ -4,6 +4,7 @@ import { createQuality, MethodCreator, Method } from '../../../model/concept'; import { Subject, map } from 'rxjs'; import { axiumConcludeType } from './conclude.quality'; import { strategySuccess } from '../../../model/actionStrategy'; +import { selectPayload } from '../../../model/selector'; export const axiumSetModeType = 'set Axium Mode'; @@ -30,7 +31,7 @@ export const createOwnershipMethodCreator: MethodCreator = () : [Method, Subject }; export function setModeReducer(state: AxiumState, _action: Action) { - const payload = _action.payload as SetModePayload; + const payload = selectPayload(_action); return { ...state, modeIndex: [payload.modeIndex], diff --git a/src/concepts/axium/strategies/addConcept.strategy.ts b/src/concepts/axium/strategies/addConcept.strategy.ts index 6cb324f..ec75fca 100644 --- a/src/concepts/axium/strategies/addConcept.strategy.ts +++ b/src/concepts/axium/strategies/addConcept.strategy.ts @@ -6,8 +6,9 @@ import { AddConceptsFromQuePayload, axiumAddConceptFromQueType } from '../qualit import { AppendConceptsToAddQuePayload, axiumAppendConceptsToAddQueType } from '../qualities/appendConceptsToAddQue.quality'; import { axiumOpenType } from '../qualities/open.quality'; import { axiumSetBlockingModeType } from '../qualities/setBlockingMode.quality'; -import { axiumSetDefaultModeType } from '../qualities/setDefaultMode.quality'; +import { SetDefaultModePayload, axiumSetDefaultModeType } from '../qualities/setDefaultMode.quality'; import { axiumName } from '../axium.concept'; +import { createPayload } from '../../../model/selector'; // Step One to Add Concepts to Axium export const addConceptsToAddQueThenBlockTopic = 'Add Concepts to add que then set Axium Mode to Blocking'; @@ -20,7 +21,7 @@ export function addConceptsToAddQueThenBlockStrategy(concepts: Concept[], newCon }, failureNode: null, semaphore: getSemaphore(concepts, axiumName, axiumAppendConceptsToAddQueType), - payload: {concepts: newConcepts} as AppendConceptsToAddQuePayload, + payload: createPayload({concepts: newConcepts}), }; const stepOne: ActionNode = { actionType: axiumSetBlockingModeType, @@ -30,7 +31,7 @@ export function addConceptsToAddQueThenBlockStrategy(concepts: Concept[], newCon }, failureNode: null, semaphore: getSemaphore(concepts, axiumName, axiumSetBlockingModeType), - payload: {concepts} as AppendConceptsToAddQuePayload, + payload: createPayload({concepts}), }; const params: ActionStrategyParameters = { @@ -64,7 +65,7 @@ export function addConceptsFromQueThenUnblockStrategy(action$: Subject, preposition: 'Then' }, failureNode: null, - payload: {concepts: conceptualSet}, + payload: createPayload({concepts: conceptualSet}), }; const stepOne: ActionNode = { actionType: axiumAddConceptFromQueType, @@ -74,7 +75,7 @@ export function addConceptsFromQueThenUnblockStrategy(action$: Subject, preposition: 'First' }, failureNode: null, - payload: {action$} as AddConceptsFromQuePayload, + payload: createPayload({action$}), }; const params: ActionStrategyParameters = { diff --git a/src/concepts/axium/strategies/initialization.strategy.ts b/src/concepts/axium/strategies/initialization.strategy.ts index deea3b1..76c5e4e 100644 --- a/src/concepts/axium/strategies/initialization.strategy.ts +++ b/src/concepts/axium/strategies/initialization.strategy.ts @@ -1,10 +1,11 @@ import { createStrategy, ActionNode, ActionStrategy, ActionStrategyParameters } from '../../../model/actionStrategy'; import { Concept } from '../../../model/concept'; import { getSemaphore } from '../../../model/action'; -import { axiumOpenType } from '../qualities/open.quality'; -import { axiumInitializePrinciplesType } from '../qualities/initializePrinciples.quality'; -import { axiumSetDefaultModeType } from '../qualities/setDefaultMode.quality'; +import { OpenPayload, axiumOpenType } from '../qualities/open.quality'; +import { InitializePrinciplesPayload, axiumInitializePrinciplesType } from '../qualities/initializePrinciples.quality'; +import { SetDefaultModePayload, axiumSetDefaultModeType } from '../qualities/setDefaultMode.quality'; import { axiumName } from '../axium.concept'; +import { createPayload } from '../../../model/selector'; export const initializeTopic = 'Axium Initialization Strategy'; export function initializationStrategy(concepts: Concept[]): ActionStrategy { @@ -21,7 +22,7 @@ export function initializationStrategy(concepts: Concept[]): ActionStrategy { denoter: 'to Notify Subscribers of State changes.' }, failureNode: null, - payload: {concepts}, + payload: createPayload({open: true}), }; const stepTwo: ActionNode = { actionType: axiumSetDefaultModeType, @@ -31,7 +32,7 @@ export function initializationStrategy(concepts: Concept[]): ActionStrategy { preposition: 'Then' }, failureNode: null, - payload: {concepts}, + payload: createPayload({concepts}), }; const stepOne: ActionNode = { actionType: axiumInitializePrinciplesType, @@ -41,7 +42,7 @@ export function initializationStrategy(concepts: Concept[]): ActionStrategy { preposition: 'Begin with' }, failureNode: null, - payload: {concepts}, + payload: createPayload({concepts}), }; const params: ActionStrategyParameters = { diff --git a/src/concepts/axium/strategies/removeConcept.strategy.ts b/src/concepts/axium/strategies/removeConcept.strategy.ts index 0917cc5..7302c4c 100644 --- a/src/concepts/axium/strategies/removeConcept.strategy.ts +++ b/src/concepts/axium/strategies/removeConcept.strategy.ts @@ -7,6 +7,7 @@ import { SetBlockingModePayload, axiumSetBlockingModeType } from '../qualities/s import { axiumOpenType } from '../qualities/open.quality'; import { SetDefaultModePayload, axiumSetDefaultModeType } from '../qualities/setDefaultMode.quality'; import { axiumName } from '../axium.concept'; +import { createPayload } from '../../../model/selector'; export const addConceptsToRemovalQueThenBlockTopic = 'Add Concepts to removal Que then set Axium Mode to Blocking'; export function addConceptsToRemovalQueThenBlockStrategy(concepts: Concept[], targetConcepts: Concept[]) { @@ -18,14 +19,14 @@ export function addConceptsToRemovalQueThenBlockStrategy(concepts: Concept[], ta semaphore: appendConceptsToRemoveQueSemaphore, successNode: null, failureNode: null, - payload: {concepts: targetConcepts} as AppendConceptsToRemoveQuePayload + payload: createPayload({concepts: targetConcepts}) }; const stepOne: ActionNode = { actionType: axiumSetBlockingModeType, semaphore: setBlockingModeSemaphore, successNode: stepTwo, failureNode: null, - payload: {concepts} as SetBlockingModePayload + payload: createPayload({concepts}) }; const params: ActionStrategyParameters = { topic: addConceptsToRemovalQueThenBlockTopic, @@ -58,7 +59,7 @@ export function removeConceptsViaQueThenUnblockStrategy(concepts: Concept[]): Ac preposition: 'Then' }, failureNode: null, - payload: {concepts} as SetDefaultModePayload, + payload: createPayload({concepts}), }; const stepOne: ActionNode = { actionType: axiumRemoveConceptsViaQueType, diff --git a/src/concepts/chain/qualities/prepareChain.quality.ts b/src/concepts/chain/qualities/prepareChain.quality.ts index b8b072f..566482c 100644 --- a/src/concepts/chain/qualities/prepareChain.quality.ts +++ b/src/concepts/chain/qualities/prepareChain.quality.ts @@ -1,5 +1,6 @@ import { Action, ActionType, prepareActionCreator } from '../../../model/action'; import { createQuality } from '../../../model/concept'; +import { selectPayload } from '../../../model/selector'; import { Chain } from '../chain.concept'; export const chainDispatchActionsType: ActionType = 'dispatch Actions from Action Que via Payload to be Chained'; @@ -11,7 +12,7 @@ export type ChainDispatchActionsPayload = { } export function prepareChainReducer(state: Chain, action: Action) { - const payload = action.payload as ChainDispatchActionsPayload; + const payload = selectPayload(action); return { ...state, actionQue: [ diff --git a/src/concepts/counter/qualities/setCount.quality.ts b/src/concepts/counter/qualities/setCount.quality.ts index ad038a1..a47aeaf 100644 --- a/src/concepts/counter/qualities/setCount.quality.ts +++ b/src/concepts/counter/qualities/setCount.quality.ts @@ -3,6 +3,7 @@ import { Action, prepareActionCreator } from '../../../model/action'; import { createQuality } from '../../../model/concept'; import { Counter } from '../counter.concept'; import { counterSelectCount } from '../counter.selector'; +import { selectPayload } from '../../../model/selector'; export const counterSetCountType = 'set Count'; @@ -12,7 +13,7 @@ export type SetCountPayload = { } export function setCountReducer(state: Counter, action: Action) { - const payload = action.payload as SetCountPayload; + const payload = selectPayload(action); return { ...state, count: payload.newCount diff --git a/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts b/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts index eaa1e0e..b39d4b3 100644 --- a/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts +++ b/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts @@ -2,12 +2,13 @@ import { createQuality, defaultMethodCreator } from '../../../model/concept'; import { Action, ActionType } from '../../../model/action'; import { OwnershipState } from '../ownership.concept'; import { OwnershipTicket, OwnershipTicketStub } from '../../../model/ownership'; +import { selectPayload } from '../../../model/selector'; export const ownershipClearPayloadStubsType: ActionType = 'clear payload Stubs from Ownership Ledger'; export type ClearPayloadStubsPayload = OwnershipTicketStub[]; export function clearPayloadStubsReducer(state: OwnershipState, action: Action): OwnershipState { - const stubs = action.payload as ClearPayloadStubsPayload; + const stubs = selectPayload(action); const ownershipLedger = state.ownershipLedger; stubs.forEach(ticketStub => { const line = ownershipLedger.get(ticketStub.key); diff --git a/src/concepts/ownership/qualities/clearPendingActions.quality.ts b/src/concepts/ownership/qualities/clearPendingActions.quality.ts index 12e225e..ec159c9 100644 --- a/src/concepts/ownership/qualities/clearPendingActions.quality.ts +++ b/src/concepts/ownership/qualities/clearPendingActions.quality.ts @@ -4,7 +4,7 @@ import { OwnershipState } from '../ownership.concept'; export const ownershipClearPendingActionsType: ActionType = 'clear Ownership\'s Pending Actions'; -export function clearPendingActionsReducer(state: OwnershipState, action: Action): OwnershipState { +export function clearPendingActionsReducer(state: OwnershipState, _: Action): OwnershipState { return { ...state, pendingActions: [] diff --git a/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts b/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts index ddea413..096cc01 100644 --- a/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts +++ b/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts @@ -2,12 +2,13 @@ import { createQuality, defaultMethodCreator } from '../../../model/concept'; import { Action, ActionType } from '../../../model/action'; import { OwnershipState } from '../ownership.concept'; import { ActionStrategyTopic } from '../../../model/actionStrategy'; +import { selectPayload } from '../../../model/selector'; export const ownershipClearPendingActionsOfStrategyType: ActionType = 'clear Ownership\'s Pending Actions of Strategy Topic'; export type ClearPendingActionsOfStrategyPayload = ActionStrategyTopic; export function clearPendingActionsOfStrategyReducer(state: OwnershipState, action: Action): OwnershipState { - const topic = action.payload as ClearPendingActionsOfStrategyPayload; + const topic = selectPayload(action); const newPendingActions: Action[] = []; for (const act of state.pendingActions) { if (act.strategy?.topic) { diff --git a/src/concepts/ownership/qualities/initializeOwnership.quality.ts b/src/concepts/ownership/qualities/initializeOwnership.quality.ts index c33bccd..6a5f4b9 100644 --- a/src/concepts/ownership/qualities/initializeOwnership.quality.ts +++ b/src/concepts/ownership/qualities/initializeOwnership.quality.ts @@ -4,7 +4,7 @@ import { OwnershipState } from '../ownership.concept'; export const ownershipInitializeOwnershipType: ActionType = 'Ownership Initialize to True to enable Ownership Principle'; -export function initializeOwnershipReducer(state: OwnershipState, action: Action) { +export function initializeOwnershipReducer(state: OwnershipState, _: Action) { return { ...state, initialized: true diff --git a/src/concepts/ownership/qualities/resetOwnershipLedger.quality.ts b/src/concepts/ownership/qualities/resetOwnershipLedger.quality.ts index a33a990..515c22a 100644 --- a/src/concepts/ownership/qualities/resetOwnershipLedger.quality.ts +++ b/src/concepts/ownership/qualities/resetOwnershipLedger.quality.ts @@ -5,7 +5,7 @@ import { createOwnershipLedger } from '../../../model/ownership'; export const ownershipResetOwnershipLedgerType: ActionType = 'reset Ownership Ledger'; -export function resetOwnershipLedgerReducer(state: OwnershipState, action: Action): OwnershipState { +export function resetOwnershipLedgerReducer(state: OwnershipState, _: Action): OwnershipState { return { ...state, ownershipLedger: createOwnershipLedger() diff --git a/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts b/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts index 7d9ea70..f25d88e 100644 --- a/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts +++ b/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts @@ -6,12 +6,12 @@ import { SetModePayload, axiumSetModeType } from '../../axium/qualities/setMode. import { ownershipName } from '../ownership.concept'; import { SetDefaultModeIndexPayload, axiumSetDefaultModeIndexType } from '../../axium/qualities/setDefaultModeIndex.quality'; import { AxiumState } from '../../axium/axium.concept'; +import { createPayload } from '../../../model/selector'; export const setOwnerShipModeTopic = 'Axium set Mode to Ownership then Initialize Ownership Principle'; export function setOwnershipModeStrategy(concepts: Concept[], modeName: string): ActionStrategy { const initializeOwnershipSemaphore = getSemaphore(concepts, ownershipName, ownershipInitializeOwnershipType); const setModeSemaphore = getSemaphore(concepts, ownershipName, axiumSetModeType); - const setDefaultModeIndexSemaphore = getSemaphore(concepts, ownershipName, axiumSetDefaultModeIndexType); let ownershipModeIndex = 2; (concepts[0].state as AxiumState).modeNames.forEach((key, i) => { if (key === ownershipName) { @@ -36,7 +36,7 @@ export function setOwnershipModeStrategy(concepts: Concept[], modeName: string): preposition: 'Successfully' }, failureNode: null, - payload: { modeIndex: 2, modeName } as SetModePayload, + payload: createPayload({ modeIndex: ownershipModeIndex, modeName }), }; const params: ActionStrategyParameters = { topic: setOwnerShipModeTopic, diff --git a/src/index.ts b/src/index.ts index 8cfe9fc..ea8b8a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,7 +26,7 @@ export type { MethodCreator } from './model/concept'; export type { KeyedSelector } from './model/selector'; -export { selectState, selectConcept, selectSlice } from './model/selector'; +export { selectState, selectConcept, selectSlice, createPayload, selectPayload } from './model/selector'; export { PrincipleFunction } from './model/principle'; export type { dispatchOptions, Staging, UnifiedSubject } from './model/unifiedSubject'; export type { OwnershipTicket, OwnershipTicketStub, OwnershipLedger } from './model/ownership'; diff --git a/src/model/selector.ts b/src/model/selector.ts index dc9ec5e..5bfd91e 100644 --- a/src/model/selector.ts +++ b/src/model/selector.ts @@ -1,3 +1,4 @@ +import { Action } from './action'; import { Concept } from './concept'; // Dumb association, as we would be setting this value via a generated value @@ -21,6 +22,23 @@ export function selectState(concepts: Concept[], name: string): T { return concept?.state as T; } +/** + * Simple helper function that returns payload casted to T. + * Prior to emitting action, use createPayload with the action's payload type to provide the logical guarantee. + * As Typescript does not care if payload is undefined or the entire window object. + * You must set the payload, if the payload is required in your logic. + */ +export function selectPayload(action: Action): T { + return action.payload as T; +} + +/** + * Provides logical guarantee that your payload is set to the appropriate type without casting. + */ +export function createPayload(payload: T): T { + return payload; +} + // Note: The Concept Key within the selector has to be set Explicitly for now export function selectSlice( concepts: Concept[], diff --git a/src/test/chain.test.ts b/src/test/chain.test.ts index 29018ce..a897b8d 100644 --- a/src/test/chain.test.ts +++ b/src/test/chain.test.ts @@ -1,7 +1,7 @@ import { createAxium } from '../model/axium'; import { Concept } from '../model/concept'; import { primeAction } from '../model/action'; -import { selectState } from '../model/selector'; +import { createPayload, selectState } from '../model/selector'; import { Counter, createCounterConcept, counterName } from '../concepts/counter/counter.concept'; import { createChainConcept } from '../concepts/chain/chain.concept'; import { ChainDispatchActionsPayload, chainDispatchActions } from '../concepts/chain/qualities/prepareChain.quality'; @@ -18,15 +18,21 @@ test('Axium Test', (done) => { willDispatch = false; const primedAdd = primeAction(concepts, counterAdd()); const primedSubtract = primeAction(concepts, counterSubtract()); - const primedPrepareChain = primeAction(concepts, chainDispatchActions({ - actions: [ - primedAdd, - primedAdd, - primedSubtract, - primedAdd, - primedSubtract, - primedAdd, - ]} as ChainDispatchActionsPayload)); + const primedPrepareChain = + primeAction(concepts, + chainDispatchActions( + createPayload({ + actions: [ + primedAdd, + primedAdd, + primedSubtract, + primedAdd, + primedSubtract, + primedAdd, + ] + }) + ) + ); axium.dispatch(primedPrepareChain); } else if (count === 7) { diff --git a/src/test/selector.test.ts b/src/test/selector.test.ts index 1bd8537..f06711f 100644 --- a/src/test/selector.test.ts +++ b/src/test/selector.test.ts @@ -1,8 +1,9 @@ import { createAxium } from '../model/axium'; import { Concept } from '../model/concept'; -import { selectSlice, selectState } from '../model/selector'; +import { createPayload, selectPayload, selectSlice, selectState } from '../model/selector'; import { Counter, createCounterConcept, counterName } from '../concepts/counter/counter.concept'; import { counterSelectCount } from '../concepts/counter/counter.selector'; +import { SetCountPayload, counterSetCount } from '../concepts/counter/qualities/setCount.quality'; test('Axium Selector Test', (done) => { const counter = createCounterConcept(); @@ -11,9 +12,7 @@ test('Axium Selector Test', (done) => { const axium = createAxium('axiumSelectorTest', [counter], true, true); const sub = axium.subscribe((concepts: Concept[]) => { const state = selectState(concepts, counterName); - // const count = selectSlice(concepts, counterSelectCount); expect(state.count).toBe(10); - // expect(count).toBe(10); done(); }); }); @@ -26,22 +25,13 @@ test('Axium Selector State Slice Test', (done) => { const sub = axium.subscribe((concepts: Concept[]) => { const count = selectSlice(concepts, counterSelectCount); expect(count).toBe(10); - // console.log('Check State Slice', 12); setTimeout(() => {done();}, 500); }); }); -// Deno.test( 'Axium Selector Test', async () => { -// const counter = counterConcept; -// const counterState = counterConcept.state as Counter; -// counterState.count = 10; -// const axium = await createAxium([counter]); -// const sub = axium.subscribe((concepts: Concept[]) => { -// const state = selectState(concepts, counter.key); -// console.log(`Count: ${state.count}`); -// assertEquals(state.count, 10); -// }); -// }, -// // sanitizeResources: false, -// // sanitizeOps: false, -// ); \ No newline at end of file +test('Axium Selector Payload Test', (done) => { + const setCount = counterSetCount(createPayload({newCount: 10 })); + const payload = selectPayload(setCount); + expect(payload.newCount).toBe(10); + done(); +});