Skip to content

TS 5.2 -> 5.8 #3410

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

Merged
merged 11 commits into from
May 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@
"ts-patch": "^3.0.2",
"ts-transformer-keys": "^0.4.4",
"type-fest": "^4.15.0",
"typescript": "~5.2.2",
"typescript": "~5.8.3",
"typescript-transform-paths": "^3.4.6"
},
"resolutions": {
Expand All @@ -158,7 +158,7 @@
"@nestjs/cli/fork-ts-checker-webpack-plugin": "npm:empty-npm-package@*",
"@nestjs/cli/glob": "^11",
"@nestjs/cli/webpack": "npm:empty-npm-package@*",
"@nestjs/cli/typescript": "~5.2.2",
"@nestjs/cli/typescript": "~5.8.3",
"@whatwg-node/fetch@npm:^0.10.0": "patch:@whatwg-node/fetch@npm%3A0.10.6#~/.yarn/patches/@whatwg-node-fetch-npm-0.10.6-bca79028fb.patch",
"@whatwg-node/fetch@npm:^0.10.1": "patch:@whatwg-node/fetch@npm%3A0.10.6#~/.yarn/patches/@whatwg-node-fetch-npm-0.10.6-bca79028fb.patch",
"@whatwg-node/fetch@npm:^0.10.4": "patch:@whatwg-node/fetch@npm%3A0.10.6#~/.yarn/patches/@whatwg-node-fetch-npm-0.10.6-bca79028fb.patch",
Expand Down
16 changes: 5 additions & 11 deletions src/common/db-sort.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { AbstractClassType } from './types';

const DbSortSymbol = Symbol('DbSortSymbol');
import { createMetadataDecorator } from '@seedcompany/nest';

/**
* A function given a cypher variable will output cypher to transform it for sorting.
Expand All @@ -10,11 +8,7 @@ export type SortTransformer = (value: string) => string;
/**
* Customize the way this field is sorted upon.
*/
export const DbSort = (transformer: SortTransformer) =>
Reflect.metadata(DbSortSymbol, transformer);

export const getDbSortTransformer = (
type: AbstractClassType<unknown>,
property: string,
): SortTransformer | undefined =>
Reflect.getMetadata(DbSortSymbol, type.prototype, property);
export const DbSort = createMetadataDecorator({
types: ['property'],
setter: (transformer: SortTransformer) => transformer,
});
34 changes: 14 additions & 20 deletions src/common/db-unique.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,21 @@
import { createMetadataDecorator } from '@seedcompany/nest';
import { startCase } from 'lodash';
import { DbLabel } from './db-label.decorator';
import { AbstractClassType } from './types';

const DbUniqueSymbol = Symbol('DbUnique');

/**
* This property value should have a unique constraint in database.
* The property node needs a unique label, which can be given or will based on
* This property value should have a unique constraint in the neo4j database.
* The property node needs a unique label, which can be given or will be based on
* the resource & property name.
*/
export const DbUnique =
(label?: string): PropertyDecorator =>
(target, propertyKey) => {
if (typeof propertyKey === 'symbol') {
throw new Error('DbUnique() cannot be used on symbol properties');
}
label ??= target.constructor.name + startCase(propertyKey);
Reflect.defineMetadata(DbUniqueSymbol, label, target, propertyKey);
DbLabel(label)(target, propertyKey);
};
export const DbUnique = (label?: string) => (target: object, key: string) => {
label ??= target.constructor.name + startCase(key);
DbUniqueInner(label)(target, key);
DbLabel(label)(target, key);
};

const DbUniqueInner = createMetadataDecorator({
types: ['property'],
setter: (label?: string) => label,
});

export const getDbPropertyUnique = (
type: AbstractClassType<unknown>,
property: string,
): string | undefined =>
Reflect.getMetadata(DbUniqueSymbol, type.prototype, property);
DbUnique.get = DbUniqueInner.get;
15 changes: 2 additions & 13 deletions src/common/disabled.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
/* eslint-disable @seedcompany/no-unused-vars */

import { FnLike } from '@seedcompany/common';

type Decorator =
| ClassDecorator
| PropertyDecorator
| MethodDecorator
| ParameterDecorator
| FnLike;

/**
* Mark the decorator is disabled and give a reason why.
* Allows to keep code versioned without being enabled
* without all wall of commented out text that can get outdated.
*/
export const Disabled =
(why?: string) =>
<T extends Decorator>(decorator: T): T =>
// @ts-expect-error yeah all decorators can return void
() => {
(why: string, ...anything: unknown[]) =>
(...decoratorArgs: unknown[]) => {
// noop
};
3 changes: 2 additions & 1 deletion src/components/admin/admin.gel.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export class AdminGelRepository {
const rootAlias = e.select(e.Alias, () => ({
filter_single: { name: RootUserAlias },
}));
const rootUser = e.select(rootAlias.target.is(e.User), (u) => ({
const rootUser = e.select(e.User, (u) => ({
filter: e.op(u, '=', rootAlias.target),
id: true,
email: true,
hash: u['<user[is Auth::Identity]'].passwordHash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const createAllPermissionsView = <
propPerms[compatMap.backward[action]] = perm;
return perm;
},
}),
}) as any,
});

export type AllPermissionsOfEdgeView<TAction extends string> = Record<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class UpdateProjectBudgetStatusHandler
session,
);

const budget = budgets.items.find((b) => b.status === change![0]);
const budget = budgets.items.find((b) => b.status === change[0]);
if (!budget) {
return;
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/engagement/engagement.gel.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ const baseHydrate = e.shape(e.Engagement, (engagement) => ({
step: true,
type: true,
},
parent: e.tuple({
parent: e.select({
identity: engagement.project.id,
labels: e.array_agg(e.set(engagement.project.__type__.name.slice(9, null))),
properties: e.tuple({
properties: e.select({
id: engagement.project.id,
createdAt: engagement.project.createdAt,
}),
Expand Down
25 changes: 13 additions & 12 deletions src/components/partnership/partnership.gel.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ export class PartnershipGelRepository
partner: true,
mou: true,
agreement: true,
parent: e.tuple({
parent: e.select({
identity: partnership.project.id,
labels: e.array_agg(
e.set(partnership.project.__type__.name.slice(9, null)),
),
properties: e.tuple({
properties: e.select({
id: partnership.project.id,
createdAt: partnership.project.createdAt,
}),
Expand All @@ -37,16 +37,17 @@ export class PartnershipGelRepository
private readonly readManyByProjectAndPartnerQuery = e.params(
{ input: e.array(e.tuple({ project: e.uuid, partner: e.uuid })) },
({ input }) =>
e.for(e.array_unpack(input), ({ project, partner }) =>
e.select(e.Partnership, (partnership) => ({
...this.hydrate(partnership),
filter: e.op(
e.op(partnership.project, '=', e.cast(e.Project, project)),
'and',
e.op(partnership.partner, '=', e.cast(e.Partner, partner)),
),
})),
),
e.select(e.Partnership, (partnership) => ({
...this.hydrate(partnership),
filter: e.op(
e.tuple({
project: partnership.project.id,
partner: partnership.partner.id,
}),
'in',
e.array_unpack(input),
),
})),
);

async listAllByProjectId(project: ID) {
Expand Down
11 changes: 6 additions & 5 deletions src/components/project/dto/project.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,12 @@ class Project extends Interfaces {
* Optimization for {@link ProjectResolver.engagements}.
* This doesn't account for changesets or item filters.
*/
@Disabled(`
I'm not convinced this wont have unintended consequences.
it is still handled with the workflow condition currently and deletes are
restricted, so this is a super edge case effectively.
`)(
@Disabled(
`
I'm not convinced this wont have unintended consequences.
it is still handled with the workflow condition currently and deletes are
restricted, so this is a super edge case effectively.
`,
RequiredWhenNotInDev({
field: 'engagements',
isMissing: (project) => project.engagementTotal === 0,
Expand Down
4 changes: 2 additions & 2 deletions src/core/database/common.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { setOf } from '@seedcompany/common';
import { inArray, node, relation } from 'cypher-query-builder';
import { DateTime } from 'luxon';
import {
DbUnique,
EnhancedResource,
getDbClassLabels,
getDbPropertyUnique,
ID,
InputException,
isIdLike,
Expand Down Expand Up @@ -175,7 +175,7 @@ export class CommonRepository {
? [createUniqueConstraint(getDbClassLabels(resource)[0], 'id')]
: []),
...resource.Props.flatMap((prop) => {
const label = getDbPropertyUnique(resource, prop);
const label = DbUnique.get(resource, prop);
return label
? createUniqueConstraint(label, 'value', `${resource.name}_${prop}`)
: [];
Expand Down
4 changes: 2 additions & 2 deletions src/core/database/dto.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { inArray, Query } from 'cypher-query-builder';
import { LazyGetter as Once } from 'lazy-get-decorator';
import { lowerCase } from 'lodash';
import {
DbUnique,
EnhancedResource,
getDbPropertyUnique,
ID,
NotFoundException,
ResourceShape,
Expand Down Expand Up @@ -66,7 +66,7 @@ export const DtoRepository = <
}
@Once() private get uniqueLabel() {
const labels = resource.Props.flatMap(
(p) => getDbPropertyUnique(resource, p) ?? [],
(p) => DbUnique.get(resource, p) ?? [],
);
if (labels.length === 0) {
return new ServerException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,9 @@ import { camelCase } from 'lodash';
import { isExp } from '../query';
import { WhereAndList } from '../query/where-and-list';

// Add line breaks for each pattern when there's multiple per statement
// Add line breaks for each pattern when there is multiple per statement
// And ignore empty patterns
PatternClause.prototype.build = function build() {
// @ts-expect-error private but we are using it
const patternStrings = this.patterns.map((pattern) =>
pattern.reduce((str: string, clause: Clause) => str + clause.build(), ''),
);
Expand Down
7 changes: 2 additions & 5 deletions src/core/database/query/sorting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ import { node, Query, relation } from 'cypher-query-builder';
import { identity } from 'rxjs';
import { LiteralUnion } from 'type-fest';
import { MadeEnum, Order, Resource, ResourceShape } from '~/common';
import {
getDbSortTransformer,
SortTransformer,
} from '~/common/db-sort.decorator';
import { DbSort, SortTransformer } from '~/common/db-sort.decorator';
import { apoc } from './cypher-functions';
import { ACTIVE } from './matching';

Expand Down Expand Up @@ -128,7 +125,7 @@ export const defineSorters = <TResourceStatic extends ResourceShape<any>>(
matchers: SortMatchers<SortFieldOf<TResourceStatic>>,
): DefinedSorters<SortFieldOf<TResourceStatic>> => {
const fn = ({ sort, order }: Sort<SortFieldOf<TResourceStatic>>) => {
const transformer = getDbSortTransformer(resource, sort) ?? identity;
const transformer = DbSort.get(resource, sort as string) ?? identity;
const common = { sort, order, transformer };

const exactCustom = matchers[sort];
Expand Down
7 changes: 5 additions & 2 deletions test/region.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { RawUser } from './utility/fragments';
describe('Region e2e', () => {
let app: TestApp;
let director: RawUser;
let newDirector: RawUser;
let fieldZone: FieldZone;

beforeAll(async () => {
Expand Down Expand Up @@ -162,7 +161,7 @@ describe('Region e2e', () => {
});

const newZone = await createZone(app, {
directorId: newDirector.id,
directorId: director.id,
});

const result = await app.graphql.mutate(
Expand Down Expand Up @@ -202,6 +201,10 @@ describe('Region e2e', () => {
it.skip('update region`s director', async () => {
const fieldRegion = await createRegion(app, { directorId: director.id });

const newDirector = await createPerson(app, {
roles: [Role.FieldOperationsDirector, Role.ProjectManager],
});

const result = await app.graphql.mutate(
gql`
mutation updateFieldRegion($input: UpdateFieldRegionInput!) {
Expand Down
18 changes: 9 additions & 9 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5908,7 +5908,7 @@ __metadata:
ts-patch: "npm:^3.0.2"
ts-transformer-keys: "npm:^0.4.4"
type-fest: "npm:^4.15.0"
typescript: "npm:~5.2.2"
typescript: "npm:~5.8.3"
typescript-transform-paths: "npm:^3.4.6"
urlpattern-polyfill: "npm:^10.0.0"
uuid: "npm:^11.1.0"
Expand Down Expand Up @@ -13746,23 +13746,23 @@ __metadata:
languageName: node
linkType: hard

"typescript@npm:~5.2.2":
version: 5.2.2
resolution: "typescript@npm:5.2.2"
"typescript@npm:~5.8.3":
version: 5.8.3
resolution: "typescript@npm:5.8.3"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/91ae3e6193d0ddb8656d4c418a033f0f75dec5e077ebbc2bd6d76439b93f35683936ee1bdc0e9cf94ec76863aa49f27159b5788219b50e1cd0cd6d110aa34b07
checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48
languageName: node
linkType: hard

"typescript@patch:typescript@npm%3A~5.2.2#optional!builtin<compat/typescript>":
version: 5.2.2
resolution: "typescript@patch:typescript@npm%3A5.2.2#optional!builtin<compat/typescript>::version=5.2.2&hash=f3b441"
"typescript@patch:typescript@npm%3A~5.8.3#optional!builtin<compat/typescript>":
version: 5.8.3
resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin<compat/typescript>::version=5.8.3&hash=5786d5"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 10c0/062c1cee1990e6b9419ce8a55162b8dc917eb87f807e4de0327dbc1c2fa4e5f61bc0dd4e034d38ff541d1ed0479b53bcee8e4de3a4075c51a1724eb6216cb6f5
checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb
languageName: node
linkType: hard

Expand Down