diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 0f9f565c5e..926109aa4e 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -16,3 +16,6 @@ c2b727a449bafa0aea4569e9f120eed930f35a26 eb3a00ed47950acb46b96f4ccc3905d9b86c9dc2 517627a0f0204420265595501ad539f5d49b70ce 167247c0c55926c4fbef3ef3795924ee7f503b0b + +# Adjust imports/exports +bfed26416fb0bd22aa9437145b081ea4216b9816 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c6044ea396..051c9c4724 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,7 +47,9 @@ jobs: strategy: matrix: shard: [1, 2, 3, 4, 5, 6] - database: [neo4j, edgedb] + database: + - neo4j +# - edgedb fail-fast: false steps: - uses: actions/checkout@v4 diff --git a/dbschema/migrations/00008-m1pgopp.edgeql b/dbschema/migrations/00008-m1pgopp.edgeql new file mode 100644 index 0000000000..fe24e0c897 --- /dev/null +++ b/dbschema/migrations/00008-m1pgopp.edgeql @@ -0,0 +1,17 @@ +CREATE MIGRATION m1gq2hsptfudyqzcqhaz3o5ikdckynzcdegdixqtrdtnisldpyqv6a + ONTO m1s2cbqfqayiw2giggpp3dlfwrxnmpaziw7irc4h74chugwr4noluq +{ + CREATE SCALAR TYPE Project::Type EXTENDING enum; + CREATE TYPE Project::FinancialApprover { + CREATE REQUIRED LINK user: default::User { + CREATE CONSTRAINT std::exclusive; + }; + CREATE REQUIRED MULTI PROPERTY projectTypes: Project::Type; + CREATE ACCESS POLICY CanInsertDeleteGeneratedFromAppPoliciesForFinancialApprover + ALLOW DELETE, INSERT USING ((default::Role.Administrator IN GLOBAL default::currentRoles)); + CREATE ACCESS POLICY CanSelectUpdateReadGeneratedFromAppPoliciesForFinancialApprover + ALLOW SELECT, UPDATE READ USING (EXISTS (({'Administrator', 'Leadership'} INTERSECT GLOBAL default::currentRoles))); + CREATE ACCESS POLICY CanUpdateWriteGeneratedFromAppPoliciesForFinancialApprover + ALLOW UPDATE WRITE; + }; +}; diff --git a/dbschema/project.esdl b/dbschema/project.esdl index 27630213c9..81103f9f2d 100644 --- a/dbschema/project.esdl +++ b/dbschema/project.esdl @@ -176,6 +176,19 @@ module Project { required single property isMember := exists .projectContext.projects.membership; } + scalar type Type extending enum< + MomentumTranslation, + MultiplicationTranslation, + Internship + >; + + type FinancialApprover { + required user: default::User { + constraint exclusive; + }; + required multi projectTypes: Type; + } + type Context { annotation description := "\ A type that holds a reference to a list of projects. \ diff --git a/dbschema/seeds/019.pins.edgeql b/dbschema/seeds/019.pins.edgeql new file mode 100644 index 0000000000..7c31e6c45a --- /dev/null +++ b/dbschema/seeds/019.pins.edgeql @@ -0,0 +1,53 @@ +with + usersJson := to_json('[ + { + "name": "Bilbo", + "pinnables": [ + "Sindarin", + "Quenya", + "Dwarvish/Elvish Alliance", + "Fellowship of Halfing Languages", + "Emyn Muil", + "Arnor Lake", + "South Downs" + ] + }, + { + "name": "Peregrin", + "pinnables": [ + "English", + "Sindarin", + "Eriador Church", + "The Rivendell Partnership", + "Misty Mountains", + "Lothlorien" + ] + }, + { + "name": "Aragorn", + "pinnables": [ + "Sindarin", + "Eriador Church", + "The Rivendell Partnership", + "Emyn Muil", + "Misty Mountains", + "Lothlorien" + ] + } + ]'), + users := distinct ( + for user in json_array_unpack(usersJson) + union ( + update User + filter .realFirstName = user['name'] + set { + pins += ( + select Mixin::Pinnable + filter [is Mixin::Named].name = json_array_unpack(user['pinnables']) + ) + } + ) + ), + modified := (select users filter .modifiedAt = datetime_of_statement()) +select {`Modified Users` := modified.realFirstName ++ ' ' ++ modified.realLastName} +filter count(modified) > 0; diff --git a/docker-compose.override.example.yml b/docker-compose.override.example.yml index d9ca8d67a1..b709e36c8c 100644 --- a/docker-compose.override.example.yml +++ b/docker-compose.override.example.yml @@ -1,5 +1,4 @@ # Copy this file to docker-compose.override.yml to use -version: '3.7' services: db: diff --git a/docker-compose.yml b/docker-compose.yml index a6fccc858e..5f7041ca37 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,3 @@ -version: '3.7' services: db: image: neo4j:5.10-enterprise diff --git a/package.json b/package.json index 4fe8ec40f4..c83bc52410 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "fastest-levenshtein": "^1.0.16", "file-type": "^18.6.0", "glob": "^10.3.10", - "got": "^13.0.0", + "got": "^14.3.0", "graphql": "^16.8.1", "graphql-parse-resolve-info": "^4.14.0", "graphql-scalars": "^1.22.4", diff --git a/src/common/id-field.test.ts b/src/common/id-field.test.ts index 028794857b..b29e5964f2 100644 --- a/src/common/id-field.test.ts +++ b/src/common/id-field.test.ts @@ -1,6 +1,6 @@ /* eslint-disable @seedcompany/no-unused-vars */ import { test } from '@jest/globals'; -import type { User } from '../components/user'; +import type { User } from '../components/user/dto'; import { ID } from './id-field'; test('only types here', () => undefined); diff --git a/src/common/resource.dto.ts b/src/common/resource.dto.ts index b7dcd20adf..2c42054c1a 100644 --- a/src/common/resource.dto.ts +++ b/src/common/resource.dto.ts @@ -6,7 +6,7 @@ import { keys as keysOf } from 'ts-transformer-keys'; import { inspect } from 'util'; import type { ResourceDBMap, ResourceName } from '~/core'; import { $, e } from '~/core/edgedb/reexports'; -import { ScopedRole } from '../components/authorization'; +import { ScopedRole } from '../components/authorization/dto'; import { CalculatedSymbol } from './calculated.decorator'; import { DataObject } from './data-object'; import { DbLabel } from './db-label.decorator'; diff --git a/src/common/sensitivity.enum.ts b/src/common/sensitivity.enum.ts index b008ba9a71..da2475b99b 100644 --- a/src/common/sensitivity.enum.ts +++ b/src/common/sensitivity.enum.ts @@ -2,7 +2,7 @@ import { applyDecorators } from '@nestjs/common'; import { Field, FieldOptions } from '@nestjs/graphql'; import { Transform } from 'class-transformer'; import { uniq } from 'lodash'; -import { rankSens } from '../core/database/query'; +import { rankSens } from '~/core/database/query'; import { DbSort } from './db-sort.decorator'; import { EnumType, makeEnum } from './make-enum'; diff --git a/src/common/session.ts b/src/common/session.ts index 9df2b6013c..bcd6c87cf7 100644 --- a/src/common/session.ts +++ b/src/common/session.ts @@ -9,7 +9,7 @@ import { Context } from '@nestjs/graphql'; import { uniq } from 'lodash'; import { DateTime } from 'luxon'; import { NoSessionException } from '../components/authentication/no-session.exception'; -import { ScopedRole } from '../components/authorization'; +import { ScopedRole } from '../components/authorization/dto'; import { GqlContextType } from './context.type'; import { UnauthenticatedException } from './exceptions'; import { ID } from './id-field'; diff --git a/src/components/authentication/authentication.repository.ts b/src/components/authentication/authentication.repository.ts index 956621b2a2..bc587a7426 100644 --- a/src/components/authentication/authentication.repository.ts +++ b/src/components/authentication/authentication.repository.ts @@ -1,15 +1,15 @@ import { Injectable } from '@nestjs/common'; import { node, relation } from 'cypher-query-builder'; import { DateTime } from 'luxon'; -import { ID, ServerException, Session } from '../../common'; -import { DatabaseService, OnIndex } from '../../core'; +import { ID, ServerException, Session } from '~/common'; +import { DatabaseService, OnIndex } from '~/core/database'; import { ACTIVE, matchUserGloballyScopedRoles, requestingUser, variable, -} from '../../core/database/query'; -import { ScopedRole } from '../authorization'; +} from '~/core/database/query'; +import { ScopedRole } from '../authorization/dto'; import { LoginInput } from './dto'; interface EmailToken { diff --git a/src/components/authentication/authentication.service.ts b/src/components/authentication/authentication.service.ts index 46645ae319..1ae256095e 100644 --- a/src/components/authentication/authentication.service.ts +++ b/src/components/authentication/authentication.service.ts @@ -4,8 +4,6 @@ import { EmailService } from '@seedcompany/nestjs-email'; import JWT from 'jsonwebtoken'; import { DateTime } from 'luxon'; import { Writable } from 'ts-essentials'; -import { sessionFromContext } from '~/common/session'; -import { disableAccessPolicies, EdgeDB } from '~/core/edgedb'; import { DuplicateException, GqlContextType, @@ -16,10 +14,13 @@ import { Session, UnauthenticatedException, UnauthorizedException, -} from '../../common'; -import { ConfigService, ILogger, Logger } from '../../core'; -import { ForgotPassword } from '../../core/email/templates'; -import { Privileges, rolesForScope, withoutScope } from '../authorization'; +} from '~/common'; +import { sessionFromContext } from '~/common/session'; +import { ConfigService, ILogger, Logger } from '~/core'; +import { disableAccessPolicies, EdgeDB } from '~/core/edgedb'; +import { ForgotPassword } from '~/core/email/templates'; +import { Privileges } from '../authorization'; +import { rolesForScope, withoutScope } from '../authorization/dto'; import { AssignableRoles } from '../authorization/dto/assignable-roles'; import { ActorRepository } from '../user/actor.repository'; import { AuthenticationRepository } from './authentication.repository'; diff --git a/src/components/authentication/crypto.service.ts b/src/components/authentication/crypto.service.ts index 91f70e604e..b7c2f052e3 100644 --- a/src/components/authentication/crypto.service.ts +++ b/src/components/authentication/crypto.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import * as argon2 from 'argon2'; import { pickBy } from 'lodash'; import { Except } from 'type-fest'; -import { ConfigService } from '../../core'; +import { ConfigService } from '~/core'; @Injectable() export class CryptoService { diff --git a/src/components/authentication/dto/logout.dto.ts b/src/components/authentication/dto/logout.dto.ts index 2a9c78ea0d..b7a1bea064 100644 --- a/src/components/authentication/dto/logout.dto.ts +++ b/src/components/authentication/dto/logout.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class LogoutOutput extends MutationPlaceholderOutput {} diff --git a/src/components/authentication/dto/session.dto.ts b/src/components/authentication/dto/session.dto.ts index 2fe355aed9..c3b34259e3 100644 --- a/src/components/authentication/dto/session.dto.ts +++ b/src/components/authentication/dto/session.dto.ts @@ -1,6 +1,6 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { ID, Session } from '../../../common'; +import { ID, Session } from '~/common'; @ObjectType() export abstract class SessionOutput { diff --git a/src/components/authentication/index.ts b/src/components/authentication/index.ts index 639b7e18bf..f6d76d5e9f 100644 --- a/src/components/authentication/index.ts +++ b/src/components/authentication/index.ts @@ -1,2 +1 @@ -export * from './dto'; export * from './authentication.service'; diff --git a/src/components/authentication/login.resolver.ts b/src/components/authentication/login.resolver.ts index 77a6fbabd8..ad6e94773a 100644 --- a/src/components/authentication/login.resolver.ts +++ b/src/components/authentication/login.resolver.ts @@ -7,10 +7,12 @@ import { Resolver, } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { AnonSession, GqlContextType, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { Power, Privileges } from '../authorization'; -import { User, UserLoader } from '../user'; +import { AnonSession, GqlContextType, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { Privileges } from '../authorization'; +import { Power } from '../authorization/dto'; +import { UserLoader } from '../user'; +import { User } from '../user/dto'; import { AuthenticationService } from './authentication.service'; import { LoginInput, LoginOutput, LogoutOutput } from './dto'; diff --git a/src/components/authentication/no-session.exception.ts b/src/components/authentication/no-session.exception.ts index e8d629ea55..59d807c19a 100644 --- a/src/components/authentication/no-session.exception.ts +++ b/src/components/authentication/no-session.exception.ts @@ -1,4 +1,4 @@ -import { UnauthenticatedException } from '../../common'; +import { UnauthenticatedException } from '~/common'; /** * No session established for the user diff --git a/src/components/authentication/password.resolver.ts b/src/components/authentication/password.resolver.ts index 5526a86a41..0db03acabb 100644 --- a/src/components/authentication/password.resolver.ts +++ b/src/components/authentication/password.resolver.ts @@ -1,6 +1,6 @@ import { Args, Mutation, Resolver } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { AnonSession, LoggedInSession, Session } from '../../common'; +import { AnonSession, LoggedInSession, Session } from '~/common'; import { AuthenticationService } from './authentication.service'; import { ChangePasswordArgs, diff --git a/src/components/authentication/register.resolver.ts b/src/components/authentication/register.resolver.ts index aa0cbc1c25..ee5c441331 100644 --- a/src/components/authentication/register.resolver.ts +++ b/src/components/authentication/register.resolver.ts @@ -7,10 +7,12 @@ import { Resolver, } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { AnonSession, GqlContextType, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { Power, Privileges } from '../authorization'; -import { User, UserLoader } from '../user'; +import { AnonSession, GqlContextType, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { Privileges } from '../authorization'; +import { Power } from '../authorization/dto'; +import { UserLoader } from '../user'; +import { User } from '../user/dto'; import { AuthenticationService } from './authentication.service'; import { RegisterInput, RegisterOutput } from './dto'; diff --git a/src/components/authentication/session.interceptor.ts b/src/components/authentication/session.interceptor.ts index 9a67244a82..eb67b6d149 100644 --- a/src/components/authentication/session.interceptor.ts +++ b/src/components/authentication/session.interceptor.ts @@ -25,7 +25,7 @@ import { UnauthenticatedException, } from '~/common'; import { ConfigService } from '~/core'; -import { rolesForScope } from '../authorization'; +import { rolesForScope } from '../authorization/dto'; import { AuthenticationService } from './authentication.service'; @Injectable() diff --git a/src/components/authentication/session.resolver.ts b/src/components/authentication/session.resolver.ts index 6b2b9d2668..1296159985 100644 --- a/src/components/authentication/session.resolver.ts +++ b/src/components/authentication/session.resolver.ts @@ -11,10 +11,12 @@ import { GqlContextType, ServerException, UnauthenticatedException, -} from '../../common'; -import { ConfigService, ILogger, Loader, LoaderOf, Logger } from '../../core'; -import { Power, Privileges } from '../authorization'; -import { User, UserLoader, UserService } from '../user'; +} from '~/common'; +import { ConfigService, ILogger, Loader, LoaderOf, Logger } from '~/core'; +import { Privileges } from '../authorization'; +import { Power } from '../authorization/dto'; +import { UserLoader, UserService } from '../user'; +import { User } from '../user/dto'; import { AuthenticationService } from './authentication.service'; import { SessionOutput } from './dto'; import { SessionInterceptor } from './session.interceptor'; diff --git a/src/components/authorization/assignable-roles.granter.ts b/src/components/authorization/assignable-roles.granter.ts index 91be8617ee..961848fe4b 100644 --- a/src/components/authorization/assignable-roles.granter.ts +++ b/src/components/authorization/assignable-roles.granter.ts @@ -1,4 +1,4 @@ -import { Role } from './dto'; +import { Role } from '~/common'; import { AssignableRoles } from './dto/assignable-roles'; import { Granter, ResourceGranter } from './policy'; diff --git a/src/components/authorization/dto/assignable-roles.ts b/src/components/authorization/dto/assignable-roles.ts index dc4e3db432..cbe46aee4a 100644 --- a/src/components/authorization/dto/assignable-roles.ts +++ b/src/components/authorization/dto/assignable-roles.ts @@ -1,7 +1,6 @@ import { mapValues } from '@seedcompany/common'; -import { Calculated, ResourceRelationsShape } from '~/common'; +import { Calculated, ResourceRelationsShape, Role } from '~/common'; import { RegisterResource } from '~/core/resources'; -import { Role } from './role.dto'; /** * A special type of object that declares what roles a user can assign to another user. diff --git a/src/components/authorization/dto/role.dto.ts b/src/components/authorization/dto/role.dto.ts index 77ef33ca84..69205c173c 100644 --- a/src/components/authorization/dto/role.dto.ts +++ b/src/components/authorization/dto/role.dto.ts @@ -1,7 +1,5 @@ import { Role } from '~/common'; -export * from '~/common/role.dto'; - export type ProjectScope = 'project'; export type GlobalScope = 'global'; diff --git a/src/components/authorization/index.ts b/src/components/authorization/index.ts index bafcd32bdd..6d028ae319 100644 --- a/src/components/authorization/index.ts +++ b/src/components/authorization/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './policy'; export { HasCreator, diff --git a/src/components/authorization/policies/conditions/member.condition.ts b/src/components/authorization/policies/conditions/member.condition.ts index a7117256ae..500b58d3a3 100644 --- a/src/components/authorization/policies/conditions/member.condition.ts +++ b/src/components/authorization/policies/conditions/member.condition.ts @@ -1,14 +1,9 @@ import { Query } from 'cypher-query-builder'; import { intersection } from 'lodash'; import { inspect, InspectOptionsStylized } from 'util'; -import { ResourceShape } from '~/common'; +import { ResourceShape, Role } from '~/common'; import { matchProjectScopedRoles, variable } from '~/core/database/query'; -import { - Role, - rolesForScope, - ScopedRole, - splitScope, -} from '../../dto/role.dto'; +import { rolesForScope, ScopedRole, splitScope } from '../../dto/role.dto'; import { AsCypherParams, AsEdgeQLParams, diff --git a/src/components/authorization/policy/builder/policy.decorator.ts b/src/components/authorization/policy/builder/policy.decorator.ts index 61c6d69940..ad32187d7f 100644 --- a/src/components/authorization/policy/builder/policy.decorator.ts +++ b/src/components/authorization/policy/builder/policy.decorator.ts @@ -1,7 +1,6 @@ import { SetMetadata } from '@nestjs/common'; import { ValueOf } from 'type-fest'; -import { Many } from '~/common'; -import { Role } from '../../dto/role.dto'; +import { Many, Role } from '~/common'; import type { ResourcesGranter } from '../granters'; type ResourceGranterFn = ( diff --git a/src/components/authorization/policy/conditions/flatten-aggregate.optimizer.ts b/src/components/authorization/policy/conditions/flatten-aggregate.optimizer.ts index 43592e0de9..67c181cebc 100644 --- a/src/components/authorization/policy/conditions/flatten-aggregate.optimizer.ts +++ b/src/components/authorization/policy/conditions/flatten-aggregate.optimizer.ts @@ -1,4 +1,6 @@ -import { AndConditions, Condition, Optimizer, OrConditions } from './index'; +import { AndConditions, OrConditions } from './aggregate.condition'; +import { Condition } from './condition.interface'; +import { Optimizer } from './optimizer.interface'; @Optimizer.register() export class FlattenAggregateOptimizer implements Optimizer { diff --git a/src/components/authorization/policy/executor/policy-executor.ts b/src/components/authorization/policy/executor/policy-executor.ts index 4fc954f687..97d29ad54e 100644 --- a/src/components/authorization/policy/executor/policy-executor.ts +++ b/src/components/authorization/policy/executor/policy-executor.ts @@ -3,7 +3,7 @@ import { CachedByArg } from '@seedcompany/common'; import { identity, intersection } from 'lodash'; import { EnhancedResource, Session } from '~/common'; import { QueryFragment } from '~/core/database/query'; -import { withoutScope } from '../../dto/role.dto'; +import { withoutScope } from '../../dto'; import { RoleCondition } from '../../policies/conditions/role.condition'; import { Permission } from '../builder/perm-granter'; import { all, any, CalculatedCondition, OrConditions } from '../conditions'; diff --git a/src/components/budget/budget-record.loader.ts b/src/components/budget/budget-record.loader.ts index 99de879047..e755ae6b86 100644 --- a/src/components/budget/budget-record.loader.ts +++ b/src/components/budget/budget-record.loader.ts @@ -1,5 +1,5 @@ -import { ID, NotFoundException, ObjectView } from '../../common'; -import { LoaderFactory, ObjectViewAwareLoader } from '../../core'; +import { ID, NotFoundException, ObjectView } from '~/common'; +import { LoaderFactory, ObjectViewAwareLoader } from '~/core'; import { BudgetService } from './budget.service'; import { BudgetRecord } from './dto'; diff --git a/src/components/budget/budget-record.repository.ts b/src/components/budget/budget-record.repository.ts index 95c1148853..4c528bbf99 100644 --- a/src/components/budget/budget-record.repository.ts +++ b/src/components/budget/budget-record.repository.ts @@ -1,6 +1,5 @@ import { Injectable } from '@nestjs/common'; import { node, Query, relation } from 'cypher-query-builder'; -import { ChangesOf } from '~/core/database/changes'; import { ID, labelForView, @@ -9,8 +8,9 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { DtoRepository } from '../../core'; +} from '~/common'; +import { DtoRepository } from '~/core/database'; +import { ChangesOf } from '~/core/database/changes'; import { ACTIVE, createNode, @@ -21,7 +21,7 @@ import { merge, paginate, sorting, -} from '../../core/database/query'; +} from '~/core/database/query'; import { Budget, BudgetRecord, diff --git a/src/components/budget/budget-record.resolver.ts b/src/components/budget/budget-record.resolver.ts index 2434b3c25e..52f1da299c 100644 --- a/src/components/budget/budget-record.resolver.ts +++ b/src/components/budget/budget-record.resolver.ts @@ -5,8 +5,8 @@ import { ResolveField, Resolver, } from '@nestjs/graphql'; -import { LoggedInSession, mapSecuredValue, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; +import { LoggedInSession, mapSecuredValue, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { OrganizationLoader } from '../organization'; import { SecuredOrganization } from '../organization/dto'; import { BudgetService } from './budget.service'; diff --git a/src/components/budget/budget.loader.ts b/src/components/budget/budget.loader.ts index 8c40f8a636..6e65527367 100644 --- a/src/components/budget/budget.loader.ts +++ b/src/components/budget/budget.loader.ts @@ -1,5 +1,5 @@ -import { ID, ObjectView } from '../../common'; -import { LoaderFactory, ObjectViewAwareLoader } from '../../core'; +import { ID, ObjectView } from '~/common'; +import { LoaderFactory, ObjectViewAwareLoader } from '~/core'; import { BudgetService } from './budget.service'; import { Budget } from './dto'; diff --git a/src/components/budget/budget.repository.ts b/src/components/budget/budget.repository.ts index 1e00231b71..02d0b6cf38 100644 --- a/src/components/budget/budget.repository.ts +++ b/src/components/budget/budget.repository.ts @@ -1,7 +1,6 @@ import { Injectable } from '@nestjs/common'; import { inArray, node, Query, relation } from 'cypher-query-builder'; import { pickBy } from 'lodash'; -import { ChangesOf } from '~/core/database/changes'; import { ID, labelForView, @@ -11,8 +10,9 @@ import { Session, UnsecuredDto, viewOfChangeset, -} from '../../common'; -import { DtoRepository } from '../../core'; +} from '~/common'; +import { DtoRepository } from '~/core/database'; +import { ChangesOf } from '~/core/database/changes'; import { ACTIVE, createNode, @@ -24,8 +24,8 @@ import { paginate, requestingUser, sorting, -} from '../../core/database/query'; -import { FileId } from '../file'; +} from '~/core/database/query'; +import { FileId } from '../file/dto'; import { BudgetRecordRepository } from './budget-record.repository'; import { Budget, diff --git a/src/components/budget/budget.resolver.ts b/src/components/budget/budget.resolver.ts index 4706210552..7512f306d5 100644 --- a/src/components/budget/budget.resolver.ts +++ b/src/components/budget/budget.resolver.ts @@ -7,10 +7,11 @@ import { Resolver, } from '@nestjs/graphql'; import { sumBy } from 'lodash'; -import { LoggedInSession, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; +import { LoggedInSession, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { BudgetService } from '../budget'; -import { FileNodeLoader, resolveDefinedFile, SecuredFile } from '../file'; +import { FileNodeLoader, resolveDefinedFile } from '../file'; +import { SecuredFile } from '../file/dto'; import { Budget, UpdateBudgetInput, UpdateBudgetOutput } from './dto'; @Resolver(Budget) diff --git a/src/components/budget/budget.service.ts b/src/components/budget/budget.service.ts index 376de570b9..22553f668a 100644 --- a/src/components/budget/budget.service.ts +++ b/src/components/budget/budget.service.ts @@ -9,11 +9,12 @@ import { ServerException, Session, viewOfChangeset, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger, ResourceResolver } from '../../core'; -import { mapListResults } from '../../core/database/results'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger, ResourceResolver } from '~/core'; +import { mapListResults } from '~/core/database/results'; import { Privileges } from '../authorization'; -import { FileId, FileService } from '../file'; +import { FileService } from '../file'; +import { FileId } from '../file/dto'; import { ProjectChangeRequest } from '../project-change-request/dto'; import { BudgetRecordRepository } from './budget-record.repository'; import { BudgetRepository } from './budget.repository'; diff --git a/src/components/budget/dto/budget-record.dto.ts b/src/components/budget/dto/budget-record.dto.ts index 4242b31870..5c04386097 100644 --- a/src/components/budget/dto/budget-record.dto.ts +++ b/src/components/budget/dto/budget-record.dto.ts @@ -1,8 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { BaseNode } from '~/core/database/results'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { Calculated, ID, @@ -14,7 +11,10 @@ import { SecuredProps, Sensitivity, SensitivityField, -} from '../../../common'; +} from '~/common'; +import { BaseNode } from '~/core/database/results'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { ChangesetAware } from '../../changeset/dto'; import { BudgetStatus } from './budget-status.enum'; import { Budget } from './budget.dto'; diff --git a/src/components/budget/dto/budget.dto.ts b/src/components/budget/dto/budget.dto.ts index b6c948ac06..76c18046b3 100644 --- a/src/components/budget/dto/budget.dto.ts +++ b/src/components/budget/dto/budget.dto.ts @@ -1,8 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { BaseNode } from '~/core/database/results'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { Calculated, DbLabel, @@ -13,7 +10,10 @@ import { SecuredProps, Sensitivity, SensitivityField, -} from '../../../common'; +} from '~/common'; +import { BaseNode } from '~/core/database/results'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { ChangesetAware } from '../../changeset/dto'; import { DefinedFile } from '../../file/dto'; import { IProject } from '../../project/dto'; diff --git a/src/components/budget/handlers/create-project-default-budget.handler.ts b/src/components/budget/handlers/create-project-default-budget.handler.ts index e644d0a2ba..d562599847 100644 --- a/src/components/budget/handlers/create-project-default-budget.handler.ts +++ b/src/components/budget/handlers/create-project-default-budget.handler.ts @@ -1,4 +1,4 @@ -import { EventsHandler, IEventHandler } from '../../../core'; +import { EventsHandler, IEventHandler } from '~/core'; import { ProjectCreatedEvent } from '../../project/events'; import { BudgetService } from '../budget.service'; diff --git a/src/components/budget/handlers/sync-budget-records-to-funding-partners.handler.ts b/src/components/budget/handlers/sync-budget-records-to-funding-partners.handler.ts index a3b0479c8f..d99e76642c 100644 --- a/src/components/budget/handlers/sync-budget-records-to-funding-partners.handler.ts +++ b/src/components/budget/handlers/sync-budget-records-to-funding-partners.handler.ts @@ -8,15 +8,9 @@ import { Session, UnauthorizedException, UnsecuredDto, -} from '../../../common'; -import { - DatabaseService, - EventsHandler, - IEventHandler, - ILogger, - Logger, -} from '../../../core'; -import { PartnerType } from '../../partner'; +} from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { PartnerType } from '../../partner/dto'; import { PartnershipService } from '../../partnership'; import { Partnership } from '../../partnership/dto'; import { @@ -49,7 +43,6 @@ export class SyncBudgetRecordsToFundingPartners implements IEventHandler { constructor( - private readonly db: DatabaseService, private readonly budgets: BudgetService, private readonly budgetRepo: BudgetRepository, private readonly partnershipService: PartnershipService, diff --git a/src/components/budget/handlers/update-project-current-budget-status.handler.ts b/src/components/budget/handlers/update-project-current-budget-status.handler.ts index 30b883e629..2cb102dbc9 100644 --- a/src/components/budget/handlers/update-project-current-budget-status.handler.ts +++ b/src/components/budget/handlers/update-project-current-budget-status.handler.ts @@ -1,5 +1,5 @@ -import { EventsHandler, IEventHandler } from '../../../core'; -import { ProjectStatus, stepToStatus } from '../../project'; +import { EventsHandler, IEventHandler } from '~/core'; +import { ProjectStatus, stepToStatus } from '../../project/dto'; import { ProjectUpdatedEvent } from '../../project/events'; import { BudgetService } from '../budget.service'; import { BudgetStatus } from '../dto'; diff --git a/src/components/budget/index.ts b/src/components/budget/index.ts index f7790565b8..54e492e603 100644 --- a/src/components/budget/index.ts +++ b/src/components/budget/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './budget.service'; export * from './budget.loader'; diff --git a/src/components/ceremony/ceremony.loader.ts b/src/components/ceremony/ceremony.loader.ts index b690c0b68c..f1b5cd49c2 100644 --- a/src/components/ceremony/ceremony.loader.ts +++ b/src/components/ceremony/ceremony.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { CeremonyService } from './ceremony.service'; import { Ceremony } from './dto'; diff --git a/src/components/ceremony/ceremony.repository.ts b/src/components/ceremony/ceremony.repository.ts index 009cfe6c63..cb7df0f96b 100644 --- a/src/components/ceremony/ceremony.repository.ts +++ b/src/components/ceremony/ceremony.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { node, Query, relation } from 'cypher-query-builder'; import { ID, ServerException, Session, UnsecuredDto } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, diff --git a/src/components/ceremony/ceremony.resolver.ts b/src/components/ceremony/ceremony.resolver.ts index f6f254f372..b1c83b5a62 100644 --- a/src/components/ceremony/ceremony.resolver.ts +++ b/src/components/ceremony/ceremony.resolver.ts @@ -7,7 +7,7 @@ import { LoggedInSession, Session, } from '~/common'; -import { Loader, LoaderOf } from '../../core'; +import { Loader, LoaderOf } from '~/core'; import { CeremonyLoader, CeremonyService } from '../ceremony'; import { Ceremony, diff --git a/src/components/ceremony/ceremony.service.ts b/src/components/ceremony/ceremony.service.ts index 7b198c69d7..f871581491 100644 --- a/src/components/ceremony/ceremony.service.ts +++ b/src/components/ceremony/ceremony.service.ts @@ -6,8 +6,8 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger } from '../../core'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger } from '~/core'; import { Privileges } from '../authorization'; import { CeremonyRepository } from './ceremony.repository'; import { diff --git a/src/components/ceremony/handlers/create-engagement-default-ceremony.handler.ts b/src/components/ceremony/handlers/create-engagement-default-ceremony.handler.ts index 5c6eb900fa..d699d1f539 100644 --- a/src/components/ceremony/handlers/create-engagement-default-ceremony.handler.ts +++ b/src/components/ceremony/handlers/create-engagement-default-ceremony.handler.ts @@ -1,11 +1,7 @@ import { node, relation } from 'cypher-query-builder'; import { DateTime } from 'luxon'; -import { - ConfigService, - DatabaseService, - EventsHandler, - IEventHandler, -} from '~/core'; +import { ConfigService, EventsHandler, IEventHandler } from '~/core'; +import { DatabaseService } from '~/core/database'; import { EngagementCreatedEvent } from '../../engagement/events'; import { CeremonyService } from '../ceremony.service'; import { CeremonyType } from '../dto'; diff --git a/src/components/ceremony/handlers/delete-engagement-default-ceremony.handler.ts b/src/components/ceremony/handlers/delete-engagement-default-ceremony.handler.ts index e33e33f3a3..89aed2607f 100644 --- a/src/components/ceremony/handlers/delete-engagement-default-ceremony.handler.ts +++ b/src/components/ceremony/handlers/delete-engagement-default-ceremony.handler.ts @@ -1,4 +1,4 @@ -import { DatabaseService, EventsHandler, IEventHandler } from '../../../core'; +import { EventsHandler, IEventHandler } from '~/core'; import { EngagementWillDeleteEvent } from '../../engagement/events'; import { CeremonyService } from '../ceremony.service'; @@ -6,10 +6,7 @@ import { CeremonyService } from '../ceremony.service'; export class DetachEngagementRootDirectoryHandler implements IEventHandler { - constructor( - private readonly ceremonies: CeremonyService, - private readonly db: DatabaseService, - ) {} + constructor(private readonly ceremonies: CeremonyService) {} async handle({ engagement, session }: EngagementWillDeleteEvent) { const ceremonyId = engagement?.ceremony?.value; diff --git a/src/components/ceremony/index.ts b/src/components/ceremony/index.ts index 39209d0237..c4899103e2 100644 --- a/src/components/ceremony/index.ts +++ b/src/components/ceremony/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './ceremony.service'; export * from './ceremony.loader'; diff --git a/src/components/changeset/changeset.repository.ts b/src/components/changeset/changeset.repository.ts index 097aeb0478..4b74b0e024 100644 --- a/src/components/changeset/changeset.repository.ts +++ b/src/components/changeset/changeset.repository.ts @@ -8,10 +8,10 @@ import { or, relation, } from 'cypher-query-builder'; -import { ID, NotFoundException } from '../../common'; -import { DtoRepository } from '../../core'; -import { ACTIVE, path, variable } from '../../core/database/query'; -import { BaseNode } from '../../core/database/results'; +import { ID, NotFoundException } from '~/common'; +import { DtoRepository } from '~/core/database'; +import { ACTIVE, path, variable } from '~/core/database/query'; +import { BaseNode } from '~/core/database/results'; import { Changeset, ChangesetDiff } from './dto'; @Injectable() diff --git a/src/components/changeset/changeset.resolver.ts b/src/components/changeset/changeset.resolver.ts index 3ae133956f..ff52e6dcf4 100644 --- a/src/components/changeset/changeset.resolver.ts +++ b/src/components/changeset/changeset.resolver.ts @@ -1,7 +1,7 @@ import { Parent, Query, ResolveField, Resolver } from '@nestjs/graphql'; -import { ID, IdArg, LoggedInSession, ObjectView, Session } from '../../common'; -import { ResourceLoader } from '../../core'; -import { BaseNode } from '../../core/database/results'; +import { ID, IdArg, LoggedInSession, ObjectView, Session } from '~/common'; +import { ResourceLoader } from '~/core'; +import { BaseNode } from '~/core/database/results'; import { ChangesetRepository } from './changeset.repository'; import { Changeset, ChangesetDiff, ResourceChange } from './dto'; diff --git a/src/components/changeset/commit-changeset-props.query.ts b/src/components/changeset/commit-changeset-props.query.ts index 0b2721126f..2f6bcea546 100644 --- a/src/components/changeset/commit-changeset-props.query.ts +++ b/src/components/changeset/commit-changeset-props.query.ts @@ -4,7 +4,7 @@ import { ACTIVE, INACTIVE, prefixNodeLabelsWithDeleted, -} from '../../core/database/query'; +} from '~/core/database/query'; export interface CommitChangesetPropsOptions { nodeVar?: string; diff --git a/src/components/changeset/dto/changeset.dto.ts b/src/components/changeset/dto/changeset.dto.ts index 7ab3795da9..33cd4b35d5 100644 --- a/src/components/changeset/dto/changeset.dto.ts +++ b/src/components/changeset/dto/changeset.dto.ts @@ -1,7 +1,7 @@ import { Field, InterfaceType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; +import { Resource, SecuredProps } from '~/common'; import { RegisterResource } from '~/core/resources'; -import { Resource, SecuredProps } from '../../../common'; @RegisterResource() @InterfaceType({ diff --git a/src/components/changeset/enforce-changeset-editable.pipe.ts b/src/components/changeset/enforce-changeset-editable.pipe.ts index 0f6707a5e4..a6c76d101f 100644 --- a/src/components/changeset/enforce-changeset-editable.pipe.ts +++ b/src/components/changeset/enforce-changeset-editable.pipe.ts @@ -10,8 +10,8 @@ import { isIdLike, loadManyIgnoreMissingThrowAny, } from '~/common'; -import { GqlContextHost, NotGraphQLContext } from '../../core'; -import { ResourceLoaderRegistry } from '../../core/resources/loader.registry'; +import { GqlContextHost, NotGraphQLContext } from '~/core'; +import { ResourceLoaderRegistry } from '~/core/resources/loader.registry'; import { Changeset } from './dto'; import { shouldValidateEditability } from './validate-editability.decorator'; diff --git a/src/components/changeset/events/changeset-finalizing.event.ts b/src/components/changeset/events/changeset-finalizing.event.ts index 1af811fddf..d853de9f55 100644 --- a/src/components/changeset/events/changeset-finalizing.event.ts +++ b/src/components/changeset/events/changeset-finalizing.event.ts @@ -1,4 +1,4 @@ -import { Session, UnsecuredDto } from '../../../common'; +import { Session, UnsecuredDto } from '~/common'; import { Changeset } from '../dto'; /** diff --git a/src/components/changeset/index.ts b/src/components/changeset/index.ts index 53b492d22b..fec007eb7f 100644 --- a/src/components/changeset/index.ts +++ b/src/components/changeset/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './events'; export * from './changeset.field'; export * from './commit-changeset-props.query'; diff --git a/src/components/changeset/reject-changeset-props.query.ts b/src/components/changeset/reject-changeset-props.query.ts index e65b9988b0..cf05be374e 100644 --- a/src/components/changeset/reject-changeset-props.query.ts +++ b/src/components/changeset/reject-changeset-props.query.ts @@ -1,6 +1,6 @@ import { node, Query, relation } from 'cypher-query-builder'; import { DateTime } from 'luxon'; -import { ACTIVE, INACTIVE } from '../../core/database/query'; +import { ACTIVE, INACTIVE } from '~/core/database/query'; export interface RejectChangesetPropsOptions { nodeVar?: string; diff --git a/src/components/comments/comment-thread.repository.ts b/src/components/comments/comment-thread.repository.ts index ef2cb189bf..d1e104772a 100644 --- a/src/components/comments/comment-thread.repository.ts +++ b/src/components/comments/comment-thread.repository.ts @@ -1,7 +1,7 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { node, Query, relation } from 'cypher-query-builder'; -import { ID, Session, UnsecuredDto } from '../../common'; -import { DtoRepository } from '../../core'; +import { ID, Session, UnsecuredDto } from '~/common'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, @@ -10,7 +10,7 @@ import { paginate, requestingUser, sorting, -} from '../../core/database/query'; +} from '~/core/database/query'; import { CommentRepository } from './comment.repository'; import { CommentThread, CommentThreadListInput } from './dto'; diff --git a/src/components/comments/comment-thread.resolver.ts b/src/components/comments/comment-thread.resolver.ts index 0c7c3c8193..643aedd4be 100644 --- a/src/components/comments/comment-thread.resolver.ts +++ b/src/components/comments/comment-thread.resolver.ts @@ -9,7 +9,8 @@ import { Session, } from '~/common'; import { Loader, LoaderOf, ResourceLoader } from '~/core'; -import { User, UserLoader } from '../user'; +import { UserLoader } from '../user'; +import { User } from '../user/dto'; import { CommentThreadLoader } from './comment-thread.loader'; import { CommentLoader } from './comment.loader'; import { CommentService } from './comment.service'; diff --git a/src/components/comments/comment.loader.ts b/src/components/comments/comment.loader.ts index 633fee76dc..628b09bbff 100644 --- a/src/components/comments/comment.loader.ts +++ b/src/components/comments/comment.loader.ts @@ -1,6 +1,6 @@ -import { ID } from '../../common'; -import { OrderedNestDataLoader } from '../../core'; -import { LoaderFactory } from '../../core/resources/loader.registry'; +import { ID } from '~/common'; +import { OrderedNestDataLoader } from '~/core'; +import { LoaderFactory } from '~/core/resources/loader.registry'; import { CommentService } from './comment.service'; import { Comment } from './dto'; diff --git a/src/components/comments/comment.repository.ts b/src/components/comments/comment.repository.ts index 6f6f51eed6..3207d82cbe 100644 --- a/src/components/comments/comment.repository.ts +++ b/src/components/comments/comment.repository.ts @@ -1,9 +1,9 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common'; import { node, Query, relation } from 'cypher-query-builder'; import { DateTime } from 'luxon'; +import { ID, Session, UnsecuredDto } from '~/common'; +import { DtoRepository } from '~/core/database'; import { ChangesOf } from '~/core/database/changes'; -import { ID, Session, UnsecuredDto } from '../../common'; -import { DtoRepository } from '../../core'; import { ACTIVE, createNode, @@ -14,7 +14,7 @@ import { requestingUser, sorting, variable, -} from '../../core/database/query'; +} from '~/core/database/query'; import { CommentThreadRepository } from './comment-thread.repository'; import { Comment, diff --git a/src/components/comments/comment.resolver.ts b/src/components/comments/comment.resolver.ts index 8435dc35be..191db02531 100644 --- a/src/components/comments/comment.resolver.ts +++ b/src/components/comments/comment.resolver.ts @@ -5,9 +5,10 @@ import { ResolveField, Resolver, } from '@nestjs/graphql'; -import { ID, IdArg, LoggedInSession, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { User, UserLoader } from '../user'; +import { ID, IdArg, LoggedInSession, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { UserLoader } from '../user'; +import { User } from '../user/dto'; import { CommentService } from './comment.service'; import { Comment, diff --git a/src/components/comments/comment.service.ts b/src/components/comments/comment.service.ts index f7f7713726..a8992969e2 100644 --- a/src/components/comments/comment.service.ts +++ b/src/components/comments/comment.service.ts @@ -22,8 +22,8 @@ import { CommentThreadList, CommentThreadListInput, CreateCommentInput, + UpdateCommentInput, } from './dto'; -import { UpdateCommentInput } from './dto/update-comment.dto'; type CommentableRef = ID | BaseNode | Commentable; diff --git a/src/components/comments/commentable.resolver.ts b/src/components/comments/commentable.resolver.ts index 00ee4f14e0..bf183b0371 100644 --- a/src/components/comments/commentable.resolver.ts +++ b/src/components/comments/commentable.resolver.ts @@ -7,7 +7,7 @@ import { Resource, Session, } from '~/common'; -import { Loader, LoaderOf } from '../../core'; +import { Loader, LoaderOf } from '~/core'; import { CommentThreadLoader } from './comment-thread.loader'; import { CommentService } from './comment.service'; import { Commentable, CommentThreadList, CommentThreadListInput } from './dto'; diff --git a/src/components/comments/dto/comment.dto.ts b/src/components/comments/dto/comment.dto.ts index 1c8b759e45..1500368973 100644 --- a/src/components/comments/dto/comment.dto.ts +++ b/src/components/comments/dto/comment.dto.ts @@ -1,15 +1,15 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { DateTime } from 'luxon'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DateTimeField, ID, Resource, SecuredProps, SecuredRichText, -} from '../../../common'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; @RegisterResource({ db: e.Comments.Comment }) @ObjectType({ diff --git a/src/components/comments/dto/create-comment.dto.ts b/src/components/comments/dto/create-comment.dto.ts index ff1b42b566..2f585dc169 100644 --- a/src/components/comments/dto/create-comment.dto.ts +++ b/src/components/comments/dto/create-comment.dto.ts @@ -1,5 +1,5 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; -import { ID, IdField, RichTextDocument, RichTextField } from '../../../common'; +import { ID, IdField, RichTextDocument, RichTextField } from '~/common'; import { Comment } from './comment.dto'; @InputType() diff --git a/src/components/comments/dto/delete-comment-thread.dto.ts b/src/components/comments/dto/delete-comment-thread.dto.ts index afe2d0809e..e9fccce27f 100644 --- a/src/components/comments/dto/delete-comment-thread.dto.ts +++ b/src/components/comments/dto/delete-comment-thread.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteCommentThreadOutput extends MutationPlaceholderOutput {} diff --git a/src/components/comments/dto/delete-comment.dto.ts b/src/components/comments/dto/delete-comment.dto.ts index e76c19c7ad..04b599eb1e 100644 --- a/src/components/comments/dto/delete-comment.dto.ts +++ b/src/components/comments/dto/delete-comment.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteCommentOutput extends MutationPlaceholderOutput {} diff --git a/src/components/comments/dto/list-comment-thread.dto.ts b/src/components/comments/dto/list-comment-thread.dto.ts index 6df0cbae02..8af6161761 100644 --- a/src/components/comments/dto/list-comment-thread.dto.ts +++ b/src/components/comments/dto/list-comment-thread.dto.ts @@ -1,5 +1,5 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; -import { Order, PaginatedList, SortablePaginationInput } from '../../../common'; +import { Order, PaginatedList, SortablePaginationInput } from '~/common'; import { CommentThread } from './comment-thread.dto'; import { Commentable } from './commentable.dto'; diff --git a/src/components/comments/dto/update-comment.dto.ts b/src/components/comments/dto/update-comment.dto.ts index f37d44b3aa..6dd40350ad 100644 --- a/src/components/comments/dto/update-comment.dto.ts +++ b/src/components/comments/dto/update-comment.dto.ts @@ -1,5 +1,5 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; -import { ID, IdField, RichTextDocument, RichTextField } from '../../../common'; +import { ID, IdField, RichTextDocument, RichTextField } from '~/common'; import { Comment } from './comment.dto'; @InputType() diff --git a/src/components/comments/index.ts b/src/components/comments/index.ts index dacfee3d06..e69de29bb2 100644 --- a/src/components/comments/index.ts +++ b/src/components/comments/index.ts @@ -1 +0,0 @@ -export * from './dto'; diff --git a/src/components/engagement/dto/create-engagement.dto.ts b/src/components/engagement/dto/create-engagement.dto.ts index bb13db65ce..995f624bce 100644 --- a/src/components/engagement/dto/create-engagement.dto.ts +++ b/src/components/engagement/dto/create-engagement.dto.ts @@ -3,7 +3,7 @@ import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; import { stripIndent } from 'common-tags'; import { keys as keysOf } from 'ts-transformer-keys'; -import { CalendarDate, DateField, ID, IdField } from '../../../common'; +import { CalendarDate, DateField, ID, IdField } from '~/common'; import { ChangesetIdField } from '../../changeset'; import { CreateDefinedFileVersionInput } from '../../file/dto'; import { ProductMethodology } from '../../product/dto'; diff --git a/src/components/engagement/dto/delete-engagement.dto.ts b/src/components/engagement/dto/delete-engagement.dto.ts index a3489feb05..2085f82b59 100644 --- a/src/components/engagement/dto/delete-engagement.dto.ts +++ b/src/components/engagement/dto/delete-engagement.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteEngagementOutput extends MutationPlaceholderOutput {} diff --git a/src/components/engagement/dto/engagement.dto.ts b/src/components/engagement/dto/engagement.dto.ts index b5ddbb7d8b..6fd425ed30 100644 --- a/src/components/engagement/dto/engagement.dto.ts +++ b/src/components/engagement/dto/engagement.dto.ts @@ -3,9 +3,6 @@ import { Field, InterfaceType, ObjectType } from '@nestjs/graphql'; import { DateTime } from 'luxon'; import { keys as keysOf } from 'ts-transformer-keys'; import { MergeExclusive } from 'type-fest'; -import { BaseNode } from '~/core/database/results'; -import { e } from '~/core/edgedb'; -import { LinkTo, RegisterResource } from '~/core/resources'; import { Calculated, DateInterval, @@ -26,8 +23,11 @@ import { Sensitivity, SensitivityField, UnsecuredDto, -} from '../../../common'; -import { ScopedRole } from '../../authorization'; +} from '~/common'; +import { BaseNode } from '~/core/database/results'; +import { e } from '~/core/edgedb'; +import { LinkTo, RegisterResource } from '~/core/resources'; +import { ScopedRole } from '../../authorization/dto'; import { ChangesetAware } from '../../changeset/dto'; import { DefinedFile } from '../../file/dto'; import { Product, SecuredMethodologies } from '../../product/dto'; diff --git a/src/components/engagement/dto/list-engagements.dto.ts b/src/components/engagement/dto/list-engagements.dto.ts index ac0b0b2f56..d8d62f3d9d 100644 --- a/src/components/engagement/dto/list-engagements.dto.ts +++ b/src/components/engagement/dto/list-engagements.dto.ts @@ -22,6 +22,8 @@ export abstract class EngagementFilters { readonly type?: 'language' | 'internship'; readonly projectId?: ID; + + readonly partnerId?: ID<'Partner'>; } @InputType() diff --git a/src/components/engagement/engagement.loader.ts b/src/components/engagement/engagement.loader.ts index 953555c897..05afeda238 100644 --- a/src/components/engagement/engagement.loader.ts +++ b/src/components/engagement/engagement.loader.ts @@ -1,5 +1,5 @@ -import { ID, ObjectView } from '../../common'; -import { LoaderFactory, ObjectViewAwareLoader } from '../../core'; +import { ID, ObjectView } from '~/common'; +import { LoaderFactory, ObjectViewAwareLoader } from '~/core'; import { Engagement, IEngagement, diff --git a/src/components/engagement/engagement.repository.ts b/src/components/engagement/engagement.repository.ts index bf89dedc9e..630d73401a 100644 --- a/src/components/engagement/engagement.repository.ts +++ b/src/components/engagement/engagement.repository.ts @@ -15,14 +15,15 @@ import { typenameForView, UnsecuredDto, viewOfChangeset, -} from '../../common'; -import { CommonRepository, OnIndex } from '../../core'; -import { ChangesOf, getChanges } from '../../core/database/changes'; +} from '~/common'; +import { CommonRepository, OnIndex } from '~/core/database'; +import { ChangesOf, getChanges } from '~/core/database/changes'; import { ACTIVE, coalesce, createNode, createRelationships, + filter, INACTIVE, matchChangesetAndChangedProps, matchPropsAndProjectSensAndScopedRoles, @@ -32,10 +33,10 @@ import { requestingUser, sorting, whereNotDeletedInChangeset, -} from '../../core/database/query'; +} from '~/core/database/query'; import { Privileges } from '../authorization'; -import { FileId } from '../file'; -import { ProjectType } from '../project'; +import { FileId } from '../file/dto'; +import { ProjectType } from '../project/dto'; import { CreateInternshipEngagement, CreateLanguageEngagement, @@ -338,7 +339,7 @@ export class EngagementRepository extends CommonRepository { .match([ node('project', 'Project', pickBy({ id: input.filter.projectId })), relation('out', '', 'engagement', ACTIVE), - node('node', 'Engagement'), + node('node', label), ]) .apply(whereNotDeletedInChangeset(changeset)) .return(['node', 'project']) @@ -358,6 +359,21 @@ export class EngagementRepository extends CommonRepository { ), ) .match(requestingUser(session)) + .apply( + filter.builder(input.filter, { + type: filter.skip, + projectId: filter.skip, + partnerId: filter.pathExists((id) => [ + node('node'), + relation('in', '', 'engagement'), + node('', 'Project'), + relation('out', '', 'partnership', ACTIVE), + node('', 'Partnership'), + relation('out', '', 'partner'), + node('', 'Partner', { id }), + ]), + }), + ) .apply( this.privileges.for(session, IEngagement).filterToReadable({ wrapContext: oncePerProject, diff --git a/src/components/engagement/engagement.resolver.ts b/src/components/engagement/engagement.resolver.ts index 2b2b29efda..cb771c98ea 100644 --- a/src/components/engagement/engagement.resolver.ts +++ b/src/components/engagement/engagement.resolver.ts @@ -14,15 +14,12 @@ import { mapSecuredValue, SecuredDateRange, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { CeremonyLoader, SecuredCeremony } from '../ceremony'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { CeremonyLoader } from '../ceremony'; +import { SecuredCeremony } from '../ceremony/dto'; import { ChangesetIds, IdsAndView, IdsAndViewArg } from '../changeset/dto'; -import { - EngagementLoader, - EngagementService, - LanguageEngagementListOutput, -} from '../engagement'; +import { EngagementLoader, EngagementService } from '../engagement'; import { CreateInternshipEngagementInput, CreateInternshipEngagementOutput, @@ -34,6 +31,7 @@ import { EngagementListOutput, IEngagement, LanguageEngagement, + LanguageEngagementListOutput, UpdateInternshipEngagementInput, UpdateInternshipEngagementOutput, UpdateLanguageEngagementInput, diff --git a/src/components/engagement/engagement.rules.ts b/src/components/engagement/engagement.rules.ts index ad182b1254..8488e3a420 100644 --- a/src/components/engagement/engagement.rules.ts +++ b/src/components/engagement/engagement.rules.ts @@ -1,17 +1,19 @@ /* eslint-disable no-case-declarations */ import { Injectable } from '@nestjs/common'; import { node, relation } from 'cypher-query-builder'; -import { first, intersection } from 'lodash'; +import { first, intersection, startCase } from 'lodash'; import { ID, + Role, ServerException, Session, UnauthorizedException, -} from '../../common'; -import { ConfigService, DatabaseService, ILogger, Logger } from '../../core'; -import { ACTIVE, INACTIVE } from '../../core/database/query'; -import { Role, withoutScope } from '../authorization'; -import { ProjectStep } from '../project'; +} from '~/common'; +import { ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; +import { ACTIVE, INACTIVE } from '~/core/database/query'; +import { withoutScope } from '../authorization/dto'; +import { ProjectStep } from '../project/dto'; import { EngagementStatus, EngagementStatusTransition, @@ -33,7 +35,6 @@ const rolesThatCanBypassWorkflow: Role[] = [Role.Administrator]; export class EngagementRules { constructor( private readonly db: DatabaseService, - private readonly config: ConfigService, // eslint-disable-next-line @seedcompany/no-unused-vars @Logger('engagement:rules') private readonly logger: ILogger, ) {} @@ -383,7 +384,9 @@ export class EngagementRules { ); if (!validNextStatus) { throw new UnauthorizedException( - 'This status is not in an authorized sequence', + `One or more engagements cannot be changed to ${startCase( + nextStatus, + )}. Please check engagement statuses.`, 'engagement.status', ); } diff --git a/src/components/engagement/engagement.service.ts b/src/components/engagement/engagement.service.ts index 0ba846bc64..8c7d3671fb 100644 --- a/src/components/engagement/engagement.service.ts +++ b/src/components/engagement/engagement.service.ts @@ -10,7 +10,7 @@ import { Session, UnsecuredDto, viewOfChangeset, -} from '../../common'; +} from '~/common'; import { ConfigService, HandleIdLookup, @@ -18,20 +18,16 @@ import { ILogger, Logger, ResourceLoader, -} from '../../core'; -import { mapListResults } from '../../core/database/results'; +} from '~/core'; +import { mapListResults } from '~/core/database/results'; import { Privileges } from '../authorization'; import { CeremonyService } from '../ceremony'; import { FileService } from '../file'; import { Location } from '../location/dto'; -import { - ProductListInput, - ProductService, - SecuredProductList, -} from '../product'; -import { IProject } from '../project'; -import { ProjectType } from '../project/dto'; -import { ProjectService } from '../project/project.service'; +import { ProductService } from '../product'; +import { ProductListInput, SecuredProductList } from '../product/dto'; +import { ProjectService } from '../project'; +import { IProject, ProjectType } from '../project/dto'; import { User } from '../user/dto'; import { CreateInternshipEngagement, diff --git a/src/components/engagement/events/engagement-created.event.ts b/src/components/engagement/events/engagement-created.event.ts index 3eef6e4b26..2bb6a841b8 100644 --- a/src/components/engagement/events/engagement-created.event.ts +++ b/src/components/engagement/events/engagement-created.event.ts @@ -1,4 +1,4 @@ -import { Session, UnsecuredDto } from '../../../common'; +import { Session, UnsecuredDto } from '~/common'; import { CreateInternshipEngagement, CreateLanguageEngagement, diff --git a/src/components/engagement/events/engagement-updated.event.ts b/src/components/engagement/events/engagement-updated.event.ts index 42080c441e..84b21cc860 100644 --- a/src/components/engagement/events/engagement-updated.event.ts +++ b/src/components/engagement/events/engagement-updated.event.ts @@ -1,4 +1,4 @@ -import { Session, UnsecuredDto } from '../../../common'; +import { Session, UnsecuredDto } from '~/common'; import { Engagement, InternshipEngagement, diff --git a/src/components/engagement/events/engagement-will-delete.event.ts b/src/components/engagement/events/engagement-will-delete.event.ts index d335ffdb38..3e143f5d1a 100644 --- a/src/components/engagement/events/engagement-will-delete.event.ts +++ b/src/components/engagement/events/engagement-will-delete.event.ts @@ -1,4 +1,4 @@ -import { Session } from '../../../common'; +import { Session } from '~/common'; import { Engagement } from '../dto'; export class EngagementWillDeleteEvent { diff --git a/src/components/engagement/handlers/apply-finalized-changeset-to-engagement.handler.ts b/src/components/engagement/handlers/apply-finalized-changeset-to-engagement.handler.ts index e9b0dbc4d3..545b0583e7 100644 --- a/src/components/engagement/handlers/apply-finalized-changeset-to-engagement.handler.ts +++ b/src/components/engagement/handlers/apply-finalized-changeset-to-engagement.handler.ts @@ -1,17 +1,14 @@ import { asyncPool, setOf } from '@seedcompany/common'; import { node, relation } from 'cypher-query-builder'; import { ID, ServerException, Session } from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; +import { ACTIVE, deleteBaseNode, INACTIVE } from '~/core/database/query'; import { - DatabaseService, - EventsHandler, - IEventHandler, - ILogger, - Logger, -} from '../../../core'; -import { ACTIVE, deleteBaseNode, INACTIVE } from '../../../core/database/query'; -import { commitChangesetProps } from '../../changeset/commit-changeset-props.query'; -import { ChangesetFinalizingEvent } from '../../changeset/events'; -import { rejectChangesetProps } from '../../changeset/reject-changeset-props.query'; + ChangesetFinalizingEvent, + commitChangesetProps, + rejectChangesetProps, +} from '../../changeset'; import { EngagementService } from '../engagement.service'; type SubscribedEvent = ChangesetFinalizingEvent; diff --git a/src/components/engagement/handlers/set-initial-end-date.handler.ts b/src/components/engagement/handlers/set-initial-end-date.handler.ts index 8318d01279..cdb3accb56 100644 --- a/src/components/engagement/handlers/set-initial-end-date.handler.ts +++ b/src/components/engagement/handlers/set-initial-end-date.handler.ts @@ -1,10 +1,5 @@ -import { - CalendarDate, - ID, - ServerException, - UnsecuredDto, -} from '../../../common'; -import { EventsHandler, IEventHandler, ILogger, Logger } from '../../../core'; +import { CalendarDate, ID, ServerException, UnsecuredDto } from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; import { Engagement, EngagementStatus, diff --git a/src/components/engagement/handlers/set-last-status-date.handler.ts b/src/components/engagement/handlers/set-last-status-date.handler.ts index ad3359e363..c2e63e9f64 100644 --- a/src/components/engagement/handlers/set-last-status-date.handler.ts +++ b/src/components/engagement/handlers/set-last-status-date.handler.ts @@ -1,12 +1,12 @@ -import { ServerException } from '../../../common'; +import { ServerException } from '~/common'; import { ConfigService, - DatabaseService, EventsHandler, IEventHandler, ILogger, Logger, -} from '../../../core'; +} from '~/core'; +import { DatabaseService } from '~/core/database'; import { EngagementStatus, InternshipEngagement, diff --git a/src/components/engagement/handlers/update-project-status.handler.ts b/src/components/engagement/handlers/update-project-status.handler.ts index 9481371d68..e704dd6888 100644 --- a/src/components/engagement/handlers/update-project-status.handler.ts +++ b/src/components/engagement/handlers/update-project-status.handler.ts @@ -1,12 +1,12 @@ import { MergeExclusive, RequireAtLeastOne } from 'type-fest'; -import { ID, Session, UnsecuredDto } from '../../../common'; -import { EventsHandler, IEventHandler } from '../../../core'; +import { ID, Session, UnsecuredDto } from '~/common'; +import { EventsHandler, IEventHandler } from '~/core'; import { Project, ProjectStatus, ProjectStep, ProjectType, -} from '../../project'; +} from '../../project/dto'; import { ProjectUpdatedEvent } from '../../project/events'; import { EngagementStatus } from '../dto'; import { EngagementRepository } from '../engagement.repository'; @@ -115,22 +115,20 @@ export class UpdateProjectStatusHandler type: ProjectType, session: Session, ) { - await Promise.all( - engagementIds.map(async (id) => { - const updateInput = { - id, - status, - }; - type !== ProjectType.Internship - ? await this.engagementService.updateLanguageEngagement( - updateInput, - session, - ) - : await this.engagementService.updateInternshipEngagement( - updateInput, - session, - ); - }), - ); + for await (const id of engagementIds) { + const updateInput = { + id, + status, + }; + type !== ProjectType.Internship + ? await this.engagementService.updateLanguageEngagement( + updateInput, + session, + ) + : await this.engagementService.updateInternshipEngagement( + updateInput, + session, + ); + } } } diff --git a/src/components/engagement/index.ts b/src/components/engagement/index.ts index d2f7308244..77f7e10093 100644 --- a/src/components/engagement/index.ts +++ b/src/components/engagement/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './engagement.service'; export * from './engagement.rules'; export * from './engagement.loader'; diff --git a/src/components/engagement/internship-engagement.resolver.ts b/src/components/engagement/internship-engagement.resolver.ts index fd246a5761..87d2089284 100644 --- a/src/components/engagement/internship-engagement.resolver.ts +++ b/src/components/engagement/internship-engagement.resolver.ts @@ -1,9 +1,12 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { mapSecuredValue } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { FileNodeLoader, resolveDefinedFile, SecuredFile } from '../file'; -import { LocationLoader, SecuredLocation } from '../location'; -import { SecuredUser, UserLoader } from '../user'; +import { mapSecuredValue } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { FileNodeLoader, resolveDefinedFile } from '../file'; +import { SecuredFile } from '../file/dto'; +import { LocationLoader } from '../location'; +import { SecuredLocation } from '../location/dto'; +import { UserLoader } from '../user'; +import { SecuredUser } from '../user/dto'; import { InternshipEngagement } from './dto'; @Resolver(InternshipEngagement) diff --git a/src/components/engagement/language-engagement.resolver.ts b/src/components/engagement/language-engagement.resolver.ts index 7deec9892b..fd469e4c69 100644 --- a/src/components/engagement/language-engagement.resolver.ts +++ b/src/components/engagement/language-engagement.resolver.ts @@ -5,9 +5,10 @@ import { mapSecuredValue, Session, viewOfChangeset, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { FileNodeLoader, resolveDefinedFile, SecuredFile } from '../file'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { FileNodeLoader, resolveDefinedFile } from '../file'; +import { SecuredFile } from '../file/dto'; import { LanguageLoader } from '../language'; import { SecuredLanguage } from '../language/dto'; import { ProductLoader } from '../product'; diff --git a/src/components/engagement/product-connection.resolver.ts b/src/components/engagement/product-connection.resolver.ts index 1e4a86114e..6cde769873 100644 --- a/src/components/engagement/product-connection.resolver.ts +++ b/src/components/engagement/product-connection.resolver.ts @@ -1,7 +1,7 @@ import { Info, Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { Fields, IsOnlyId } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { Product } from '../product'; +import { Fields, IsOnlyId } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { Product } from '../product/dto'; import { LanguageEngagement } from './dto'; import { EngagementLoader } from './engagement.loader'; diff --git a/src/components/ethno-art/dto/create-ethno-art.dto.ts b/src/components/ethno-art/dto/create-ethno-art.dto.ts index 8fd3c6c9cd..2005795774 100644 --- a/src/components/ethno-art/dto/create-ethno-art.dto.ts +++ b/src/components/ethno-art/dto/create-ethno-art.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { NameField } from '../../../common'; -import { ScriptureField, ScriptureRangeInput } from '../../scripture'; +import { NameField } from '~/common'; +import { ScriptureField, ScriptureRangeInput } from '../../scripture/dto'; import { EthnoArt } from './ethno-art.dto'; @InputType() diff --git a/src/components/ethno-art/dto/delete-ethno-art.dto.ts b/src/components/ethno-art/dto/delete-ethno-art.dto.ts index 0bae908945..e95768c27d 100644 --- a/src/components/ethno-art/dto/delete-ethno-art.dto.ts +++ b/src/components/ethno-art/dto/delete-ethno-art.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteEthnoArtOutput extends MutationPlaceholderOutput {} diff --git a/src/components/ethno-art/dto/ethno-art.dto.ts b/src/components/ethno-art/dto/ethno-art.dto.ts index 368c585e97..ca673b3cf7 100644 --- a/src/components/ethno-art/dto/ethno-art.dto.ts +++ b/src/components/ethno-art/dto/ethno-art.dto.ts @@ -1,14 +1,14 @@ import { ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DbUnique, NameField, Resource, SecuredProps, SecuredString, -} from '../../../common'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { Producible } from '../../product/dto/producible.dto'; declare module '../../product/dto/producible.dto' { diff --git a/src/components/ethno-art/dto/update-ethno-art.dto.ts b/src/components/ethno-art/dto/update-ethno-art.dto.ts index 9aea8a89d2..3bbc6a61d9 100644 --- a/src/components/ethno-art/dto/update-ethno-art.dto.ts +++ b/src/components/ethno-art/dto/update-ethno-art.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; -import { ScriptureField, ScriptureRangeInput } from '../../scripture'; +import { ID, IdField, NameField } from '~/common'; +import { ScriptureField, ScriptureRangeInput } from '../../scripture/dto'; import { EthnoArt } from './ethno-art.dto'; @InputType() diff --git a/src/components/ethno-art/ethno-art.edgedb.repository.ts b/src/components/ethno-art/ethno-art.edgedb.repository.ts new file mode 100644 index 0000000000..605aceaf2f --- /dev/null +++ b/src/components/ethno-art/ethno-art.edgedb.repository.ts @@ -0,0 +1,56 @@ +import { Injectable } from '@nestjs/common'; +import { PublicOf, UnsecuredDto } from '~/common'; +import { e, RepoFor } from '~/core/edgedb'; +import * as scripture from '../scripture/edgedb.utils'; +import { CreateEthnoArt, EthnoArt, UpdateEthnoArt } from './dto'; +import { EthnoArtRepository } from './ethno-art.repository'; + +@Injectable() +export class EthnoArtEdgeDBRepository + extends RepoFor(EthnoArt, { + hydrate: (ethnoArt) => ({ + ...ethnoArt['*'], + scriptureReferences: scripture.hydrate(ethnoArt.scripture), + }), + omit: ['create', 'update'], + }) + implements PublicOf +{ + async create(input: CreateEthnoArt): Promise> { + const query = e.params( + { name: e.str, scripture: e.optional(scripture.type) }, + ($) => { + const created = e.insert(this.resource.db, { + name: $.name, + scripture: scripture.insert($.scripture), + }); + return e.select(created, this.hydrate); + }, + ); + return await this.db.run(query, { + name: input.name, + scripture: scripture.valueOptional(input.scriptureReferences), + }); + } + + async update({ + id, + ...changes + }: UpdateEthnoArt): Promise> { + const query = e.params({ scripture: e.optional(scripture.type) }, ($) => { + const ethnoArt = e.cast(e.EthnoArt, e.uuid(id)); + const updated = e.update(ethnoArt, () => ({ + set: { + ...(changes.name ? { name: changes.name } : {}), + ...(changes.scriptureReferences !== undefined + ? { scripture: scripture.insert($.scripture) } + : {}), + }, + })); + return e.select(updated, this.hydrate); + }); + return await this.db.run(query, { + scripture: scripture.valueOptional(changes.scriptureReferences), + }); + } +} diff --git a/src/components/ethno-art/ethno-art.loader.ts b/src/components/ethno-art/ethno-art.loader.ts index 7bbfb6da80..53d7bf3e54 100644 --- a/src/components/ethno-art/ethno-art.loader.ts +++ b/src/components/ethno-art/ethno-art.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { EthnoArt } from './dto'; import { EthnoArtService } from './ethno-art.service'; diff --git a/src/components/ethno-art/ethno-art.module.ts b/src/components/ethno-art/ethno-art.module.ts index 695a93a4db..b66fbe063d 100644 --- a/src/components/ethno-art/ethno-art.module.ts +++ b/src/components/ethno-art/ethno-art.module.ts @@ -1,6 +1,8 @@ import { forwardRef, Module } from '@nestjs/common'; +import { splitDb } from '~/core'; import { AuthorizationModule } from '../authorization/authorization.module'; import { ScriptureModule } from '../scripture/scripture.module'; +import { EthnoArtEdgeDBRepository } from './ethno-art.edgedb.repository'; import { EthnoArtLoader } from './ethno-art.loader'; import { EthnoArtRepository } from './ethno-art.repository'; import { EthnoArtResolver } from './ethno-art.resolver'; @@ -11,7 +13,7 @@ import { EthnoArtService } from './ethno-art.service'; providers: [ EthnoArtLoader, EthnoArtResolver, - EthnoArtRepository, + splitDb(EthnoArtRepository, EthnoArtEdgeDBRepository), EthnoArtService, ], exports: [EthnoArtService], diff --git a/src/components/ethno-art/ethno-art.repository.ts b/src/components/ethno-art/ethno-art.repository.ts index 7989e13931..fbf5144ebf 100644 --- a/src/components/ethno-art/ethno-art.repository.ts +++ b/src/components/ethno-art/ethno-art.repository.ts @@ -1,16 +1,25 @@ import { Injectable } from '@nestjs/common'; import { Query } from 'cypher-query-builder'; -import { ChangesOf } from '~/core/database/changes'; -import { ID } from '../../common'; -import { DbTypeOf, DtoRepository } from '../../core'; +import { + DuplicateException, + ID, + PaginatedListType, + ServerException, + Session, + UnsecuredDto, +} from '~/common'; +import { DbTypeOf, DtoRepository } from '~/core/database'; import { createNode, matchProps, merge, paginate, sorting, -} from '../../core/database/query'; -import { ScriptureReferenceRepository } from '../scripture'; +} from '~/core/database/query'; +import { + ScriptureReferenceRepository, + ScriptureReferenceService, +} from '../scripture'; import { CreateEthnoArt, EthnoArt, @@ -20,46 +29,95 @@ import { @Injectable() export class EthnoArtRepository extends DtoRepository(EthnoArt) { - constructor(private readonly scriptureRefs: ScriptureReferenceRepository) { + constructor( + private readonly scriptureRefsRepository: ScriptureReferenceRepository, + private readonly scriptureRefsService: ScriptureReferenceService, + ) { super(); } - async create(input: CreateEthnoArt) { + + async create(input: CreateEthnoArt, session: Session) { + if (!(await this.isUnique(input.name))) { + throw new DuplicateException( + 'ethnoArt.name', + 'Ethno art with this name already exists', + ); + } + const initialProps = { name: input.name, canDelete: true, }; - return await this.db + const result = await this.db .query() .apply(await createNode(EthnoArt, { initialProps })) .return<{ id: ID }>('node.id as id') .first(); + + if (!result) { + throw new ServerException('Failed to create ethno art'); + } + + await this.scriptureRefsService.create( + result.id, + input.scriptureReferences, + session, + ); + + return await this.readOne(result.id); } - async update( - existing: EthnoArt, - simpleChanges: Omit< - ChangesOf, - 'scriptureReferences' - >, - ) { - await this.updateProperties(existing, simpleChanges); + async update(input: UpdateEthnoArt) { + const { id, name, scriptureReferences } = input; + await this.updateProperties({ id }, { name }); + if (scriptureReferences !== undefined) { + await this.scriptureRefsService.update(id, scriptureReferences); + } + return await this.readOne(input.id); + } + + async readOne(id: ID) { + return (await super.readOne(id)) as UnsecuredDto; } - async list(input: EthnoArtListInput) { + async readMany( + ids: readonly ID[], + ): Promise>> { + const items = await super.readMany(ids); + return items.map((r) => ({ + ...r, + scriptureReferences: this.scriptureRefsService.parseList( + r.scriptureReferences, + ), + })); + } + + async list({ + filter, + ...input + }: EthnoArtListInput): Promise>> { const result = await this.db .query() .matchNode('node', 'EthnoArt') .apply(sorting(EthnoArt, input)) .apply(paginate(input, this.hydrate())) .first(); - return result!; // result from paginate() will always have 1 row. + return { + ...result!, + items: result!.items.map((r) => ({ + ...r, + scriptureReferences: this.scriptureRefsService.parseList( + r.scriptureReferences, + ), + })), + }; } protected hydrate() { return (query: Query) => query .apply(matchProps()) - .subQuery('node', this.scriptureRefs.list()) + .subQuery('node', this.scriptureRefsRepository.list()) .return<{ dto: DbTypeOf }>( merge('props', { scriptureReferences: 'scriptureReferences', diff --git a/src/components/ethno-art/ethno-art.resolver.ts b/src/components/ethno-art/ethno-art.resolver.ts index 44b8d0e5c9..677081bb38 100644 --- a/src/components/ethno-art/ethno-art.resolver.ts +++ b/src/components/ethno-art/ethno-art.resolver.ts @@ -6,16 +6,13 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { - DeleteEthnoArtOutput, - EthnoArtLoader, - EthnoArtService, -} from '../ethno-art'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { EthnoArtLoader, EthnoArtService } from '../ethno-art'; import { CreateEthnoArtInput, CreateEthnoArtOutput, + DeleteEthnoArtOutput, EthnoArt, EthnoArtListInput, EthnoArtListOutput, diff --git a/src/components/ethno-art/ethno-art.service.ts b/src/components/ethno-art/ethno-art.service.ts index 257249b170..a9c3c19dcc 100644 --- a/src/components/ethno-art/ethno-art.service.ts +++ b/src/components/ethno-art/ethno-art.service.ts @@ -1,20 +1,20 @@ import { Injectable } from '@nestjs/common'; import { - DuplicateException, ID, ObjectView, ServerException, Session, -} from '../../common'; -import { DbTypeOf, HandleIdLookup, ILogger, Logger } from '../../core'; -import { ifDiff } from '../../core/database/changes'; -import { mapListResults } from '../../core/database/results'; + UnsecuredDto, +} from '~/common'; +import { HandleIdLookup } from '~/core'; +import { ifDiff } from '~/core/database/changes'; import { Privileges } from '../authorization'; -import { isScriptureEqual, ScriptureReferenceService } from '../scripture'; +import { isScriptureEqual } from '../scripture'; import { CreateEthnoArt, EthnoArt, EthnoArtListInput, + EthnoArtListOutput, UpdateEthnoArt, } from './dto'; import { EthnoArtRepository } from './ethno-art.repository'; @@ -22,42 +22,14 @@ import { EthnoArtRepository } from './ethno-art.repository'; @Injectable() export class EthnoArtService { constructor( - @Logger('ethno-art:service') private readonly logger: ILogger, - private readonly scriptureRefs: ScriptureReferenceService, private readonly privileges: Privileges, private readonly repo: EthnoArtRepository, ) {} async create(input: CreateEthnoArt, session: Session): Promise { - this.privileges.for(session, EthnoArt).verifyCan('create'); - if (!(await this.repo.isUnique(input.name))) { - throw new DuplicateException( - 'ethnoArt.name', - 'Ethno art with this name already exists', - ); - } - - try { - const result = await this.repo.create(input); - - if (!result) { - throw new ServerException('Failed to create ethno art'); - } - - await this.scriptureRefs.create( - result.id, - input.scriptureReferences, - session, - ); - - this.logger.debug(`ethno art created`, { id: result.id }); - return await this.readOne(result.id, session); - } catch (exception) { - this.logger.error('Could not create ethno art', { - exception, - }); - throw new ServerException('Could not create ethno art', exception); - } + const dto = await this.repo.create(input, session); + this.privileges.for(session, EthnoArt, dto).verifyCan('create'); + return this.secure(dto, session); } @HandleIdLookup(EthnoArt) @@ -67,67 +39,53 @@ export class EthnoArtService { _view?: ObjectView, ): Promise { const result = await this.repo.readOne(id); - return await this.secure(result, session); + return this.secure(result, session); } async readMany(ids: readonly ID[], session: Session) { const ethnoArt = await this.repo.readMany(ids); - return await Promise.all(ethnoArt.map((dto) => this.secure(dto, session))); + return ethnoArt.map((dto) => this.secure(dto, session)); } - private async secure( - dto: DbTypeOf, - session: Session, - ): Promise { - return this.privileges.for(session, EthnoArt).secure({ - ...dto, - scriptureReferences: this.scriptureRefs.parseList( - dto.scriptureReferences, - ), - }); + private secure(dto: UnsecuredDto, session: Session): EthnoArt { + return this.privileges.for(session, EthnoArt).secure(dto); } async update(input: UpdateEthnoArt, session: Session): Promise { - const ethnoArt = await this.readOne(input.id, session); - + const ethnoArt = await this.repo.readOne(input.id); const changes = { ...this.repo.getActualChanges(ethnoArt, input), scriptureReferences: ifDiff(isScriptureEqual)( input.scriptureReferences, - ethnoArt.scriptureReferences.value, + ethnoArt.scriptureReferences, ), }; - this.privileges.for(session, EthnoArt, ethnoArt).verifyChanges(changes); - const { scriptureReferences, ...simpleChanges } = changes; - - await this.scriptureRefs.update(input.id, scriptureReferences); - - await this.repo.update(ethnoArt, simpleChanges); - - return await this.readOne(input.id, session); + const updated = await this.repo.update({ id: input.id, ...changes }); + return this.secure(updated, session); } async delete(id: ID, session: Session): Promise { - const ethnoArt = await this.readOne(id, session); + const ethnoArt = await this.repo.readOne(id); this.privileges.for(session, EthnoArt, ethnoArt).verifyCan('delete'); try { await this.repo.deleteNode(ethnoArt); } catch (exception) { - this.logger.error('Failed to delete', { id, exception }); throw new ServerException('Failed to delete', exception); } - - this.logger.debug(`deleted ethnoArt with id`, { id }); } - async list(input: EthnoArtListInput, session: Session) { - // -- don't need a check for canList. all roles are allowed to see at least one prop, - // and this isn't a sensitive component. + async list( + input: EthnoArtListInput, + session: Session, + ): Promise { const results = await this.repo.list(input); - return await mapListResults(results, (dto) => this.secure(dto, session)); + return { + ...results, + items: results.items.map((dto) => this.secure(dto, session)), + }; } } diff --git a/src/components/ethno-art/index.ts b/src/components/ethno-art/index.ts index 2a5b145a69..7b652e959e 100644 --- a/src/components/ethno-art/index.ts +++ b/src/components/ethno-art/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './ethno-art.loader'; export * from './ethno-art.resolver'; export * from './ethno-art.service'; diff --git a/src/components/field-region/dto/create-field-region.dto.ts b/src/components/field-region/dto/create-field-region.dto.ts index fc07a8fd40..bd2bc9d9ae 100644 --- a/src/components/field-region/dto/create-field-region.dto.ts +++ b/src/components/field-region/dto/create-field-region.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; import { FieldRegion } from './field-region.dto'; @InputType() diff --git a/src/components/field-region/dto/delete-field-region.dto.ts b/src/components/field-region/dto/delete-field-region.dto.ts index 5b2ac549dc..cdcfc1906f 100644 --- a/src/components/field-region/dto/delete-field-region.dto.ts +++ b/src/components/field-region/dto/delete-field-region.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteFieldRegionOutput extends MutationPlaceholderOutput {} diff --git a/src/components/field-region/dto/update-field-region.dto.ts b/src/components/field-region/dto/update-field-region.dto.ts index c64a664ce4..650d5d5763 100644 --- a/src/components/field-region/dto/update-field-region.dto.ts +++ b/src/components/field-region/dto/update-field-region.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; import { FieldRegion } from './field-region.dto'; @InputType() diff --git a/src/components/field-region/field-region.loader.ts b/src/components/field-region/field-region.loader.ts index eb7f35b346..a8db3adeec 100644 --- a/src/components/field-region/field-region.loader.ts +++ b/src/components/field-region/field-region.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { FieldRegion } from './dto'; import { FieldRegionService } from './field-region.service'; diff --git a/src/components/field-region/field-region.repository.ts b/src/components/field-region/field-region.repository.ts index 3b9e5bb833..ff1d1b11ea 100644 --- a/src/components/field-region/field-region.repository.ts +++ b/src/components/field-region/field-region.repository.ts @@ -8,7 +8,7 @@ import { Session, UnsecuredDto, } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, diff --git a/src/components/field-region/field-region.resolver.ts b/src/components/field-region/field-region.resolver.ts index b982859797..da522a5f35 100644 --- a/src/components/field-region/field-region.resolver.ts +++ b/src/components/field-region/field-region.resolver.ts @@ -14,10 +14,12 @@ import { LoggedInSession, mapSecuredValue, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { FieldZoneLoader, SecuredFieldZone } from '../field-zone'; -import { SecuredUser, UserLoader } from '../user'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { FieldZoneLoader } from '../field-zone'; +import { SecuredFieldZone } from '../field-zone/dto'; +import { UserLoader } from '../user'; +import { SecuredUser } from '../user/dto'; import { CreateFieldRegionInput, CreateFieldRegionOutput, diff --git a/src/components/field-region/index.ts b/src/components/field-region/index.ts index 479a3f48b5..bfc8c8a686 100644 --- a/src/components/field-region/index.ts +++ b/src/components/field-region/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './field-region.service'; export * from './field-region.loader'; diff --git a/src/components/field-zone/dto/create-field-zone.dto.ts b/src/components/field-zone/dto/create-field-zone.dto.ts index 749c4ff040..97fcfd9bae 100644 --- a/src/components/field-zone/dto/create-field-zone.dto.ts +++ b/src/components/field-zone/dto/create-field-zone.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; import { FieldZone } from './field-zone.dto'; @InputType() diff --git a/src/components/field-zone/dto/delete-field-zone.dto.ts b/src/components/field-zone/dto/delete-field-zone.dto.ts index 412afa8525..214debf076 100644 --- a/src/components/field-zone/dto/delete-field-zone.dto.ts +++ b/src/components/field-zone/dto/delete-field-zone.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteFieldZoneOutput extends MutationPlaceholderOutput {} diff --git a/src/components/field-zone/dto/field-zone.dto.ts b/src/components/field-zone/dto/field-zone.dto.ts index 47078a19a7..0d794d004b 100644 --- a/src/components/field-zone/dto/field-zone.dto.ts +++ b/src/components/field-zone/dto/field-zone.dto.ts @@ -1,7 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { LinkTo, RegisterResource } from '~/core/resources'; import { DbUnique, NameField, @@ -10,7 +8,9 @@ import { SecuredProperty, SecuredProps, SecuredString, -} from '../../../common'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { LinkTo, RegisterResource } from '~/core/resources'; @RegisterResource({ db: e.FieldZone }) @ObjectType({ diff --git a/src/components/field-zone/dto/update-field-zone.dto.ts b/src/components/field-zone/dto/update-field-zone.dto.ts index a03554300a..5427dfc32b 100644 --- a/src/components/field-zone/dto/update-field-zone.dto.ts +++ b/src/components/field-zone/dto/update-field-zone.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; import { FieldZone } from './field-zone.dto'; @InputType() diff --git a/src/components/field-zone/field-zone.loader.ts b/src/components/field-zone/field-zone.loader.ts index 78cb446913..268090c8c0 100644 --- a/src/components/field-zone/field-zone.loader.ts +++ b/src/components/field-zone/field-zone.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { FieldZone } from './dto'; import { FieldZoneService } from './field-zone.service'; diff --git a/src/components/field-zone/field-zone.repository.ts b/src/components/field-zone/field-zone.repository.ts index b5fcb9ef77..22a79a0763 100644 --- a/src/components/field-zone/field-zone.repository.ts +++ b/src/components/field-zone/field-zone.repository.ts @@ -8,8 +8,8 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { DtoRepository } from '../../core'; +} from '~/common'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, @@ -19,7 +19,7 @@ import { paginate, requestingUser, sorting, -} from '../../core/database/query'; +} from '~/core/database/query'; import { CreateFieldZone, FieldZone, diff --git a/src/components/field-zone/field-zone.resolver.ts b/src/components/field-zone/field-zone.resolver.ts index 0170cbbd1f..6927117405 100644 --- a/src/components/field-zone/field-zone.resolver.ts +++ b/src/components/field-zone/field-zone.resolver.ts @@ -14,9 +14,10 @@ import { LoggedInSession, mapSecuredValue, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { SecuredUser, UserLoader } from '../user'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { UserLoader } from '../user'; +import { SecuredUser } from '../user/dto'; import { CreateFieldZoneInput, CreateFieldZoneOutput, diff --git a/src/components/field-zone/field-zone.service.ts b/src/components/field-zone/field-zone.service.ts index 21b46c149e..d85a02530b 100644 --- a/src/components/field-zone/field-zone.service.ts +++ b/src/components/field-zone/field-zone.service.ts @@ -5,8 +5,8 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger } from '../../core'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger } from '~/core'; import { Privileges } from '../authorization'; import { CreateFieldZone, diff --git a/src/components/field-zone/index.ts b/src/components/field-zone/index.ts index 54ef01da21..a91d4db486 100644 --- a/src/components/field-zone/index.ts +++ b/src/components/field-zone/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './field-zone.service'; export * from './field-zone.loader'; diff --git a/src/components/file/bucket/filesystem-bucket.ts b/src/components/file/bucket/filesystem-bucket.ts index 559d4c4b18..54c8fdaa85 100644 --- a/src/components/file/bucket/filesystem-bucket.ts +++ b/src/components/file/bucket/filesystem-bucket.ts @@ -1,6 +1,6 @@ import { promises as fs } from 'fs'; import { dirname, join } from 'path'; -import { NotFoundException } from '../../../common'; +import { NotFoundException } from '~/common'; import { FakeAwsFile, LocalBucket, LocalBucketOptions } from './local-bucket'; export interface FilesystemBucketOptions extends LocalBucketOptions { diff --git a/src/components/file/bucket/local-bucket.ts b/src/components/file/bucket/local-bucket.ts index ab9dff0122..d5d19424e5 100644 --- a/src/components/file/bucket/local-bucket.ts +++ b/src/components/file/bucket/local-bucket.ts @@ -8,6 +8,7 @@ import { Command } from '@smithy/smithy-client'; import { pickBy } from 'lodash'; import { DateTime, Duration } from 'luxon'; import { URL } from 'node:url'; +import { firstValueFrom, Observable } from 'rxjs'; import { Readable } from 'stream'; import { assert } from 'ts-essentials'; import { @@ -19,7 +20,7 @@ import { } from './file-bucket'; export interface LocalBucketOptions { - baseUrl: URL; + baseUrl: Observable; } export type FakeAwsFile = Required> & @@ -96,7 +97,8 @@ export abstract class LocalBucket< .toMillis(), }, }); - const url = new URL(this.options.baseUrl.toString()); + const baseUrl = await firstValueFrom(this.options.baseUrl); + const url = new URL(baseUrl.toString()); url.searchParams.set('signed', signed); return url.toString(); } diff --git a/src/components/file/bucket/memory-bucket.ts b/src/components/file/bucket/memory-bucket.ts index 02be882bae..b1cb8e7106 100644 --- a/src/components/file/bucket/memory-bucket.ts +++ b/src/components/file/bucket/memory-bucket.ts @@ -1,5 +1,5 @@ import { Readable } from 'stream'; -import { NotFoundException } from '../../../common'; +import { NotFoundException } from '~/common'; import { FakeAwsFile, LocalBucket } from './local-bucket'; /** diff --git a/src/components/file/directory.resolver.ts b/src/components/file/directory.resolver.ts index 8113774f50..621535ef1c 100644 --- a/src/components/file/directory.resolver.ts +++ b/src/components/file/directory.resolver.ts @@ -14,9 +14,10 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { User, UserLoader } from '../user'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { UserLoader } from '../user'; +import { User } from '../user/dto'; import { asDirectory, CreateDirectoryInput, diff --git a/src/components/file/dto/delete.dto.ts b/src/components/file/dto/delete.dto.ts index ce4e7087a1..96d8c5b6dc 100644 --- a/src/components/file/dto/delete.dto.ts +++ b/src/components/file/dto/delete.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteFileNodeOutput extends MutationPlaceholderOutput {} diff --git a/src/components/file/dto/node.ts b/src/components/file/dto/node.ts index 9e7278bfb7..24c05e04ca 100644 --- a/src/components/file/dto/node.ts +++ b/src/components/file/dto/node.ts @@ -5,9 +5,6 @@ import { DateTime } from 'luxon'; import { Readable } from 'stream'; import { keys as keysOf } from 'ts-transformer-keys'; import { MergeExclusive } from 'type-fest'; -import { BaseNode } from '~/core/database/results'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DateTimeField, DbLabel, @@ -20,7 +17,10 @@ import { SecuredProperty, SecuredProps, ServerException, -} from '../../../common'; +} from '~/common'; +import { BaseNode } from '~/core/database/results'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { FileNodeType } from './file-node-type.enum'; /** diff --git a/src/components/file/dto/update.dto.ts b/src/components/file/dto/update.dto.ts index 2748c9232b..489a021abf 100644 --- a/src/components/file/dto/update.dto.ts +++ b/src/components/file/dto/update.dto.ts @@ -1,6 +1,6 @@ import { Field, InputType } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; @InputType() export abstract class RenameFileInput { diff --git a/src/components/file/file-node.loader.ts b/src/components/file/file-node.loader.ts index 46af2552f6..dc4ebcd9dc 100644 --- a/src/components/file/file-node.loader.ts +++ b/src/components/file/file-node.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Directory, File, FileNode, FileVersion } from './dto'; import { FileService } from './file.service'; diff --git a/src/components/file/file-node.resolver.ts b/src/components/file/file-node.resolver.ts index 12417a28cf..091b997bb3 100644 --- a/src/components/file/file-node.resolver.ts +++ b/src/components/file/file-node.resolver.ts @@ -1,8 +1,9 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { AnonSession, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { User, UserLoader } from '../user'; +import { AnonSession, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { UserLoader } from '../user'; +import { User } from '../user/dto'; import { FileNode, IFileNode, isDirectory } from './dto'; import { FileService } from './file.service'; import { MediaByFileVersionLoader } from './media/media-by-file-version.loader'; diff --git a/src/components/file/file-version.resolver.ts b/src/components/file/file-version.resolver.ts index 63ee47bfca..e2594f81f1 100644 --- a/src/components/file/file-version.resolver.ts +++ b/src/components/file/file-version.resolver.ts @@ -1,6 +1,4 @@ -import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { stripIndent } from 'common-tags'; -import { URL } from 'url'; +import { Parent, Resolver } from '@nestjs/graphql'; import { FileVersion } from './dto'; import * as FileUrl from './file-url.resolver-util'; import { FileService } from './file.service'; @@ -16,16 +14,4 @@ export class FileVersionResolver { ) { return await this.service.getUrl(node, download); } - - @ResolveField(() => URL, { - description: 'A direct url to download the file version', - deprecationReason: stripIndent` - Use \`url\` instead. - - Note while this url is anonymous, the new field, \`url\` is not. - `, - }) - downloadUrl(@Parent() node: FileVersion): Promise { - return this.service.getDownloadUrl(node); - } } diff --git a/src/components/file/file.repository.ts b/src/components/file/file.repository.ts index 5498fa93b3..4dcb29d1e8 100644 --- a/src/components/file/file.repository.ts +++ b/src/components/file/file.repository.ts @@ -13,8 +13,9 @@ import { import { Direction } from 'cypher-query-builder/dist/typings/clauses/order-by'; import { AnyConditions } from 'cypher-query-builder/dist/typings/clauses/where-utils'; import { DateTime } from 'luxon'; -import { ID, NotFoundException, ServerException, Session } from '../../common'; -import { CommonRepository, ILogger, LinkTo, Logger, OnIndex } from '../../core'; +import { ID, NotFoundException, ServerException, Session } from '~/common'; +import { ILogger, LinkTo, Logger } from '~/core'; +import { CommonRepository, OnIndex } from '~/core/database'; import { ACTIVE, createNode, @@ -25,8 +26,8 @@ import { paginate, sorting, variable, -} from '../../core/database/query'; -import { BaseNode } from '../../core/database/results'; +} from '~/core/database/query'; +import { BaseNode } from '~/core/database/results'; import { Directory, File, diff --git a/src/components/file/file.resolver.ts b/src/components/file/file.resolver.ts index 3215558a21..52ecf87699 100644 --- a/src/components/file/file.resolver.ts +++ b/src/components/file/file.resolver.ts @@ -7,7 +7,6 @@ import { Resolver, } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { URL } from 'url'; import { AnonSession, ID, @@ -15,9 +14,10 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { User, UserLoader } from '../user'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { UserLoader } from '../user'; +import { User } from '../user/dto'; import { asFile, CreateFileVersionInput, @@ -81,18 +81,6 @@ export class FileResolver { return await this.service.getUrl(node, download); } - @ResolveField(() => URL, { - description: 'A direct url to download the file', - deprecationReason: stripIndent` - Use \`url\` instead. - - Note while this url is anonymous, the new field, \`url\` is not. - `, - }) - downloadUrl(@Parent() node: File): Promise { - return this.service.getDownloadUrl(node); - } - @Mutation(() => DeleteFileNodeOutput, { description: 'Delete a file node', }) diff --git a/src/components/file/file.service.ts b/src/components/file/file.service.ts index a64d2f6da4..6fd4d64aa2 100644 --- a/src/components/file/file.service.ts +++ b/src/components/file/file.service.ts @@ -24,14 +24,8 @@ import { UnauthorizedException, } from '~/common'; import { withAddedPath } from '~/common/url.util'; -import { - ConfigService, - IEventBus, - ILogger, - LinkTo, - Logger, - RollbackManager, -} from '~/core'; +import { ConfigService, IEventBus, ILogger, LinkTo, Logger } from '~/core'; +import { RollbackManager } from '~/core/database'; import { FileBucket } from './bucket'; import { CreateDefinedFileVersionInput, @@ -150,7 +144,7 @@ export class FileService { async getUrl(node: FileNode, download: boolean) { const url = withAddedPath( - this.config.hostUrl, + this.config.hostUrl$.value, FileUrl.path, isFile(node) ? node.latestVersionId : node.id, encodeURIComponent(node.name), diff --git a/src/components/file/files-bucket.factory.ts b/src/components/file/files-bucket.factory.ts index f1ba617169..b7d444bc06 100644 --- a/src/components/file/files-bucket.factory.ts +++ b/src/components/file/files-bucket.factory.ts @@ -1,8 +1,9 @@ import { S3 } from '@aws-sdk/client-s3'; import { FactoryProvider } from '@nestjs/common'; import { resolve } from 'path'; +import { map } from 'rxjs/operators'; import { withAddedPath } from '~/common/url.util'; -import { ConfigService } from '../../core'; +import { ConfigService } from '~/core'; import { CompositeBucket, FileBucket, @@ -21,7 +22,9 @@ export const FilesBucketFactory: FactoryProvider = { useFactory: (s3: S3, config: ConfigService) => { const { sources } = config.files; - const baseUrl = withAddedPath(config.hostUrl, LocalBucketController.path); + const baseUrl = config.hostUrl$.pipe( + map((hostUrl) => withAddedPath(hostUrl, LocalBucketController.path)), + ); const files: FileFactory = ({ path }) => new FilesystemBucket({ diff --git a/src/components/file/handlers/attach-project-root-directory.handler.ts b/src/components/file/handlers/attach-project-root-directory.handler.ts index 7e5a55b2c1..529fad6f44 100644 --- a/src/components/file/handlers/attach-project-root-directory.handler.ts +++ b/src/components/file/handlers/attach-project-root-directory.handler.ts @@ -1,4 +1,4 @@ -import { DatabaseService, EventsHandler, IEventHandler } from '~/core'; +import { EventsHandler, IEventHandler } from '~/core'; import { ProjectCreatedEvent } from '../../project/events'; import { FileService } from '../file.service'; @@ -6,10 +6,7 @@ import { FileService } from '../file.service'; export class AttachProjectRootDirectoryHandler implements IEventHandler { - constructor( - private readonly files: FileService, - private readonly db: DatabaseService, - ) {} + constructor(private readonly files: FileService) {} async handle(event: ProjectCreatedEvent) { const { project, session } = event; diff --git a/src/components/file/handlers/detach-project-root-directory.handler.ts b/src/components/file/handlers/detach-project-root-directory.handler.ts index 1d7e2b975d..51a20e9dba 100644 --- a/src/components/file/handlers/detach-project-root-directory.handler.ts +++ b/src/components/file/handlers/detach-project-root-directory.handler.ts @@ -1,4 +1,4 @@ -import { EventsHandler, IEventHandler } from '../../../core'; +import { EventsHandler, IEventHandler } from '~/core'; import { ProjectCreatedEvent, ProjectDeletedEvent } from '../../project/events'; @EventsHandler(ProjectDeletedEvent) diff --git a/src/components/file/index.ts b/src/components/file/index.ts index a287410ab1..7034574f03 100644 --- a/src/components/file/index.ts +++ b/src/components/file/index.ts @@ -1,5 +1,3 @@ -export * from './dto'; -export * from './media/media.dto'; export * from './file.service'; export * from './resolve-defined-file'; export * from './file-node.loader'; diff --git a/src/components/file/local-bucket.controller.ts b/src/components/file/local-bucket.controller.ts index 03a4649376..9e08818cf9 100644 --- a/src/components/file/local-bucket.controller.ts +++ b/src/components/file/local-bucket.controller.ts @@ -5,6 +5,7 @@ import { Put, Request, Response, + StreamableFile, } from '@nestjs/common'; import { Request as IRequest, Response as IResponse } from 'express'; import { DateTime } from 'luxon'; @@ -49,7 +50,10 @@ export class LocalBucketController { } @Get() - async download(@Request() req: IRequest, @Response() res: IResponse) { + async download( + @Request() req: IRequest, + @Response({ passthrough: true }) res: IResponse, + ) { const url = new URL(`https://localhost${req.url}`); const { Key, operation, ...rest } = await this.bucket.parseSignedUrl(url); if (operation !== 'GetObject') { @@ -84,6 +88,6 @@ export class LocalBucketController { } } - out.Body.pipe(res); + return new StreamableFile(out.Body); } } diff --git a/src/components/file/media/media.repository.ts b/src/components/file/media/media.repository.ts index 873851cf63..a50d03f1e3 100644 --- a/src/components/file/media/media.repository.ts +++ b/src/components/file/media/media.repository.ts @@ -8,7 +8,7 @@ import { NotFoundException, ServerException, } from '~/common'; -import { CommonRepository } from '~/core'; +import { CommonRepository } from '~/core/database'; import { ACTIVE, apoc, merge } from '~/core/database/query'; import { AnyMedia, MediaUserMetadata, resolveMedia } from './media.dto'; diff --git a/src/components/film/dto/create-film.dto.ts b/src/components/film/dto/create-film.dto.ts index ea74ea8b52..5b623c7eca 100644 --- a/src/components/film/dto/create-film.dto.ts +++ b/src/components/film/dto/create-film.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { NameField } from '../../../common'; -import { ScriptureField, ScriptureRangeInput } from '../../scripture'; +import { NameField } from '~/common'; +import { ScriptureField, ScriptureRangeInput } from '../../scripture/dto'; import { Film } from './film.dto'; @InputType() diff --git a/src/components/film/dto/delete-film.dto.ts b/src/components/film/dto/delete-film.dto.ts index e89fb30b2e..9cda92824b 100644 --- a/src/components/film/dto/delete-film.dto.ts +++ b/src/components/film/dto/delete-film.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteFilmOutput extends MutationPlaceholderOutput {} diff --git a/src/components/film/dto/film.dto.ts b/src/components/film/dto/film.dto.ts index eb88fb6532..5e86f5122d 100644 --- a/src/components/film/dto/film.dto.ts +++ b/src/components/film/dto/film.dto.ts @@ -1,14 +1,14 @@ import { ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DbUnique, NameField, Resource, SecuredProps, SecuredString, -} from '../../../common'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { Producible } from '../../product/dto/producible.dto'; declare module '../../product/dto/producible.dto' { diff --git a/src/components/film/dto/update-film.dto.ts b/src/components/film/dto/update-film.dto.ts index 5bf96352cb..7ffe0f97d6 100644 --- a/src/components/film/dto/update-film.dto.ts +++ b/src/components/film/dto/update-film.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; -import { ScriptureField, ScriptureRangeInput } from '../../scripture'; +import { ID, IdField, NameField } from '~/common'; +import { ScriptureField, ScriptureRangeInput } from '../../scripture/dto'; import { Film } from './film.dto'; @InputType() diff --git a/src/components/film/film.edgedb.repository.ts b/src/components/film/film.edgedb.repository.ts new file mode 100644 index 0000000000..fbdb32209b --- /dev/null +++ b/src/components/film/film.edgedb.repository.ts @@ -0,0 +1,53 @@ +import { Injectable } from '@nestjs/common'; +import { PublicOf, UnsecuredDto } from '~/common'; +import { e, RepoFor } from '~/core/edgedb'; +import * as scripture from '../scripture/edgedb.utils'; +import { CreateFilm, Film, UpdateFilm } from './dto'; +import { FilmRepository } from './film.repository'; + +@Injectable() +export class FilmEdgedbRepository + extends RepoFor(Film, { + hydrate: (film) => ({ + ...film['*'], + scriptureReferences: scripture.hydrate(film.scripture), + }), + omit: ['create', 'update'], + }) + implements PublicOf +{ + async create(input: CreateFilm): Promise> { + const query = e.params( + { name: e.str, scripture: e.optional(scripture.type) }, + ($) => { + const created = e.insert(this.resource.db, { + name: $.name, + scripture: scripture.insert($.scripture), + }); + return e.select(created, this.hydrate); + }, + ); + return await this.db.run(query, { + name: input.name, + scripture: scripture.valueOptional(input.scriptureReferences), + }); + } + + async update({ id, ...changes }: UpdateFilm): Promise> { + const query = e.params({ scripture: e.optional(scripture.type) }, ($) => { + const film = e.cast(e.Film, e.uuid(id)); + const updated = e.update(film, () => ({ + set: { + ...(changes.name ? { name: changes.name } : {}), + ...(changes.scriptureReferences !== undefined + ? { scripture: scripture.insert($.scripture) } + : {}), + }, + })); + return e.select(updated, this.hydrate); + }); + return await this.db.run(query, { + scripture: scripture.valueOptional(changes.scriptureReferences), + }); + } +} diff --git a/src/components/film/film.loader.ts b/src/components/film/film.loader.ts index 9953ed03e2..a8962358ce 100644 --- a/src/components/film/film.loader.ts +++ b/src/components/film/film.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Film } from './dto'; import { FilmService } from './film.service'; diff --git a/src/components/film/film.module.ts b/src/components/film/film.module.ts index 0af767dc1d..bc14c96bc2 100644 --- a/src/components/film/film.module.ts +++ b/src/components/film/film.module.ts @@ -1,6 +1,8 @@ import { forwardRef, Module } from '@nestjs/common'; +import { splitDb } from '~/core'; import { AuthorizationModule } from '../authorization/authorization.module'; import { ScriptureModule } from '../scripture'; +import { FilmEdgedbRepository } from './film.edgedb.repository'; import { FilmLoader } from './film.loader'; import { FilmRepository } from './film.repository'; import { FilmResolver } from './film.resolver'; @@ -8,7 +10,12 @@ import { FilmService } from './film.service'; @Module({ imports: [forwardRef(() => AuthorizationModule), ScriptureModule], - providers: [FilmResolver, FilmService, FilmRepository, FilmLoader], + providers: [ + FilmResolver, + FilmService, + splitDb(FilmRepository, FilmEdgedbRepository), + FilmLoader, + ], exports: [FilmService], }) export class FilmModule {} diff --git a/src/components/film/film.repository.ts b/src/components/film/film.repository.ts index fbedc16804..c45771db8e 100644 --- a/src/components/film/film.repository.ts +++ b/src/components/film/film.repository.ts @@ -1,60 +1,118 @@ import { Injectable } from '@nestjs/common'; -import { node, Query } from 'cypher-query-builder'; -import { ChangesOf } from '~/core/database/changes'; -import { ID, Session } from '../../common'; -import { DbTypeOf, DtoRepository } from '../../core'; +import { Query } from 'cypher-query-builder'; +import { + DuplicateException, + ID, + PaginatedListType, + ServerException, + Session, + UnsecuredDto, +} from '~/common'; +import { DbTypeOf, DtoRepository } from '~/core/database'; import { createNode, matchProps, merge, paginate, - requestingUser, sorting, -} from '../../core/database/query'; -import { ScriptureReferenceRepository } from '../scripture'; +} from '~/core/database/query'; +import { + ScriptureReferenceRepository, + ScriptureReferenceService, +} from '../scripture'; import { CreateFilm, Film, FilmListInput, UpdateFilm } from './dto'; @Injectable() export class FilmRepository extends DtoRepository(Film) { - constructor(private readonly scriptureRefs: ScriptureReferenceRepository) { + constructor( + private readonly scriptureRefsRepository: ScriptureReferenceRepository, + private readonly scriptureRefsService: ScriptureReferenceService, + ) { super(); } - async create(input: CreateFilm) { + async create(input: CreateFilm, session: Session) { + if (!(await this.isUnique(input.name))) { + throw new DuplicateException( + 'film.name', + 'Film with this name already exists', + ); + } + const initialProps = { name: input.name, canDelete: true, }; - return await this.db + const result = await this.db .query() .apply(await createNode(Film, { initialProps })) .return<{ id: ID }>('node.id as id') .first(); + + if (!result) { + throw new ServerException('failed to create a film'); + } + + await this.scriptureRefsService.create( + result.id, + input.scriptureReferences, + session, + ); + + return await this.readOne(result.id); } - async update( - existing: Film, - simpleChanges: Omit, 'scriptureReferences'>, - ) { - await this.updateProperties(existing, simpleChanges); + async update(input: UpdateFilm) { + const { id, name, scriptureReferences } = input; + await this.updateProperties({ id }, { name }); + if (scriptureReferences !== undefined) { + await this.scriptureRefsService.update(id, scriptureReferences); + } + return await this.readOne(input.id); + } + + async readOne(id: ID) { + return (await super.readOne(id)) as UnsecuredDto; } - async list({ filter, ...input }: FilmListInput, session: Session) { + async readMany( + ids: readonly ID[], + ): Promise>> { + const items = await super.readMany(ids); + return items.map((r) => ({ + ...r, + scriptureReferences: this.scriptureRefsService.parseList( + r.scriptureReferences, + ), + })); + } + + async list({ + filter, + ...input + }: FilmListInput): Promise>> { const result = await this.db .query() - .match(requestingUser(session)) - .match(node('node', 'Film')) + .matchNode('node', 'Film') .apply(sorting(Film, input)) .apply(paginate(input, this.hydrate())) .first(); - return result!; // result from paginate() will always have 1 row. + return { + ...result!, + items: result!.items.map((r) => ({ + ...r, + scriptureReferences: this.scriptureRefsService.parseList( + r.scriptureReferences, + ), + })), + }; } protected hydrate() { return (query: Query) => query .apply(matchProps()) - .subQuery('node', this.scriptureRefs.list()) + .subQuery('node', this.scriptureRefsRepository.list()) .return<{ dto: DbTypeOf }>( merge('props', { scriptureReferences: 'scriptureReferences', diff --git a/src/components/film/film.resolver.ts b/src/components/film/film.resolver.ts index 596170151e..802b91f492 100644 --- a/src/components/film/film.resolver.ts +++ b/src/components/film/film.resolver.ts @@ -6,8 +6,8 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { CreateFilmInput, CreateFilmOutput, diff --git a/src/components/film/film.service.ts b/src/components/film/film.service.ts index b450e8e014..26e5d8f784 100644 --- a/src/components/film/film.service.ts +++ b/src/components/film/film.service.ts @@ -1,18 +1,15 @@ import { Injectable } from '@nestjs/common'; import { - DuplicateException, ID, ObjectView, - SecuredList, ServerException, Session, -} from '../../common'; -import { DbTypeOf, HandleIdLookup, ILogger, Logger } from '../../core'; -import { ifDiff } from '../../core/database/changes'; -import { mapListResults } from '../../core/database/results'; + UnsecuredDto, +} from '~/common'; +import { HandleIdLookup } from '~/core'; +import { ifDiff } from '~/core/database/changes'; import { Privileges } from '../authorization'; import { isScriptureEqual } from '../scripture'; -import { ScriptureReferenceService } from '../scripture/scripture-reference.service'; import { CreateFilm, Film, @@ -25,111 +22,63 @@ import { FilmRepository } from './film.repository'; @Injectable() export class FilmService { constructor( - @Logger('film:service') private readonly logger: ILogger, - private readonly scriptureRefs: ScriptureReferenceService, private readonly privileges: Privileges, private readonly repo: FilmRepository, ) {} async create(input: CreateFilm, session: Session): Promise { - this.privileges.for(session, Film).verifyCan('create'); - - if (!(await this.repo.isUnique(input.name))) { - throw new DuplicateException( - 'film.name', - 'Film with this name already exists', - ); - } - - try { - const result = await this.repo.create(input); - - if (!result) { - throw new ServerException('failed to create a film'); - } - - await this.scriptureRefs.create( - result.id, - input.scriptureReferences, - session, - ); - - this.logger.debug(`flim created`, { id: result.id }); - return await this.readOne(result.id, session); - } catch (exception) { - this.logger.error(`Could not create film`, { - exception, - userId: session.userId, - }); - throw new ServerException('Could not create film', exception); - } + const dto = await this.repo.create(input, session); + this.privileges.for(session, Film, dto).verifyCan('create'); + return this.secure(dto, session); } @HandleIdLookup(Film) async readOne(id: ID, session: Session, _view?: ObjectView): Promise { - this.logger.debug(`Read film`, { - id, - userId: session.userId, - }); - const result = await this.repo.readOne(id); - return await this.secure(result, session); + return this.secure(result, session); } async readMany(ids: readonly ID[], session: Session) { const films = await this.repo.readMany(ids); - return await Promise.all(films.map((dto) => this.secure(dto, session))); + return films.map((dto) => this.secure(dto, session)); } - private async secure(dto: DbTypeOf, session: Session): Promise { - return this.privileges.for(session, Film).secure({ - ...dto, - scriptureReferences: this.scriptureRefs.parseList( - dto.scriptureReferences, - ), - }); + private secure(dto: UnsecuredDto, session: Session): Film { + return this.privileges.for(session, Film).secure(dto); } async update(input: UpdateFilm, session: Session): Promise { - const film = await this.readOne(input.id, session); + const film = await this.repo.readOne(input.id); const changes = { ...this.repo.getActualChanges(film, input), scriptureReferences: ifDiff(isScriptureEqual)( input.scriptureReferences, - film.scriptureReferences.value, + film.scriptureReferences, ), }; this.privileges.for(session, Film, film).verifyChanges(changes); - const { scriptureReferences, ...simpleChanges } = changes; - - await this.scriptureRefs.update(input.id, scriptureReferences); - await this.repo.update(film, simpleChanges); - - return await this.readOne(input.id, session); + const updated = await this.repo.update({ id: input.id, ...changes }); + return this.secure(updated, session); } async delete(id: ID, session: Session): Promise { - const film = await this.readOne(id, session); + const film = await this.repo.readOne(id); this.privileges.for(session, Film, film).verifyCan('delete'); try { await this.repo.deleteNode(film); } catch (exception) { - this.logger.error('Failed to delete', { id, exception }); throw new ServerException('Failed to delete', exception); } - - this.logger.debug(`deleted film with id`, { id }); } async list(input: FilmListInput, session: Session): Promise { - if (this.privileges.for(session, Film).can('read')) { - const results = await this.repo.list(input, session); - return await mapListResults(results, (dto) => this.secure(dto, session)); - } else { - return SecuredList.Redacted; - } + const results = await this.repo.list(input); + return { + ...results, + items: results.items.map((dto) => this.secure(dto, session)), + }; } } diff --git a/src/components/film/index.ts b/src/components/film/index.ts index 317ad5a002..7e6a73ed80 100644 --- a/src/components/film/index.ts +++ b/src/components/film/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './film.resolver'; export * from './film.service'; export * from './film.loader'; diff --git a/src/components/funding-account/dto/create-funding-account.dto.ts b/src/components/funding-account/dto/create-funding-account.dto.ts index 91234c1dbd..ba598245b7 100644 --- a/src/components/funding-account/dto/create-funding-account.dto.ts +++ b/src/components/funding-account/dto/create-funding-account.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, Int, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { Max, Min, ValidateNested } from 'class-validator'; -import { NameField } from '../../../common'; +import { NameField } from '~/common'; import { FundingAccount } from './funding-account.dto'; @InputType() diff --git a/src/components/funding-account/dto/delete-funding-account.dto.ts b/src/components/funding-account/dto/delete-funding-account.dto.ts index fa47043681..04490f5eaf 100644 --- a/src/components/funding-account/dto/delete-funding-account.dto.ts +++ b/src/components/funding-account/dto/delete-funding-account.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteFundingAccountOutput extends MutationPlaceholderOutput {} diff --git a/src/components/funding-account/dto/funding-account.dto.ts b/src/components/funding-account/dto/funding-account.dto.ts index 8e54c70b97..f774a38351 100644 --- a/src/components/funding-account/dto/funding-account.dto.ts +++ b/src/components/funding-account/dto/funding-account.dto.ts @@ -1,7 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DbLabel, DbUnique, @@ -11,7 +9,9 @@ import { SecuredProperty, SecuredProps, SecuredString, -} from '../../../common'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; @RegisterResource({ db: e.FundingAccount }) @ObjectType({ diff --git a/src/components/funding-account/dto/list-funding-account.dto.ts b/src/components/funding-account/dto/list-funding-account.dto.ts index 1a9cd03aee..a1581eeff7 100644 --- a/src/components/funding-account/dto/list-funding-account.dto.ts +++ b/src/components/funding-account/dto/list-funding-account.dto.ts @@ -1,5 +1,5 @@ import { InputType, ObjectType } from '@nestjs/graphql'; -import { PaginatedList, SortablePaginationInput } from '../../../common'; +import { PaginatedList, SortablePaginationInput } from '~/common'; import { FundingAccount } from './funding-account.dto'; @InputType() diff --git a/src/components/funding-account/dto/update-funding-account.dto.ts b/src/components/funding-account/dto/update-funding-account.dto.ts index c4238a8216..d18e90f7e0 100644 --- a/src/components/funding-account/dto/update-funding-account.dto.ts +++ b/src/components/funding-account/dto/update-funding-account.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, Int, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { Max, Min, ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; import { FundingAccount } from './funding-account.dto'; @InputType() diff --git a/src/components/funding-account/funding-account.loader.ts b/src/components/funding-account/funding-account.loader.ts index 5c92e8e2eb..ad006317d4 100644 --- a/src/components/funding-account/funding-account.loader.ts +++ b/src/components/funding-account/funding-account.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { FundingAccount } from './dto'; import { FundingAccountService } from './funding-account.service'; diff --git a/src/components/funding-account/funding-account.repository.ts b/src/components/funding-account/funding-account.repository.ts index 6f601a864e..1532b37303 100644 --- a/src/components/funding-account/funding-account.repository.ts +++ b/src/components/funding-account/funding-account.repository.ts @@ -1,13 +1,13 @@ import { Injectable } from '@nestjs/common'; import { node } from 'cypher-query-builder'; -import { ID, Session } from '../../common'; -import { DtoRepository } from '../../core'; +import { ID, Session } from '~/common'; +import { DtoRepository } from '~/core/database'; import { createNode, paginate, requestingUser, sorting, -} from '../../core/database/query'; +} from '~/core/database/query'; import { CreateFundingAccount, FundingAccount, diff --git a/src/components/funding-account/funding-account.resolver.ts b/src/components/funding-account/funding-account.resolver.ts index f4dd643495..1272322cd2 100644 --- a/src/components/funding-account/funding-account.resolver.ts +++ b/src/components/funding-account/funding-account.resolver.ts @@ -6,8 +6,8 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { CreateFundingAccountInput, CreateFundingAccountOutput, diff --git a/src/components/funding-account/funding-account.service.ts b/src/components/funding-account/funding-account.service.ts index 81e6615773..01cbdafef2 100644 --- a/src/components/funding-account/funding-account.service.ts +++ b/src/components/funding-account/funding-account.service.ts @@ -8,9 +8,9 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger } from '../../core'; -import { mapListResults } from '../../core/database/results'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger } from '~/core'; +import { mapListResults } from '~/core/database/results'; import { Privileges } from '../authorization'; import { CreateFundingAccount, diff --git a/src/components/funding-account/index.ts b/src/components/funding-account/index.ts index 56e80fd742..4c3f4a5ffc 100644 --- a/src/components/funding-account/index.ts +++ b/src/components/funding-account/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './funding-account.resolver'; export * from './funding-account.service'; export * from './funding-account.loader'; diff --git a/src/components/language/dto/create-language.dto.ts b/src/components/language/dto/create-language.dto.ts index 90ac831e7e..01e2d30807 100644 --- a/src/components/language/dto/create-language.dto.ts +++ b/src/components/language/dto/create-language.dto.ts @@ -15,8 +15,8 @@ import { NameField, Sensitivity, SensitivityField, -} from '../../../common'; -import { ExactLength } from '../../../common/validators/exactLength'; +} from '~/common'; +import { ExactLength } from '~/common/validators/exactLength'; import { Language } from './language.dto'; @InputType() diff --git a/src/components/language/dto/delete-language.dto.ts b/src/components/language/dto/delete-language.dto.ts index aad81c1aa0..a3d85ebf20 100644 --- a/src/components/language/dto/delete-language.dto.ts +++ b/src/components/language/dto/delete-language.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteLanguageOutput extends MutationPlaceholderOutput {} diff --git a/src/components/language/dto/update-language.dto.ts b/src/components/language/dto/update-language.dto.ts index 014aa3a987..b72fdb4ce7 100644 --- a/src/components/language/dto/update-language.dto.ts +++ b/src/components/language/dto/update-language.dto.ts @@ -17,8 +17,8 @@ import { NameField, Sensitivity, SensitivityField, -} from '../../../common'; -import { ExactLength } from '../../../common/validators/exactLength'; +} from '~/common'; +import { ExactLength } from '~/common/validators/exactLength'; import { ChangesetIdField } from '../../changeset'; import { Language } from './language.dto'; diff --git a/src/components/language/ethnologue-language/ethnologue-language.repository.ts b/src/components/language/ethnologue-language/ethnologue-language.repository.ts index 757422c0c3..ce238d0390 100644 --- a/src/components/language/ethnologue-language/ethnologue-language.repository.ts +++ b/src/components/language/ethnologue-language/ethnologue-language.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { simpleSwitch } from '@seedcompany/common'; import { DuplicateException, ID, ServerException } from '~/common'; -import { DtoRepository, UniquenessError } from '~/core'; +import { DtoRepository, UniquenessError } from '~/core/database'; import { createNode } from '~/core/database/query'; import { CreateEthnologueLanguage, diff --git a/src/components/language/index.ts b/src/components/language/index.ts index 1a404f2a9e..7b783659c1 100644 --- a/src/components/language/index.ts +++ b/src/components/language/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './language.service'; export * from './language.loader'; diff --git a/src/components/language/internal-first-scripture.resolver.ts b/src/components/language/internal-first-scripture.resolver.ts index 0fc2cf5de9..82329222d2 100644 --- a/src/components/language/internal-first-scripture.resolver.ts +++ b/src/components/language/internal-first-scripture.resolver.ts @@ -1,6 +1,7 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { Loader, LoaderOf } from '../../core'; -import { EngagementLoader, LanguageEngagement } from '../engagement'; +import { Loader, LoaderOf } from '~/core'; +import { EngagementLoader } from '../engagement'; +import { LanguageEngagement } from '../engagement/dto'; import { InternalFirstScripture } from './dto'; @Resolver(InternalFirstScripture) diff --git a/src/components/language/language.loader.ts b/src/components/language/language.loader.ts index df7d9015f0..2a36790ac8 100644 --- a/src/components/language/language.loader.ts +++ b/src/components/language/language.loader.ts @@ -1,5 +1,5 @@ -import { ID, ObjectView } from '../../common'; -import { LoaderFactory, ObjectViewAwareLoader } from '../../core'; +import { ID, ObjectView } from '~/common'; +import { LoaderFactory, ObjectViewAwareLoader } from '~/core'; import { Language } from './dto'; import { LanguageService } from './language.service'; diff --git a/src/components/language/language.repository.ts b/src/components/language/language.repository.ts index fc8ee75f44..41a5d1e5c5 100644 --- a/src/components/language/language.repository.ts +++ b/src/components/language/language.repository.ts @@ -17,7 +17,7 @@ import { Session, UnsecuredDto, } from '~/common'; -import { DtoRepository, UniquenessError } from '~/core'; +import { DtoRepository, UniquenessError } from '~/core/database'; import { ACTIVE, any, @@ -38,7 +38,7 @@ import { sorting, variable, } from '~/core/database/query'; -import { ProjectStatus } from '../project'; +import { ProjectStatus } from '../project/dto'; import { CreateLanguage, Language, diff --git a/src/components/language/language.resolver.ts b/src/components/language/language.resolver.ts index 267023231d..2dbcd7b6b0 100644 --- a/src/components/language/language.resolver.ts +++ b/src/components/language/language.resolver.ts @@ -20,13 +20,17 @@ import { SecuredIntNullable, Session, viewOfChangeset, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { IdsAndView, IdsAndViewArg } from '../changeset/dto'; -import { LocationListInput, SecuredLocationList } from '../location'; -import { LocationLoader } from '../location/location.loader'; -import { ProjectLoader, SecuredTranslationProjectList } from '../project'; -import { ProjectListInput, SecuredProjectList } from '../project/dto'; +import { LocationLoader } from '../location'; +import { LocationListInput, SecuredLocationList } from '../location/dto'; +import { ProjectLoader } from '../project'; +import { + ProjectListInput, + SecuredProjectList, + SecuredTranslationProjectList, +} from '../project/dto'; import { CreateLanguageInput, CreateLanguageOutput, diff --git a/src/components/language/language.service.ts b/src/components/language/language.service.ts index bedfe01f55..2ebc6fa830 100644 --- a/src/components/language/language.service.ts +++ b/src/components/language/language.service.ts @@ -9,21 +9,15 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger } from '../../core'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger } from '~/core'; import { Privileges } from '../authorization'; -import { EngagementService, EngagementStatus } from '../engagement'; -import { - LocationListInput, - LocationService, - SecuredLocationList, -} from '../location'; -import { - IProject, - ProjectListInput, - ProjectService, - SecuredProjectList, -} from '../project'; +import { EngagementService } from '../engagement'; +import { EngagementStatus } from '../engagement/dto'; +import { LocationService } from '../location'; +import { LocationListInput, SecuredLocationList } from '../location/dto'; +import { ProjectService } from '../project'; +import { IProject, ProjectListInput, SecuredProjectList } from '../project/dto'; import { CreateLanguage, Language, diff --git a/src/components/location/dto/create-location.dto.ts b/src/components/location/dto/create-location.dto.ts index 42962f6e7d..de2558a997 100644 --- a/src/components/location/dto/create-location.dto.ts +++ b/src/components/location/dto/create-location.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, IdOf, ISO31661Alpha3, NameField } from '../../../common'; -import { Transform } from '../../../common/transform.decorator'; +import { ID, IdField, IdOf, ISO31661Alpha3, NameField } from '~/common'; +import { Transform } from '~/common/transform.decorator'; import { CreateDefinedFileVersionInput } from '../../file/dto'; import { LocationType } from './location-type.enum'; import { Location } from './location.dto'; diff --git a/src/components/location/dto/delete-location.dto.ts b/src/components/location/dto/delete-location.dto.ts index 81577fe829..8745a5e24d 100644 --- a/src/components/location/dto/delete-location.dto.ts +++ b/src/components/location/dto/delete-location.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteLocationOutput extends MutationPlaceholderOutput {} diff --git a/src/components/location/dto/update-location.dto.ts b/src/components/location/dto/update-location.dto.ts index be7a835fc9..186f2faf1b 100644 --- a/src/components/location/dto/update-location.dto.ts +++ b/src/components/location/dto/update-location.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, IdOf, ISO31661Alpha3, NameField } from '../../../common'; -import { Transform } from '../../../common/transform.decorator'; +import { ID, IdField, IdOf, ISO31661Alpha3, NameField } from '~/common'; +import { Transform } from '~/common/transform.decorator'; import { CreateDefinedFileVersionInput } from '../../file/dto'; import { LocationType } from './location-type.enum'; import { Location } from './location.dto'; diff --git a/src/components/location/index.ts b/src/components/location/index.ts index e56f3845c5..2e1fe983ed 100644 --- a/src/components/location/index.ts +++ b/src/components/location/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './location.service'; export * from './location.loader'; diff --git a/src/components/location/location.loader.ts b/src/components/location/location.loader.ts index 2961309e6e..c74d83a9ee 100644 --- a/src/components/location/location.loader.ts +++ b/src/components/location/location.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Location } from './dto'; import { LocationService } from './location.service'; diff --git a/src/components/location/location.repository.ts b/src/components/location/location.repository.ts index 0ba54cd468..1070fff4f0 100644 --- a/src/components/location/location.repository.ts +++ b/src/components/location/location.repository.ts @@ -9,7 +9,7 @@ import { Session, UnsecuredDto, } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, @@ -19,7 +19,8 @@ import { paginate, sorting, } from '~/core/database/query'; -import { FileId, FileService } from '../file'; +import { FileService } from '../file'; +import { FileId } from '../file/dto'; import { CreateLocation, Location, diff --git a/src/components/location/location.resolver.ts b/src/components/location/location.resolver.ts index 210d73c4ee..eb27fbee83 100644 --- a/src/components/location/location.resolver.ts +++ b/src/components/location/location.resolver.ts @@ -15,14 +15,14 @@ import { LoggedInSession, mapSecuredValue, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { FieldRegionLoader, SecuredFieldRegion } from '../field-region'; -import { FileNodeLoader, resolveDefinedFile, SecuredFile } from '../file'; -import { - FundingAccountLoader, - SecuredFundingAccount, -} from '../funding-account'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { FieldRegionLoader } from '../field-region'; +import { SecuredFieldRegion } from '../field-region/dto'; +import { FileNodeLoader, resolveDefinedFile } from '../file'; +import { SecuredFile } from '../file/dto'; +import { FundingAccountLoader } from '../funding-account'; +import { SecuredFundingAccount } from '../funding-account/dto'; import { CreateLocationInput, CreateLocationOutput, diff --git a/src/components/location/location.service.ts b/src/components/location/location.service.ts index 12bfd00744..ed2a78ff58 100644 --- a/src/components/location/location.service.ts +++ b/src/components/location/location.service.ts @@ -7,8 +7,8 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger } from '../../core'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger } from '~/core'; import { Privileges, UserEdgePrivileges } from '../authorization'; import { PropAction } from '../authorization/policy/actions'; import { diff --git a/src/components/organization/dto/create-organization.dto.ts b/src/components/organization/dto/create-organization.dto.ts index 62e5f25da6..811c53a9ca 100644 --- a/src/components/organization/dto/create-organization.dto.ts +++ b/src/components/organization/dto/create-organization.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { NameField } from '../../../common'; +import { NameField } from '~/common'; import { OrganizationReach } from './organization-reach.dto'; import { OrganizationType } from './organization-type.dto'; import { Organization } from './organization.dto'; diff --git a/src/components/organization/dto/delete-organization.dto.ts b/src/components/organization/dto/delete-organization.dto.ts index d6841569a1..4be3a20e8b 100644 --- a/src/components/organization/dto/delete-organization.dto.ts +++ b/src/components/organization/dto/delete-organization.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteOrganizationOutput extends MutationPlaceholderOutput {} diff --git a/src/components/organization/dto/organization.dto.ts b/src/components/organization/dto/organization.dto.ts index e004f63a41..ed9f1c28e0 100644 --- a/src/components/organization/dto/organization.dto.ts +++ b/src/components/organization/dto/organization.dto.ts @@ -1,7 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DbUnique, NameField, @@ -13,7 +11,9 @@ import { SecuredStringNullable, Sensitivity, SensitivityField, -} from '../../../common'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { Location } from '../../location/dto'; import { SecuredOrganizationReach } from './organization-reach.dto'; import { SecuredOrganizationTypes } from './organization-type.dto'; diff --git a/src/components/organization/dto/update-organization.dto.ts b/src/components/organization/dto/update-organization.dto.ts index 7931f42ee3..cf9d4cd1fe 100644 --- a/src/components/organization/dto/update-organization.dto.ts +++ b/src/components/organization/dto/update-organization.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; import { OrganizationReach } from './organization-reach.dto'; import { OrganizationType } from './organization-type.dto'; import { Organization } from './organization.dto'; diff --git a/src/components/organization/index.ts b/src/components/organization/index.ts index e9a798ca27..a85ecc8581 100644 --- a/src/components/organization/index.ts +++ b/src/components/organization/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './organization.service'; export * from './organization.loader'; diff --git a/src/components/organization/migrations/add-reach.migration.ts b/src/components/organization/migrations/add-reach.migration.ts index 5d61d8fa3c..af64e0e998 100644 --- a/src/components/organization/migrations/add-reach.migration.ts +++ b/src/components/organization/migrations/add-reach.migration.ts @@ -1,4 +1,4 @@ -import { BaseMigration, Migration } from '~/core'; +import { BaseMigration, Migration } from '~/core/database'; import { Organization } from '../dto'; @Migration('2023-08-04T00:00:00') diff --git a/src/components/organization/migrations/add-type.migration.ts b/src/components/organization/migrations/add-type.migration.ts index 6656e00057..698ea165d3 100644 --- a/src/components/organization/migrations/add-type.migration.ts +++ b/src/components/organization/migrations/add-type.migration.ts @@ -1,4 +1,4 @@ -import { BaseMigration, Migration } from '~/core'; +import { BaseMigration, Migration } from '~/core/database'; import { Organization } from '../dto'; @Migration('2023-08-04T00:00:00') diff --git a/src/components/organization/organization.loader.ts b/src/components/organization/organization.loader.ts index de9bf99406..ef970d2cad 100644 --- a/src/components/organization/organization.loader.ts +++ b/src/components/organization/organization.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Organization } from './dto'; import { OrganizationService } from './organization.service'; diff --git a/src/components/organization/organization.resolver.ts b/src/components/organization/organization.resolver.ts index c1b5100f63..7a268ff772 100644 --- a/src/components/organization/organization.resolver.ts +++ b/src/components/organization/organization.resolver.ts @@ -16,13 +16,10 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { - LocationListInput, - LocationLoader, - SecuredLocationList, -} from '../location'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { LocationLoader } from '../location'; +import { LocationListInput, SecuredLocationList } from '../location/dto'; import { OrganizationLoader, OrganizationService } from '../organization'; import { CreateOrganizationInput, diff --git a/src/components/organization/organization.service.ts b/src/components/organization/organization.service.ts index c6f476f96f..b625bb8bfe 100644 --- a/src/components/organization/organization.service.ts +++ b/src/components/organization/organization.service.ts @@ -8,11 +8,8 @@ import { } from '~/common'; import { HandleIdLookup } from '~/core'; import { Privileges } from '../authorization'; -import { - LocationListInput, - LocationService, - SecuredLocationList, -} from '../location'; +import { LocationService } from '../location'; +import { LocationListInput, SecuredLocationList } from '../location/dto'; import { CreateOrganization, Organization, diff --git a/src/components/partner/dto/delete-partner.dto.ts b/src/components/partner/dto/delete-partner.dto.ts index 34e11fb694..0d1138ec7c 100644 --- a/src/components/partner/dto/delete-partner.dto.ts +++ b/src/components/partner/dto/delete-partner.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeletePartnerOutput extends MutationPlaceholderOutput {} diff --git a/src/components/partner/index.ts b/src/components/partner/index.ts index 30f7d65094..26a27ab383 100644 --- a/src/components/partner/index.ts +++ b/src/components/partner/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './partner.service'; export * from './partner.loader'; diff --git a/src/components/partner/partner.loader.ts b/src/components/partner/partner.loader.ts index 6174fda751..b859de5b2a 100644 --- a/src/components/partner/partner.loader.ts +++ b/src/components/partner/partner.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Partner } from './dto'; import { PartnerService } from './partner.service'; diff --git a/src/components/partner/partner.module.ts b/src/components/partner/partner.module.ts index 0c32cd9efb..ec247f0070 100644 --- a/src/components/partner/partner.module.ts +++ b/src/components/partner/partner.module.ts @@ -1,6 +1,7 @@ import { forwardRef, Module } from '@nestjs/common'; import { splitDb } from '~/core'; import { AuthorizationModule } from '../authorization/authorization.module'; +import { EngagementModule } from '../engagement/engagement.module'; import { LanguageModule } from '../language/language.module'; import { OrganizationModule } from '../organization/organization.module'; import { ProjectModule } from '../project/project.module'; @@ -14,6 +15,7 @@ import { PartnerService } from './partner.service'; @Module({ imports: [ forwardRef(() => AuthorizationModule), + forwardRef(() => EngagementModule), forwardRef(() => LanguageModule), forwardRef(() => ProjectModule), forwardRef(() => OrganizationModule), diff --git a/src/components/partner/partner.repository.ts b/src/components/partner/partner.repository.ts index 1c3aa26134..a2005938aa 100644 --- a/src/components/partner/partner.repository.ts +++ b/src/components/partner/partner.repository.ts @@ -9,8 +9,8 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { DtoRepository } from '../../core'; +} from '~/common'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, collect, @@ -26,7 +26,7 @@ import { rankSens, requestingUser, sorting, -} from '../../core/database/query'; +} from '~/core/database/query'; import { CreatePartner, Partner, PartnerListInput, UpdatePartner } from './dto'; @Injectable() diff --git a/src/components/partner/partner.resolver.ts b/src/components/partner/partner.resolver.ts index 2c86164645..f8a0efe118 100644 --- a/src/components/partner/partner.resolver.ts +++ b/src/components/partner/partner.resolver.ts @@ -16,25 +16,28 @@ import { LoggedInSession, mapSecuredValue, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { FieldRegionLoader, SecuredFieldRegions } from '../field-region'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { EngagementLoader } from '../engagement'; +import { EngagementListInput, EngagementListOutput } from '../engagement/dto'; +import { FieldRegionLoader } from '../field-region'; +import { SecuredFieldRegions } from '../field-region/dto'; +import { LanguageLoader } from '../language'; import { LanguageListInput, - LanguageLoader, SecuredLanguageList, SecuredLanguageNullable, SecuredLanguages, -} from '../language'; -import { LocationLoader, SecuredLocations } from '../location'; -import { OrganizationLoader, SecuredOrganization } from '../organization'; +} from '../language/dto'; +import { LocationLoader } from '../location'; +import { SecuredLocations } from '../location/dto'; +import { OrganizationLoader } from '../organization'; +import { SecuredOrganization } from '../organization/dto'; import { PartnerLoader, PartnerService } from '../partner'; -import { - ProjectListInput, - SecuredProjectList, -} from '../project/dto/list-projects.dto'; -import { ProjectLoader } from '../project/project.loader'; -import { SecuredUser, UserLoader } from '../user'; +import { ProjectLoader } from '../project'; +import { ProjectListInput, SecuredProjectList } from '../project/dto'; +import { UserLoader } from '../user'; +import { SecuredUser } from '../user/dto'; import { CreatePartnerInput, CreatePartnerOutput, @@ -175,6 +178,24 @@ export class PartnerResolver { return list; } + @ResolveField(() => EngagementListOutput, { + description: "Engagements of the partner's affiliated projects", + }) + async engagements( + @AnonSession() session: Session, + @Parent() partner: Partner, + @ListArg(EngagementListInput) input: EngagementListInput, + @Loader(EngagementLoader) loader: LoaderOf, + ): Promise { + const list = await this.partnerService.listEngagements( + partner, + input, + session, + ); + loader.primeAll(list.items); + return list; + } + @Mutation(() => CreatePartnerOutput, { description: 'Create a partner', }) diff --git a/src/components/partner/partner.service.ts b/src/components/partner/partner.service.ts index 6aad0edd1c..e143880815 100644 --- a/src/components/partner/partner.service.ts +++ b/src/components/partner/partner.service.ts @@ -11,19 +11,15 @@ import { } from '~/common'; import { HandleIdLookup, ResourceLoader } from '~/core'; import { Privileges } from '../authorization'; -import { - LanguageListInput, - LanguageService, - SecuredLanguageList, -} from '../language'; -import { Location, LocationLoader, LocationType } from '../location'; +import { EngagementService } from '../engagement'; +import { EngagementListInput } from '../engagement/dto'; +import { LanguageService } from '../language'; +import { LanguageListInput, SecuredLanguageList } from '../language/dto'; +import { LocationLoader } from '../location'; +import { Location, LocationType } from '../location/dto'; import { FinancialReportingType } from '../partnership/dto'; -import { - IProject, - ProjectListInput, - ProjectService, - SecuredProjectList, -} from '../project'; +import { ProjectService } from '../project'; +import { IProject, ProjectListInput, SecuredProjectList } from '../project/dto'; import { CreatePartner, Partner, @@ -40,6 +36,8 @@ export class PartnerService { private readonly privileges: Privileges, @Inject(forwardRef(() => ProjectService)) private readonly projectService: ProjectService & {}, + @Inject(forwardRef(() => EngagementService)) + private readonly engagementService: EngagementService & {}, @Inject(forwardRef(() => LanguageService)) private readonly languageService: LanguageService & {}, private readonly repo: PartnerRepository, @@ -185,6 +183,19 @@ export class PartnerService { canCreate: false, }; } + async listEngagements( + partner: Partner, + input: EngagementListInput, + session: Session, + ) { + return await this.engagementService.list( + { + ...input, + filter: { ...input.filter, partnerId: partner.id }, + }, + session, + ); + } protected verifyFinancialReportingType( financialReportingTypes: FinancialReportingType[] | undefined, diff --git a/src/components/partnership-producing-medium/dto/partnership-producing-medium.dto.ts b/src/components/partnership-producing-medium/dto/partnership-producing-medium.dto.ts index 4559847c0a..da616fc59e 100644 --- a/src/components/partnership-producing-medium/dto/partnership-producing-medium.dto.ts +++ b/src/components/partnership-producing-medium/dto/partnership-producing-medium.dto.ts @@ -1,6 +1,6 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; -import { ID, IdField, SecuredList } from '../../../common'; -import { ProductMedium as Medium } from '../../product'; +import { ID, IdField, SecuredList } from '~/common'; +import { ProductMedium as Medium } from '../../product/dto'; @ObjectType() export class PartnershipProducingMedium { diff --git a/src/components/partnership-producing-medium/partnership-producing-medium-engagement-connection.resolver.ts b/src/components/partnership-producing-medium/partnership-producing-medium-engagement-connection.resolver.ts index 53150a1583..56201fcdac 100644 --- a/src/components/partnership-producing-medium/partnership-producing-medium-engagement-connection.resolver.ts +++ b/src/components/partnership-producing-medium/partnership-producing-medium-engagement-connection.resolver.ts @@ -1,7 +1,7 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { AnonSession, Session } from '../../common'; -import { LanguageEngagement } from '../engagement'; +import { AnonSession, Session } from '~/common'; +import { LanguageEngagement } from '../engagement/dto'; import { SecuredPartnershipsProducingMediums } from './dto/partnership-producing-medium.dto'; import { PartnershipProducingMediumService } from './partnership-producing-medium.service'; diff --git a/src/components/partnership-producing-medium/partnership-producing-medium.repository.ts b/src/components/partnership-producing-medium/partnership-producing-medium.repository.ts index 35e5fc0c12..0f81b6c0a1 100644 --- a/src/components/partnership-producing-medium/partnership-producing-medium.repository.ts +++ b/src/components/partnership-producing-medium/partnership-producing-medium.repository.ts @@ -1,15 +1,10 @@ import { Injectable } from '@nestjs/common'; import { node, relation } from 'cypher-query-builder'; -import { ID, NotFoundException } from '../../common'; -import { CommonRepository, ILogger, Logger } from '../../core'; -import { - ACTIVE, - apoc, - collect, - merge, - variable, -} from '../../core/database/query'; -import { ProductMedium } from '../product'; +import { ID, NotFoundException } from '~/common'; +import { ILogger, Logger } from '~/core'; +import { CommonRepository } from '~/core/database'; +import { ACTIVE, apoc, collect, merge, variable } from '~/core/database/query'; +import { ProductMedium } from '../product/dto'; import { PartnershipProducingMediumInput } from './dto/partnership-producing-medium.dto'; @Injectable() diff --git a/src/components/partnership-producing-medium/partnership-producing-medium.resolver.ts b/src/components/partnership-producing-medium/partnership-producing-medium.resolver.ts index 061278f57d..abc14b8b29 100644 --- a/src/components/partnership-producing-medium/partnership-producing-medium.resolver.ts +++ b/src/components/partnership-producing-medium/partnership-producing-medium.resolver.ts @@ -5,9 +5,10 @@ import { ResolveField, Resolver, } from '@nestjs/graphql'; -import { ID, IdArg, LoggedInSession, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { Partnership, PartnershipLoader } from '../partnership'; +import { ID, IdArg, LoggedInSession, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { PartnershipLoader } from '../partnership'; +import { Partnership } from '../partnership/dto'; import { PartnershipProducingMedium, PartnershipProducingMediumInput, diff --git a/src/components/partnership-producing-medium/partnership-producing-medium.service.ts b/src/components/partnership-producing-medium/partnership-producing-medium.service.ts index 37da4d3237..14ecbcb4f8 100644 --- a/src/components/partnership-producing-medium/partnership-producing-medium.service.ts +++ b/src/components/partnership-producing-medium/partnership-producing-medium.service.ts @@ -7,11 +7,11 @@ import { SecuredList, Session, UnauthorizedException, -} from '../../common'; -import { ResourceResolver } from '../../core'; +} from '~/common'; +import { ResourceResolver } from '~/core'; import { Privileges } from '../authorization'; -import { LanguageEngagement } from '../engagement'; -import { IProject } from '../project'; +import { LanguageEngagement } from '../engagement/dto'; +import { IProject } from '../project/dto'; import { PartnershipProducingMediumInput, SecuredPartnershipsProducingMediums, diff --git a/src/components/partnership-producing-medium/update-partnership-producing-medium-output.resolver.ts b/src/components/partnership-producing-medium/update-partnership-producing-medium-output.resolver.ts index cd5bf56c17..f81e44d954 100644 --- a/src/components/partnership-producing-medium/update-partnership-producing-medium-output.resolver.ts +++ b/src/components/partnership-producing-medium/update-partnership-producing-medium-output.resolver.ts @@ -1,10 +1,7 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { Loader, LoaderOf } from '../../core'; -import { - Engagement, - EngagementLoader, - LanguageEngagement, -} from '../engagement'; +import { Loader, LoaderOf } from '~/core'; +import { EngagementLoader } from '../engagement'; +import { Engagement, LanguageEngagement } from '../engagement/dto'; import { UpdatePartnershipProducingMediumOutput } from './dto/partnership-producing-medium.dto'; @Resolver(UpdatePartnershipProducingMediumOutput) diff --git a/src/components/partnership/dto/create-partnership.dto.ts b/src/components/partnership/dto/create-partnership.dto.ts index c732a52340..2b1c6ab758 100644 --- a/src/components/partnership/dto/create-partnership.dto.ts +++ b/src/components/partnership/dto/create-partnership.dto.ts @@ -2,7 +2,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Transform, Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; import { uniq } from 'lodash'; -import { CalendarDate, DateField, ID, IdField } from '../../../common'; +import { CalendarDate, DateField, ID, IdField } from '~/common'; import { ChangesetIdField } from '../../changeset'; import { CreateDefinedFileVersionInput } from '../../file/dto'; import { PartnerType } from '../../partner/dto'; diff --git a/src/components/partnership/dto/delete-partnership.dto.ts b/src/components/partnership/dto/delete-partnership.dto.ts index 7f25997144..29215749db 100644 --- a/src/components/partnership/dto/delete-partnership.dto.ts +++ b/src/components/partnership/dto/delete-partnership.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeletePartnershipOutput extends MutationPlaceholderOutput {} diff --git a/src/components/partnership/dto/partnership.dto.ts b/src/components/partnership/dto/partnership.dto.ts index defa6166a5..8f62f2e318 100644 --- a/src/components/partnership/dto/partnership.dto.ts +++ b/src/components/partnership/dto/partnership.dto.ts @@ -1,8 +1,5 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { BaseNode } from '~/core/database/results'; -import { e } from '~/core/edgedb'; -import { LinkTo, RegisterResource } from '~/core/resources'; import { Calculated, IntersectionType, @@ -15,7 +12,10 @@ import { SecuredProps, Sensitivity, SensitivityField, -} from '../../../common'; +} from '~/common'; +import { BaseNode } from '~/core/database/results'; +import { e } from '~/core/edgedb'; +import { LinkTo, RegisterResource } from '~/core/resources'; import { ChangesetAware } from '../../changeset/dto'; import { Organization } from '../../organization/dto'; import { SecuredPartnerTypes } from '../../partner/dto'; diff --git a/src/components/partnership/dto/update-partnership.dto.ts b/src/components/partnership/dto/update-partnership.dto.ts index d1aaeaf4c6..14706661b9 100644 --- a/src/components/partnership/dto/update-partnership.dto.ts +++ b/src/components/partnership/dto/update-partnership.dto.ts @@ -2,7 +2,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Transform, Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; import { uniq } from 'lodash'; -import { CalendarDate, DateField, ID, IdField } from '../../../common'; +import { CalendarDate, DateField, ID, IdField } from '~/common'; import { ChangesetIdField } from '../../changeset'; import { CreateDefinedFileVersionInput } from '../../file/dto'; import { PartnerType } from '../../partner/dto'; diff --git a/src/components/partnership/events/partnership-created.event.ts b/src/components/partnership/events/partnership-created.event.ts index 9955b19824..0e400f7f8d 100644 --- a/src/components/partnership/events/partnership-created.event.ts +++ b/src/components/partnership/events/partnership-created.event.ts @@ -1,4 +1,4 @@ -import { Session } from '../../../common'; +import { Session } from '~/common'; import { Partnership } from '../dto'; export class PartnershipCreatedEvent { diff --git a/src/components/partnership/events/partnership-deleted.event.ts b/src/components/partnership/events/partnership-deleted.event.ts index 2be026632d..bb5984883a 100644 --- a/src/components/partnership/events/partnership-deleted.event.ts +++ b/src/components/partnership/events/partnership-deleted.event.ts @@ -1,4 +1,4 @@ -import { Session } from '../../../common'; +import { Session } from '~/common'; import { Partnership } from '../dto'; export class PartnershipWillDeleteEvent { diff --git a/src/components/partnership/events/partnership-updated.event.ts b/src/components/partnership/events/partnership-updated.event.ts index 52c6dc51bf..8e8d842bb7 100644 --- a/src/components/partnership/events/partnership-updated.event.ts +++ b/src/components/partnership/events/partnership-updated.event.ts @@ -1,4 +1,4 @@ -import { Session } from '../../../common'; +import { Session } from '~/common'; import { Partnership, UpdatePartnership } from '../dto'; export class PartnershipUpdatedEvent { diff --git a/src/components/partnership/handlers/apply-finalized-changeset-to-partnership.handler.ts b/src/components/partnership/handlers/apply-finalized-changeset-to-partnership.handler.ts index d3ccad456b..77db9b735f 100644 --- a/src/components/partnership/handlers/apply-finalized-changeset-to-partnership.handler.ts +++ b/src/components/partnership/handlers/apply-finalized-changeset-to-partnership.handler.ts @@ -1,16 +1,13 @@ import { node, relation } from 'cypher-query-builder'; -import { ID, ServerException } from '../../../common'; +import { ID, ServerException } from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; +import { ACTIVE, deleteBaseNode, INACTIVE } from '~/core/database/query'; import { - DatabaseService, - EventsHandler, - IEventHandler, - ILogger, - Logger, -} from '../../../core'; -import { ACTIVE, deleteBaseNode, INACTIVE } from '../../../core/database/query'; -import { commitChangesetProps } from '../../changeset/commit-changeset-props.query'; -import { ChangesetFinalizingEvent } from '../../changeset/events'; -import { rejectChangesetProps } from '../../changeset/reject-changeset-props.query'; + ChangesetFinalizingEvent, + commitChangesetProps, + rejectChangesetProps, +} from '../../changeset'; type SubscribedEvent = ChangesetFinalizingEvent; diff --git a/src/components/partnership/index.ts b/src/components/partnership/index.ts index 6fa7b249a1..e451f6b4ec 100644 --- a/src/components/partnership/index.ts +++ b/src/components/partnership/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './partnership.service'; export * from './partnership.loader'; diff --git a/src/components/partnership/partnership.loader.ts b/src/components/partnership/partnership.loader.ts index a9d3851749..f4128a06fb 100644 --- a/src/components/partnership/partnership.loader.ts +++ b/src/components/partnership/partnership.loader.ts @@ -1,5 +1,5 @@ -import { ID, ObjectView } from '../../common'; -import { LoaderFactory, ObjectViewAwareLoader } from '../../core'; +import { ID, ObjectView } from '~/common'; +import { LoaderFactory, ObjectViewAwareLoader } from '~/core'; import { Partnership } from './dto'; import { PartnershipService } from './partnership.service'; diff --git a/src/components/partnership/partnership.repository.ts b/src/components/partnership/partnership.repository.ts index dc470ae79a..6808eb04d0 100644 --- a/src/components/partnership/partnership.repository.ts +++ b/src/components/partnership/partnership.repository.ts @@ -13,8 +13,8 @@ import { Session, UnsecuredDto, viewOfChangeset, -} from '../../common'; -import { DtoRepository } from '../../core'; +} from '~/common'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, coalesce, @@ -30,8 +30,9 @@ import { requestingUser, sorting, whereNotDeletedInChangeset, -} from '../../core/database/query'; -import { FileId, FileService } from '../file'; +} from '~/core/database/query'; +import { FileService } from '../file'; +import { FileId } from '../file/dto'; import { CreatePartnership, Partnership, diff --git a/src/components/partnership/partnership.resolver.ts b/src/components/partnership/partnership.resolver.ts index 24b65d87b4..f4b50ff049 100644 --- a/src/components/partnership/partnership.resolver.ts +++ b/src/components/partnership/partnership.resolver.ts @@ -14,11 +14,13 @@ import { SecuredDateRange, Session, viewOfChangeset, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { ChangesetIds, IdsAndView, IdsAndViewArg } from '../changeset/dto'; -import { FileNodeLoader, resolveDefinedFile, SecuredFile } from '../file'; -import { PartnerLoader, SecuredPartner } from '../partner'; +import { FileNodeLoader, resolveDefinedFile } from '../file'; +import { SecuredFile } from '../file/dto'; +import { PartnerLoader } from '../partner'; +import { SecuredPartner } from '../partner/dto'; import { PartnershipLoader, PartnershipService } from '../partnership'; import { CreatePartnershipInput, diff --git a/src/components/partnership/partnership.service.ts b/src/components/partnership/partnership.service.ts index 0e03becbec..e7ab6a7088 100644 --- a/src/components/partnership/partnership.service.ts +++ b/src/components/partnership/partnership.service.ts @@ -7,17 +7,18 @@ import { Session, UnsecuredDto, viewOfChangeset, -} from '../../common'; +} from '~/common'; import { HandleIdLookup, IEventBus, ILogger, Logger, ResourceLoader, -} from '../../core'; +} from '~/core'; import { Privileges } from '../authorization'; import { FileService } from '../file'; -import { Partner, PartnerService, PartnerType } from '../partner'; +import { PartnerService } from '../partner'; +import { Partner, PartnerType } from '../partner/dto'; import { ProjectService } from '../project'; import { CreatePartnership, diff --git a/src/components/periodic-report/dto/create-periodic-report.dto.ts b/src/components/periodic-report/dto/create-periodic-report.dto.ts index 46bd188994..cb0609ad78 100644 --- a/src/components/periodic-report/dto/create-periodic-report.dto.ts +++ b/src/components/periodic-report/dto/create-periodic-report.dto.ts @@ -1,4 +1,4 @@ -import { CalendarDate, ID, Range, Session } from '../../../common'; +import { CalendarDate, ID, Range, Session } from '~/common'; import { ReportType } from './report-type.enum'; export abstract class MergePeriodicReports { diff --git a/src/components/periodic-report/dto/periodic-report.dto.ts b/src/components/periodic-report/dto/periodic-report.dto.ts index f7644362fd..944b13b224 100644 --- a/src/components/periodic-report/dto/periodic-report.dto.ts +++ b/src/components/periodic-report/dto/periodic-report.dto.ts @@ -1,7 +1,5 @@ import { Field, InterfaceType, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { Calculated, CalendarDate, @@ -13,10 +11,12 @@ import { SecuredStringNullable, Sensitivity, SensitivityField, -} from '../../../common'; -import { BaseNode as DbBaseNode } from '../../../core/database/results'; -import { ScopedRole } from '../../authorization'; -import { DefinedFile } from '../../file'; +} from '~/common'; +import { BaseNode as DbBaseNode } from '~/core/database/results'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; +import { ScopedRole } from '../../authorization/dto'; +import { DefinedFile } from '../../file/dto'; import { ReportType } from './report-type.enum'; @RegisterResource({ db: e.PeriodicReport }) diff --git a/src/components/periodic-report/events/periodic-report-uploaded.event.ts b/src/components/periodic-report/events/periodic-report-uploaded.event.ts index 5d197b6bb4..c4bbdadd33 100644 --- a/src/components/periodic-report/events/periodic-report-uploaded.event.ts +++ b/src/components/periodic-report/events/periodic-report-uploaded.event.ts @@ -1,5 +1,5 @@ -import { Session } from '../../../common'; -import { Downloadable, FileNode } from '../../file'; +import { Session } from '~/common'; +import { Downloadable, FileNode } from '../../file/dto'; import { PeriodicReport } from '../dto'; /** diff --git a/src/components/periodic-report/handlers/abstract-periodic-report-sync.ts b/src/components/periodic-report/handlers/abstract-periodic-report-sync.ts index 6a6893ba6b..8ec2bf23be 100644 --- a/src/components/periodic-report/handlers/abstract-periodic-report-sync.ts +++ b/src/components/periodic-report/handlers/abstract-periodic-report-sync.ts @@ -1,11 +1,5 @@ import { DateTimeUnit } from 'luxon'; -import { - CalendarDate, - DateInterval, - ID, - Range, - Session, -} from '../../../common'; +import { CalendarDate, DateInterval, ID, Range, Session } from '~/common'; import { ReportType } from '../dto'; import { PeriodicReportService } from '../periodic-report.service'; diff --git a/src/components/periodic-report/handlers/sync-periodic-report-to-project.handler.ts b/src/components/periodic-report/handlers/sync-periodic-report-to-project.handler.ts index 839583a45b..66c7923084 100644 --- a/src/components/periodic-report/handlers/sync-periodic-report-to-project.handler.ts +++ b/src/components/periodic-report/handlers/sync-periodic-report-to-project.handler.ts @@ -1,7 +1,7 @@ import { DateTimeUnit } from 'luxon'; -import { DateInterval } from '../../../common'; -import { EventsHandler, IEventHandler, ILogger, Logger } from '../../../core'; -import { projectRange } from '../../project'; +import { DateInterval } from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { projectRange } from '../../project/dto'; import { ProjectUpdatedEvent } from '../../project/events'; import { ReportPeriod, ReportType } from '../dto'; import { PeriodicReportService } from '../periodic-report.service'; diff --git a/src/components/periodic-report/handlers/sync-progress-report-to-engagement.handler.ts b/src/components/periodic-report/handlers/sync-progress-report-to-engagement.handler.ts index 048c89fd8f..37fc1b2a80 100644 --- a/src/components/periodic-report/handlers/sync-progress-report-to-engagement.handler.ts +++ b/src/components/periodic-report/handlers/sync-progress-report-to-engagement.handler.ts @@ -1,10 +1,7 @@ -import { DateInterval, UnsecuredDto } from '../../../common'; -import { EventsHandler, IEventHandler, ILogger, Logger } from '../../../core'; -import { - Engagement, - engagementRange, - EngagementService, -} from '../../engagement'; +import { DateInterval, UnsecuredDto } from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { EngagementService } from '../../engagement'; +import { Engagement, engagementRange } from '../../engagement/dto'; import { EngagementCreatedEvent, EngagementUpdatedEvent, diff --git a/src/components/periodic-report/index.ts b/src/components/periodic-report/index.ts index d1b32f59c8..172a53d216 100644 --- a/src/components/periodic-report/index.ts +++ b/src/components/periodic-report/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './periodic-report.service'; export * from './periodic-report.loader'; diff --git a/src/components/periodic-report/periodic-report-parent.resolver.ts b/src/components/periodic-report/periodic-report-parent.resolver.ts index f7d189381c..45e13544a8 100644 --- a/src/components/periodic-report/periodic-report-parent.resolver.ts +++ b/src/components/periodic-report/periodic-report-parent.resolver.ts @@ -1,6 +1,6 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { ResourceLoader } from '../../core'; -import { IPeriodicReport, PeriodicReport } from '../periodic-report'; +import { ResourceLoader } from '~/core'; +import { IPeriodicReport, PeriodicReport } from '../periodic-report/dto'; @Resolver(IPeriodicReport) export class PeriodicReportParentResolver { diff --git a/src/components/periodic-report/periodic-report-project-connection.resolver.ts b/src/components/periodic-report/periodic-report-project-connection.resolver.ts index 225ce428ba..dcb154e377 100644 --- a/src/components/periodic-report/periodic-report-project-connection.resolver.ts +++ b/src/components/periodic-report/periodic-report-project-connection.resolver.ts @@ -1,6 +1,6 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { AnonSession, ListArg, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; +import { AnonSession, ListArg, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { PeriodicReportLoader, PeriodicReportService, diff --git a/src/components/periodic-report/periodic-report.loader.ts b/src/components/periodic-report/periodic-report.loader.ts index 205db15f03..dcc6f423a9 100644 --- a/src/components/periodic-report/periodic-report.loader.ts +++ b/src/components/periodic-report/periodic-report.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { ProgressReport } from '../progress-report/dto'; import { FinancialReport, diff --git a/src/components/periodic-report/periodic-report.repository.ts b/src/components/periodic-report/periodic-report.repository.ts index dc433defdf..de460f0358 100644 --- a/src/components/periodic-report/periodic-report.repository.ts +++ b/src/components/periodic-report/periodic-report.repository.ts @@ -9,7 +9,6 @@ import { Query, relation, } from 'cypher-query-builder'; -import { ChangesOf } from '~/core/database/changes'; import { CalendarDate, generateId, @@ -17,8 +16,9 @@ import { Range, Session, UnsecuredDto, -} from '../../common'; -import { DtoRepository } from '../../core'; +} from '~/common'; +import { DtoRepository } from '~/core/database'; +import { ChangesOf } from '~/core/database/changes'; import { ACTIVE, createNode, @@ -31,8 +31,8 @@ import { sorting, variable, Variable, -} from '../../core/database/query'; -import { File } from '../file'; +} from '~/core/database/query'; +import { File } from '../file/dto'; import { ProgressReportStatus as ProgressStatus } from '../progress-report/dto'; import { ProgressReportExtraForPeriodicInterfaceRepository } from '../progress-report/progress-report-extra-for-periodic-interface.repository'; import { diff --git a/src/components/periodic-report/periodic-report.resolver.ts b/src/components/periodic-report/periodic-report.resolver.ts index 162e4f6a46..01e9c0708a 100644 --- a/src/components/periodic-report/periodic-report.resolver.ts +++ b/src/components/periodic-report/periodic-report.resolver.ts @@ -13,10 +13,11 @@ import { LoggedInSession, Session, UnauthorizedException, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { IdsAndView, IdsAndViewArg } from '../changeset/dto'; -import { FileNodeLoader, resolveDefinedFile, SecuredFile } from '../file'; +import { FileNodeLoader, resolveDefinedFile } from '../file'; +import { SecuredFile } from '../file/dto'; import { IPeriodicReport, PeriodicReportListInput, diff --git a/src/components/periodic-report/periodic-report.service.ts b/src/components/periodic-report/periodic-report.service.ts index 1db9032cfa..fbc128f032 100644 --- a/src/components/periodic-report/periodic-report.service.ts +++ b/src/components/periodic-report/periodic-report.service.ts @@ -9,9 +9,9 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, IEventBus, ILogger, Logger } from '../../core'; -import { Variable } from '../../core/database/query'; +} from '~/common'; +import { HandleIdLookup, IEventBus, ILogger, Logger } from '~/core'; +import { Variable } from '~/core/database/query'; import { Privileges } from '../authorization'; import { FileService } from '../file'; import { ProgressReport } from '../progress-report/dto'; diff --git a/src/components/pin/dto/pinnable.dto.ts b/src/components/pin/dto/pinnable.dto.ts index 36945789c1..08a57d32c3 100644 --- a/src/components/pin/dto/pinnable.dto.ts +++ b/src/components/pin/dto/pinnable.dto.ts @@ -1,10 +1,14 @@ import { Field, InterfaceType } from '@nestjs/graphql'; -import { ID, IdField } from '../../../common'; +import { keys } from 'ts-transformer-keys'; +import { ID, IdField } from '~/common'; @InterfaceType({ description: 'An item that can be pinned', }) export class Pinnable { + static readonly Props = keys(); + static readonly SecuredProps = keys(); + @IdField() readonly id: ID; diff --git a/src/components/pin/dto/pinned-list.dto.ts b/src/components/pin/dto/pinned-list.dto.ts index 1d9d3a2851..0d63eff46e 100644 --- a/src/components/pin/dto/pinned-list.dto.ts +++ b/src/components/pin/dto/pinned-list.dto.ts @@ -1,5 +1,5 @@ import { InputType, ObjectType } from '@nestjs/graphql'; -import { PaginatedList, PaginationInput } from '../../../common'; +import { PaginatedList, PaginationInput } from '~/common'; import { Pinnable } from './pinnable.dto'; @InputType() diff --git a/src/components/pin/pin.edgedb.repository.ts b/src/components/pin/pin.edgedb.repository.ts new file mode 100644 index 0000000000..64778d69bb --- /dev/null +++ b/src/components/pin/pin.edgedb.repository.ts @@ -0,0 +1,63 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { ID, PublicOf } from '~/common'; +import { CommonRepository } from '~/core/database'; +import { Client } from '~/core/edgedb'; +import { PinRepository } from './pin.repository'; + +@Injectable() +export class PinEdgeDBRepository + extends CommonRepository + implements PublicOf +{ + constructor(@Inject(Client) private readonly client: Client) { + super(); + } + + async isPinned(id: ID): Promise { + const result = await this.client.querySingle( + ` + select exists( + select global currentUser { + pins: { + id + } + } + filter $id in global currentUser.pins.id + ) + `, + { + id, + }, + ); + + return result as boolean; + } + + async add(id: ID): Promise { + await this.client.query( + ` + update global currentUser + set { + pins += $id + } + `, + { + id, + }, + ); + } + + async remove(id: ID): Promise { + await this.client.query( + ` + update global currentUser + set { + pins -= $id + } + `, + { + id, + }, + ); + } +} diff --git a/src/components/pin/pin.module.ts b/src/components/pin/pin.module.ts index af39df436c..443dda13e8 100644 --- a/src/components/pin/pin.module.ts +++ b/src/components/pin/pin.module.ts @@ -1,10 +1,16 @@ import { Module } from '@nestjs/common'; +import { splitDb } from '~/core'; +import { PinEdgeDBRepository } from './pin.edgedb.repository'; import { PinRepository } from './pin.repository'; import { PinResolver } from './pin.resolver'; import { PinService } from './pin.service'; @Module({ - providers: [PinResolver, PinService, PinRepository], + providers: [ + PinResolver, + PinService, + splitDb(PinRepository, PinEdgeDBRepository), + ], exports: [PinService], }) export class PinModule {} diff --git a/src/components/pin/pin.repository.ts b/src/components/pin/pin.repository.ts index 5d4f8438d1..92c6278b61 100644 --- a/src/components/pin/pin.repository.ts +++ b/src/components/pin/pin.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { node, relation } from 'cypher-query-builder'; import { DateTime } from 'luxon'; -import { ID, Session } from '../../common'; -import { DatabaseService } from '../../core'; -import { requestingUser } from '../../core/database/query'; +import { ID, Session } from '~/common'; +import { DatabaseService } from '~/core/database'; +import { requestingUser } from '~/core/database/query'; @Injectable() export class PinRepository { diff --git a/src/components/pin/pin.resolver.ts b/src/components/pin/pin.resolver.ts index a24fa39acc..a636df4357 100644 --- a/src/components/pin/pin.resolver.ts +++ b/src/components/pin/pin.resolver.ts @@ -6,7 +6,7 @@ import { LoggedInSession, NotImplementedException, Session, -} from '../../common'; +} from '~/common'; import { PinnedListInput, PinnedListOutput } from './dto'; import { PinService } from './pin.service'; diff --git a/src/components/pin/pin.service.ts b/src/components/pin/pin.service.ts index ff1711f169..c7222c77e7 100644 --- a/src/components/pin/pin.service.ts +++ b/src/components/pin/pin.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { ID, Session } from '../../common'; +import { ID, Session } from '~/common'; import { PinRepository } from './pin.repository'; @Injectable() diff --git a/src/components/pnp/extract-scripture.ts b/src/components/pnp/extract-scripture.ts index afaff50fb9..2a60c3b20b 100644 --- a/src/components/pnp/extract-scripture.ts +++ b/src/components/pnp/extract-scripture.ts @@ -1,6 +1,6 @@ import { parseScripture, tryParseScripture } from '@seedcompany/scripture'; import { Row } from '~/common/xlsx.util'; -import { ScriptureRange } from '../scripture'; +import { ScriptureRange } from '../scripture/dto'; import { WrittenScripturePlanningSheet } from './planning-sheet'; export const extractScripture = (row: Row) => { diff --git a/src/components/pnp/findStepColumns.ts b/src/components/pnp/findStepColumns.ts index 361b3b5b9c..3bd9b4582f 100644 --- a/src/components/pnp/findStepColumns.ts +++ b/src/components/pnp/findStepColumns.ts @@ -1,8 +1,8 @@ import { sortBy } from '@seedcompany/common'; import levenshtein from 'fastest-levenshtein'; import { startCase, without } from 'lodash'; -import { Column } from '../../common/xlsx.util'; -import { ProductStep as Step } from '../product'; +import { Column } from '~/common/xlsx.util'; +import { ProductStep as Step } from '../product/dto'; import { PlanningSheet } from './planning-sheet'; import { ProgressSheet } from './progress-sheet'; import 'ix/add/iterable-operators/filter.js'; diff --git a/src/components/pnp/isGoalRow.ts b/src/components/pnp/isGoalRow.ts index f05d4f7b9b..cf7f3f4cdc 100644 --- a/src/components/pnp/isGoalRow.ts +++ b/src/components/pnp/isGoalRow.ts @@ -1,6 +1,6 @@ import { Book, parseScripture } from '@seedcompany/scripture'; import { Cell } from '~/common/xlsx.util'; -import { ScriptureRange } from '../scripture'; +import { ScriptureRange } from '../scripture/dto'; import { PlanningSheet } from './planning-sheet'; import { ProgressSheet } from './progress-sheet'; diff --git a/src/components/pnp/isGoalStepPlannedInsideProject.ts b/src/components/pnp/isGoalStepPlannedInsideProject.ts index 6129e0b1f6..9f216ace13 100644 --- a/src/components/pnp/isGoalStepPlannedInsideProject.ts +++ b/src/components/pnp/isGoalStepPlannedInsideProject.ts @@ -1,6 +1,6 @@ import { trimStart } from 'lodash'; -import { CalendarDate, fullFiscalYear } from '../../common'; -import { Cell } from '../../common/xlsx.util'; +import { CalendarDate, fullFiscalYear } from '~/common'; +import { Cell } from '~/common/xlsx.util'; import { PlanningSheet } from './planning-sheet'; import { Pnp } from './pnp'; diff --git a/src/components/pnp/isProgressCompletedOutsideProject.ts b/src/components/pnp/isProgressCompletedOutsideProject.ts index 42c6aaa7fb..74866a3775 100644 --- a/src/components/pnp/isProgressCompletedOutsideProject.ts +++ b/src/components/pnp/isProgressCompletedOutsideProject.ts @@ -1,5 +1,5 @@ -import { fullFiscalQuarter } from '../../common'; -import { Cell } from '../../common/xlsx.util'; +import { fullFiscalQuarter } from '~/common'; +import { Cell } from '~/common/xlsx.util'; import { Pnp } from './pnp'; import { ProgressSheet } from './progress-sheet'; diff --git a/src/components/pnp/planning-sheet.ts b/src/components/pnp/planning-sheet.ts index 128ecbef69..cda739101f 100644 --- a/src/components/pnp/planning-sheet.ts +++ b/src/components/pnp/planning-sheet.ts @@ -1,13 +1,6 @@ import { LazyGetter as Once } from 'lazy-get-decorator'; -import { DateInterval, expandToFullFiscalYears } from '../../common'; -import { - Cell, - Column, - Range, - Row, - Sheet, - WorkBook, -} from '../../common/xlsx.util'; +import { DateInterval, expandToFullFiscalYears } from '~/common'; +import { Cell, Column, Range, Row, Sheet, WorkBook } from '~/common/xlsx.util'; export abstract class PlanningSheet extends Sheet { static register(book: WorkBook) { diff --git a/src/components/pnp/pnp.ts b/src/components/pnp/pnp.ts index 6f40d111a9..6f10c823a9 100644 --- a/src/components/pnp/pnp.ts +++ b/src/components/pnp/pnp.ts @@ -1,5 +1,5 @@ -import { WorkBook } from '../../common/xlsx.util'; -import { Downloadable } from '../file'; +import { WorkBook } from '~/common/xlsx.util'; +import { Downloadable } from '../file/dto'; import { PlanningSheet } from './planning-sheet'; import { ProgressSheet } from './progress-sheet'; diff --git a/src/components/pnp/progress-sheet.ts b/src/components/pnp/progress-sheet.ts index 7d93084d72..c78674d2a4 100644 --- a/src/components/pnp/progress-sheet.ts +++ b/src/components/pnp/progress-sheet.ts @@ -1,5 +1,5 @@ import { LazyGetter as Once } from 'lazy-get-decorator'; -import { Column, Range, Row, Sheet, WorkBook } from '../../common/xlsx.util'; +import { Column, Range, Row, Sheet, WorkBook } from '~/common/xlsx.util'; export abstract class ProgressSheet extends Sheet { static register(book: WorkBook) { diff --git a/src/components/post/dto/create-post.dto.ts b/src/components/post/dto/create-post.dto.ts index 90788574e7..2f8004f2cd 100644 --- a/src/components/post/dto/create-post.dto.ts +++ b/src/components/post/dto/create-post.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { IsNotEmpty, ValidateNested } from 'class-validator'; -import { ID, IdField } from '../../../common'; +import { ID, IdField } from '~/common'; import { PostType } from './post-type.enum'; import { Post } from './post.dto'; import { PostShareability } from './shareability.dto'; diff --git a/src/components/post/dto/delete-post.dto.ts b/src/components/post/dto/delete-post.dto.ts index c851d838fa..8e4a7f81b9 100644 --- a/src/components/post/dto/delete-post.dto.ts +++ b/src/components/post/dto/delete-post.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeletePostOutput extends MutationPlaceholderOutput {} diff --git a/src/components/post/dto/post.dto.ts b/src/components/post/dto/post.dto.ts index 09be58b585..c55ac520f6 100644 --- a/src/components/post/dto/post.dto.ts +++ b/src/components/post/dto/post.dto.ts @@ -1,16 +1,16 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { DateTime } from 'luxon'; import { keys as keysOf } from 'ts-transformer-keys'; -import { BaseNode } from '~/core/database/results'; -import { e } from '~/core/edgedb'; -import { LinkTo, RegisterResource } from '~/core/resources'; import { DateTimeField, Resource, Secured, SecuredProps, SecuredString, -} from '../../../common'; +} from '~/common'; +import { BaseNode } from '~/core/database/results'; +import { e } from '~/core/edgedb'; +import { LinkTo, RegisterResource } from '~/core/resources'; import { PostType } from './post-type.enum'; import { PostShareability } from './shareability.dto'; diff --git a/src/components/post/dto/update-post.dto.ts b/src/components/post/dto/update-post.dto.ts index 2379ebf167..1c281e755c 100644 --- a/src/components/post/dto/update-post.dto.ts +++ b/src/components/post/dto/update-post.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { IsNotEmpty, ValidateNested } from 'class-validator'; -import { ID, IdField } from '../../../common'; +import { ID, IdField } from '~/common'; import { PostType } from './post-type.enum'; import { Post } from './post.dto'; import { PostShareability } from './shareability.dto'; diff --git a/src/components/post/index.ts b/src/components/post/index.ts index 68137231f8..9a5c4bcbfc 100644 --- a/src/components/post/index.ts +++ b/src/components/post/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './post.service'; export * from './post.loader'; diff --git a/src/components/post/post.resolver.ts b/src/components/post/post.resolver.ts index 901b0a3b29..ba072a754d 100644 --- a/src/components/post/post.resolver.ts +++ b/src/components/post/post.resolver.ts @@ -6,16 +6,11 @@ import { ResolveField, Resolver, } from '@nestjs/graphql'; -import { - ID, - IdArg, - LoggedInSession, - mapSecuredValue, - Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +import { ID, IdArg, LoggedInSession, mapSecuredValue, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { PostLoader, PostService } from '../post'; -import { SecuredUser, UserLoader } from '../user'; +import { UserLoader } from '../user'; +import { SecuredUser } from '../user/dto'; import { CreatePostInput, CreatePostOutput, diff --git a/src/components/post/post.service.ts b/src/components/post/post.service.ts index aa94fac632..e13240daf9 100644 --- a/src/components/post/post.service.ts +++ b/src/components/post/post.service.ts @@ -1,6 +1,4 @@ import { Injectable } from '@nestjs/common'; -import { ILogger, Logger, ResourceLoader, ResourcesHost } from '~/core'; -import { BaseNode, isBaseNode } from '~/core/database/results'; import { ID, InputException, @@ -12,7 +10,9 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; +} from '~/common'; +import { ILogger, Logger, ResourceLoader, ResourcesHost } from '~/core'; +import { BaseNode, isBaseNode } from '~/core/database/results'; import { Privileges } from '../authorization'; import { CreatePost, Post, Postable, UpdatePost } from './dto'; import { PostListInput, SecuredPostList } from './dto/list-posts.dto'; diff --git a/src/components/product-progress/create-product-connection.resolver.ts b/src/components/product-progress/create-product-connection.resolver.ts index beac2cfa08..1b73606fce 100644 --- a/src/components/product-progress/create-product-connection.resolver.ts +++ b/src/components/product-progress/create-product-connection.resolver.ts @@ -1,6 +1,6 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { LoggedInSession, Session, Variant } from '~/common'; -import { CreateProductOutput } from '../product'; +import { CreateProductOutput } from '../product/dto'; import { ProductProgressService } from './product-progress.service'; @Resolver(() => CreateProductOutput) diff --git a/src/components/product-progress/dto/product-progress.dto.ts b/src/components/product-progress/dto/product-progress.dto.ts index 112eda1bcf..912d3f4ea5 100644 --- a/src/components/product-progress/dto/product-progress.dto.ts +++ b/src/components/product-progress/dto/product-progress.dto.ts @@ -13,7 +13,7 @@ import { } from '~/common'; import { e } from '~/core/edgedb'; import { RegisterResource } from '~/core/resources'; -import { Product, ProductStep } from '../../product'; +import { Product, ProductStep } from '../../product/dto'; import { ProgressReport } from '../../progress-report/dto'; import { ProgressReportVariantProgress, diff --git a/src/components/product-progress/dto/product-progress.input.ts b/src/components/product-progress/dto/product-progress.input.ts index 7972172292..7cf7f45b64 100644 --- a/src/components/product-progress/dto/product-progress.input.ts +++ b/src/components/product-progress/dto/product-progress.input.ts @@ -3,7 +3,7 @@ import { Type } from 'class-transformer'; import { Min, ValidateNested } from 'class-validator'; import { stripIndent } from 'common-tags'; import { ID, IdField } from '~/common'; -import { ProductStep } from '../../product'; +import { ProductStep } from '../../product/dto'; import { VariantProgressArg } from './variant-progress.dto'; @InputType() diff --git a/src/components/product-progress/handlers/extract-pnp-progress.handler.ts b/src/components/product-progress/handlers/extract-pnp-progress.handler.ts index 7d562f42ec..4efcdcb9cb 100644 --- a/src/components/product-progress/handlers/extract-pnp-progress.handler.ts +++ b/src/components/product-progress/handlers/extract-pnp-progress.handler.ts @@ -1,8 +1,9 @@ import { mapOf } from '@seedcompany/common'; -import { EventsHandler, ILogger, Logger } from '../../../core'; +import { EventsHandler, ILogger, Logger } from '~/core'; import { ReportType } from '../../periodic-report/dto'; import { PeriodicReportUploadedEvent } from '../../periodic-report/events'; -import { ProducibleType, ProductService } from '../../product'; +import { ProductService } from '../../product'; +import { ProducibleType } from '../../product/dto'; import { isScriptureEqual } from '../../scripture'; import { ProgressReportVariantProgress as Progress } from '../dto'; import { ProductProgressService } from '../product-progress.service'; diff --git a/src/components/product-progress/product-connection.resolver.ts b/src/components/product-progress/product-connection.resolver.ts index be1095a82a..aa08881ad8 100644 --- a/src/components/product-progress/product-connection.resolver.ts +++ b/src/components/product-progress/product-connection.resolver.ts @@ -1,7 +1,7 @@ import { Args, Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { AnonSession, ID, IdArg, Session } from '~/common'; import { Loader, LoaderOf } from '~/core'; -import { Product } from '../product'; +import { Product } from '../product/dto'; import { ProductProgress, VariantProgressArg } from './dto'; import { ProductProgressByProductLoader } from './product-progress-by-product.loader'; import { ProductProgressService } from './product-progress.service'; diff --git a/src/components/product-progress/product-progress.repository.ts b/src/components/product-progress/product-progress.repository.ts index c887f00e98..cbdcc6102e 100644 --- a/src/components/product-progress/product-progress.repository.ts +++ b/src/components/product-progress/product-progress.repository.ts @@ -9,8 +9,8 @@ import { NotFoundException, Session, Variant, -} from '../../common'; -import { DatabaseService } from '../../core'; +} from '~/common'; +import { DatabaseService } from '~/core/database'; import { ACTIVE, collect, @@ -20,9 +20,10 @@ import { merge, updateProperty, variable, -} from '../../core/database/query'; -import { PeriodicReportService, ReportType } from '../periodic-report'; -import { ProductStep } from '../product'; +} from '~/core/database/query'; +import { PeriodicReportService } from '../periodic-report'; +import { ReportType } from '../periodic-report/dto'; +import { ProductStep } from '../product/dto'; import { ProductProgress, ProductProgressInput, diff --git a/src/components/product-progress/product-progress.resolver.ts b/src/components/product-progress/product-progress.resolver.ts index f887e577a6..b32b4e98b4 100644 --- a/src/components/product-progress/product-progress.resolver.ts +++ b/src/components/product-progress/product-progress.resolver.ts @@ -5,10 +5,11 @@ import { ResolveField, Resolver, } from '@nestjs/graphql'; -import { LoggedInSession, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; +import { LoggedInSession, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { PeriodicReportLoader } from '../periodic-report'; -import { Product, ProductLoader } from '../product'; +import { ProductLoader } from '../product'; +import { Product } from '../product/dto'; import { ProgressReport } from '../progress-report/dto'; import { ProductProgress, ProductProgressInput } from './dto'; import { ProductProgressService } from './product-progress.service'; diff --git a/src/components/product-progress/product-progress.service.ts b/src/components/product-progress/product-progress.service.ts index d5ccc0dd13..c88cc40b2f 100644 --- a/src/components/product-progress/product-progress.service.ts +++ b/src/components/product-progress/product-progress.service.ts @@ -16,7 +16,7 @@ import { UserResourcePrivileges, withVariant, } from '../authorization'; -import { Product } from '../product'; +import { Product } from '../product/dto'; import type { ProgressReport } from '../progress-report/dto'; import { ProductProgress, diff --git a/src/components/product-progress/step-not-planned.exception.ts b/src/components/product-progress/step-not-planned.exception.ts index c0cb9ce6e4..1d520ba7bf 100644 --- a/src/components/product-progress/step-not-planned.exception.ts +++ b/src/components/product-progress/step-not-planned.exception.ts @@ -1,5 +1,5 @@ -import { ID, InputException } from '../../common'; -import { ProductStep } from '../product'; +import { ID, InputException } from '~/common'; +import { ProductStep } from '../product/dto'; export class StepNotPlannedException extends InputException { constructor( diff --git a/src/components/product-progress/step-progress-extractor.service.ts b/src/components/product-progress/step-progress-extractor.service.ts index 22da5fc7c1..06796a639d 100644 --- a/src/components/product-progress/step-progress-extractor.service.ts +++ b/src/components/product-progress/step-progress-extractor.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { entries } from '@seedcompany/common'; import { assert } from 'ts-essentials'; import { MergeExclusive } from 'type-fest'; -import { Cell, Column, Row } from '../../common/xlsx.util'; -import { Downloadable } from '../file'; +import { Cell, Column, Row } from '~/common/xlsx.util'; +import { Downloadable } from '../file/dto'; import { extractScripture, findStepColumns, @@ -14,8 +14,8 @@ import { ProgressSheet, WrittenScripturePlanningSheet, } from '../pnp'; -import { ProductStep as Step } from '../product'; -import { ScriptureRange } from '../scripture'; +import { ProductStep as Step } from '../product/dto'; +import { ScriptureRange } from '../scripture/dto'; import { StepProgressInput } from './dto'; type ExtractedRow = MergeExclusive< diff --git a/src/components/product-progress/step-progress.resolver.ts b/src/components/product-progress/step-progress.resolver.ts index 5f1136d89e..3a4a502d30 100644 --- a/src/components/product-progress/step-progress.resolver.ts +++ b/src/components/product-progress/step-progress.resolver.ts @@ -2,7 +2,7 @@ import { Args, Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { simpleSwitch } from '@seedcompany/common'; import { stripIndent } from 'common-tags'; import { ID, mapSecuredValue, SecuredFloatNullable } from '~/common'; -import { Loader, LoaderOf } from '../../core'; +import { Loader, LoaderOf } from '~/core'; import { ProductLoader } from '../product'; import { ProgressFormat, StepProgress } from './dto'; diff --git a/src/components/product/dto/completion-description.dto.ts b/src/components/product/dto/completion-description.dto.ts index 7d67025557..ec084c7ee3 100644 --- a/src/components/product/dto/completion-description.dto.ts +++ b/src/components/product/dto/completion-description.dto.ts @@ -1,5 +1,5 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; -import { PaginatedList, PaginationInput } from '../../../common'; +import { PaginatedList, PaginationInput } from '~/common'; import { ProductMethodology } from './product-methodology.enum'; @InputType() diff --git a/src/components/product/dto/create-product.dto.ts b/src/components/product/dto/create-product.dto.ts index c2af2f8fbc..20266d8514 100644 --- a/src/components/product/dto/create-product.dto.ts +++ b/src/components/product/dto/create-product.dto.ts @@ -4,12 +4,12 @@ import { IsPositive, ValidateNested } from 'class-validator'; import { stripIndent } from 'common-tags'; import { uniq } from 'lodash'; import { DateTime } from 'luxon'; -import { ID, IdField, NameField } from '../../../common'; +import { ID, IdField, NameField } from '~/common'; import { ScriptureField, ScriptureRangeInput, UnspecifiedScripturePortionInput, -} from '../../scripture'; +} from '../../scripture/dto'; import { ProductMedium } from './product-medium.enum'; import { ProductMethodology } from './product-methodology.enum'; import { ProductPurpose } from './product-purpose.enum'; diff --git a/src/components/product/dto/delete-product.dto.ts b/src/components/product/dto/delete-product.dto.ts index c2551d5f98..d75575a705 100644 --- a/src/components/product/dto/delete-product.dto.ts +++ b/src/components/product/dto/delete-product.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteProductOutput extends MutationPlaceholderOutput {} diff --git a/src/components/product/dto/producible.dto.ts b/src/components/product/dto/producible.dto.ts index 4b8b3c4ed2..fa824a497f 100644 --- a/src/components/product/dto/producible.dto.ts +++ b/src/components/product/dto/producible.dto.ts @@ -1,9 +1,6 @@ import { Field, InterfaceType, ObjectType } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; import { keys as keysOf } from 'ts-transformer-keys'; -import { SetDbType } from '~/core/database'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { EnumType, makeEnum, @@ -11,13 +8,16 @@ import { SecuredProperty, SecuredProps, UnsecuredDto, -} from '../../../common'; -import { SetChangeType } from '../../../core/database/changes'; +} from '~/common'; +import { SetDbType } from '~/core/database'; +import { SetChangeType } from '~/core/database/changes'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; +import { DbScriptureReferences } from '../../scripture'; import { - DbScriptureReferences, ScriptureRangeInput, SecuredScriptureRanges, -} from '../../scripture'; +} from '../../scripture/dto'; @RegisterResource({ db: e.Producible }) @InterfaceType({ diff --git a/src/components/product/dto/product.dto.ts b/src/components/product/dto/product.dto.ts index 2b1bcb7568..cca1a3426d 100644 --- a/src/components/product/dto/product.dto.ts +++ b/src/components/product/dto/product.dto.ts @@ -3,9 +3,6 @@ import { stripIndent } from 'common-tags'; import { startCase } from 'lodash'; import { keys as keysOf } from 'ts-transformer-keys'; import { MergeExclusive } from 'type-fest'; -import { SetDbType } from '~/core'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DbLabel, ID, @@ -19,14 +16,17 @@ import { SensitivityField, ServerException, UnsecuredDto, -} from '../../../common'; -import { SetChangeType } from '../../../core/database/changes'; +} from '~/common'; +import { SetDbType } from '~/core/database'; +import { SetChangeType } from '~/core/database/changes'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; +import { DbScriptureReferences } from '../../scripture'; import { - DbScriptureReferences, ScriptureRangeInput, SecuredScriptureRangesOverride, SecuredUnspecifiedScripturePortion, -} from '../../scripture'; +} from '../../scripture/dto'; import { Producible, ProducibleRef, SecuredProducible } from './producible.dto'; import { SecuredProductMediums } from './product-medium.enum'; import { SecuredMethodology } from './product-methodology.enum'; diff --git a/src/components/product/dto/update-product.dto.ts b/src/components/product/dto/update-product.dto.ts index 50800bae18..cc3f436fc5 100644 --- a/src/components/product/dto/update-product.dto.ts +++ b/src/components/product/dto/update-product.dto.ts @@ -7,7 +7,7 @@ import { NameField, OmitType, PickType, -} from '../../../common'; +} from '~/common'; import { CreateBaseProduct, CreateDerivativeScriptureProduct, diff --git a/src/components/product/handlers/extract-products-from-pnp.handler.ts b/src/components/product/handlers/extract-products-from-pnp.handler.ts index 6833a5b9fa..48b6fecbe1 100644 --- a/src/components/product/handlers/extract-products-from-pnp.handler.ts +++ b/src/components/product/handlers/extract-products-from-pnp.handler.ts @@ -3,8 +3,8 @@ import { labelOfVerseRanges } from '@seedcompany/scripture'; import { difference, uniq } from 'lodash'; import { DateTime } from 'luxon'; import { ID, Session, UnsecuredDto } from '~/common'; -import { EventsHandler, IEventHandler, ILogger, Logger } from '../../../core'; -import { Engagement } from '../../engagement'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { Engagement } from '../../engagement/dto'; import { EngagementCreatedEvent, EngagementUpdatedEvent, diff --git a/src/components/product/index.ts b/src/components/product/index.ts index 9e72e164ae..3b5bcc1822 100644 --- a/src/components/product/index.ts +++ b/src/components/product/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './product.service'; export * from './product.loader'; diff --git a/src/components/product/migrations/fix-nan-total-verse-equivalents.migration.ts b/src/components/product/migrations/fix-nan-total-verse-equivalents.migration.ts index bed9457573..681527e7e5 100644 --- a/src/components/product/migrations/fix-nan-total-verse-equivalents.migration.ts +++ b/src/components/product/migrations/fix-nan-total-verse-equivalents.migration.ts @@ -2,7 +2,7 @@ import { node, relation } from 'cypher-query-builder'; import { ID } from '~/common'; import { BaseMigration, Migration } from '~/core/database'; import { ACTIVE } from '~/core/database/query'; -import { getTotalVerseEquivalents } from '../../scripture/verse-equivalents'; +import { getTotalVerseEquivalents } from '../../scripture'; import { ProductService } from '../product.service'; @Migration('2023-10-27T09:47:07') diff --git a/src/components/product/producible.resolver.ts b/src/components/product/producible.resolver.ts index 8a88c45e11..309d2365a5 100644 --- a/src/components/product/producible.resolver.ts +++ b/src/components/product/producible.resolver.ts @@ -1,6 +1,6 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { Secured } from '../../common'; -import { ResourceLoader } from '../../core'; +import { Secured } from '~/common'; +import { ResourceLoader } from '~/core'; import { ProducibleRef, SecuredProducible } from './dto'; @Resolver(SecuredProducible) diff --git a/src/components/product/product-extractor.service.ts b/src/components/product/product-extractor.service.ts index 51230085b2..7d14463758 100644 --- a/src/components/product/product-extractor.service.ts +++ b/src/components/product/product-extractor.service.ts @@ -3,9 +3,9 @@ import { entries } from '@seedcompany/common'; import { parseScripture } from '@seedcompany/scripture'; import { assert } from 'ts-essentials'; import { MergeExclusive } from 'type-fest'; -import { CalendarDate } from '../../common'; -import { Cell, Column, Row } from '../../common/xlsx.util'; -import { Downloadable } from '../file'; +import { CalendarDate } from '~/common'; +import { Cell, Column, Row } from '~/common/xlsx.util'; +import { Downloadable } from '../file/dto'; import { extractScripture, findStepColumns, @@ -17,7 +17,7 @@ import { stepPlanCompleteDate, WrittenScripturePlanningSheet, } from '../pnp'; -import { ScriptureRange, UnspecifiedScripturePortion } from '../scripture'; +import { ScriptureRange, UnspecifiedScripturePortion } from '../scripture/dto'; import { ProductStep as Step } from './dto'; @Injectable() diff --git a/src/components/product/product.loader.ts b/src/components/product/product.loader.ts index 54c377cfa4..6e64ca4648 100644 --- a/src/components/product/product.loader.ts +++ b/src/components/product/product.loader.ts @@ -1,9 +1,9 @@ -import { ID } from '../../common'; +import { ID } from '~/common'; import { LoaderFactory, OrderedNestDataLoader, OrderedNestDataLoaderOptions, -} from '../../core'; +} from '~/core'; import { AnyProduct, DerivativeScriptureProduct, diff --git a/src/components/product/product.repository.ts b/src/components/product/product.repository.ts index 348e9c8fe3..d7e59a5b83 100644 --- a/src/components/product/product.repository.ts +++ b/src/components/product/product.repository.ts @@ -16,9 +16,9 @@ import { Range, ServerException, Session, -} from '../../common'; -import { CommonRepository, DbTypeOf, OnIndex } from '../../core'; -import { DbChanges, getChanges } from '../../core/database/changes'; +} from '~/common'; +import { CommonRepository, DbTypeOf, OnIndex } from '~/core/database'; +import { DbChanges, getChanges } from '~/core/database/changes'; import { ACTIVE, collect, @@ -33,14 +33,14 @@ import { merge, paginate, sorting, -} from '../../core/database/query'; +} from '~/core/database/query'; +import { ScriptureReferenceRepository } from '../scripture'; import { ScriptureRange, ScriptureRangeInput, - ScriptureReferenceRepository, UnspecifiedScripturePortion, UnspecifiedScripturePortionInput, -} from '../scripture'; +} from '../scripture/dto'; import { ApproachToMethodologies, CreateDerivativeScriptureProduct, diff --git a/src/components/product/product.resolver.ts b/src/components/product/product.resolver.ts index ded6d31c9d..07127f8a4e 100644 --- a/src/components/product/product.resolver.ts +++ b/src/components/product/product.resolver.ts @@ -20,21 +20,21 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { IdsAndView, IdsAndViewArg } from '../changeset/dto'; +import { ProductLoader, ProductService } from '../product'; import { AvailableStepsOptions, CreateDerivativeScriptureProduct, CreateDirectScriptureProduct, getAvailableSteps, - ProductLoader, - ProductService, ProductStep as Step, UpdateDerivativeScriptureProduct, UpdateDirectScriptureProduct, -} from '../product'; -import { ProjectLoader, TranslationProject } from '../project'; +} from '../product/dto'; +import { ProjectLoader } from '../project'; +import { TranslationProject } from '../project/dto'; import { AnyProduct, CreateOtherProduct, diff --git a/src/components/product/product.service.ts b/src/components/product/product.service.ts index 3681bf3e8b..b9070decb9 100644 --- a/src/components/product/product.service.ts +++ b/src/components/product/product.service.ts @@ -9,19 +9,18 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger, ResourceResolver } from '../../core'; -import { compareNullable, ifDiff, isSame } from '../../core/database/changes'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger, ResourceResolver } from '~/core'; +import { compareNullable, ifDiff, isSame } from '~/core/database/changes'; import { Privileges } from '../authorization'; import { getTotalVerseEquivalents, getTotalVerses, getVerseEquivalentsFromUnspecified, isScriptureEqual, - ScriptureRange, ScriptureReferenceService, - UnspecifiedScripturePortion, } from '../scripture'; +import { ScriptureRange, UnspecifiedScripturePortion } from '../scripture/dto'; import { AnyProduct, asProductType, @@ -33,6 +32,7 @@ import { getAvailableSteps, MethodologyToApproach, OtherProduct, + ProducibleType, Product, ProductApproach, ProductCompletionDescriptionSuggestionsInput, @@ -45,7 +45,6 @@ import { UpdateOtherProduct, UpdateBaseProduct as UpdateProduct, } from './dto'; -import { ProducibleType } from './dto/producible.dto'; import { HydratedProductRow, ProductRepository } from './product.repository'; @Injectable() diff --git a/src/components/progress-report/community-stories/progress-report-community-story.resolver.ts b/src/components/progress-report/community-stories/progress-report-community-story.resolver.ts index 39e28b6fa7..7859492d38 100644 --- a/src/components/progress-report/community-stories/progress-report-community-story.resolver.ts +++ b/src/components/progress-report/community-stories/progress-report-community-story.resolver.ts @@ -7,7 +7,8 @@ import { } from '@nestjs/graphql'; import { AnonSession, IdArg, IdOf, LoggedInSession, Session } from '~/common'; import { Loader, LoaderOf } from '~/core'; -import { PeriodicReport, PeriodicReportLoader } from '../../periodic-report'; +import { PeriodicReportLoader } from '../../periodic-report'; +import { PeriodicReport } from '../../periodic-report/dto'; import { ChangePrompt, ChoosePrompt, diff --git a/src/components/progress-report/community-stories/progress-report-community-story.service.ts b/src/components/progress-report/community-stories/progress-report-community-story.service.ts index 1c0b3b2a41..5a2673f1a9 100644 --- a/src/components/progress-report/community-stories/progress-report-community-story.service.ts +++ b/src/components/progress-report/community-stories/progress-report-community-story.service.ts @@ -1,9 +1,6 @@ import { Injectable } from '@nestjs/common'; import { UnsecuredDto } from '~/common'; -import { - withEffectiveSensitivity, - withScope, -} from '../../authorization/policies/conditions'; +import { withEffectiveSensitivity, withScope } from '../../authorization'; import { Prompt } from '../../prompts/dto'; import { PromptVariantResponseListService } from '../../prompts/prompt-variant-response.service'; import { ProgressReport } from '../dto'; diff --git a/src/components/progress-report/dto/highlights.dto.ts b/src/components/progress-report/dto/highlights.dto.ts index 77fa443e49..75e25c78d1 100644 --- a/src/components/progress-report/dto/highlights.dto.ts +++ b/src/components/progress-report/dto/highlights.dto.ts @@ -1,8 +1,7 @@ import { keys as keysOf } from 'ts-transformer-keys'; -import { SecuredProps, Variant, VariantOf } from '~/common'; +import { Role, SecuredProps, Variant, VariantOf } from '~/common'; import { e } from '~/core/edgedb'; import { RegisterResource } from '~/core/resources'; -import { Role } from '../../authorization'; import { PromptVariantResponse } from '../../prompts/dto'; const variants = Variant.createList({ diff --git a/src/components/progress-report/dto/progress-report.entity.ts b/src/components/progress-report/dto/progress-report.entity.ts index 20178c276a..3cd21aeb93 100644 --- a/src/components/progress-report/dto/progress-report.entity.ts +++ b/src/components/progress-report/dto/progress-report.entity.ts @@ -11,7 +11,7 @@ import { BaseNode } from '~/core/database/results'; import { e } from '~/core/edgedb'; import { RegisterResource } from '~/core/resources'; import { LanguageEngagement } from '../../engagement/dto'; -import { DefinedFile } from '../../file'; +import { DefinedFile } from '../../file/dto'; import { IPeriodicReport } from '../../periodic-report/dto/periodic-report.dto'; import { ProgressReportCommunityStory } from './community-stories.dto'; import { ProgressReportHighlight } from './highlights.dto'; diff --git a/src/components/progress-report/highlights/progress-report-highlights.resolver.ts b/src/components/progress-report/highlights/progress-report-highlights.resolver.ts index 347c574afc..4e75b061b0 100644 --- a/src/components/progress-report/highlights/progress-report-highlights.resolver.ts +++ b/src/components/progress-report/highlights/progress-report-highlights.resolver.ts @@ -7,7 +7,8 @@ import { } from '@nestjs/graphql'; import { AnonSession, IdArg, IdOf, LoggedInSession, Session } from '~/common'; import { Loader, LoaderOf } from '~/core'; -import { PeriodicReport, PeriodicReportLoader } from '../../periodic-report'; +import { PeriodicReportLoader } from '../../periodic-report'; +import { PeriodicReport } from '../../periodic-report/dto'; import { ChangePrompt, ChoosePrompt, diff --git a/src/components/progress-report/highlights/progress-report-highlights.service.ts b/src/components/progress-report/highlights/progress-report-highlights.service.ts index d69cd65ad8..53c3d9df8b 100644 --- a/src/components/progress-report/highlights/progress-report-highlights.service.ts +++ b/src/components/progress-report/highlights/progress-report-highlights.service.ts @@ -1,9 +1,6 @@ import { Injectable } from '@nestjs/common'; import { UnsecuredDto } from '~/common'; -import { - withEffectiveSensitivity, - withScope, -} from '../../authorization/policies/conditions'; +import { withEffectiveSensitivity, withScope } from '../../authorization'; import { Prompt } from '../../prompts/dto'; import { PromptVariantResponseListService } from '../../prompts/prompt-variant-response.service'; import { ProgressReport } from '../dto'; diff --git a/src/components/progress-report/media/dto/media.dto.ts b/src/components/progress-report/media/dto/media.dto.ts index 722410715b..90b327096d 100644 --- a/src/components/progress-report/media/dto/media.dto.ts +++ b/src/components/progress-report/media/dto/media.dto.ts @@ -9,10 +9,12 @@ import { Variant, VariantOf, } from '~/common'; -import { LinkTo, SetDbType } from '~/core'; +import { LinkTo } from '~/core'; +import { SetDbType } from '~/core/database'; import { e } from '~/core/edgedb'; import { RegisterResource } from '~/core/resources'; -import { FileId, Media } from '../../../file'; +import { FileId } from '../../../file/dto'; +import { Media } from '../../../file/media/media.dto'; import { ProgressReport } from '../../dto'; import { ProgressReportHighlight } from '../../dto/highlights.dto'; import { MediaCategory } from '../media-category.enum'; diff --git a/src/components/progress-report/media/dto/upload.dto.ts b/src/components/progress-report/media/dto/upload.dto.ts index 07168f1250..41cdac7674 100644 --- a/src/components/progress-report/media/dto/upload.dto.ts +++ b/src/components/progress-report/media/dto/upload.dto.ts @@ -8,10 +8,8 @@ import { Variant, VariantInputField, } from '~/common'; -import { - CreateDefinedFileVersionInput, - MediaUserMetadata, -} from '../../../file'; +import { CreateDefinedFileVersionInput } from '../../../file/dto'; +import { MediaUserMetadata } from '../../../file/media/media.dto'; import { ProgressReport } from '../../dto'; import { MediaVariant, ProgressReportMedia, VariantGroup } from './media.dto'; diff --git a/src/components/progress-report/media/progress-report-media.repository.ts b/src/components/progress-report/media/progress-report-media.repository.ts index 0992bb64c3..6e5c4e1840 100644 --- a/src/components/progress-report/media/progress-report-media.repository.ts +++ b/src/components/progress-report/media/progress-report-media.repository.ts @@ -9,7 +9,7 @@ import { ServerException, Session, } from '~/common'; -import { DbTypeOf, DtoRepository } from '~/core'; +import { DbTypeOf, DtoRepository } from '~/core/database'; import { ACTIVE, createNode, diff --git a/src/components/progress-report/media/progress-report-media.service.ts b/src/components/progress-report/media/progress-report-media.service.ts index 3882564da1..72cfa3bf82 100644 --- a/src/components/progress-report/media/progress-report-media.service.ts +++ b/src/components/progress-report/media/progress-report-media.service.ts @@ -6,7 +6,8 @@ import { Session, UnsecuredDto, } from '~/common'; -import { DbTypeOf, ResourceLoader } from '~/core'; +import { ResourceLoader } from '~/core'; +import { DbTypeOf } from '~/core/database'; import { Privileges, withVariant } from '../../authorization'; import { FileService } from '../../file'; import { MediaService } from '../../file/media/media.service'; diff --git a/src/components/progress-report/media/resolvers/media.resolver.ts b/src/components/progress-report/media/resolvers/media.resolver.ts index 168497eb51..8096ed6793 100644 --- a/src/components/progress-report/media/resolvers/media.resolver.ts +++ b/src/components/progress-report/media/resolvers/media.resolver.ts @@ -8,7 +8,7 @@ import { import { AnonSession, IdArg, IdOf, LoggedInSession, Session } from '~/common'; import { Loader, LoaderOf } from '~/core'; import { Privileges } from '../../../authorization'; -import { Media } from '../../../file'; +import { Media } from '../../../file/media/media.dto'; import { MediaLoader } from '../../../file/media/media.loader'; import { PeriodicReportLoader } from '../../../periodic-report'; import { ProgressReport } from '../../dto'; diff --git a/src/components/progress-report/progress-report.repository.ts b/src/components/progress-report/progress-report.repository.ts index c3b4173f3c..8869190db4 100644 --- a/src/components/progress-report/progress-report.repository.ts +++ b/src/components/progress-report/progress-report.repository.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ProgressReport } from './dto'; @Injectable() diff --git a/src/components/progress-report/team-news/progress-report-team-news.resolver.ts b/src/components/progress-report/team-news/progress-report-team-news.resolver.ts index 06f90e34d4..95a08f2a45 100644 --- a/src/components/progress-report/team-news/progress-report-team-news.resolver.ts +++ b/src/components/progress-report/team-news/progress-report-team-news.resolver.ts @@ -7,7 +7,8 @@ import { } from '@nestjs/graphql'; import { AnonSession, IdArg, IdOf, LoggedInSession, Session } from '~/common'; import { Loader, LoaderOf } from '~/core'; -import { PeriodicReport, PeriodicReportLoader } from '../../periodic-report'; +import { PeriodicReportLoader } from '../../periodic-report'; +import { PeriodicReport } from '../../periodic-report/dto'; import { ChangePrompt, ChoosePrompt, diff --git a/src/components/progress-report/team-news/progress-report-team-news.service.ts b/src/components/progress-report/team-news/progress-report-team-news.service.ts index 9904252564..e21bab43db 100644 --- a/src/components/progress-report/team-news/progress-report-team-news.service.ts +++ b/src/components/progress-report/team-news/progress-report-team-news.service.ts @@ -1,9 +1,6 @@ import { Injectable } from '@nestjs/common'; import { UnsecuredDto } from '~/common'; -import { - withEffectiveSensitivity, - withScope, -} from '../../authorization/policies/conditions'; +import { withEffectiveSensitivity, withScope } from '../../authorization'; import { Prompt } from '../../prompts/dto'; import { PromptVariantResponseListService } from '../../prompts/prompt-variant-response.service'; import { ProgressReport } from '../dto'; diff --git a/src/components/progress-report/variance-explanation/migrations/rename.migration.ts b/src/components/progress-report/variance-explanation/migrations/rename.migration.ts index ce03c895a4..eb4f5b910f 100644 --- a/src/components/progress-report/variance-explanation/migrations/rename.migration.ts +++ b/src/components/progress-report/variance-explanation/migrations/rename.migration.ts @@ -1,5 +1,5 @@ import { node, relation } from 'cypher-query-builder'; -import { BaseMigration, Migration } from '~/core'; +import { BaseMigration, Migration } from '~/core/database'; import { ACTIVE } from '~/core/database/query'; @Migration('2023-10-12T11:00:00') diff --git a/src/components/progress-report/variance-explanation/variance-explanation.repository.ts b/src/components/progress-report/variance-explanation/variance-explanation.repository.ts index ef07a0ab8a..0bda1d70ff 100644 --- a/src/components/progress-report/variance-explanation/variance-explanation.repository.ts +++ b/src/components/progress-report/variance-explanation/variance-explanation.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { inArray, node, Query, relation } from 'cypher-query-builder'; import { ID, UnsecuredDto } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, ExpressionInput, diff --git a/src/components/progress-report/workflow/progress-report-workflow.repository.ts b/src/components/progress-report/workflow/progress-report-workflow.repository.ts index f34d8de70a..05468d2e9f 100644 --- a/src/components/progress-report/workflow/progress-report-workflow.repository.ts +++ b/src/components/progress-report/workflow/progress-report-workflow.repository.ts @@ -10,7 +10,7 @@ import { Session, UnsecuredDto, } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, diff --git a/src/components/progress-report/workflow/resolvers/progress-report-workflow-event.resolver.ts b/src/components/progress-report/workflow/resolvers/progress-report-workflow-event.resolver.ts index 404e683e26..881fffea94 100644 --- a/src/components/progress-report/workflow/resolvers/progress-report-workflow-event.resolver.ts +++ b/src/components/progress-report/workflow/resolvers/progress-report-workflow-event.resolver.ts @@ -1,7 +1,8 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { mapSecuredValue } from '~/common'; import { Loader, LoaderOf } from '~/core'; -import { SecuredUser, UserLoader } from '../../../user'; +import { UserLoader } from '../../../user'; +import { SecuredUser } from '../../../user/dto'; import { ProgressReportWorkflowEvent as WorkflowEvent } from '../dto/workflow-event.dto'; @Resolver(WorkflowEvent) diff --git a/src/components/progress-summary/handlers/extract-pnp-file-on-upload.handler.ts b/src/components/progress-summary/handlers/extract-pnp-file-on-upload.handler.ts index ff71e55303..739b7284c7 100644 --- a/src/components/progress-summary/handlers/extract-pnp-file-on-upload.handler.ts +++ b/src/components/progress-summary/handlers/extract-pnp-file-on-upload.handler.ts @@ -1,4 +1,4 @@ -import { EventsHandler, ILogger, Logger } from '../../../core'; +import { EventsHandler, ILogger, Logger } from '~/core'; import { ReportType } from '../../periodic-report/dto'; import { PeriodicReportUploadedEvent } from '../../periodic-report/events'; import { SummaryPeriod } from '../dto'; diff --git a/src/components/progress-summary/progress-report-connection.resolver.ts b/src/components/progress-summary/progress-report-connection.resolver.ts index e8f3621f8a..a396de861b 100644 --- a/src/components/progress-summary/progress-report-connection.resolver.ts +++ b/src/components/progress-summary/progress-report-connection.resolver.ts @@ -1,5 +1,5 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { Loader, LoaderOf } from '../../core'; +import { Loader, LoaderOf } from '~/core'; import { ProgressReport } from '../progress-report/dto'; import { ProgressSummary, SummaryPeriod } from './dto'; import { ProgressSummaryLoader } from './progress-summary.loader'; diff --git a/src/components/progress-summary/progress-summary.extractor.ts b/src/components/progress-summary/progress-summary.extractor.ts index 1f22e2c834..27edbbed34 100644 --- a/src/components/progress-summary/progress-summary.extractor.ts +++ b/src/components/progress-summary/progress-summary.extractor.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { Nil } from '@seedcompany/common'; import { clamp, round } from 'lodash'; -import { CalendarDate, fiscalQuarter, fiscalYear } from '../../common'; -import { Column, Row } from '../../common/xlsx.util'; -import { Downloadable } from '../file'; +import { CalendarDate, fiscalQuarter, fiscalYear } from '~/common'; +import { Column, Row } from '~/common/xlsx.util'; +import { Downloadable } from '../file/dto'; import { Pnp, ProgressSheet } from '../pnp'; import { ProgressSummary as Progress } from './dto'; diff --git a/src/components/progress-summary/progress-summary.repository.ts b/src/components/progress-summary/progress-summary.repository.ts index 5efecadded..4589d0a8bf 100644 --- a/src/components/progress-summary/progress-summary.repository.ts +++ b/src/components/progress-summary/progress-summary.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { inArray, node, relation } from 'cypher-query-builder'; import { ID } from '~/common'; -import { CommonRepository } from '~/core'; +import { CommonRepository } from '~/core/database'; import { ACTIVE, listConcat, merge } from '~/core/database/query'; import { ProgressReport } from '../progress-report/dto'; import { FetchedSummaries, ProgressSummary, SummaryPeriod } from './dto'; diff --git a/src/components/project-change-request/dto/create-project-change-request.dto.ts b/src/components/project-change-request/dto/create-project-change-request.dto.ts index af821672d8..7f5a751a36 100644 --- a/src/components/project-change-request/dto/create-project-change-request.dto.ts +++ b/src/components/project-change-request/dto/create-project-change-request.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField } from '../../../common'; +import { ID, IdField } from '~/common'; import { ProjectChangeRequestType } from './project-change-request-type.enum'; import { ProjectChangeRequest } from './project-change-request.dto'; diff --git a/src/components/project-change-request/dto/delete-project-change-request.dto.ts b/src/components/project-change-request/dto/delete-project-change-request.dto.ts index ef5475e4b5..6c12547181 100644 --- a/src/components/project-change-request/dto/delete-project-change-request.dto.ts +++ b/src/components/project-change-request/dto/delete-project-change-request.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteProjectChangeRequestOutput extends MutationPlaceholderOutput {} diff --git a/src/components/project-change-request/dto/project-change-request.dto.ts b/src/components/project-change-request/dto/project-change-request.dto.ts index e747a9d141..6e6b97d60e 100644 --- a/src/components/project-change-request/dto/project-change-request.dto.ts +++ b/src/components/project-change-request/dto/project-change-request.dto.ts @@ -1,7 +1,7 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; +import { ID, SecuredProps, SecuredString } from '~/common'; import { RegisterResource } from '~/core/resources'; -import { ID, SecuredProps, SecuredString } from '../../../common'; import { Changeset } from '../../changeset/dto'; import { SecuredProjectChangeRequestStatus } from './project-change-request-status.enum'; import { SecuredProjectChangeRequestTypes } from './project-change-request-type.enum'; diff --git a/src/components/project-change-request/dto/update-project-change-request.dto.ts b/src/components/project-change-request/dto/update-project-change-request.dto.ts index 586379f438..bccc0a66ba 100644 --- a/src/components/project-change-request/dto/update-project-change-request.dto.ts +++ b/src/components/project-change-request/dto/update-project-change-request.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField } from '../../../common'; +import { ID, IdField } from '~/common'; import { ProjectChangeRequestStatus } from './project-change-request-status.enum'; import { ProjectChangeRequestType } from './project-change-request-type.enum'; import { ProjectChangeRequest } from './project-change-request.dto'; diff --git a/src/components/project-change-request/events/project-change-request-approved.event.ts b/src/components/project-change-request/events/project-change-request-approved.event.ts index fb3438ed33..f7a29a5e64 100644 --- a/src/components/project-change-request/events/project-change-request-approved.event.ts +++ b/src/components/project-change-request/events/project-change-request-approved.event.ts @@ -1,4 +1,4 @@ -import { Session, UnsecuredDto } from '../../../common'; +import { Session, UnsecuredDto } from '~/common'; import { ProjectChangeRequest } from '../dto'; export class ProjectChangeRequestApprovedEvent { diff --git a/src/components/project-change-request/project-change-request.loader.ts b/src/components/project-change-request/project-change-request.loader.ts index acedbfa41d..d1c97a824b 100644 --- a/src/components/project-change-request/project-change-request.loader.ts +++ b/src/components/project-change-request/project-change-request.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Changeset } from '../changeset/dto'; import { ProjectChangeRequest } from './dto'; import { ProjectChangeRequestService } from './project-change-request.service'; diff --git a/src/components/project-change-request/project-change-request.repository.ts b/src/components/project-change-request/project-change-request.repository.ts index 2827cf3773..b7b9a06547 100644 --- a/src/components/project-change-request/project-change-request.repository.ts +++ b/src/components/project-change-request/project-change-request.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { node, Query, relation } from 'cypher-query-builder'; -import { ID, ServerException, Session, UnsecuredDto } from '../../common'; -import { DtoRepository } from '../../core'; +import { ID, ServerException, Session, UnsecuredDto } from '~/common'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, @@ -10,7 +10,7 @@ import { merge, paginate, sorting, -} from '../../core/database/query'; +} from '~/core/database/query'; import { CreateProjectChangeRequest, ProjectChangeRequest, diff --git a/src/components/project-change-request/project-change-request.resolver.ts b/src/components/project-change-request/project-change-request.resolver.ts index 8d8016b2db..6e4ac29b80 100644 --- a/src/components/project-change-request/project-change-request.resolver.ts +++ b/src/components/project-change-request/project-change-request.resolver.ts @@ -5,9 +5,10 @@ import { ResolveField, Resolver, } from '@nestjs/graphql'; -import { ID, IdArg, LoggedInSession, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { IProject, Project, ProjectLoader } from '../project'; +import { ID, IdArg, LoggedInSession, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { ProjectLoader } from '../project'; +import { IProject, Project } from '../project/dto'; import { CreateProjectChangeRequestInput, CreateProjectChangeRequestOutput, diff --git a/src/components/project-change-request/project-change-request.service.ts b/src/components/project-change-request/project-change-request.service.ts index c678cedb3a..8707bae8c5 100644 --- a/src/components/project-change-request/project-change-request.service.ts +++ b/src/components/project-change-request/project-change-request.service.ts @@ -6,19 +6,14 @@ import { ServerException, Session, UnsecuredDto, -} from '../../common'; -import { - ConfigService, - DatabaseService, - HandleIdLookup, - IEventBus, - ILogger, - Logger, -} from '../../core'; -import { mapListResults } from '../../core/database/results'; +} from '~/common'; +import { HandleIdLookup, IEventBus, ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; +import { mapListResults } from '~/core/database/results'; import { Privileges } from '../authorization'; -import { ChangesetFinalizingEvent } from '../changeset/events'; -import { ProjectService, ProjectStatus } from '../project'; +import { ChangesetFinalizingEvent } from '../changeset'; +import { ProjectService } from '../project'; +import { ProjectStatus } from '../project/dto'; import { CreateProjectChangeRequest, ProjectChangeRequest, @@ -34,7 +29,6 @@ import { ProjectChangeRequestRepository } from './project-change-request.reposit export class ProjectChangeRequestService { constructor( private readonly db: DatabaseService, - private readonly config: ConfigService, @Logger('project:change-request:service') private readonly logger: ILogger, private readonly privileges: Privileges, private readonly eventBus: IEventBus, diff --git a/src/components/project/dto/create-project.dto.ts b/src/components/project/dto/create-project.dto.ts index 815bf65272..727f8c41b8 100644 --- a/src/components/project/dto/create-project.dto.ts +++ b/src/components/project/dto/create-project.dto.ts @@ -14,7 +14,7 @@ import { NameField, Sensitivity, SensitivityField, -} from '../../../common'; +} from '~/common'; import { Location } from '../../location/dto'; import { ReportPeriod } from '../../periodic-report/dto'; import { ProjectStep } from './project-step.enum'; diff --git a/src/components/project/dto/delete-project.dto.ts b/src/components/project/dto/delete-project.dto.ts index 36aef4061d..ba982e67e2 100644 --- a/src/components/project/dto/delete-project.dto.ts +++ b/src/components/project/dto/delete-project.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteProjectOutput extends MutationPlaceholderOutput {} diff --git a/src/components/project/dto/project.dto.ts b/src/components/project/dto/project.dto.ts index 820869091e..26e4e7cb3f 100644 --- a/src/components/project/dto/project.dto.ts +++ b/src/components/project/dto/project.dto.ts @@ -34,10 +34,10 @@ import { e } from '~/core/edgedb'; import { LinkTo, RegisterResource } from '~/core/resources'; import { Budget } from '../../budget/dto'; import { ChangesetAware } from '../../changeset/dto'; -import { Commentable } from '../../comments'; +import { Commentable } from '../../comments/dto'; import { IEngagement as Engagement } from '../../engagement/dto'; import { Directory } from '../../file/dto'; -import { SecuredTags } from '../../language/dto/language.dto'; +import { SecuredTags } from '../../language/dto'; import { Location } from '../../location/dto'; import { Partnership } from '../../partnership/dto'; import { SecuredReportPeriod } from '../../periodic-report/dto'; diff --git a/src/components/project/dto/update-project.dto.ts b/src/components/project/dto/update-project.dto.ts index 111103fd75..f0282d7879 100644 --- a/src/components/project/dto/update-project.dto.ts +++ b/src/components/project/dto/update-project.dto.ts @@ -13,7 +13,7 @@ import { NameField, Sensitivity, SensitivityField, -} from '../../../common'; +} from '~/common'; import { ChangesetIdField } from '../../changeset'; import { Location } from '../../location/dto'; import { ReportPeriod } from '../../periodic-report/dto'; diff --git a/src/components/project/engagement-connection.resolver.ts b/src/components/project/engagement-connection.resolver.ts index a1cbe75379..c908f7864d 100644 --- a/src/components/project/engagement-connection.resolver.ts +++ b/src/components/project/engagement-connection.resolver.ts @@ -1,7 +1,7 @@ import { Info, Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { Fields, IsOnly, viewOfChangeset } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { IEngagement } from '../engagement'; +import { Fields, IsOnly, viewOfChangeset } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { IEngagement } from '../engagement/dto'; import { IProject } from './dto'; import { ProjectLoader } from './project.loader'; diff --git a/src/components/project/events/project-created.event.ts b/src/components/project/events/project-created.event.ts index 8f0b7fb570..80f5ed1327 100644 --- a/src/components/project/events/project-created.event.ts +++ b/src/components/project/events/project-created.event.ts @@ -1,4 +1,4 @@ -import { Session, UnsecuredDto } from '../../../common'; +import { Session, UnsecuredDto } from '~/common'; import { Project } from '../dto'; export class ProjectCreatedEvent { diff --git a/src/components/project/events/project-deleted.event.ts b/src/components/project/events/project-deleted.event.ts index 4d121e76d4..e1b609459d 100644 --- a/src/components/project/events/project-deleted.event.ts +++ b/src/components/project/events/project-deleted.event.ts @@ -1,4 +1,4 @@ -import { Session, UnsecuredDto } from '../../../common'; +import { Session, UnsecuredDto } from '~/common'; import { Project } from '../dto'; export class ProjectDeletedEvent { diff --git a/src/components/project/events/project-updated.event.ts b/src/components/project/events/project-updated.event.ts index a888e15572..6a448f1f47 100644 --- a/src/components/project/events/project-updated.event.ts +++ b/src/components/project/events/project-updated.event.ts @@ -1,4 +1,4 @@ -import { Session, UnsecuredDto } from '../../../common'; +import { Session, UnsecuredDto } from '~/common'; import { Project, UpdateProject } from '../dto'; export class ProjectUpdatedEvent { diff --git a/src/components/project/financial-approver/dto/financial-approver.dto.ts b/src/components/project/financial-approver/dto/financial-approver.dto.ts new file mode 100644 index 0000000000..fd2c4da889 --- /dev/null +++ b/src/components/project/financial-approver/dto/financial-approver.dto.ts @@ -0,0 +1,39 @@ +import { Field, InputType, ObjectType } from '@nestjs/graphql'; +import { keys as keysOf } from 'ts-transformer-keys'; +import { ID, IdField, SecuredProps, UnsecuredDto } from '~/common'; +import { LinkTo, RegisterResource } from '~/core'; +import { e } from '~/core/edgedb'; +import { User } from '../../../user/dto'; +import { ProjectType } from '../../dto'; + +@RegisterResource({ + db: e.Project.FinancialApprover, +}) +@ObjectType('ProjectTypeFinancialApprover') +export class FinancialApprover { + static readonly Props = keysOf(); + static readonly SecuredProps = keysOf>(); + + readonly user: LinkTo<'User'> & Pick, 'email'>; + + @Field(() => [ProjectType]) + readonly projectTypes: readonly [ProjectType, ...ProjectType[]]; +} + +@InputType('ProjectTypeFinancialApproverInput') +export abstract class FinancialApproverInput { + @IdField() + readonly user: ID<'User'>; + + @Field(() => [ProjectType]) + readonly projectTypes: readonly [ProjectType, ...ProjectType[]]; +} + +declare module '~/core/resources/map' { + interface ResourceMap { + FinancialApprover: typeof FinancialApprover; + } + interface ResourceDBMap { + FinancialApprover: typeof e.Project.FinancialApprover; + } +} diff --git a/src/components/project/financial-approver/dto/index.ts b/src/components/project/financial-approver/dto/index.ts new file mode 100644 index 0000000000..e1f188cf2b --- /dev/null +++ b/src/components/project/financial-approver/dto/index.ts @@ -0,0 +1 @@ +export * from './financial-approver.dto'; diff --git a/src/components/project/financial-approver/financial-approver-neo4j.repository.ts b/src/components/project/financial-approver/financial-approver-neo4j.repository.ts new file mode 100644 index 0000000000..f95294448f --- /dev/null +++ b/src/components/project/financial-approver/financial-approver-neo4j.repository.ts @@ -0,0 +1,87 @@ +import { Injectable } from '@nestjs/common'; +import { many, Many } from '@seedcompany/common'; +import { node, Query, relation } from 'cypher-query-builder'; +import { PublicOf, ServerException } from '~/common'; +import { CommonRepository } from '~/core/database'; +import { ACTIVE, merge } from '~/core/database/query'; +import { ProjectType } from '../dto/project-type.enum'; +import { FinancialApprover, FinancialApproverInput } from './dto'; +import { FinancialApproverRepository } from './financial-approver.repository'; + +@Injectable() +export class FinancialApproverNeo4jRepository + extends CommonRepository + implements PublicOf +{ + async read(types?: Many) { + const query = this.db + .query() + .match([ + node('node', 'ProjectTypeFinancialApprover'), + relation('out', '', 'financialApprover', ACTIVE), + node('user', 'User'), + ]) + .apply((q) => + types + ? q.raw( + `WHERE size(apoc.coll.intersection(node.projectTypes, $types)) > 0`, + { types: many(types) }, + ) + : q, + ) + .apply(this.hydrate()); + return await query.run(); + } + + async write(input: FinancialApproverInput) { + if (input.projectTypes.length === 0) { + const query = this.db + .query() + .match([ + node('node', 'ProjectTypeFinancialApprover'), + relation('out', '', 'financialApprover', ACTIVE), + node('user', 'User', { id: input.user }), + ]) + .detachDelete('node'); + await query.run(); + return null; + } + + const query = this.db + .query() + .match(node('user', 'User', { id: input.user })) + .merge([ + node('node', 'ProjectTypeFinancialApprover'), + relation('out', '', 'financialApprover', { active: true }), + node('user'), + ]) + .setValues({ + 'node.projectTypes': input.projectTypes, + }) + .apply(this.hydrate()); + + const result = await query.first(); + if (!result) { + throw new ServerException('Failed to set financial approver.'); + } + + return result; + } + + private hydrate() { + return (query: Query) => + query + .with('node, user') + .optionalMatch([ + node('user'), + relation('out', '', 'email', ACTIVE), + node('email'), + ]) + .return<{ dto: FinancialApprover }>( + merge('node', { + user: merge('user { .id }', { email: 'email.value' }), + }).as('dto'), + ) + .map('dto'); + } +} diff --git a/src/components/project/financial-approver/financial-approver.module.ts b/src/components/project/financial-approver/financial-approver.module.ts new file mode 100644 index 0000000000..75efd5718a --- /dev/null +++ b/src/components/project/financial-approver/financial-approver.module.ts @@ -0,0 +1,17 @@ +import { Module } from '@nestjs/common'; +import { splitDb2 } from '~/core'; +import { FinancialApproverNeo4jRepository } from './financial-approver-neo4j.repository'; +import { FinancialApproverRepository } from './financial-approver.repository'; +import { FinancialApproverResolver } from './financial-approver.resolver'; + +@Module({ + providers: [ + FinancialApproverResolver, + splitDb2(FinancialApproverRepository, { + edge: FinancialApproverRepository, + neo4j: FinancialApproverNeo4jRepository, + }), + ], + exports: [FinancialApproverRepository], +}) +export class FinancialApproverModule {} diff --git a/src/components/project/financial-approver/financial-approver.repository.ts b/src/components/project/financial-approver/financial-approver.repository.ts new file mode 100644 index 0000000000..de238adf2a --- /dev/null +++ b/src/components/project/financial-approver/financial-approver.repository.ts @@ -0,0 +1,57 @@ +import { Injectable } from '@nestjs/common'; +import { many, Many } from '@seedcompany/common'; +import { e, EdgeDB } from '~/core/edgedb'; +import { ProjectType } from '../dto'; +import { FinancialApproverInput } from './dto'; + +@Injectable() +export class FinancialApproverRepository { + constructor(private readonly db: EdgeDB) {} + + async read(types?: Many) { + const query = e.select(e.Project.FinancialApprover, (approver) => ({ + projectTypes: true, + user: () => ({ id: true, email: true }), + ...(types + ? { + filter: e.op( + 'exists', + e.op( + approver.projectTypes, + 'intersect', + e.cast(e.Project.Type, e.set(...many(types))), + ), + ), + } + : {}), + })); + return await this.db.run(query); + } + + async write({ user: userId, projectTypes }: FinancialApproverInput) { + const user = e.cast(e.User, e.cast(e.uuid, userId)); + + if (projectTypes.length === 0) { + const query = e.delete(e.Project.FinancialApprover, (fa) => ({ + filter: e.op(fa.user, '=', user), + })); + await this.db.run(query); + return null; + } + + const written = e + .insert(e.Project.FinancialApprover, { user, projectTypes }) + .unlessConflict(({ user }) => ({ + on: user, + else: e.update(e.Project.FinancialApprover, (approver) => ({ + filter_single: e.op(approver.user, '=', user), + set: { projectTypes }, + })), + })); + const query = e.select(written, () => ({ + projectTypes: true, + user: () => ({ id: true, email: true }), + })); + return await this.db.run(query); + } +} diff --git a/src/components/project/financial-approver/financial-approver.resolver.ts b/src/components/project/financial-approver/financial-approver.resolver.ts new file mode 100644 index 0000000000..4dad21116f --- /dev/null +++ b/src/components/project/financial-approver/financial-approver.resolver.ts @@ -0,0 +1,57 @@ +import { + Args, + Mutation, + Parent, + Query, + ResolveField, + Resolver, +} from '@nestjs/graphql'; +import { LoggedInSession, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { Privileges } from '../../authorization'; +import { UserLoader } from '../../user'; +import { User } from '../../user/dto'; +import { ProjectType } from '../dto/project-type.enum'; +import { FinancialApprover, FinancialApproverInput } from './dto'; +import { FinancialApproverRepository } from './financial-approver.repository'; + +@Resolver(FinancialApprover) +export class FinancialApproverResolver { + constructor( + private readonly repo: FinancialApproverRepository, + private readonly privileges: Privileges, + ) {} + + @Query(() => [FinancialApprover]) + async projectTypeFinancialApprovers( + @Args({ + name: 'projectTypes', + type: () => [ProjectType], + nullable: true, + }) + types: readonly ProjectType[] | undefined, + @LoggedInSession() _: Session, // require login + ): Promise { + return await this.repo.read(types); + } + + @Mutation(() => FinancialApprover, { + description: 'Set a user as a financial approver for some project types', + nullable: true, + }) + async setProjectTypeFinancialApprover( + @Args('input') input: FinancialApproverInput, + @LoggedInSession() session: Session, + ): Promise { + this.privileges.for(session, FinancialApprover).verifyCan('edit'); + return await this.repo.write(input); + } + + @ResolveField(() => User) + async user( + @Parent() { user }: FinancialApprover, + @Loader(UserLoader) users: LoaderOf, + ): Promise { + return await users.load(user.id); + } +} diff --git a/src/components/project/financial-approver/index.ts b/src/components/project/financial-approver/index.ts new file mode 100644 index 0000000000..a03886210e --- /dev/null +++ b/src/components/project/financial-approver/index.ts @@ -0,0 +1 @@ +export * from './financial-approver.repository'; diff --git a/src/components/project/handlers/apply-finalized-changeset-to-project.handler.ts b/src/components/project/handlers/apply-finalized-changeset-to-project.handler.ts index 79b7d4ddb1..c206daa1c5 100644 --- a/src/components/project/handlers/apply-finalized-changeset-to-project.handler.ts +++ b/src/components/project/handlers/apply-finalized-changeset-to-project.handler.ts @@ -1,16 +1,13 @@ import { node, relation } from 'cypher-query-builder'; -import { ServerException } from '../../../common'; +import { ServerException } from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; +import { ACTIVE, INACTIVE } from '~/core/database/query'; import { - DatabaseService, - EventsHandler, - IEventHandler, - ILogger, - Logger, -} from '../../../core'; -import { ACTIVE, INACTIVE } from '../../../core/database/query'; -import { commitChangesetProps } from '../../changeset/commit-changeset-props.query'; -import { ChangesetFinalizingEvent } from '../../changeset/events'; -import { rejectChangesetProps } from '../../changeset/reject-changeset-props.query'; + ChangesetFinalizingEvent, + commitChangesetProps, + rejectChangesetProps, +} from '../../changeset'; type SubscribedEvent = ChangesetFinalizingEvent; diff --git a/src/components/project/handlers/send-step-change-notification-on-change-request-approved.ts b/src/components/project/handlers/send-step-change-notification-on-change-request-approved.ts index 20815b4b80..6ede119d09 100644 --- a/src/components/project/handlers/send-step-change-notification-on-change-request-approved.ts +++ b/src/components/project/handlers/send-step-change-notification-on-change-request-approved.ts @@ -2,14 +2,14 @@ import { EmailService } from '@seedcompany/nestjs-email'; import { node, relation } from 'cypher-query-builder'; import { ConfigService, - DatabaseService, EventsHandler, IEventHandler, ILogger, Logger, -} from '../../../core'; -import { ACTIVE, INACTIVE } from '../../../core/database/query'; -import { ProjectStepChanged } from '../../../core/email/templates'; +} from '~/core'; +import { DatabaseService } from '~/core/database'; +import { ACTIVE, INACTIVE } from '~/core/database/query'; +import { ProjectStepChanged } from '~/core/email/templates'; import { ProjectChangeRequestApprovedEvent } from '../../project-change-request/events'; import { Project, ProjectStep } from '../dto'; import { ProjectRules } from '../project.rules'; diff --git a/src/components/project/handlers/set-department-id.handler.ts b/src/components/project/handlers/set-department-id.handler.ts index f9f013628e..f97d2f8106 100644 --- a/src/components/project/handlers/set-department-id.handler.ts +++ b/src/components/project/handlers/set-department-id.handler.ts @@ -1,15 +1,6 @@ -import { - ClientException, - ID, - ServerException, - UnsecuredDto, -} from '../../../common'; -import { - ConfigService, - DatabaseService, - EventsHandler, - IEventHandler, -} from '../../../core'; +import { ClientException, ID, ServerException, UnsecuredDto } from '~/common'; +import { ConfigService, EventsHandler, IEventHandler } from '~/core'; +import { DatabaseService } from '~/core/database'; import { Project, ProjectStep, ProjectType } from '../dto'; import { ProjectUpdatedEvent } from '../events'; diff --git a/src/components/project/handlers/set-initial-mou-end.handler.ts b/src/components/project/handlers/set-initial-mou-end.handler.ts index 64691e42a0..929f8e155d 100644 --- a/src/components/project/handlers/set-initial-mou-end.handler.ts +++ b/src/components/project/handlers/set-initial-mou-end.handler.ts @@ -1,11 +1,6 @@ -import { ServerException } from '../../../common'; -import { - DatabaseService, - EventsHandler, - IEventHandler, - ILogger, - Logger, -} from '../../../core'; +import { ServerException } from '~/common'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; import { IProject, ProjectStatus } from '../dto'; import { ProjectCreatedEvent, ProjectUpdatedEvent } from '../events'; diff --git a/src/components/project/handlers/set-step-changed-at.handler.ts b/src/components/project/handlers/set-step-changed-at.handler.ts index 8bd0d96303..70dbbc8d56 100644 --- a/src/components/project/handlers/set-step-changed-at.handler.ts +++ b/src/components/project/handlers/set-step-changed-at.handler.ts @@ -1,13 +1,7 @@ -import { - DatabaseService, - EventsHandler, - IEventHandler, - ILogger, - Logger, -} from '../../../core'; +import { EventsHandler, IEventHandler, ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; import { resolveProjectType } from '../dto'; import { ProjectUpdatedEvent } from '../events'; -import { ProjectService } from '../project.service'; @EventsHandler(ProjectUpdatedEvent) export class ProjectStepChangedAtHandler @@ -15,7 +9,6 @@ export class ProjectStepChangedAtHandler { constructor( private readonly db: DatabaseService, - private readonly projectService: ProjectService, @Logger('project:step-changed-at') private readonly logger: ILogger, ) {} diff --git a/src/components/project/handlers/step-changed-notification.handler.ts b/src/components/project/handlers/step-changed-notification.handler.ts index 67f2bfac92..fb5d15f99b 100644 --- a/src/components/project/handlers/step-changed-notification.handler.ts +++ b/src/components/project/handlers/step-changed-notification.handler.ts @@ -5,8 +5,8 @@ import { IEventHandler, ILogger, Logger, -} from '../../../core'; -import { ProjectStepChanged } from '../../../core/email/templates'; +} from '~/core'; +import { ProjectStepChanged } from '~/core/email/templates'; import { ProjectUpdatedEvent } from '../events'; import { ProjectRules } from '../project.rules'; diff --git a/src/components/project/index.ts b/src/components/project/index.ts index baaeb276d5..a3e1a926aa 100644 --- a/src/components/project/index.ts +++ b/src/components/project/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './project.service'; export * from './project-member'; export * from './list-filter.query'; diff --git a/src/components/project/internship-project.resolver.ts b/src/components/project/internship-project.resolver.ts index 408a70e6b4..7d4315b409 100644 --- a/src/components/project/internship-project.resolver.ts +++ b/src/components/project/internship-project.resolver.ts @@ -1,14 +1,15 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { AnonSession, ListArg, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; +import { AnonSession, ListArg, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { EngagementLoader } from '../engagement'; import { EngagementListInput, SecuredEngagementList, SecuredInternshipEngagementList, } from '../engagement/dto'; -import { EngagementLoader } from '../engagement/engagement.loader'; -import { InternshipProject, Project, ProjectService } from './index'; +import { InternshipProject, Project } from './dto'; +import { ProjectService } from './project.service'; @Resolver(InternshipProject) export class InternshipProjectResolver { diff --git a/src/components/project/list-filter.query.ts b/src/components/project/list-filter.query.ts index ff20d75541..c28560bb53 100644 --- a/src/components/project/list-filter.query.ts +++ b/src/components/project/list-filter.query.ts @@ -1,10 +1,5 @@ import { greaterThan, inArray, node, relation } from 'cypher-query-builder'; -import { - ACTIVE, - filter, - matchProjectSens, - path, -} from '../../core/database/query'; +import { ACTIVE, filter, matchProjectSens, path } from '~/core/database/query'; import { ProjectListInput } from './dto'; export const projectListFilter = (input: ProjectListInput) => diff --git a/src/components/project/migrations/rename-translation-to-momentum.migration.ts b/src/components/project/migrations/rename-translation-to-momentum.migration.ts index 72b28d0120..f5f050d084 100644 --- a/src/components/project/migrations/rename-translation-to-momentum.migration.ts +++ b/src/components/project/migrations/rename-translation-to-momentum.migration.ts @@ -1,4 +1,4 @@ -import { BaseMigration, Migration } from '~/core'; +import { BaseMigration, Migration } from '~/core/database'; @Migration('2024-04-08T12:51:00') export class RenameTranslationToMomentumMigration extends BaseMigration { diff --git a/src/components/project/project-member/dto/create-project-member.dto.ts b/src/components/project/project-member/dto/create-project-member.dto.ts index 9b84aac3ed..a0d25f01d5 100644 --- a/src/components/project/project-member/dto/create-project-member.dto.ts +++ b/src/components/project/project-member/dto/create-project-member.dto.ts @@ -1,8 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, UnsecuredDto } from '../../../../common'; -import { Role } from '../../../authorization'; +import { ID, IdField, Role, UnsecuredDto } from '~/common'; import { Project } from '../../dto'; import { ProjectMember } from './project-member.dto'; diff --git a/src/components/project/project-member/dto/delete-project-member.dto.ts b/src/components/project/project-member/dto/delete-project-member.dto.ts index d6f816054e..9944c92457 100644 --- a/src/components/project/project-member/dto/delete-project-member.dto.ts +++ b/src/components/project/project-member/dto/delete-project-member.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteProjectMemberOutput extends MutationPlaceholderOutput {} diff --git a/src/components/project/project-member/dto/project-member.dto.ts b/src/components/project/project-member/dto/project-member.dto.ts index aed95752ea..0e71be3218 100644 --- a/src/components/project/project-member/dto/project-member.dto.ts +++ b/src/components/project/project-member/dto/project-member.dto.ts @@ -1,18 +1,18 @@ import { Field, ObjectType } from '@nestjs/graphql'; import { DateTime } from 'luxon'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DateTimeField, Resource, SecuredProps, + SecuredRoles, Sensitivity, SensitivityField, SetUnsecuredType, UnsecuredDto, -} from '../../../../common'; -import { SecuredRoles } from '../../../authorization'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { SecuredUser, User } from '../../../user/dto'; @RegisterResource({ db: e.Project.Member }) diff --git a/src/components/project/project-member/dto/update-project-member.dto.ts b/src/components/project/project-member/dto/update-project-member.dto.ts index 123beb5723..b103a29b4f 100644 --- a/src/components/project/project-member/dto/update-project-member.dto.ts +++ b/src/components/project/project-member/dto/update-project-member.dto.ts @@ -1,8 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField } from '../../../../common'; -import { Role } from '../../../authorization'; +import { ID, IdField, Role } from '~/common'; import { ProjectMember } from './project-member.dto'; @InputType() diff --git a/src/components/project/project-member/index.ts b/src/components/project/project-member/index.ts index 6f89595df8..c4305488fd 100644 --- a/src/components/project/project-member/index.ts +++ b/src/components/project/project-member/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './project-member.service'; export * from './project-member.loader'; diff --git a/src/components/project/project-member/project-member.loader.ts b/src/components/project/project-member/project-member.loader.ts index 02129503be..47584f5eea 100644 --- a/src/components/project/project-member/project-member.loader.ts +++ b/src/components/project/project-member/project-member.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { ProjectMember } from './dto'; import { ProjectMemberService } from './project-member.service'; diff --git a/src/components/project/project-member/project-member.resolver.ts b/src/components/project/project-member/project-member.resolver.ts index b31e00322f..dd2af774c8 100644 --- a/src/components/project/project-member/project-member.resolver.ts +++ b/src/components/project/project-member/project-member.resolver.ts @@ -6,8 +6,8 @@ import { ListArg, LoggedInSession, Session, -} from '../../../common'; -import { Loader, LoaderOf } from '../../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { ProjectMemberLoader, ProjectMemberService } from '../project-member'; import { CreateProjectMemberInput, diff --git a/src/components/project/project-member/project-member.service.ts b/src/components/project/project-member/project-member.service.ts index 1157b61e86..72ee49e4e2 100644 --- a/src/components/project/project-member/project-member.service.ts +++ b/src/components/project/project-member/project-member.service.ts @@ -6,14 +6,16 @@ import { InputException, NotFoundException, ObjectView, + Role, ServerException, Session, UnauthorizedException, UnsecuredDto, } from '~/common'; import { HandleIdLookup, ResourceLoader } from '~/core'; -import { Privileges, Role } from '../../authorization'; -import { User, UserService } from '../../user'; +import { Privileges } from '../../authorization'; +import { UserService } from '../../user'; +import { User } from '../../user/dto'; import { CreateProjectMember, ProjectMember, diff --git a/src/components/project/project.loader.ts b/src/components/project/project.loader.ts index 3eb1b4a54e..ef4fed9230 100644 --- a/src/components/project/project.loader.ts +++ b/src/components/project/project.loader.ts @@ -1,5 +1,5 @@ -import { ID, ObjectView } from '../../common'; -import { LoaderFactory, ObjectViewAwareLoader } from '../../core'; +import { ID, ObjectView } from '~/common'; +import { LoaderFactory, ObjectViewAwareLoader } from '~/core'; import { InternshipProject, IProject, diff --git a/src/components/project/project.module.ts b/src/components/project/project.module.ts index 1d23236768..9934fe4dc1 100644 --- a/src/components/project/project.module.ts +++ b/src/components/project/project.module.ts @@ -11,6 +11,7 @@ import { PartnershipModule } from '../partnership/partnership.module'; import { ProjectChangeRequestModule } from '../project-change-request/project-change-request.module'; import { UserModule } from '../user/user.module'; import { ProjectEngagementConnectionResolver } from './engagement-connection.resolver'; +import { FinancialApproverModule } from './financial-approver/financial-approver.module'; import * as handlers from './handlers'; import { InternshipProjectResolver } from './internship-project.resolver'; import { RenameTranslationToMomentumMigration } from './migrations/rename-translation-to-momentum.migration'; @@ -41,6 +42,7 @@ import { ProjectUserConnectionResolver } from './user-connection.resolver'; forwardRef(() => AuthorizationModule), PartnerModule, forwardRef(() => OrganizationModule), + FinancialApproverModule, ], providers: [ ProjectResolver, diff --git a/src/components/project/project.repository.ts b/src/components/project/project.repository.ts index da52524ff5..33e8ea10d0 100644 --- a/src/components/project/project.repository.ts +++ b/src/components/project/project.repository.ts @@ -9,7 +9,8 @@ import { Session, UnsecuredDto, } from '~/common'; -import { CommonRepository, ConfigService, OnIndex } from '~/core'; +import { ConfigService } from '~/core'; +import { CommonRepository, OnIndex } from '~/core/database'; import { ChangesOf, getChanges } from '~/core/database/changes'; import { ACTIVE, diff --git a/src/components/project/project.resolver.ts b/src/components/project/project.resolver.ts index 97eb0513fc..6b3d9d069e 100644 --- a/src/components/project/project.resolver.ts +++ b/src/components/project/project.resolver.ts @@ -22,29 +22,29 @@ import { NotFoundException, SecuredDateRange, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { SecuredBudget } from '../budget'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { SecuredBudget } from '../budget/dto'; import { IdsAndView, IdsAndViewArg } from '../changeset/dto'; -import { - EngagementListInput, - EngagementLoader, - SecuredEngagementList, -} from '../engagement'; -import { FieldRegionLoader, SecuredFieldRegion } from '../field-region'; -import { asDirectory, FileNodeLoader, SecuredDirectory } from '../file'; +import { EngagementLoader } from '../engagement'; +import { EngagementListInput, SecuredEngagementList } from '../engagement/dto'; +import { FieldRegionLoader } from '../field-region'; +import { SecuredFieldRegion } from '../field-region/dto'; +import { FileNodeLoader } from '../file'; +import { asDirectory, SecuredDirectory } from '../file/dto'; +import { LocationLoader } from '../location'; import { LocationListInput, - LocationLoader, SecuredLocation, SecuredLocationList, -} from '../location'; -import { OrganizationLoader, SecuredOrganization } from '../organization'; +} from '../location/dto'; +import { OrganizationLoader } from '../organization'; +import { SecuredOrganization } from '../organization/dto'; +import { PartnershipLoader } from '../partnership'; import { PartnershipListInput, - PartnershipLoader, SecuredPartnershipList, -} from '../partnership'; +} from '../partnership/dto'; import { ProjectChangeRequestLoader } from '../project-change-request'; import { ProjectChangeRequestListInput, @@ -64,11 +64,11 @@ import { UpdateProjectInput, UpdateProjectOutput, } from './dto'; +import { ProjectMemberLoader } from './project-member'; import { ProjectMemberListInput, - ProjectMemberLoader, SecuredProjectMemberList, -} from './project-member'; +} from './project-member/dto'; import { ProjectLoader } from './project.loader'; import { ProjectService } from './project.service'; diff --git a/src/components/project/project.rules.ts b/src/components/project/project.rules.ts index 560e9a39c7..d3fdba6979 100644 --- a/src/components/project/project.rules.ts +++ b/src/components/project/project.rules.ts @@ -8,24 +8,31 @@ import { Promisable } from 'type-fest'; import { ID, maybeMany, + Role, ServerException, Session, UnauthorizedException, UnsecuredDto, -} from '../../common'; -import { ConfigService, DatabaseService, ILogger, Logger } from '../../core'; -import { ACTIVE, INACTIVE } from '../../core/database/query'; +} from '~/common'; +import { ConfigService, ILogger, Logger } from '~/core'; +import { DatabaseService } from '~/core/database'; +import { ACTIVE, INACTIVE, merge } from '~/core/database/query'; import { AuthenticationService } from '../authentication'; -import { Role, withoutScope } from '../authorization'; -import { EngagementService, EngagementStatus } from '../engagement'; -import { ProjectType } from '../project'; -import { User, UserService } from '../user'; +import { withoutScope } from '../authorization/dto'; +import { EngagementService } from '../engagement'; +import { EngagementStatus } from '../engagement/dto'; +import { OrganizationService } from '../organization'; +import { Organization } from '../organization/dto'; +import { UserService } from '../user'; +import { User } from '../user/dto'; import { Project, ProjectStep, ProjectStepTransition, + ProjectType, TransitionType, } from './dto'; +import { FinancialApproverRepository } from './financial-approver'; import { ProjectService } from './project.service'; type EmailAddress = string; @@ -54,8 +61,9 @@ export interface EmailNotification { 'email' | 'displayFirstName' | 'displayLastName' | 'timezone' >; changedBy: Pick; - project: Pick; + project: Pick; previousStep?: ProjectStep; + primaryPartnerName?: string | undefined; } const rolesThatCanBypassWorkflow: Role[] = [Role.Administrator]; @@ -70,9 +78,11 @@ export class ProjectRules { private readonly projectService: ProjectService & {}, @Inject(forwardRef(() => EngagementService)) private readonly engagements: EngagementService & {}, + private readonly organizations: OrganizationService, @Inject(forwardRef(() => AuthenticationService)) private readonly auth: AuthenticationService & {}, private readonly configService: ConfigService, + private readonly financialApproverRepo: FinancialApproverRepository, // eslint-disable-next-line @seedcompany/no-unused-vars @Logger('project:rules') private readonly logger: ILogger, ) {} @@ -85,6 +95,10 @@ export class ProjectRules { ): Promise { const mostRecentPreviousStep = (steps: ProjectStep[]) => this.getMostRecentPreviousStep(id, steps, changeset); + const financialApprovers = async () => + (await this.financialApproverRepo.read(projectType)).map( + ({ user }) => user.id, + ); const isMultiplication = projectType === ProjectType.MultiplicationTranslation; @@ -405,7 +419,7 @@ export class ProjectRules { type: TransitionType.Approve, label: 'Confirm Project 🎉', notifiers: async () => [ - ...(await this.getRoleEmails(Role.Controller)), + ...(await financialApprovers()), 'project_approval@tsco.org', 'projects@tsco.org', ], @@ -413,7 +427,7 @@ export class ProjectRules { ], getNotifiers: async () => [ ...(await this.getProjectTeamUserIds(id)), - ...(await this.getRoleEmails(Role.Controller)), + ...(await financialApprovers()), ], }; case ProjectStep.OnHoldFinanceConfirmation: @@ -425,7 +439,7 @@ export class ProjectRules { type: TransitionType.Approve, label: 'Confirm Project 🎉', notifiers: async () => [ - ...(await this.getRoleEmails(Role.Controller)), + ...(await financialApprovers()), 'project_approval@tsco.org', 'projects@tsco.org', ], @@ -443,7 +457,7 @@ export class ProjectRules { ], getNotifiers: async () => [ ...(await this.getProjectTeamUserIds(id)), - ...(await this.getRoleEmails(Role.Controller)), + ...(await financialApprovers()), ], }; case ProjectStep.Active: @@ -500,7 +514,7 @@ export class ProjectRules { ], getNotifiers: async () => [ ...(await this.getProjectTeamUserIds(id)), - ...(await this.getRoleEmails(Role.Controller)), + ...(await financialApprovers()), 'project_extension@tsco.org', 'project_revision@tsco.org', ], @@ -598,7 +612,7 @@ export class ProjectRules { ], getNotifiers: async () => [ ...(await this.getProjectTeamUserIds(id)), - ...(await this.getRoleEmails(Role.Controller)), + ...(await financialApprovers()), 'project_extension@tsco.org', 'project_revision@tsco.org', ], @@ -1046,22 +1060,6 @@ export class ProjectRules { return users?.ids ?? []; } - private async getRoleEmails(role: Role): Promise { - const emails = await this.db - .query() - .match([ - node('email', 'EmailAddress'), - relation('in', '', 'email', ACTIVE), - node('user', 'User'), - relation('out', '', 'roles', ACTIVE), - node('role', 'Property', { value: role }), - ]) - .return<{ emails: string[] }>('collect(email.value) as emails') - .first(); - - return emails?.emails ?? []; - } - /** Of the given steps which one was the most recent previous step */ private async getMostRecentPreviousStep( id: ID, @@ -1105,6 +1103,35 @@ export class ProjectRules { return result.steps; } + async getPrimaryOrganizationByProjectId(id: ID) { + const result = await this.db + .query() + .match([ + node('project', 'Project', { id }), + relation('out', '', 'partnership', ACTIVE), + node('partnership', 'Partnership'), + relation('out', '', 'primary', ACTIVE), + node('primary', 'Property', { value: true }), + ]) + .with('partnership') + .match([ + node('partnership'), + relation('out', '', 'partner', ACTIVE), + node('', 'Partner'), + relation('out', '', 'organization', ACTIVE), + node('org', 'Organization'), + relation('out', '', 'name', ACTIVE), + node('name', 'Property'), + ]) + .return<{ dto: UnsecuredDto }>( + merge('org', { + name: 'name.value', + }).as('dto'), + ) + .first(); + return result?.dto ?? null; + } + private async getEmailNotificationObject( changedById: ID, projectId: ID, @@ -1141,11 +1168,24 @@ export class ProjectRules { recipientSession, ); + const organization = await this.getPrimaryOrganizationByProjectId( + projectId, + ); + let orgName; + if (organization) { + const org = await this.organizations.readOne( + organization.id, + recipientSession, + ); + orgName = org.name.value; + } + return { changedBy, project, recipient, previousStep, + primaryPartnerName: orgName, }; } } diff --git a/src/components/project/project.service.ts b/src/components/project/project.service.ts index 284067b31d..8a59455522 100644 --- a/src/components/project/project.service.ts +++ b/src/components/project/project.service.ts @@ -20,33 +20,28 @@ import { IEventBus, ILogger, Logger, - Transactional, - UniquenessError, } from '~/core'; -import { Privileges, withoutScope } from '../authorization'; -import { BudgetService, BudgetStatus, SecuredBudget } from '../budget'; -import { - EngagementListInput, - EngagementService, - SecuredEngagementList, -} from '../engagement'; -import { - LocationListInput, - LocationService, - SecuredLocationList, -} from '../location'; +import { Transactional, UniquenessError } from '~/core/database'; +import { Privileges } from '../authorization'; +import { withoutScope } from '../authorization/dto'; +import { BudgetService } from '../budget'; +import { BudgetStatus, SecuredBudget } from '../budget/dto'; +import { EngagementService } from '../engagement'; +import { EngagementListInput, SecuredEngagementList } from '../engagement/dto'; +import { LocationService } from '../location'; +import { LocationListInput, SecuredLocationList } from '../location/dto'; import { PartnerService } from '../partner'; +import { PartnershipService } from '../partnership'; import { PartnershipListInput, - PartnershipService, SecuredPartnershipList, -} from '../partnership'; +} from '../partnership/dto'; import { ProjectChangeRequestService } from '../project-change-request'; import { ProjectChangeRequestListInput, SecuredProjectChangeRequestList, } from '../project-change-request/dto'; -import { User } from '../user'; +import { User } from '../user/dto'; import { CreateProject, InternshipProject, @@ -67,11 +62,11 @@ import { ProjectDeletedEvent, ProjectUpdatedEvent, } from './events'; +import { ProjectMemberService } from './project-member'; import { ProjectMemberListInput, - ProjectMemberService, SecuredProjectMemberList, -} from './project-member'; +} from './project-member/dto'; import { ProjectRepository } from './project.repository'; import { ProjectRules } from './project.rules'; diff --git a/src/components/project/translation-project.resolver.ts b/src/components/project/translation-project.resolver.ts index dae4b3bf19..78d1eef6ec 100644 --- a/src/components/project/translation-project.resolver.ts +++ b/src/components/project/translation-project.resolver.ts @@ -1,14 +1,15 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { stripIndent } from 'common-tags'; -import { AnonSession, ListArg, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; +import { AnonSession, ListArg, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { EngagementLoader } from '../engagement'; import { EngagementListInput, SecuredEngagementList, SecuredLanguageEngagementList, } from '../engagement/dto'; -import { EngagementLoader } from '../engagement/engagement.loader'; -import { Project, ProjectService, TranslationProject } from './index'; +import { Project, TranslationProject } from './dto'; +import { ProjectService } from './project.service'; @Resolver(TranslationProject) export class TranslationProjectResolver { diff --git a/src/components/project/user-connection.resolver.ts b/src/components/project/user-connection.resolver.ts index 9fce40e120..fafa60c7c3 100644 --- a/src/components/project/user-connection.resolver.ts +++ b/src/components/project/user-connection.resolver.ts @@ -1,9 +1,10 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { AnonSession, ListArg, Session } from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { User } from '../user'; +import { AnonSession, ListArg, Session } from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { User } from '../user/dto'; import { ProjectListInput, SecuredProjectList } from './dto'; -import { ProjectLoader, ProjectService } from './index'; +import { ProjectLoader } from './project.loader'; +import { ProjectService } from './project.service'; @Resolver(User) export class ProjectUserConnectionResolver { diff --git a/src/components/prompts/prompt-variant-response.repository.ts b/src/components/prompts/prompt-variant-response.repository.ts index 5fcbbea17d..9b274a0bad 100644 --- a/src/components/prompts/prompt-variant-response.repository.ts +++ b/src/components/prompts/prompt-variant-response.repository.ts @@ -13,7 +13,7 @@ import { VariantList, VariantOf, } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { DbTypeOf } from '~/core/database/db-type'; import { privileges } from '~/core/database/dto.repository'; import { diff --git a/src/components/prompts/prompt-variant-response.resolver.ts b/src/components/prompts/prompt-variant-response.resolver.ts index 034d446951..592a1b1574 100644 --- a/src/components/prompts/prompt-variant-response.resolver.ts +++ b/src/components/prompts/prompt-variant-response.resolver.ts @@ -1,7 +1,8 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { mapSecuredValue, Resource } from '~/common'; import { Loader, LoaderOf, ResourceLoader } from '~/core'; -import { SecuredUser, UserLoader } from '../user'; +import { UserLoader } from '../user'; +import { SecuredUser } from '../user/dto'; import { PromptResponse, PromptVariantResponse, VariantResponse } from './dto'; @Resolver(() => PromptResponse) diff --git a/src/components/prompts/prompt-variant-response.service.ts b/src/components/prompts/prompt-variant-response.service.ts index cd57002143..a93eba3046 100644 --- a/src/components/prompts/prompt-variant-response.service.ts +++ b/src/components/prompts/prompt-variant-response.service.ts @@ -18,8 +18,11 @@ import { } from '~/common'; import { ResourceLoader } from '~/core'; import { mapListResults } from '~/core/database/results'; -import { Privileges, UserResourcePrivileges } from '../authorization'; -import { withVariant } from '../authorization/policies/conditions'; +import { + Privileges, + UserResourcePrivileges, + withVariant, +} from '../authorization'; import { ChangePrompt, ChoosePrompt, diff --git a/src/components/scripture/dto/scripture-range.validator.ts b/src/components/scripture/dto/scripture-range.validator.ts index 7a1e66c1f0..37a75a72ae 100644 --- a/src/components/scripture/dto/scripture-range.validator.ts +++ b/src/components/scripture/dto/scripture-range.validator.ts @@ -1,6 +1,6 @@ import { ValidationArguments } from 'class-validator'; import { Merge } from 'type-fest'; -import { createValidationDecorator } from '../../../common/validators/validateBy'; +import { createValidationDecorator } from '~/common/validators/validateBy'; import { ScriptureRange } from './scripture-range.dto'; // We assume this is only used on the ScriptureRange object diff --git a/src/components/scripture/dto/scripture-reference.validator.ts b/src/components/scripture/dto/scripture-reference.validator.ts index b18803c098..a09188be0b 100644 --- a/src/components/scripture/dto/scripture-reference.validator.ts +++ b/src/components/scripture/dto/scripture-reference.validator.ts @@ -2,7 +2,7 @@ import { applyDecorators } from '@nestjs/common'; import { Book, Chapter } from '@seedcompany/scripture'; import { ValidationArguments } from 'class-validator'; import { Merge } from 'type-fest'; -import { createValidationDecorator } from '../../../common/validators/validateBy'; +import { createValidationDecorator } from '~/common/validators/validateBy'; import { NormalizeBook } from './book.transformer'; import { ScriptureReference } from './scripture-reference.dto'; import { UnspecifiedScripturePortionInput } from './unspecified-scripture-portion.dto'; diff --git a/src/components/scripture/dto/unspecified-scripture-portion.dto.ts b/src/components/scripture/dto/unspecified-scripture-portion.dto.ts index cc5a95f8bd..dfb9049f3e 100644 --- a/src/components/scripture/dto/unspecified-scripture-portion.dto.ts +++ b/src/components/scripture/dto/unspecified-scripture-portion.dto.ts @@ -1,6 +1,6 @@ import { Field, InputType, Int, ObjectType } from '@nestjs/graphql'; import { IsPositive } from 'class-validator'; -import { SecuredProperty } from '../../../common'; +import { SecuredProperty } from '~/common'; import { IsValidBook, IsValidVerseTotal, diff --git a/src/components/scripture/edgedb.utils.ts b/src/components/scripture/edgedb.utils.ts index 19cd5f1d97..2418e75199 100644 --- a/src/components/scripture/edgedb.utils.ts +++ b/src/components/scripture/edgedb.utils.ts @@ -13,7 +13,7 @@ const verse = e.tuple({ book: e.str, chapter: e.int16, verse: e.int16, - verseId: e.int32, + verseId: e.int16, }); const verseRangeType = e.tuple({ @@ -66,13 +66,13 @@ export const insert = (param: $expr_Param) => { book: e.cast(e.str, start.book), chapter: e.cast(e.int16, start.chapter), verse: e.cast(e.int16, start.verse), - verseId: e.cast(e.int32, start.verseId), + verseId: e.cast(e.int16, start.verseId), }), end: e.insert(e.Scripture.Verse, { book: e.cast(e.str, end.book), chapter: e.cast(e.int16, end.chapter), verse: e.cast(e.int16, end.verse), - verseId: e.cast(e.int32, end.verseId), + verseId: e.cast(e.int16, end.verseId), }), }); }), diff --git a/src/components/scripture/index.ts b/src/components/scripture/index.ts index 97bb065473..6a8e183ebd 100644 --- a/src/components/scripture/index.ts +++ b/src/components/scripture/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './is-equal'; export * from './verse-equivalents'; export * from './scripture-reference.repository'; diff --git a/src/components/scripture/scripture-reference.service.ts b/src/components/scripture/scripture-reference.service.ts index f88e7203c0..f8b4298672 100644 --- a/src/components/scripture/scripture-reference.service.ts +++ b/src/components/scripture/scripture-reference.service.ts @@ -1,6 +1,6 @@ import { sortBy } from '@seedcompany/common'; -import { ID, Session } from '../../common'; -import { ILogger, Logger } from '../../core'; +import { ID, Session } from '~/common'; +import { ILogger, Logger } from '~/core'; import { ScriptureRange, ScriptureRangeInput } from './dto'; import { DbScriptureReferences, diff --git a/src/components/search/dto/search.dto.ts b/src/components/search/dto/search.dto.ts index 2ad7860f92..e43dd462cf 100644 --- a/src/components/search/dto/search.dto.ts +++ b/src/components/search/dto/search.dto.ts @@ -1,5 +1,5 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; -import { PaginationInput } from '../../../common'; +import { PaginationInput } from '~/common'; import { GqlSearchType, SearchResult, SearchType } from './search-results.dto'; @InputType() diff --git a/src/components/search/index.ts b/src/components/search/index.ts index ecf0fc20a9..51370b569d 100644 --- a/src/components/search/index.ts +++ b/src/components/search/index.ts @@ -1,2 +1 @@ -export * from './dto'; export * from './search.service'; diff --git a/src/components/search/search.repository.ts b/src/components/search/search.repository.ts index b96c70a831..420f3f000f 100644 --- a/src/components/search/search.repository.ts +++ b/src/components/search/search.repository.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { node, relation } from 'cypher-query-builder'; -import { CommonRepository, OnIndex, OnIndexParams } from '../../core'; +import { CommonRepository, OnIndex, OnIndexParams } from '~/core/database'; import { ACTIVE, escapeLuceneSyntax, fullTextQuery, -} from '../../core/database/query'; -import { BaseNode } from '../../core/database/results'; +} from '~/core/database/query'; +import { BaseNode } from '~/core/database/results'; import { SearchInput } from './dto'; @Injectable() diff --git a/src/components/story/dto/create-story.dto.ts b/src/components/story/dto/create-story.dto.ts index 53de647c7e..4e6526cc1c 100644 --- a/src/components/story/dto/create-story.dto.ts +++ b/src/components/story/dto/create-story.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { NameField } from '../../../common'; -import { ScriptureField, ScriptureRangeInput } from '../../scripture'; +import { NameField } from '~/common'; +import { ScriptureField, ScriptureRangeInput } from '../../scripture/dto'; import { Story } from './story.dto'; @InputType() diff --git a/src/components/story/dto/delete-story.dto.ts b/src/components/story/dto/delete-story.dto.ts index e428802b45..5bb0b19ea3 100644 --- a/src/components/story/dto/delete-story.dto.ts +++ b/src/components/story/dto/delete-story.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteStoryOutput extends MutationPlaceholderOutput {} diff --git a/src/components/story/dto/story.dto.ts b/src/components/story/dto/story.dto.ts index cd56f59190..fa81fa2b7b 100644 --- a/src/components/story/dto/story.dto.ts +++ b/src/components/story/dto/story.dto.ts @@ -1,15 +1,15 @@ import { ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DbUnique, NameField, Resource, SecuredProps, SecuredString, -} from '../../../common'; -import { Producible } from '../../product/dto/producible.dto'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; +import { Producible } from '../../product/dto'; declare module '../../product/dto/producible.dto' { interface ProducibleTypeEntries { diff --git a/src/components/story/dto/update-story.dto.ts b/src/components/story/dto/update-story.dto.ts index 9bec0bd77f..ff3c6a00c3 100644 --- a/src/components/story/dto/update-story.dto.ts +++ b/src/components/story/dto/update-story.dto.ts @@ -1,8 +1,8 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, NameField } from '../../../common'; -import { ScriptureField, ScriptureRangeInput } from '../../scripture'; +import { ID, IdField, NameField } from '~/common'; +import { ScriptureField, ScriptureRangeInput } from '../../scripture/dto'; import { Story } from './story.dto'; @InputType() diff --git a/src/components/story/index.ts b/src/components/story/index.ts index fe0856d264..2be2ca86e3 100644 --- a/src/components/story/index.ts +++ b/src/components/story/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './story.resolver'; export * from './story.service'; export * from './story.loader'; diff --git a/src/components/story/story.loader.ts b/src/components/story/story.loader.ts index 94201afe05..525ec62401 100644 --- a/src/components/story/story.loader.ts +++ b/src/components/story/story.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Story } from './dto'; import { StoryService } from './story.service'; diff --git a/src/components/story/story.module.ts b/src/components/story/story.module.ts index 0fcf16076d..980fd1becf 100644 --- a/src/components/story/story.module.ts +++ b/src/components/story/story.module.ts @@ -1,6 +1,8 @@ import { forwardRef, Module } from '@nestjs/common'; +import { splitDb } from '~/core'; import { AuthorizationModule } from '../authorization/authorization.module'; import { ScriptureModule } from '../scripture'; +import { StoryEdgeDBRepository } from './story.edgedb.repository'; import { StoryLoader } from './story.loader'; import { StoryRepository } from './story.repository'; import { StoryResolver } from './story.resolver'; @@ -8,7 +10,12 @@ import { StoryService } from './story.service'; @Module({ imports: [forwardRef(() => AuthorizationModule), ScriptureModule], - providers: [StoryResolver, StoryService, StoryRepository, StoryLoader], + providers: [ + StoryResolver, + StoryService, + splitDb(StoryRepository, StoryEdgeDBRepository), + StoryLoader, + ], exports: [StoryService], }) export class StoryModule {} diff --git a/src/components/story/story.resolver.ts b/src/components/story/story.resolver.ts index a6131f9316..ab8395d608 100644 --- a/src/components/story/story.resolver.ts +++ b/src/components/story/story.resolver.ts @@ -6,8 +6,8 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { CreateStoryInput, CreateStoryOutput, diff --git a/src/components/story/story.service.ts b/src/components/story/story.service.ts index aa779aab87..1215a1ca3d 100644 --- a/src/components/story/story.service.ts +++ b/src/components/story/story.service.ts @@ -63,7 +63,7 @@ export class StoryService { } async delete(id: ID, session: Session): Promise { - const story = await this.readOne(id, session); + const story = await this.repo.readOne(id); this.privileges.for(session, Story, story).verifyCan('delete'); diff --git a/src/components/timezone/index.ts b/src/components/timezone/index.ts index 25f2504ead..6e3d47950c 100644 --- a/src/components/timezone/index.ts +++ b/src/components/timezone/index.ts @@ -1,3 +1,2 @@ -export * from './timezone.dto'; export * from './timezone.service'; export * from './timezone.module'; diff --git a/src/components/timezone/timezone.dto.ts b/src/components/timezone/timezone.dto.ts index 96004a837c..bf35af6a99 100644 --- a/src/components/timezone/timezone.dto.ts +++ b/src/components/timezone/timezone.dto.ts @@ -1,5 +1,5 @@ import { Field, Float, ObjectType } from '@nestjs/graphql'; -import { SecuredProperty } from '../../common'; +import { SecuredProperty } from '~/common'; @ObjectType({ description: 'An IANA Time Zone', diff --git a/src/components/user/actor.neo4j.repository.ts b/src/components/user/actor.neo4j.repository.ts index b8c1ef089c..e5e4b77375 100644 --- a/src/components/user/actor.neo4j.repository.ts +++ b/src/components/user/actor.neo4j.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { node } from 'cypher-query-builder'; import { ID, Role } from '~/common'; -import { DatabaseService } from '~/core'; +import { DatabaseService } from '~/core/database'; import { ActorRepository } from './actor.repository'; @Injectable() diff --git a/src/components/user/assignable-roles.resolver.ts b/src/components/user/assignable-roles.resolver.ts index bf8a47eb81..85d57ea27b 100644 --- a/src/components/user/assignable-roles.resolver.ts +++ b/src/components/user/assignable-roles.resolver.ts @@ -1,6 +1,5 @@ import { ResolveField, Resolver } from '@nestjs/graphql'; -import { AnonSession, Session } from '~/common'; -import { Role, SecuredRoles } from '../authorization'; +import { AnonSession, Role, SecuredRoles, Session } from '~/common'; import { UserService } from './user.service'; @Resolver(SecuredRoles) diff --git a/src/components/user/dto/assign-organization-to-user.dto.ts b/src/components/user/dto/assign-organization-to-user.dto.ts index d5433cc1d8..a55d7ef1b3 100644 --- a/src/components/user/dto/assign-organization-to-user.dto.ts +++ b/src/components/user/dto/assign-organization-to-user.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, MutationPlaceholderOutput } from '../../../common'; +import { ID, IdField, MutationPlaceholderOutput } from '~/common'; @InputType() export class AssignOrganizationToUser { diff --git a/src/components/user/dto/create-person.dto.ts b/src/components/user/dto/create-person.dto.ts index 11c6f180e8..a5b025ee51 100644 --- a/src/components/user/dto/create-person.dto.ts +++ b/src/components/user/dto/create-person.dto.ts @@ -2,8 +2,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Transform, Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; import { uniq } from 'lodash'; -import { EmailField, IsIanaTimezone, NameField } from '~/common'; -import { Role } from '../../authorization'; +import { EmailField, IsIanaTimezone, NameField, Role } from '~/common'; import { UserStatus } from './user-status.enum'; import { User } from './user.dto'; diff --git a/src/components/user/dto/delete-user.dto.ts b/src/components/user/dto/delete-user.dto.ts index 079d6663e3..7e0c03260f 100644 --- a/src/components/user/dto/delete-user.dto.ts +++ b/src/components/user/dto/delete-user.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteUserOutput extends MutationPlaceholderOutput {} diff --git a/src/components/user/dto/remove-organization-from-user.dto.ts b/src/components/user/dto/remove-organization-from-user.dto.ts index 5b221f494e..f84e78eb4d 100644 --- a/src/components/user/dto/remove-organization-from-user.dto.ts +++ b/src/components/user/dto/remove-organization-from-user.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField, MutationPlaceholderOutput } from '../../../common'; +import { ID, IdField, MutationPlaceholderOutput } from '~/common'; @InputType() export class RemoveOrganizationFromUser { diff --git a/src/components/user/dto/update-user.dto.ts b/src/components/user/dto/update-user.dto.ts index 74b6cfb627..081638931e 100644 --- a/src/components/user/dto/update-user.dto.ts +++ b/src/components/user/dto/update-user.dto.ts @@ -2,8 +2,14 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Transform, Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; import { uniq } from 'lodash'; -import { EmailField, ID, IdField, IsIanaTimezone, NameField } from '~/common'; -import { Role } from '../../authorization'; +import { + EmailField, + ID, + IdField, + IsIanaTimezone, + NameField, + Role, +} from '~/common'; import { UserStatus } from './user-status.enum'; import { User } from './user.dto'; diff --git a/src/components/user/dto/user.dto.ts b/src/components/user/dto/user.dto.ts index d37bbdc254..ce2bbe6ff0 100644 --- a/src/components/user/dto/user.dto.ts +++ b/src/components/user/dto/user.dto.ts @@ -1,8 +1,6 @@ import { Type } from '@nestjs/common'; import { Field, ObjectType } from '@nestjs/graphql'; import { keys as keysOf } from 'ts-transformer-keys'; -import { e } from '~/core/edgedb'; -import { RegisterResource } from '~/core/resources'; import { DbUnique, IntersectionType, @@ -12,10 +10,12 @@ import { SecuredEnum, SecuredProperty, SecuredProps, + SecuredRoles, SecuredString, SecuredStringNullable, -} from '../../../common'; -import { SecuredRoles } from '../../authorization'; +} from '~/common'; +import { e } from '~/core/edgedb'; +import { RegisterResource } from '~/core/resources'; import { Location } from '../../location/dto'; import { Organization } from '../../organization/dto'; import { Partner } from '../../partner/dto'; diff --git a/src/components/user/education/dto/create-education.dto.ts b/src/components/user/education/dto/create-education.dto.ts index 98ae81e9f4..b1153a2baa 100644 --- a/src/components/user/education/dto/create-education.dto.ts +++ b/src/components/user/education/dto/create-education.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField } from '../../../../common'; +import { ID, IdField } from '~/common'; import { Degree, Education } from './education.dto'; @InputType() diff --git a/src/components/user/education/dto/delete-education.dto.ts b/src/components/user/education/dto/delete-education.dto.ts index 0dfd1edb9a..c198717e5d 100644 --- a/src/components/user/education/dto/delete-education.dto.ts +++ b/src/components/user/education/dto/delete-education.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteEducationOutput extends MutationPlaceholderOutput {} diff --git a/src/components/user/education/dto/update-education.dto.ts b/src/components/user/education/dto/update-education.dto.ts index 47e9557b88..4a008adadc 100644 --- a/src/components/user/education/dto/update-education.dto.ts +++ b/src/components/user/education/dto/update-education.dto.ts @@ -1,7 +1,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; -import { ID, IdField } from '../../../../common'; +import { ID, IdField } from '~/common'; import { Degree, Education } from './education.dto'; @InputType() diff --git a/src/components/user/education/education.loader.ts b/src/components/user/education/education.loader.ts index 079c3790a2..4b3827aa4b 100644 --- a/src/components/user/education/education.loader.ts +++ b/src/components/user/education/education.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Education } from './dto'; import { EducationService } from './education.service'; diff --git a/src/components/user/education/education.resolver.ts b/src/components/user/education/education.resolver.ts index 9d7409c59f..621288b85e 100644 --- a/src/components/user/education/education.resolver.ts +++ b/src/components/user/education/education.resolver.ts @@ -7,8 +7,8 @@ import { ListArg, LoggedInSession, Session, -} from '../../../common'; -import { Loader, LoaderOf } from '../../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { EducationLoader, EducationService } from '../education'; import { CreateEducationInput, diff --git a/src/components/user/education/index.ts b/src/components/user/education/index.ts index 3f0819b94c..59670e3425 100644 --- a/src/components/user/education/index.ts +++ b/src/components/user/education/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './education.service'; export * from './education.loader'; diff --git a/src/components/user/index.ts b/src/components/user/index.ts index 15a38c16f0..ddc5c51ee9 100644 --- a/src/components/user/index.ts +++ b/src/components/user/index.ts @@ -1,4 +1,3 @@ -export * from './dto'; export * from './user.service'; export * from './unavailability'; export * from './education'; diff --git a/src/components/user/known-language.repository.ts b/src/components/user/known-language.repository.ts index 35e5a34efa..e910c7219e 100644 --- a/src/components/user/known-language.repository.ts +++ b/src/components/user/known-language.repository.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { node, relation } from 'cypher-query-builder'; import { DateTime } from 'luxon'; import { ID } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ACTIVE } from '~/core/database/query'; import { KnownLanguage, ModifyKnownLanguageArgs } from './dto'; diff --git a/src/components/user/known-language.resolver.ts b/src/components/user/known-language.resolver.ts index 41842d8b17..6a84fa3d42 100644 --- a/src/components/user/known-language.resolver.ts +++ b/src/components/user/known-language.resolver.ts @@ -1,7 +1,8 @@ import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; -import { Loader, LoaderOf } from '../../core'; -import { Language, LanguageLoader } from '../language'; -import { KnownLanguage } from './dto/known-language.dto'; +import { Loader, LoaderOf } from '~/core'; +import { LanguageLoader } from '../language'; +import { Language } from '../language/dto'; +import { KnownLanguage } from './dto'; @Resolver(KnownLanguage) export class KnownLanguageResolver { diff --git a/src/components/user/unavailability/dto/create-unavailability.dto.ts b/src/components/user/unavailability/dto/create-unavailability.dto.ts index d1a5f1c5ee..e4b7d9b535 100644 --- a/src/components/user/unavailability/dto/create-unavailability.dto.ts +++ b/src/components/user/unavailability/dto/create-unavailability.dto.ts @@ -2,7 +2,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; import { DateTime } from 'luxon'; -import { DateTimeField, ID, IdField } from '../../../../common'; +import { DateTimeField, ID, IdField } from '~/common'; import { Unavailability } from './unavailability.dto'; @InputType() diff --git a/src/components/user/unavailability/dto/delete-unavailability.dto.ts b/src/components/user/unavailability/dto/delete-unavailability.dto.ts index 4e25335b8f..f7f4839fdc 100644 --- a/src/components/user/unavailability/dto/delete-unavailability.dto.ts +++ b/src/components/user/unavailability/dto/delete-unavailability.dto.ts @@ -1,5 +1,5 @@ import { ObjectType } from '@nestjs/graphql'; -import { MutationPlaceholderOutput } from '../../../../common'; +import { MutationPlaceholderOutput } from '~/common'; @ObjectType() export abstract class DeleteUnavailabilityOutput extends MutationPlaceholderOutput {} diff --git a/src/components/user/unavailability/dto/update-unavailability.dto.ts b/src/components/user/unavailability/dto/update-unavailability.dto.ts index ce4e72b946..e66d172610 100644 --- a/src/components/user/unavailability/dto/update-unavailability.dto.ts +++ b/src/components/user/unavailability/dto/update-unavailability.dto.ts @@ -2,7 +2,7 @@ import { Field, InputType, ObjectType } from '@nestjs/graphql'; import { Type } from 'class-transformer'; import { ValidateNested } from 'class-validator'; import { DateTime } from 'luxon'; -import { DateTimeField, ID, IdField } from '../../../../common'; +import { DateTimeField, ID, IdField } from '~/common'; import { Unavailability } from './unavailability.dto'; @InputType() diff --git a/src/components/user/unavailability/index.ts b/src/components/user/unavailability/index.ts index 9966bbe4c1..c8d99f9649 100644 --- a/src/components/user/unavailability/index.ts +++ b/src/components/user/unavailability/index.ts @@ -1,3 +1,2 @@ -export * from './dto'; export * from './unavailability.service'; export * from './unavailability.loader'; diff --git a/src/components/user/unavailability/unavailability.loader.ts b/src/components/user/unavailability/unavailability.loader.ts index 5cbb7dca0d..35b2584fe4 100644 --- a/src/components/user/unavailability/unavailability.loader.ts +++ b/src/components/user/unavailability/unavailability.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { Unavailability } from './dto'; import { UnavailabilityService } from './unavailability.service'; diff --git a/src/components/user/unavailability/unavailability.repository.ts b/src/components/user/unavailability/unavailability.repository.ts index 8c5845028c..4434dcbc8a 100644 --- a/src/components/user/unavailability/unavailability.repository.ts +++ b/src/components/user/unavailability/unavailability.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { node, relation } from 'cypher-query-builder'; import { ID, NotFoundException, ServerException } from '~/common'; -import { DtoRepository } from '~/core'; +import { DtoRepository } from '~/core/database'; import { ACTIVE, createNode, diff --git a/src/components/user/unavailability/unavailability.resolver.ts b/src/components/user/unavailability/unavailability.resolver.ts index 144e0bf80d..4132f857c6 100644 --- a/src/components/user/unavailability/unavailability.resolver.ts +++ b/src/components/user/unavailability/unavailability.resolver.ts @@ -6,8 +6,8 @@ import { ListArg, LoggedInSession, Session, -} from '../../../common'; -import { Loader, LoaderOf } from '../../../core'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; import { UnavailabilityLoader, UnavailabilityService } from '../unavailability'; import { CreateUnavailabilityInput, diff --git a/src/components/user/user.loader.ts b/src/components/user/user.loader.ts index dd18fc910f..ba510948db 100644 --- a/src/components/user/user.loader.ts +++ b/src/components/user/user.loader.ts @@ -1,5 +1,5 @@ -import { ID } from '../../common'; -import { LoaderFactory, OrderedNestDataLoader } from '../../core'; +import { ID } from '~/common'; +import { LoaderFactory, OrderedNestDataLoader } from '~/core'; import { User } from './dto'; import { UserService } from './user.service'; diff --git a/src/components/user/user.repository.ts b/src/components/user/user.repository.ts index 660d98b221..f87dc58009 100644 --- a/src/components/user/user.repository.ts +++ b/src/components/user/user.repository.ts @@ -5,11 +5,12 @@ import { DateTime } from 'luxon'; import { DuplicateException, ID, + Role, ServerException, Session, UnsecuredDto, -} from '../../common'; -import { DtoRepository, UniquenessError } from '../../core'; +} from '~/common'; +import { DtoRepository, UniquenessError } from '~/core/database'; import { ACTIVE, createNode, @@ -22,8 +23,7 @@ import { property, requestingUser, sorting, -} from '../../core/database/query'; -import { Role } from '../authorization'; +} from '~/core/database/query'; import { AssignOrganizationToUser, CreatePerson, diff --git a/src/components/user/user.resolver.ts b/src/components/user/user.resolver.ts index 555b49e812..3b755cb360 100644 --- a/src/components/user/user.resolver.ts +++ b/src/components/user/user.resolver.ts @@ -16,24 +16,19 @@ import { ListArg, LoggedInSession, Session, -} from '../../common'; -import { Loader, LoaderOf } from '../../core'; -import { - LocationListInput, - LocationLoader, - SecuredLocationList, -} from '../location'; +} from '~/common'; +import { Loader, LoaderOf } from '~/core'; +import { LocationLoader } from '../location'; +import { LocationListInput, SecuredLocationList } from '../location/dto'; +import { OrganizationLoader } from '../organization'; import { OrganizationListInput, - OrganizationLoader, SecuredOrganizationList, -} from '../organization'; -import { - PartnerListInput, - PartnerLoader, - SecuredPartnerList, -} from '../partner'; -import { SecuredTimeZone, TimeZoneService } from '../timezone'; +} from '../organization/dto'; +import { PartnerLoader } from '../partner'; +import { PartnerListInput, SecuredPartnerList } from '../partner/dto'; +import { TimeZoneService } from '../timezone'; +import { SecuredTimeZone } from '../timezone/timezone.dto'; import { AssignOrganizationToUserInput, AssignOrganizationToUserOutput, @@ -41,6 +36,8 @@ import { CreatePersonInput, CreatePersonOutput, DeleteUserOutput, + KnownLanguage, + ModifyKnownLanguageArgs, RemoveOrganizationFromUserInput, RemoveOrganizationFromUserOutput, UpdateUserInput, @@ -49,21 +46,14 @@ import { UserListInput, UserListOutput, } from './dto'; -import { - KnownLanguage, - ModifyKnownLanguageArgs, -} from './dto/known-language.dto'; -import { - EducationListInput, - EducationLoader, - SecuredEducationList, -} from './education'; +import { EducationLoader } from './education'; +import { EducationListInput, SecuredEducationList } from './education/dto'; import { fullName } from './fullName'; +import { UnavailabilityLoader } from './unavailability'; import { SecuredUnavailabilityList, UnavailabilityListInput, - UnavailabilityLoader, -} from './unavailability'; +} from './unavailability/dto'; import { UserLoader } from './user.loader'; import { UserService } from './user.service'; diff --git a/src/components/user/user.service.ts b/src/components/user/user.service.ts index 7066b92f58..c13d717ac5 100644 --- a/src/components/user/user.service.ts +++ b/src/components/user/user.service.ts @@ -3,31 +3,27 @@ import { CachedByArg } from '@seedcompany/common'; import { ID, ObjectView, + Role, SecuredList, ServerException, Session, UnauthorizedException, UnsecuredDto, -} from '../../common'; -import { HandleIdLookup, ILogger, Logger, Transactional } from '../../core'; -import { property } from '../../core/database/query'; -import { Privileges, Role } from '../authorization'; +} from '~/common'; +import { HandleIdLookup, ILogger, Logger } from '~/core'; +import { Transactional } from '~/core/database'; +import { property } from '~/core/database/query'; +import { Privileges } from '../authorization'; import { AssignableRoles } from '../authorization/dto/assignable-roles'; -import { - LocationListInput, - LocationService, - SecuredLocationList, -} from '../location'; +import { LocationService } from '../location'; +import { LocationListInput, SecuredLocationList } from '../location/dto'; +import { OrganizationService } from '../organization'; import { OrganizationListInput, - OrganizationService, SecuredOrganizationList, -} from '../organization'; -import { - PartnerListInput, - PartnerService, - SecuredPartnerList, -} from '../partner'; +} from '../organization/dto'; +import { PartnerService } from '../partner'; +import { PartnerListInput, SecuredPartnerList } from '../partner/dto'; import { AssignOrganizationToUser, CreatePerson, @@ -38,17 +34,14 @@ import { UserListInput, UserListOutput, } from './dto'; -import { - EducationListInput, - EducationService, - SecuredEducationList, -} from './education'; +import { EducationService } from './education'; +import { EducationListInput, SecuredEducationList } from './education/dto'; import { KnownLanguageRepository } from './known-language.repository'; +import { UnavailabilityService } from './unavailability'; import { SecuredUnavailabilityList, UnavailabilityListInput, - UnavailabilityService, -} from './unavailability'; +} from './unavailability/dto'; import { UserRepository } from './user.repository'; @Injectable() diff --git a/src/core/config/config.service.ts b/src/core/config/config.service.ts index 7303f661ea..a93541f492 100644 --- a/src/core/config/config.service.ts +++ b/src/core/config/config.service.ts @@ -10,6 +10,7 @@ import LRUCache from 'lru-cache'; import { Duration, DurationLike } from 'luxon'; import { nanoid } from 'nanoid'; import { Config as Neo4JDriverConfig } from 'neo4j-driver'; +import { BehaviorSubject } from 'rxjs'; import { keys as keysOf } from 'ts-transformer-keys'; import { Class, Merge, ReadonlyDeep } from 'type-fest'; import { ID } from '~/common'; @@ -35,9 +36,9 @@ export const makeConfig = (env: EnvironmentService) => port = env.number('port').optional(3000); // The port where the app is being hosted. i.e. a docker bound port publicPort = env.number('public_port').optional(this.port); - hostUrl = env - .url('host_url') - .optional(`http://localhost:${this.publicPort}`); + hostUrl$ = new BehaviorSubject( + env.url('host_url').optional(`http://localhost:${this.publicPort}`), + ); graphQL = { persistedQueries: { diff --git a/src/core/database/changes.ts b/src/core/database/changes.ts index 41112fc0a5..bd887ea26a 100644 --- a/src/core/database/changes.ts +++ b/src/core/database/changes.ts @@ -2,7 +2,6 @@ import { entries } from '@seedcompany/common'; import { difference, omit, pickBy } from 'lodash'; import { DateTime } from 'luxon'; import { ConditionalKeys, IsAny } from 'type-fest'; -import { LinkTo } from '~/core'; import { EnhancedResource, ID, @@ -12,8 +11,9 @@ import { ResourceShape, unwrapSecured, UnwrapSecured, -} from '../../common'; -import { CreateDefinedFileVersionInput } from '../../components/file'; +} from '~/common'; +import { LinkTo } from '~/core'; +import { CreateDefinedFileVersionInput } from '../../components/file/dto'; import { Variable } from './query'; import { NativeDbValue } from './results'; diff --git a/src/core/database/database.service.ts b/src/core/database/database.service.ts index 342482ade2..15e983cc06 100644 --- a/src/core/database/database.service.ts +++ b/src/core/database/database.service.ts @@ -11,8 +11,8 @@ import { ResourceShape, ServerException, UnwrapSecured, -} from '../../common'; -import { AbortError, retry, RetryOptions } from '../../common/retry'; +} from '~/common'; +import { AbortError, retry, RetryOptions } from '~/common/retry'; import { ConfigService } from '../config/config.service'; import { ILogger, Logger } from '../logger'; import { DbChanges } from './changes'; diff --git a/src/core/database/dto.repository.ts b/src/core/database/dto.repository.ts index cc13809697..5ca1d1fe8b 100644 --- a/src/core/database/dto.repository.ts +++ b/src/core/database/dto.repository.ts @@ -10,7 +10,7 @@ import { ResourceShape, ServerException, UnsecuredDto, -} from '../../common'; +} from '~/common'; import { Privileges } from '../../components/authorization'; import { DbChanges, getChanges } from './changes'; import { CommonRepository } from './common.repository'; diff --git a/src/core/database/parameter-transformer.service.ts b/src/core/database/parameter-transformer.service.ts index 5694b94d54..ac8db6a74f 100644 --- a/src/core/database/parameter-transformer.service.ts +++ b/src/core/database/parameter-transformer.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { mapValues } from '@seedcompany/common'; import { DateTime, Duration } from 'luxon'; import * as Neo from 'neo4j-driver'; -import { CalendarDate, RichTextDocument } from '../../common'; +import { CalendarDate, RichTextDocument } from '~/common'; import { isNeoDate, isNeoDateTime, isNeoDuration } from './transformer'; /** diff --git a/src/core/database/query-augmentation/interpolate.ts b/src/core/database/query-augmentation/interpolate.ts index 53b2c24776..6fe0ea7b78 100644 --- a/src/core/database/query-augmentation/interpolate.ts +++ b/src/core/database/query-augmentation/interpolate.ts @@ -3,7 +3,7 @@ import { stripIndent } from 'common-tags'; import { Clause } from 'cypher-query-builder'; import { DateTime, Duration } from 'luxon'; import { Integer, types as neo } from 'neo4j-driver'; -import { CalendarDate } from '../../../common'; +import { CalendarDate } from '~/common'; /** * Overridden to correctly interpolate null, undefined, and temporal values. diff --git a/src/core/database/query/create-node.ts b/src/core/database/query/create-node.ts index 4b07bb46ce..50fb9896c3 100644 --- a/src/core/database/query/create-node.ts +++ b/src/core/database/query/create-node.ts @@ -10,7 +10,7 @@ import { UnsecuredDto, } from '~/common'; import { LinkTo } from '~/core'; -import { FileId } from '../../../components/file'; +import { FileId } from '../../../components/file/dto'; import { Variable } from '../query-augmentation/condition-variables'; export interface CreateNodeOptions> { diff --git a/src/core/database/query/cypher-expression.ts b/src/core/database/query/cypher-expression.ts index 5dd5d50549..bbc376cfac 100644 --- a/src/core/database/query/cypher-expression.ts +++ b/src/core/database/query/cypher-expression.ts @@ -1,6 +1,6 @@ import { Merge } from 'cypher-query-builder'; import { PatternCollection } from 'cypher-query-builder/dist/typings/clauses/pattern-clause'; -import { Many, ServerException } from '../../../common'; +import { Many, ServerException } from '~/common'; import { quoteKey } from '../query-augmentation/interpolate'; export type ExpressionInput = diff --git a/src/core/database/query/deletes.ts b/src/core/database/query/deletes.ts index 706c31ebac..12b9a58199 100644 --- a/src/core/database/query/deletes.ts +++ b/src/core/database/query/deletes.ts @@ -1,6 +1,6 @@ import { node, Query, relation } from 'cypher-query-builder'; import { DateTime } from 'luxon'; -import { ResourceShape } from '../../../common'; +import { ResourceShape } from '~/common'; import { ACTIVE } from './matching'; export const deleteBaseNode = (nodeVar: string) => (query: Query) => diff --git a/src/core/database/query/match-changeset-and-changed-props.ts b/src/core/database/query/match-changeset-and-changed-props.ts index 40799903d3..bb5941f0d1 100644 --- a/src/core/database/query/match-changeset-and-changed-props.ts +++ b/src/core/database/query/match-changeset-and-changed-props.ts @@ -1,5 +1,5 @@ import { node, Query } from 'cypher-query-builder'; -import { ID } from '../../../common'; +import { ID } from '~/common'; import { matchProps } from './matching'; export const matchChangesetAndChangedProps = diff --git a/src/core/database/query/match-project-based-props.ts b/src/core/database/query/match-project-based-props.ts index 1486f0ac95..5f46ad7092 100644 --- a/src/core/database/query/match-project-based-props.ts +++ b/src/core/database/query/match-project-based-props.ts @@ -1,11 +1,11 @@ import { oneLine } from 'common-tags'; import { node, Query, relation } from 'cypher-query-builder'; +import { ID, Sensitivity, Session } from '~/common'; import { QueryFragment, requestingUser, Variable } from '~/core/database/query'; -import { ID, Sensitivity, Session } from '../../../common'; import { GlobalScopedRole, ScopedRole, -} from '../../../components/authorization'; +} from '../../../components/authorization/dto'; import { ProjectType } from '../../../components/project/dto/project-type.enum'; import { apoc, diff --git a/src/core/database/query/matching.ts b/src/core/database/query/matching.ts index 0962599e04..417b8679a8 100644 --- a/src/core/database/query/matching.ts +++ b/src/core/database/query/matching.ts @@ -9,7 +9,7 @@ import { Many, ObjectView, Session, -} from '../../../common'; +} from '~/common'; import { variable } from '../query-augmentation/condition-variables'; import { apoc, collect, listConcat, merge } from './cypher-functions'; diff --git a/src/core/database/results/lists.ts b/src/core/database/results/lists.ts index accd1c5386..1f686a1091 100644 --- a/src/core/database/results/lists.ts +++ b/src/core/database/results/lists.ts @@ -1,4 +1,4 @@ -import { PaginatedListType } from '../../../common'; +import { PaginatedListType } from '~/common'; export const mapListResults = async ( results: PaginatedListType, diff --git a/src/core/database/split-db.provider.ts b/src/core/database/split-db.provider.ts index 1cc0dfeee6..c6ffa78fe7 100644 --- a/src/core/database/split-db.provider.ts +++ b/src/core/database/split-db.provider.ts @@ -16,3 +16,16 @@ export const splitDb = ( return await moduleRef.create(cls); }, } satisfies Provider); + +export const splitDb2 = ( + token: Type, + repos: { edge: Type>; neo4j: Type> }, +) => + ({ + provide: token, + inject: [ModuleRef, ConfigService], + useFactory: async (moduleRef: ModuleRef, config: ConfigService) => { + const cls = config.databaseEngine === 'edgedb' ? repos.edge : repos.neo4j; + return await moduleRef.create(cls); + }, + } satisfies Provider); diff --git a/src/core/database/transaction.ts b/src/core/database/transaction.ts index edc8bba37d..8845035270 100644 --- a/src/core/database/transaction.ts +++ b/src/core/database/transaction.ts @@ -1,7 +1,7 @@ import { Connection } from 'cypher-query-builder'; import { Duration, DurationLike } from 'luxon'; import { Transaction as NeoTransaction } from 'neo4j-driver'; -import { getCauseList, ServerException } from '../../common'; +import { getCauseList, ServerException } from '~/common'; import { ILogger } from '../logger'; import { PatchedConnection } from './cypher.factory'; import { isNeo4jError } from './errors'; diff --git a/src/core/database/transformer.ts b/src/core/database/transformer.ts index 1098d98ecf..4d1ca6ca6d 100644 --- a/src/core/database/transformer.ts +++ b/src/core/database/transformer.ts @@ -1,7 +1,7 @@ import { Transformer } from 'cypher-query-builder'; import { DateTime, Duration, FixedOffsetZone } from 'luxon'; import * as Neo from 'neo4j-driver'; -import { CalendarDate, RichTextDocument } from '../../common'; +import { CalendarDate, RichTextDocument } from '~/common'; // @ts-expect-error Convert private methods to protected class PatchedTransformer extends Transformer { diff --git a/src/core/edgedb/withScope.ts b/src/core/edgedb/withScope.ts index 7c795d41ba..67b5b8daf4 100644 --- a/src/core/edgedb/withScope.ts +++ b/src/core/edgedb/withScope.ts @@ -1,5 +1,5 @@ import { Role } from '~/common'; -import type { AuthScope } from '../../components/authorization'; +import type { AuthScope } from '../../components/authorization/dto'; import e from './generated-client'; import { orScalarLiteral } from './generated-client/castMaps'; import { $str } from './generated-client/modules/std'; diff --git a/src/core/email/templates/frontend-url.tsx b/src/core/email/templates/frontend-url.tsx index 2aad8139e2..2df10a10a4 100644 --- a/src/core/email/templates/frontend-url.tsx +++ b/src/core/email/templates/frontend-url.tsx @@ -1,5 +1,5 @@ import { createContext, ReactElement, useContext } from 'react'; -import { ServerException } from '../../../common/exceptions'; +import { ServerException } from '~/common/exceptions'; const FrontendUrlContext = createContext(undefined); diff --git a/src/core/email/templates/progress-report-status-changed.template.tsx b/src/core/email/templates/progress-report-status-changed.template.tsx index 8b334b0fba..2a132b25e2 100644 --- a/src/core/email/templates/progress-report-status-changed.template.tsx +++ b/src/core/email/templates/progress-report-status-changed.template.tsx @@ -6,12 +6,12 @@ import { } from '@seedcompany/nestjs-email/templates'; import { startCase } from 'lodash'; import { fiscalQuarter, fiscalYear } from '~/common'; -import { Language } from '../../../components/language'; -import { PeriodicReport } from '../../../components/periodic-report'; +import { Language } from '../../../components/language/dto'; +import { PeriodicReport } from '../../../components/periodic-report/dto'; import { ProgressReportStatus } from '../../../components/progress-report/dto'; import { ProgressReportWorkflowEvent } from '../../../components/progress-report/workflow/dto/workflow-event.dto'; -import { Project } from '../../../components/project'; -import { User } from '../../../components/user'; +import { Project } from '../../../components/project/dto'; +import { User } from '../../../components/user/dto'; import { EmailTemplate, Heading } from './base'; import { FormattedDateTime } from './formatted-date-time'; import { useFrontendUrl } from './frontend-url'; diff --git a/src/core/email/templates/project-step-changed.template.tsx b/src/core/email/templates/project-step-changed.template.tsx index 6d1f3b5c79..9a08cd4543 100644 --- a/src/core/email/templates/project-step-changed.template.tsx +++ b/src/core/email/templates/project-step-changed.template.tsx @@ -17,6 +17,7 @@ export function ProjectStepChanged({ changedBy, previousStep: oldStepVal, recipient, + primaryPartnerName, }: StepChangeNotification) { const projectUrl = useFrontendUrl(`/projects/${project.id}`); const projectName = project.name.value; @@ -63,6 +64,12 @@ export function ProjectStepChanged({ value={project.modifiedAt} timezone={recipient.timezone.value} /> +
+ Project Type: {project.type} +
+ {primaryPartnerName ? ( + <>Primary Partner: {primaryPartnerName} + ) : null}