Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: server context, new signal api #200

Merged
merged 7 commits into from
Sep 15, 2024
14 changes: 7 additions & 7 deletions packages/fsm/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ definePackage('@alwatr/signal', __package_version__);
/**
* Finite State Machine Base Class
*/
export abstract class FiniteStateMachineBase<S extends string, E extends string> extends AlwatrObservable<S> {
export abstract class FiniteStateMachineBase<S extends string, E extends string> extends AlwatrObservable<{state: S}> {
/**
* States and transitions config.
*/
Expand All @@ -24,20 +24,20 @@ export abstract class FiniteStateMachineBase<S extends string, E extends string>

protected initialState_: S;

protected override data_: S;
protected override message_: {state: S};

constructor(config: {name: string; loggerPrefix?: string; initialState: S}) {
config.loggerPrefix ??= 'fsm';
super(config);
this.data_ = this.initialState_ = config.initialState;
this.message_ = {state: this.initialState_ = config.initialState};
}

/**
* Reset machine to initial state.
* Reset machine to initial state without notify.
*/
protected resetToInitialState_(): void {
this.logger_.logMethod?.('resetToInitialState_');
this.data_ = this.initialState_;
this.message_ = {state: this.initialState_};
}

/**
Expand All @@ -52,7 +52,7 @@ export abstract class FiniteStateMachineBase<S extends string, E extends string>
* Transition finite state machine instance to new state.
*/
protected async transition_(event: E): Promise<void> {
const fromState = this.data_;
const fromState = this.message_.state;
const toState = this.stateRecord_[fromState]?.[event] ?? this.stateRecord_._all?.[event];

this.logger_.logMethodArgs?.('transition_', {fromState, event, toState});
Expand All @@ -69,7 +69,7 @@ export abstract class FiniteStateMachineBase<S extends string, E extends string>

if ((await this.shouldTransition_(eventDetail)) !== true) return;

this.notify_(toState);
this.notify_({state: toState});

this.postTransition__(eventDetail);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/fsm/src/fsm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export abstract class FiniteStateMachine<S extends string, E extends string> ext
/**
* Current state.
*/
getState(): S {
return this.data_;
get state(): S {
return this.message_.state;
}

/**
Expand Down
16 changes: 8 additions & 8 deletions packages/server-context/src/api-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ export abstract class AlwatrApiRequestBase<
> extends AlwatrServerRequestBase<ExtraState, ExtraEvent> {
protected _responseJson?: T;

protected override async _$fetch(options: FetchOptions): Promise<void> {
protected override async fetch__(options: FetchOptions): Promise<void> {
if (!NODE_MODE) {
options.headers ??= {};
if (!options.headers['client-id']) {
options.headers['client-id'] = getClientId();
}
}

await super._$fetch(options);
await super.fetch__(options);

let responseText: string;
try {
responseText = await this._response!.text();
responseText = await this.response_!.text();
}
catch (err) {
this._logger.error('_$fetch', 'invalid_response_text', err);
Expand Down Expand Up @@ -54,8 +54,8 @@ export abstract class AlwatrApiRequestBase<
}
}

protected override _reset(): void {
super._reset();
protected override resetToInitialState_(): void {
super.resetToInitialState_();
delete this._responseJson;
}
}
Expand All @@ -73,14 +73,14 @@ export class AlwatrApiRequest<T extends AlwatrServiceResponse = AlwatrServiceRes
}

get _fetchResponse(): Response | undefined {
return this._response;
return this.response_;
}

request(options?: Partial<FetchOptions>): void {
return this._request(options);
return this.request_(options);
}

cleanup(): void {
this._reset();
this.resetToInitialState_();
}
}
38 changes: 19 additions & 19 deletions packages/server-context/src/server-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ export abstract class AlwatrServerContextBase<
T extends AlwatrServiceResponse = AlwatrServiceResponse,
> extends AlwatrApiRequestBase<T, ExtraState, ExtraEvent> {
protected _context?: T;
constructor(protected override _config: ServerRequestConfig) {
super(_config);
constructor(protected override config_: ServerRequestConfig) {
super(config_);

this._stateRecord = {
this.stateRecord_ = {
initial: {
request: 'offlineCheck',
},
Expand Down Expand Up @@ -57,7 +57,7 @@ export abstract class AlwatrServerContextBase<
},
};

this._actionRecord = {
this.actionRecord_ = {
_on_offlineCheck_enter: this._$offlineRequestAction,
_on_loading_enter: this._$onlineRequestAction,
_on_reloading_enter: this._$onlineRequestAction,
Expand All @@ -66,24 +66,24 @@ export abstract class AlwatrServerContextBase<
}

protected _$offlineRequestAction(): void {
this._logger.logMethod?.('_$offlineRequestAction');
this._$fetchOptions!.cacheStrategy === 'cache_only';
this._$requestAction();
this.logger_.logMethod?.('_$offlineRequestAction');
this.fetchOptions__!.cacheStrategy === 'cache_only';
this.requestAction__();
}

protected _$onlineRequestAction(): void {
this._logger.logMethod?.('_$onlineRequestAction');
this._$fetchOptions!.cacheStrategy === 'update_cache';
this._$requestAction();
this.logger_.logMethod?.('_$onlineRequestAction');
this.fetchOptions__!.cacheStrategy === 'update_cache';
this.requestAction__();
}

protected _$updateContextAction(): void {
if (this._responseJson === undefined) {
this._logger.accident('_$updateContextAction', 'no_response_json');
this.logger_.accident('_$updateContextAction', 'no_response_json');
return;
}

this._logger.logMethod?.('_$updateContextAction');
this.logger_.logMethod?.('_$updateContextAction');

if (
this._context === undefined ||
Expand All @@ -96,15 +96,15 @@ export abstract class AlwatrServerContextBase<
this._cleanup();
}

protected override async _$requestAction(): Promise<void> {
this._logger.logMethod?.('_$requestAction');
protected override async requestAction__(): Promise<void> {
this.logger_.logMethod?.('_$requestAction');

try {
if (this._$fetchOptions === undefined) {
if (this.fetchOptions__ === undefined) {
throw new Error('invalid_fetch_options');
}

await this._$fetch(this._$fetchOptions);
await this.fetch__(this.fetchOptions__);

this._transition('requestSuccess');
}
Expand All @@ -113,14 +113,14 @@ export abstract class AlwatrServerContextBase<
this._transition('cacheNotFound');
}
else {
this._logger.error('_$requestAction', 'fetch_failed', err);
this.logger_.error('_$requestAction', 'fetch_failed', err);
this._transition('requestFailed');
}
}
}

protected _cleanup(): void {
delete this._response;
delete this.response_;
delete this._responseJson;
}
}
Expand All @@ -140,6 +140,6 @@ export class AlwatrServerContext<
}

request(options?: Partial<FetchOptions>): void {
return this._request(options);
return this.request_(options);
}
}
82 changes: 42 additions & 40 deletions packages/server-context/src/server-request.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {fetch} from '@alwatr/fetch';
import {ActionRecord, FiniteStateMachineBase, StateRecord} from '@alwatr/fsm';
import {fetch, type FetchOptions} from '@alwatr/fetch';
import {FiniteStateMachineBase, type StateRecord, type ActionRecord} from '@alwatr/fsm';
import {definePackage} from '@alwatr/logger';

import type {FetchOptions} from '@alwatr/fetch';
import type {} from '@alwatr/nano-build';

definePackage('@alwatr/signal', __package_version__);
Expand All @@ -18,10 +17,10 @@ export abstract class AlwatrServerRequestBase<
ExtraState extends string = never,
ExtraEvent extends string = never,
> extends FiniteStateMachineBase<ServerRequestState | ExtraState, ServerRequestEvent | ExtraEvent> {
protected _$fetchOptions?: FetchOptions;
protected _response?: Response;
protected fetchOptions__?: FetchOptions;
protected response_?: Response;

protected override _stateRecord = {
protected override stateRecord_ = {
initial: {
request: 'loading',
},
Expand All @@ -37,69 +36,69 @@ export abstract class AlwatrServerRequestBase<
},
} as StateRecord<ServerRequestState | ExtraState, ServerRequestEvent | ExtraEvent>;

protected override _actionRecord = {
_on_loading_enter: this._$requestAction,
protected override actionRecord_ = {
_on_loading_enter: this.requestAction__,
} as ActionRecord<ServerRequestState | ExtraState, ServerRequestEvent | ExtraEvent>;

constructor(protected _config: ServerRequestConfig) {
super({name: _config.name, initialState: 'initial'});
constructor(protected config_: ServerRequestConfig) {
super({name: config_.name, initialState: 'initial'});
}

protected _request(options?: Partial<FetchOptions>): void {
this._logger.logMethodArgs?.('_request', options);
this._setOptions(options);
this._transition('request');
protected request_(options?: Partial<FetchOptions>): void {
this.logger_.logMethodArgs?.('request_', options);
this.setOptions_(options);
this.transition_('request');
}

protected async _$fetch(options: FetchOptions): Promise<void> {
this._logger.logMethodArgs?.('_$fetch', options);
this._response = await fetch(options);
protected async fetch__(options: FetchOptions): Promise<void> {
this.logger_.logMethodArgs?.('fetch__', options);
this.response_ = await fetch(options);

if (!this._response.ok) {
if (!this.response_.ok) {
throw new Error('fetch_nok');
}
}

protected async _$requestAction(): Promise<void> {
this._logger.logMethod?.('_$requestAction');
protected async requestAction__(): Promise<void> {
this.logger_.logMethod?.('requestAction__');

try {
if (this._$fetchOptions === undefined) {
if (this.fetchOptions__ === undefined) {
throw new Error('invalid_fetch_options');
}

await this._$fetch(this._$fetchOptions);
await this.fetch__(this.fetchOptions__);

this._transition('requestSuccess');
this.transition_('requestSuccess');
}
catch (err) {
this._logger.error('_$requestAction', 'fetch_failed', err);
this._transition('requestFailed');
this.logger_.error('requestAction__', 'fetch_failed', err);
this.transition_('requestFailed');
}
}

protected _setOptions(options?: Partial<FetchOptions>): void {
this._logger.logMethodArgs?.('_setOptions', {options});
protected setOptions_(options?: Partial<FetchOptions>): void {
this.logger_.logMethodArgs?.('setOptions_', {options});

const fetchOptions = {
...this._config,
...this.config_,
...options,
queryParameters: {
...this._config.queryParameters,
...options?.queryParameters,
queryParams: {
...this.config_.queryParams,
...options?.queryParams,
},
};

if (fetchOptions.url == null) {
throw new Error('invalid_fetch_options');
}

this._$fetchOptions = fetchOptions as FetchOptions;
this.fetchOptions__ = fetchOptions as FetchOptions;
}

protected override _reset(): void {
super._reset();
delete this._response;
protected override resetToInitialState_(): void {
super.resetToInitialState_();
delete this.response_;
}
}

Expand All @@ -108,18 +107,21 @@ export class AlwatrServerRequest extends AlwatrServerRequestBase {
* Current state.
*/
get state(): ServerRequestState {
return this._state;
return this.message_.state;
}

get response(): Response | undefined {
return this._response;
return this.response_;
}

request(options?: Partial<FetchOptions>): void {
return this._request(options);
return this.request_(options);
}

cleanup(): void {
this._reset();
/**
* Reset the machine to its initial state without notifying, and clean up existing response and state.
*/
reset(): void {
this.resetToInitialState_();
}
}
4 changes: 2 additions & 2 deletions packages/signal/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class AlwatrContext<T extends Dictionary> extends AlwatrObservable<T> {
* Return undefined if context not set before or expired.
*/
getValue(): T | undefined {
return this.data_;
return this.message_;
}

/**
Expand All @@ -34,7 +34,7 @@ export class AlwatrContext<T extends Dictionary> extends AlwatrObservable<T> {
* `receivePrevious` in new subscribers not work until new context changes.
*/
expire(): void {
super.clearData_();
super.clearMessage_();
}

/**
Expand Down
Loading
Loading