Skip to content

Commit

Permalink
removed: useless type
Browse files Browse the repository at this point in the history
  • Loading branch information
Viktor Pasynok committed Nov 3, 2024
1 parent 8e6d984 commit c9b6f30
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 46 deletions.
28 changes: 0 additions & 28 deletions draft.ts

This file was deleted.

81 changes: 73 additions & 8 deletions src/compose/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,83 @@
import { combine, createEffect, createStore, launch, sample, type Store } from 'effector';
import { type AnyContainer } from '../createContainer';
import type { Status } from '../createContainer/types';

// todo: compose fn to wrap em all | like basic compose fn + passing api (no need to save em all. just reverse pipe)
// todo: clearNode $strictDepsResolvingStatus after start
// compose.up -> wait for all deps -> check enable -> set status -> start if pending
const validateContainerId = (id: string, set: Set<string>) => {
if (set.has(id)) {
throw new Error(`Duplicate container ID found: ${id}`);
}
set.add(id);
};

const READY_DEPS_LIST = [createStore<Status>('done')];

// todo: tons of tests
// todo: simplify if (x.some((s) => s === 'off')) return 'off';
// todo: clearNode extra stores and variables on container fail|off|done, and on all up
const upFn = (containers: AnyContainer[]) => {
const CONTAINER_IDS = new Set();
const CONTAINER_IDS = new Set<string>();

for (const container of containers) {
if (CONTAINER_IDS.has(container.id)) {
throw new Error(`Duplicate container ID found: ${container.id}`);
}
CONTAINER_IDS.add(container.id);
validateContainerId(container.id, CONTAINER_IDS);
}

let apis: Record<string, Awaited<ReturnType<AnyContainer['start']>>['api']> = {};

for (const container of containers) {
const $strictDepsResolvingStatus: Store<Status> = combine(
container.dependsOn ? container.dependsOn.map((d) => d.$status) : READY_DEPS_LIST,
(x) => {
if (x.some((s) => s === 'off')) return 'off';
if (x.some((s) => s === 'fail')) return 'fail';
if (x.some((s) => s === 'pending')) return 'pending';

if (x.every((s) => s === 'done')) return 'done';

return 'idle';
},
);
const $optionalDepsResolvingStatus: Store<Status> = combine(
container.optionalDependsOn ? container.optionalDependsOn.map((d) => d.$status) : READY_DEPS_LIST,
(x) => {
if (x.some((s) => s === 'pending')) return 'pending';
if (x.some((s) => s === 'idle')) return 'idle';

return 'done';
},
);
const $depsReady = combine([$strictDepsResolvingStatus, $optionalDepsResolvingStatus], (s) =>
s.every((x) => x === 'done'),
);

const startFx = createEffect(async () => {
apis[container.id] = (await container.start(apis, apis))['api'];
});

sample({ clock: startFx.finally, fn: (x) => x.status, target: container.$status });
sample({ clock: container.$status, filter: (x) => x === 'pending', target: startFx });

$strictDepsResolvingStatus.watch((s) => {
if (['off', 'fail'].includes(s)) {
launch(container.$status, s);
}
});

$depsReady.watch(async (x) => {
if (x) {
try {
const isEnabled = container.enable ? await container.enable(apis, apis) : true;

launch(container.$status, isEnabled ? 'pending' : 'off');
} catch {
launch(container.$status, 'fail');
}
}
});

// fixme: container.$status.watch(off | fail) -> clear stores (clearNode)
}

// after start
};

const compose = { up: upFn };
Expand Down
4 changes: 2 additions & 2 deletions src/createContainer/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { createStore } from 'effector';
import type { AnyAPI, AnyContainer, AnyDeps, AnyStartFn, Container, EnableResult, StartResult, Status } from './types';
import type { AnyAPI, AnyContainer, AnyDeps, EnableResult, StartResult, Status } from './types';
import { type ContainerIdEmptyStringError, validate } from './validate';

type ExtractDeps<D extends Container<string, AnyStartFn>[]> = {
type ExtractDeps<D extends AnyContainer[]> = {
[K in D[number] as Awaited<ReturnType<K['start']>>['api'] extends Record<string, never> ? never : K['id']]: Awaited<
ReturnType<K['start']>
>['api'];
Expand Down
16 changes: 8 additions & 8 deletions src/createContainer/types.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { type Store } from 'effector';
import { type StoreWritable } from 'effector';

type NonEmptyTuple<T = unknown> = [T, ...T[]];
type AnyObject = Record<string, unknown>;

type Status = 'idle' | 'pending' | 'done' | 'fail' | 'off';
type AnyAPI = AnyObject | null;
type StartResult<T> = Promise<{ api: T }> | { api: T };
type AnyStartFn = (...x: any) => StartResult<any>;
type AnyStartFn = (...x: any) => StartResult<AnyAPI>;
type EnableResult = Promise<boolean> | boolean;

type Container<Id extends string, StartFn extends AnyStartFn> = {
id: Id;
$status: Store<Status>;
start: StartFn;
type AnyContainer = {
id: string;
$status: StoreWritable<Status>;
start: AnyStartFn;
dependsOn?: AnyContainer[];
optionalDependsOn?: AnyContainer[];
enable?: (..._: any) => EnableResult;
};
type AnyContainer = Container<string, AnyStartFn>;

type AnyDeps = NonEmptyTuple<AnyContainer> | void;

export type { AnyAPI, AnyContainer, AnyDeps, AnyStartFn, Container, EnableResult, StartResult, Status };
export type { AnyAPI, AnyContainer, AnyDeps, AnyStartFn, EnableResult, StartResult, Status };

0 comments on commit c9b6f30

Please sign in to comment.