Skip to content

Commit 859a9e1

Browse files
committed
Merge branch 'develop'
2 parents 4dd6962 + 674d7f4 commit 859a9e1

File tree

96 files changed

+584
-512
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+584
-512
lines changed

.eslintrc.cjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ const namingConvention = [
124124
format: ['camelCase'],
125125
leadingUnderscore: 'allow',
126126
},
127+
{
128+
selector: 'parameter',
129+
modifiers: ['destructured'],
130+
format: ['camelCase', 'UPPER_CASE'],
131+
},
127132
];
128133

129134
/** @type {import('@typescript-eslint/utils').TSESLint.Linter.Config} */

docker-compose.yml

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,5 @@
11
version: '3.7'
22
services:
3-
api:
4-
# Use dev target locally since there's no need to save space and contains everything
5-
image: cord-api-v3:dev
6-
build:
7-
context: .
8-
target: dev
9-
command: yarn start:prod
10-
ports:
11-
- 3000:80
12-
networks:
13-
- cord
14-
depends_on:
15-
- db
16-
- pg
17-
environment:
18-
NEO4J_URL: bolt://db:7687
19-
NEO4J_USERNAME: neo4j
20-
NEO4J_PASSWORD: admin
21-
223
db:
234
image: neo4j:5.10-enterprise
245
ports:
@@ -34,29 +15,5 @@ services:
3415
NEO4J_dbms_security_auth__enabled: 'false'
3516
NEO4J_dbms_security_auth__minimum__password__length: 1
3617

37-
pg:
38-
image: postgres
39-
ports:
40-
- 5432:5432
41-
networks:
42-
- cord
43-
environment:
44-
POSTGRES_USER: postgres
45-
POSTGRES_PASSWORD: postgres
46-
POSTGRES_DB: cord
47-
48-
pgadmin:
49-
image: dpage/pgadmin4
50-
restart: always
51-
networks:
52-
- cord
53-
environment:
54-
PGADMIN_DEFAULT_EMAIL: [email protected]
55-
PGADMIN_DEFAULT_PASSWORD: postgres
56-
ports:
57-
- '5050:80'
58-
depends_on:
59-
- pg
60-
6118
networks:
6219
cord:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"@nestjs/graphql": "^12.0.8",
4343
"@nestjs/platform-express": "^10.2.1",
4444
"@patarapolw/prettyprint": "^1.0.3",
45-
"@seedcompany/common": ">=0.11 <1",
45+
"@seedcompany/common": ">=0.13.1 <1",
4646
"@seedcompany/data-loader": "^0.5.4",
4747
"@seedcompany/nest": ">=0.1 <1",
4848
"@seedcompany/nestjs-email": "^3.3.2",

src/common/db-label.decorator.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { compact, uniq } from 'lodash';
1+
import { cleanSplit, isNotFalsy } from '@seedcompany/common';
2+
import { uniq } from 'lodash';
23

34
export const DbLabelSymbol = Symbol('DbLabelSymbol');
45

@@ -11,10 +12,11 @@ export const DbLabel =
1112
: Reflect.getMetadata(DbLabelSymbol, target)) ?? [];
1213

1314
const now = uniq(
14-
compact([
15+
[
1516
...prev,
16-
...labels.flatMap((l) => l?.split(':').map((s) => s.trim())),
17-
]),
17+
// Add labels split by `:`
18+
...labels.flatMap((l) => cleanSplit(l ?? '', ':')),
19+
].filter(isNotFalsy),
1820
);
1921

2022
key

src/common/exceptions/exception.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { has } from '../util';
2-
31
/**
42
* The base of all of our exceptions.
53
* Don't throw this, but rather a sub-class instead.
@@ -26,7 +24,7 @@ export class ClientException extends Exception {
2624
}
2725

2826
export const hasPrevious = (e: Error): e is Error & { previous: Error } =>
29-
has('previous', e) && e.previous instanceof Error;
27+
'previous' in e && e.previous instanceof Error;
3028

3129
export function getPreviousList(ex: Error, includeSelf: boolean) {
3230
const previous: Error[] = includeSelf ? [ex] : [];

src/common/generate-id.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ const alphabet =
77
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
88
const size = 11;
99

10-
export const generateId = customAlphabet(alphabet, size) as () => Promise<ID>;
10+
export const generateId: <TID extends ID = ID>() => Promise<TID> =
11+
customAlphabet(alphabet, size) as any;
1112

1213
export const isValidId = (value: unknown): value is ID => {
1314
if (typeof value !== 'string') {

src/common/mask-secrets.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
import { isPlainObject } from '@nestjs/common/utils/shared.utils.js';
2-
import { mapValues } from 'lodash';
2+
import { mapValues } from '@seedcompany/common';
33

44
export const maskSecrets = (
55
obj: Record<string, any>,
66
depth = 3,
77
): Record<string, any> =>
8-
mapValues(obj, (val, key) =>
8+
mapValues(obj, (key, val) =>
99
isSecret(key, val)
1010
? maskSecret(val)
1111
: isPlainObject(val) && depth > 0
1212
? maskSecrets(val, depth - 1)
1313
: val,
14-
);
14+
).asRecord;
1515

1616
export const dropSecrets = (
1717
obj: Record<string, any>,
1818
depth = 3,
1919
): Record<string, any> =>
20-
mapValues(obj, (val, key) =>
20+
mapValues(obj, (key, val) =>
2121
isSecret(key, val)
2222
? undefined
2323
: isPlainObject(val) && depth > 0
2424
? dropSecrets(val, depth - 1)
2525
: val,
26-
);
26+
).asRecord;
2727

2828
const isSecret = (key: string, val: unknown): val is string =>
2929
typeof val === 'string' && /(password|token|key)/i.test(key);

src/common/resource.dto.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Field, InterfaceType } from '@nestjs/graphql';
2-
import { cached, FnLike } from '@seedcompany/common';
2+
import { cached, FnLike, mapValues } from '@seedcompany/common';
33
import { LazyGetter as Once } from 'lazy-get-decorator';
44
import { DateTime } from 'luxon';
55
import { keys as keysOf } from 'ts-transformer-keys';
@@ -15,12 +15,11 @@ import { DateTimeField } from './luxon.graphql';
1515
import { getParentTypes } from './parent-types';
1616
import { MaybeSecured, SecuredProps } from './secured-property';
1717
import { AbstractClassType } from './types';
18-
import { has, mapFromList } from './util';
1918

2019
const hasTypename = (value: unknown): value is { __typename: string } =>
2120
value != null &&
2221
typeof value === 'object' &&
23-
has('__typename', value) &&
22+
'__typename' in value &&
2423
typeof value.__typename === 'string';
2524

2625
export const resolveByTypename =
@@ -245,11 +244,12 @@ export class EnhancedResource<T extends ResourceShape<any>> {
245244
return this.dbLabels[0];
246245
}
247246
@Once()
248-
get dbPropLabels() {
249-
return mapFromList(this.props, (prop) => {
250-
const labels = getDbPropertyLabels(this.type, prop);
251-
return [prop, labels];
252-
});
247+
get dbPropLabels(): {
248+
readonly [K in keyof T['prototype'] & string]?: readonly string[];
249+
} {
250+
return mapValues.fromList(this.props, (prop) =>
251+
getDbPropertyLabels(this.type, prop),
252+
).asRecord;
253253
}
254254
}
255255

@@ -265,7 +265,7 @@ export interface EnhancedRelation<TResourceStatic extends ResourceShape<any>> {
265265
export const isResourceClass = <T>(
266266
cls: AbstractClassType<T>,
267267
): cls is ResourceShape<T> =>
268-
has('Props', cls) && Array.isArray(cls.Props) && cls.Props.length > 0;
268+
'Props' in cls && Array.isArray(cls.Props) && cls.Props.length > 0;
269269

270270
export type MaybeUnsecuredInstance<TResourceStatic extends ResourceShape<any>> =
271271
MaybeSecured<InstanceType<TResourceStatic>>;

src/common/util.ts

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,3 @@
1-
import { compact } from 'lodash';
2-
3-
export const simpleSwitch = <T, K extends string = string>(
4-
key: K | null | undefined,
5-
options: Record<K, T>,
6-
): T | undefined => (key ? options[key] : undefined);
7-
8-
/** Converts list to map given a function that returns a [key, value] tuple. */
9-
export const mapFromList = <T, S = T, K extends string | number = string>(
10-
list: readonly T[] | ReadonlySet<T>,
11-
mapper: (item: T) => readonly [K, S] | null,
12-
): Record<K, S> => {
13-
const out: Partial<Record<K, S>> = {};
14-
list = list instanceof Set ? [...list] : (list as T[]);
15-
return list.reduce((acc, item) => {
16-
const res = mapper(item);
17-
if (!res) {
18-
return acc;
19-
}
20-
const [key, value] = res;
21-
acc[key] = value;
22-
return acc;
23-
}, out as Record<K, S>);
24-
};
25-
26-
/**
27-
* Just like Object.entries except keys are strict
28-
*/
29-
export const entries: <K extends string, V>(o: Record<K, V>) => Array<[K, V]> =
30-
Object.entries as any;
31-
32-
/**
33-
* Just like Object.keys except keys are strict
34-
*/
35-
export const keys: <K extends string>(o: Record<K, unknown>) => K[] =
36-
Object.keys as any;
37-
38-
export const iterate = <T>(
39-
iterator: Iterable<T> | IterableIterator<T>,
40-
): readonly T[] => {
41-
const res: T[] = [];
42-
for (const item of iterator) {
43-
res.push(item);
44-
}
45-
return res;
46-
};
47-
48-
/**
49-
* Work around `in` operator not narrowing type
50-
* https://github.com/microsoft/TypeScript/issues/21732
51-
*/
52-
export function has<K extends string | number | symbol, T>(
53-
key: K,
54-
obj: T,
55-
): obj is T & Record<K, unknown> {
56-
return key in (obj as any);
57-
}
58-
59-
export const csv = (str: string): readonly string[] =>
60-
compact(str.split(',').map((s) => s.trim()));
61-
621
/**
632
* This is logically very simple.
643
* The usefulness is to allow this logic within an expression.

src/common/variant.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { applyDecorators } from '@nestjs/common';
22
import { Field, FieldOptions, ObjectType } from '@nestjs/graphql';
3+
import { entries } from '@seedcompany/common';
34
import { Transform } from 'class-transformer';
45
import { IsIn } from 'class-validator';
56
import { stripIndent } from 'common-tags';
@@ -8,7 +9,6 @@ import { ResourceShape } from '~/common/resource.dto';
89
import { InputException } from './exceptions';
910
import { IdField } from './id-field';
1011
import { Role } from './role.dto';
11-
import { entries } from './util';
1212

1313
@ObjectType()
1414
export class Variant<Key extends string = string> {

0 commit comments

Comments
 (0)