Skip to content

Commit

Permalink
Migrate to @seedcompany/common. Less lodash (#1490)
Browse files Browse the repository at this point in the history
  • Loading branch information
CarsonF authored Oct 31, 2023
1 parent e72c17c commit fbf94ad
Show file tree
Hide file tree
Showing 70 changed files with 287 additions and 345 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"@react-editor-js/client": "^2.1.0",
"@react-editor-js/core": "^2.1.0",
"@react-editor-js/server": "^2.1.0",
"@seedcompany/common": ">=0.13 <1",
"ahooks": "^3.7.8",
"body-parser": "^1.20.2",
"compression": "^1.7.4",
Expand Down
5 changes: 4 additions & 1 deletion razzle.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ const modifyWebpackOptions = ({
cache: path.resolve(__dirname, 'cache/terser-webpack-plugin'),
};

// Run editorjs through babel, since the current loader doesn't understand the newer syntax.
// Run these through babel, since the current loader doesn't understand the newer syntax.
options.babelRule.include.push(
require.resolve('@seedcompany/common').replace('.cjs', '.js'),
require.resolve('@editorjs/editorjs').replace('.umd.js', '.mjs')
);

Expand All @@ -36,6 +37,8 @@ const modifyWebpackConfig = (opts) => {

config.resolve.plugins.push(new TsconfigPathsPlugin());

config.resolve.alias['@seedcompany/common'] = '@seedcompany/common/index.js';

const define = (key, value) => {
opts.options.webpackOptions.definePluginOptions[key] = value;
};
Expand Down
16 changes: 9 additions & 7 deletions src/api/caching/invalidate-props.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ApolloCache, MutationUpdaterFunction } from '@apollo/client';
import { compact, Many } from 'lodash';
import { mapFromList, Nullable } from '~/common';
import { Modifier } from '@apollo/client/cache';
import { isNotFalsy, Many, mapValues, Nil } from '@seedcompany/common';
import { GqlObject, GqlTypeOf } from '../schema';

type PropKeys<OwningObj extends GqlObject> = ReadonlyArray<
Many<Nullable<keyof GqlTypeOf<OwningObj> & string>>
Many<(keyof GqlTypeOf<OwningObj> & string) | Nil>
>;

/**
Expand All @@ -28,13 +28,15 @@ export const invalidateProps = <OwningObj extends GqlObject>(

cache.modify({
id,
fields: mapFromList(compact(fields.flat()), (field) => [
field,
(_, { DELETE }) => DELETE,
]),
fields: mapValues.fromList(
fields.flat().filter(isNotFalsy),
() => deleteField
).asRecord,
});
};

const deleteField: Modifier<any> = (_, { DELETE }) => DELETE;

/**
* A variant of {@link invalidateProps} that can be given directly to a
* mutation's cache function.
Expand Down
20 changes: 12 additions & 8 deletions src/api/caching/lists/addItemToList.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { ApolloCache, MutationUpdaterFunction } from '@apollo/client';
import { orderBy } from 'lodash';
import {
ApolloCache,
MutationUpdaterFunction,
Reference,
} from '@apollo/client';
import { sortBy } from '@seedcompany/common';
import { Except } from 'type-fest';
import { unwrapSecured } from '~/common';
import { modifyChangesetDiff } from '../../changesets';
Expand Down Expand Up @@ -81,7 +85,7 @@ export const addItemToList =
return;
}

let newList = [...existing.items, newItemRef];
let newList: readonly Reference[] = [...existing.items, newItemRef];

// Sort the new item appropriately given the list's sort/order params
const args = argsFromStoreFieldName(storeFieldName);
Expand All @@ -90,15 +94,15 @@ export const addItemToList =
defaultSortingForList(listId)
);
if (sort && order) {
newList = orderBy(
newList,
newList = sortBy(newList, [
(ref) => {
const field = readField(sort, ref);
const fieldVal = unwrapSecured(field);
return fieldVal;
// Unsafely assume this value is sortable
return fieldVal as any;
},
order.toLowerCase() as Lowercase<Order>
);
order.toLowerCase() as Lowercase<Order>,
]);
}

return {
Expand Down
12 changes: 6 additions & 6 deletions src/api/caching/lists/modifyList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ import { ApolloCache, isReference, TypePolicies } from '@apollo/client';
import type { Reference } from '@apollo/client';
import { Modifier } from '@apollo/client/cache/core/types/common';
import type { EntityStore } from '@apollo/client/cache/inmemory/entityStore';
import { mapValues, Nil } from '@seedcompany/common';
import type { ConditionalKeys } from 'type-fest';
import { keys, mapFromList, Nullable } from '~/common';
import type { Entity, GqlTypeOf } from '../../schema';
import type { Query } from '../../schema/schema.graphql';
import { typePolicies } from '../../schema/typePolicies';
import { PaginatedListOutput, SortableListInput } from './types';

// Only the keys of T that represent list fields.
type ListFieldKeys<T> = ConditionalKeys<T, Nullable<PaginatedListOutput<any>>>;
type ListFieldKeys<T> = ConditionalKeys<T, PaginatedListOutput<any> | Nil>;

type ObjectWithField<Obj extends Entity> =
| [existingObject: Nullable<Obj>, field: ListFieldKeys<GqlTypeOf<Obj>>]
| [existingObject: Obj | Nil, field: ListFieldKeys<GqlTypeOf<Obj>>]
| [ref: Reference, field: string];

export type ListIdentifier<OwningObj extends Entity> =
| ListFieldKeys<Query>
| ObjectWithField<OwningObj>;

export type ListModifier = Modifier<Nullable<PaginatedListOutput<Reference>>>;
export type ListModifier = Modifier<PaginatedListOutput<Reference> | Nil>;

export interface ModifyListOptions<OwningObj extends Entity, Args> {
cache: ApolloCache<unknown>;
Expand All @@ -47,7 +47,7 @@ export const modifyList = <OwningObj extends Entity, Args>({
// @ts-expect-error assuming in memory cache with entity store
const store: EntityStore | null = cache.data;
const obj = store?.toObject()[id ?? 'ROOT_QUERY'] ?? {};
const listVariations = keys(obj)
const listVariations = Object.keys(obj)
.filter(
(query) =>
query === field ||
Expand All @@ -71,7 +71,7 @@ export const modifyList = <OwningObj extends Entity, Args>({
}
});

const fields = mapFromList(listVariations, (field) => [field, modifier]);
const fields = mapValues.fromList(listVariations, () => modifier).asRecord;
cache.modify({
...(id ? { id } : {}),
fields,
Expand Down
4 changes: 2 additions & 2 deletions src/api/changesets/changesetAware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Merge } from 'type-fest';
import { ChangesetIdFragment, has, IdFragment } from '~/common';
import { ChangesetIdFragment, IdFragment } from '~/common';

export const hasChangeset = (
data: IdFragment
Expand All @@ -9,7 +9,7 @@ export const hasChangeset = (
ChangesetIdFragment,
{ changeset: NonNullable<ChangesetIdFragment['changeset']> }
>
> => has('changeset', data) && !!data.changeset;
> => 'changeset' in data && !!data.changeset;

export const getChangeset = (data: IdFragment) =>
hasChangeset(data) ? data.changeset : undefined;
3 changes: 2 additions & 1 deletion src/api/client/ImpersonationContext.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Many, many } from '@seedcompany/common';
import { useLatest } from 'ahooks';
import Cookies from 'js-cookie';
import { noop, pickBy } from 'lodash';
Expand All @@ -8,7 +9,7 @@ import {
useMemo,
useState,
} from 'react';
import { ChildrenProp, Many, many } from '~/common';
import { ChildrenProp } from '~/common';
import { Role } from '../schema/schema.graphql';

export interface Impersonation {
Expand Down
4 changes: 2 additions & 2 deletions src/api/client/links/delay.link.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fromPromise, RequestHandler } from '@apollo/client';
import { sleep } from '~/common';
import { delay } from '@seedcompany/common';
import { GQLOperations } from '../../operationsList';

let API_DEBUG = {
Expand Down Expand Up @@ -33,5 +33,5 @@ export const delayLink: RequestHandler = (operation, forward) => {
) {
return forward(operation);
}
return fromPromise(sleep(currentDelay)).flatMap(() => forward(operation));
return fromPromise(delay(currentDelay)).flatMap(() => forward(operation));
};
8 changes: 5 additions & 3 deletions src/api/errorHandling/form-error-handling.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isNotFalsy, mapValues } from '@seedcompany/common';
import { FORM_ERROR, FormApi, setIn, SubmissionErrors } from 'final-form';
import { identity, mapValues } from 'lodash';
import { Promisable } from 'type-fest';
import { ErrorMap, getErrorInfo, ValidationError } from './error.types';

Expand Down Expand Up @@ -68,7 +68,9 @@ const expandDotNotation = (input: Record<string, any>) =>

// We'll just use the first human error string for each field
export const renderValidationErrors = (e: ValidationError) =>
expandDotNotation(mapValues(e.errors, (er) => Object.values(er)[0]));
expandDotNotation(
mapValues(e.errors, (_, er) => Object.values(er)[0]).asRecord
);

/**
* These are the default handlers which are used as fallbacks
Expand Down Expand Up @@ -109,7 +111,7 @@ export const handleFormError = async <T, P>(
// get handler for each code
.map((c) => mergedHandlers[c])
// remove unhandled codes
.filter(identity)
.filter(isNotFalsy)
// normalize handlers to a standard function shape
.map((h) => resolveHandler(h, utils))
// In order to build the next function for each handler we need to start
Expand Down
3 changes: 2 additions & 1 deletion src/api/schema/enumLists/enumLists.codegen.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { sortBy } from '@seedcompany/common';
import { GraphQLEnumType, GraphQLEnumValue } from 'graphql';
import { lowerCase, sortBy } from 'lodash';
import { lowerCase } from 'lodash';
import { titleCase } from 'title-case';
import {
addExportedConst,
Expand Down
3 changes: 2 additions & 1 deletion src/api/schema/typeMap/typeMap.codegen.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { sortBy } from '@seedcompany/common';
import { GraphQLNamedType, isAbstractType, isObjectType } from 'graphql';
import { difference, sortBy } from 'lodash';
import { difference } from 'lodash';
import { OptionalKind, PropertySignatureStructure } from 'ts-morph';
import { getSchemaTypes } from '../codeGenUtil/gql.util';
import { tsMorphPlugin } from '../codeGenUtil/ts.util';
Expand Down
20 changes: 9 additions & 11 deletions src/api/schema/typePolicies/lists/page-limit-pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import {
FieldPolicy,
KeySpecifier,
} from '@apollo/client/cache/inmemory/policies';
import { sortBy } from '@seedcompany/common';
import {
isObject,
last,
orderBy,
sortedIndexBy,
sortedLastIndexBy,
uniqBy,
Expand Down Expand Up @@ -143,7 +141,8 @@ const mergeList = (
return (fieldVal as VariantFragment).key;
}

return fieldVal;
// Unsafely assume this value is sortable
return fieldVal as any;
};

let items: readonly Reference[];
Expand Down Expand Up @@ -172,11 +171,10 @@ const mergeList = (
if (sort && order && uniqueItems.length !== items.length) {
// If we found duplicates, re-sort the list, because I'm not certain
// we removed the right one(s).
items = orderBy(
uniqueItems,
items = sortBy(uniqueItems, [
readSecuredField(sort),
order.toLowerCase() as Lowercase<Order>
);
order.toLowerCase() as Lowercase<Order>,
]);
} else {
items = uniqueItems;
}
Expand All @@ -195,7 +193,7 @@ const spliceAscLists = <T>(
// such as the same name or created time.
const firstIdx = sortedLastIndexBy(existing, incoming[0]!, iteratee);
// splice ending point is the first occurrence
const lastIdx = sortedIndexBy(existing, last(incoming)!, iteratee);
const lastIdx = sortedIndexBy(existing, incoming.at(-1)!, iteratee);
// start adding incoming after firstIdx,
// remove any items between firstIdx and lastIdx (if <= 0 this is skipped),
// finish incoming, and continue on with rest of existing list.
Expand Down Expand Up @@ -232,15 +230,15 @@ const objectToKeyArgsRecurse = (obj: Record<string, any>): KeySpecifier =>
(keyArgs: KeySpecifier, [key, val]) => [
...keyArgs,
key,
...(isObject(val) ? [objectToKeyArgsRecurse(val)] : []),
...(val && typeof val === 'object' ? [objectToKeyArgsRecurse(val)] : []),
],
[]
);

const cleanEmptyObjects = (obj: Record<string, any>): Record<string, any> => {
const res: Record<string, any> = {};
for (const [key, value] of Object.entries(obj)) {
if (!isObject(value)) {
if (!(value && typeof value === 'object')) {
res[key] = value;
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions src/common/approach.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
PlayCircleFilled,
Translate,
} from '@mui/icons-material';
import { entries, mapValues } from '@seedcompany/common';
import { ReactNode } from 'react';
import { ProductApproach, ProductMethodology } from '~/api/schema.graphql';
import { entries, mapFromList } from './array-helpers';

export const ApproachMethodologies: Record<
ProductApproach,
Expand All @@ -32,7 +32,7 @@ export const ApproachMethodologies: Record<
export const MethodologyToApproach = entries(ApproachMethodologies).reduce(
(map, [approach, methodologies]) => ({
...map,
...mapFromList(methodologies, (methodology) => [methodology, approach]),
...mapValues.fromList(methodologies, () => approach).asRecord,
}),
{}
) as Record<ProductMethodology, ProductApproach>;
Expand Down
Loading

0 comments on commit fbf94ad

Please sign in to comment.