Skip to content

Commit

Permalink
28 (#30)
Browse files Browse the repository at this point in the history
 added: analyze graph fns
  • Loading branch information
binjospookie authored Nov 25, 2024
1 parent 72f8155 commit 7d00e2a
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 10 deletions.
2 changes: 1 addition & 1 deletion .size-limit.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{ "path": "dist/index.js", "limit": "2.1 kB" }]
[{ "path": "dist/index.js", "limit": "2.3 kB" }]
19 changes: 19 additions & 0 deletions src/compose/graph/__tests__/dependsOn.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { randomUUID } from 'node:crypto';
import { graphFn } from '..';
import { createContainer, type AnyContainer } from '../../../createContainer';

const start = () => ({ api: null });

const a = createContainer({ id: randomUUID(), domain: randomUUID(), start });

{
const { dependsOn } = graphFn([a], { view: 'containers' });

expectTypeOf<Parameters<typeof dependsOn>[0]>().toEqualTypeOf<AnyContainer[]>();
}

{
const { dependsOn } = graphFn([a], { view: 'domains' });

expectTypeOf<Parameters<typeof dependsOn>[0]>().toEqualTypeOf<AnyContainer['domain'][]>();
}
22 changes: 22 additions & 0 deletions src/compose/graph/__tests__/dependsOn.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { randomUUID } from 'node:crypto';
import { graphFn } from '..';
import { createContainer } from '../../../createContainer';

const start = () => ({ api: null });

const a = createContainer({ id: randomUUID(), domain: randomUUID(), start });
const b = createContainer({ id: randomUUID(), domain: a.domain, dependsOn: [a], start });
const c = createContainer({ id: randomUUID(), domain: randomUUID(), dependsOn: [b], start });
const d = createContainer({ id: randomUUID(), domain: randomUUID(), optionalDependsOn: [c], start });

test('dependsOn | containers', () => {
const { dependsOn } = graphFn([a, b, c, d], { view: 'containers' });

expect(Object.keys(dependsOn([c, d]))).toStrictEqual([c.id, d.id]);
});

test('dependsOn | domains', () => {
const { dependsOn } = graphFn([a, b, c, d], { view: 'domains' });

expect(Object.keys(dependsOn([c.domain, d.domain]))).toStrictEqual([c.domain, d.domain]);
});
19 changes: 19 additions & 0 deletions src/compose/graph/__tests__/requiredBy.spec-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { randomUUID } from 'node:crypto';
import { graphFn } from '..';
import { createContainer, type AnyContainer } from '../../../createContainer';

const start = () => ({ api: null });

const a = createContainer({ id: randomUUID(), domain: randomUUID(), start });

{
const { requiredBy } = graphFn([a], { view: 'containers' });

expectTypeOf<Parameters<typeof requiredBy>[0]>().toEqualTypeOf<AnyContainer[]>();
}

{
const { requiredBy } = graphFn([a], { view: 'domains' });

expectTypeOf<Parameters<typeof requiredBy>[0]>().toEqualTypeOf<AnyContainer['domain'][]>();
}
22 changes: 22 additions & 0 deletions src/compose/graph/__tests__/requiredBy.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { randomUUID } from 'node:crypto';
import { graphFn } from '..';
import { createContainer } from '../../../createContainer';

const start = () => ({ api: null });

const a = createContainer({ id: randomUUID(), domain: randomUUID(), start });
const b = createContainer({ id: randomUUID(), domain: a.domain, dependsOn: [a], start });
const c = createContainer({ id: randomUUID(), domain: randomUUID(), dependsOn: [b], start });
const d = createContainer({ id: randomUUID(), domain: randomUUID(), optionalDependsOn: [c], start });

test('requiredBy | containers', () => {
const { requiredBy } = graphFn([a, b, c, d], { view: 'containers' });

expect(Object.keys(requiredBy([a, b]))).toStrictEqual([b.id, c.id, d.id]);
});

test('requiredBy | domains', () => {
const { requiredBy } = graphFn([a, b, c, d], { view: 'domains' });

expect(Object.keys(requiredBy([a.domain, b.domain]))).toStrictEqual([c.domain, d.domain]);
});
31 changes: 31 additions & 0 deletions src/compose/graph/dependsOn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { AnyContainer } from '../../createContainer';
import type { ContainerDomain, ContainersGraph, DomainsGraph } from './types';

type PickResult<T, K extends keyof T> = {
[P in K]: T[P];
};

const pick = <T extends object, K extends keyof T>(obj: T, keys: K[]): PickResult<T, K> => {
const result = {} as PickResult<T, K>;
for (const key of keys) {
if (key in obj) {
result[key] = obj[key];
}
}
return result;
};

const createDependsOn =
<T extends ContainersGraph | DomainsGraph>(graph: T) =>
(list: T extends ContainersGraph ? AnyContainer[] : ContainerDomain[]) => {
if (typeof list[0] === 'string') {
return pick(graph, list as ContainerDomain[]);
}

return pick(
graph,
(list as AnyContainer[]).map((item) => item.id),
);
};

export { createDependsOn };
1 change: 0 additions & 1 deletion src/compose/graph/getDomainsView.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { AnyContainer } from '../../createContainer';
import type { ContainersGraph, DomainsGraph } from './types';

const getDomainsView = (graph: ContainersGraph) =>
Expand Down
34 changes: 27 additions & 7 deletions src/compose/graph/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
import { type AnyContainer } from '../../createContainer';
import { getContainersGraph } from '../getContainersGraph';
import type { ContainerId } from '../up';
import { createDependsOn } from './dependsOn';
import { getDomainsView } from './getDomainsView';
import { getTransitiveDependencies } from './getTransitiveDependencies';
import { createRequiredBy } from './requiredBy';
import type { ContainersGraph, DomainsGraph } from './types';

type Skipped = Record<ContainerId, ContainerId[]>;
type View = 'domains' | 'containers';

type Result<T extends View = 'containers'> = T extends 'domains'
? { data: DomainsGraph; skippedContainers: Skipped }
: { data: ContainersGraph; skippedContainers: Skipped };
? {
data: DomainsGraph;
skippedContainers: Skipped;
dependsOn: (_: AnyContainer['domain'][]) => DomainsGraph;
requiredBy: (_: AnyContainer['domain'][]) => DomainsGraph;
}
: {
data: ContainersGraph;
skippedContainers: Skipped;
dependsOn: (_: AnyContainer[]) => ContainersGraph;
requiredBy: (_: AnyContainer[]) => ContainersGraph;
};

const graphFn = <T extends View = 'containers'>(__containers: AnyContainer[], config?: { view?: T }): Result<T> => {
const graph = getContainersGraph(__containers);
Expand All @@ -37,20 +49,28 @@ const graphFn = <T extends View = 'containers'>(__containers: AnyContainer[], co
return acc;
}, {});

const dataParsed = view === 'domains' ? getDomainsView(data) : data;
const dependsOn = createDependsOn(dataParsed);
const requiredBy = createRequiredBy(dataParsed);

// @ts-expect-error wtf
return view === 'domains'
? { data: getDomainsView(data), skippedContainers: graph.skippedContainers }
: { data, skippedContainers: graph.skippedContainers };
return {
data: dataParsed,
skippedContainers: graph.skippedContainers,
dependsOn,
requiredBy,
};
};

// const start = () => ({ api: null });
// const a = createContainer({ id: 'a', domain: 'domainA', start });
// console.log(a.domain)
// const b = createContainer({ id: 'b', domain: a.domain, start });
// const c = createContainer({ id: 'c', domain: 'domainC', dependsOn: [b], start });
// const d = createContainer({ id: 'd', domain: 'domainD', optionalDependsOn: [c], start });
// const e = createContainer({ id: 'e', domain: 'domainE', dependsOn: [c], start });

// console.log(JSON.stringify(graphFn([a, b, c, d, e], { view: 'domains' }).data, undefined, 2));
// const { requiredBy, data } = graphFn([a, b, c, d, e], { view: 'domains' });

// console.log(JSON.stringify(requiredBy([a.domain]), undefined, 2));

export { graphFn };
37 changes: 37 additions & 0 deletions src/compose/graph/requiredBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import type { AnyContainer } from '../../createContainer';
import type { ContainerDomain, ContainersGraph, DomainsGraph } from './types';

const createRequiredBy =
<T extends ContainersGraph | DomainsGraph>(graph: T) =>
(list: T extends ContainersGraph ? AnyContainer[] : ContainerDomain[]) => {
const keys =
typeof list[0] === 'string' ? (list as ContainerDomain[]) : (list as AnyContainer[]).map((item) => item.id);

const entries = Object.entries(graph) as [keyof typeof graph, (typeof graph)[keyof typeof graph]][];

const result = {};

for (const [key, val] of entries) {
const strict = val.strict.filter((x) => keys.includes(x));
const optional = val.optional.filter((x) => keys.includes(x));
const transitiveStrict = val.transitive.strict.filter((x) => keys.includes(x.id));
const transitiveOptional = val.transitive.optional.filter((x) => keys.includes(x.id));

if (strict.length || optional.length || transitiveStrict.length || transitiveOptional.length) {
// @ts-expect-error :c
result[key] = {
...('domain' in val ? { domain: val.domain } : { containers: val.containers }),
strict,
optional,
transitive: {
strict: transitiveStrict,
optional: transitiveOptional,
},
};
}
}

return result as T;
};

export { createRequiredBy };
2 changes: 1 addition & 1 deletion src/compose/graph/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ type DomainsGraph = Record<
}
>;

export type { ContainersGraph, DomainsGraph, TransitiveDependency };
export type { ContainerDomain, ContainersGraph, DomainsGraph, TransitiveDependency };

0 comments on commit 7d00e2a

Please sign in to comment.