upgrade typeorm to 3.0 (#359)
* upgrade typeorm to 3.0 * use new datasource object in typeorm 3 * fix tests * fix tests * migrate before creating connection * fail the test if migration failed
This commit is contained in:
@ -75,8 +75,8 @@
|
||||
"snake-case": "^3.0.3",
|
||||
"supertest": "^6.2.2",
|
||||
"ts-loader": "^8.0.3",
|
||||
"typeorm": "^0.2.37",
|
||||
"typeorm-naming-strategies": "^2.0.0",
|
||||
"typeorm": "^0.3.4",
|
||||
"typeorm-naming-strategies": "^4.1.0",
|
||||
"urlsafe-base64": "^1.0.0",
|
||||
"uuid": "^8.3.1",
|
||||
"voca": "^1.4.0",
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
import {
|
||||
Entity,
|
||||
BaseEntity,
|
||||
PrimaryGeneratedColumn,
|
||||
CreateDateColumn,
|
||||
OneToOne,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
OneToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm'
|
||||
|
||||
import { User } from './user'
|
||||
|
||||
@Entity({ name: 'user_friends' })
|
||||
export class Follower extends BaseEntity {
|
||||
export class Follower {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id?: string
|
||||
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
import {
|
||||
Entity,
|
||||
BaseEntity,
|
||||
Column,
|
||||
PrimaryGeneratedColumn,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToOne,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
OneToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm'
|
||||
|
||||
import { User } from '../user'
|
||||
|
||||
@Entity()
|
||||
export class Group extends BaseEntity {
|
||||
export class Group {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id?: string
|
||||
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import {
|
||||
Entity,
|
||||
BaseEntity,
|
||||
PrimaryGeneratedColumn,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToOne,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
OneToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm'
|
||||
|
||||
import { User } from '../user'
|
||||
@ -13,7 +12,7 @@ import { Group } from './group'
|
||||
import { Invite } from './invite'
|
||||
|
||||
@Entity()
|
||||
export class GroupMembership extends BaseEntity {
|
||||
export class GroupMembership {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id?: string
|
||||
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
import {
|
||||
Entity,
|
||||
BaseEntity,
|
||||
Column,
|
||||
PrimaryGeneratedColumn,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToOne,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
OneToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm'
|
||||
|
||||
import { User } from '../user'
|
||||
import { Group } from './group'
|
||||
|
||||
@Entity()
|
||||
export class Invite extends BaseEntity {
|
||||
export class Invite {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id?: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -12,7 +11,7 @@ import { User } from './user'
|
||||
import { Page } from './page'
|
||||
|
||||
@Entity({ name: 'highlight' })
|
||||
export class Highlight extends BaseEntity {
|
||||
export class Highlight {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id?: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -10,7 +9,7 @@ import {
|
||||
import { User } from './user'
|
||||
|
||||
@Entity({ name: 'labels' })
|
||||
export class Label extends BaseEntity {
|
||||
export class Label {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
// shared_with_highlights | boolean | | | false
|
||||
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -27,7 +26,7 @@ import { Page } from './page'
|
||||
import { Label } from './label'
|
||||
|
||||
@Entity({ name: 'links' })
|
||||
export class Link extends BaseEntity {
|
||||
export class Link {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
@ -10,7 +9,7 @@ import { Link } from './link'
|
||||
import { Label } from './label'
|
||||
|
||||
@Entity({ name: 'link_labels' })
|
||||
export class LinkLabel extends BaseEntity {
|
||||
export class LinkLabel {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -11,7 +10,7 @@ import {
|
||||
import { User } from './user'
|
||||
|
||||
@Entity({ name: 'newsletter_emails' })
|
||||
export class NewsletterEmail extends BaseEntity {
|
||||
export class NewsletterEmail {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -8,7 +7,7 @@ import {
|
||||
} from 'typeorm'
|
||||
|
||||
@Entity({ name: 'pages' })
|
||||
export class Page extends BaseEntity {
|
||||
export class Page {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
import {
|
||||
Entity,
|
||||
BaseEntity,
|
||||
Column,
|
||||
PrimaryGeneratedColumn,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
OneToOne,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
OneToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm'
|
||||
|
||||
import { User } from './user'
|
||||
|
||||
@Entity({ name: 'user_profile' })
|
||||
export class Profile extends BaseEntity {
|
||||
export class Profile {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -11,7 +10,7 @@ import {
|
||||
import { User } from './user'
|
||||
|
||||
@Entity({ name: 'reminders' })
|
||||
export class Reminder extends BaseEntity {
|
||||
export class Reminder {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -9,7 +8,7 @@ import {
|
||||
import { ReportType } from '../../generated/graphql'
|
||||
|
||||
@Entity()
|
||||
export class AbuseReport extends BaseEntity {
|
||||
export class AbuseReport {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id?: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -8,7 +7,7 @@ import {
|
||||
} from 'typeorm'
|
||||
|
||||
@Entity()
|
||||
export class ContentDisplayReport extends BaseEntity {
|
||||
export class ContentDisplayReport {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id?: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -11,7 +10,7 @@ import {
|
||||
import { User } from './user'
|
||||
|
||||
@Entity({ name: 'upload_files' })
|
||||
export class UploadFile extends BaseEntity {
|
||||
export class UploadFile {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -14,7 +13,7 @@ import { Profile } from './profile'
|
||||
import { Label } from './label'
|
||||
|
||||
@Entity()
|
||||
export class User extends BaseEntity {
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {
|
||||
BaseEntity,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
@ -10,7 +9,7 @@ import {
|
||||
import { User } from './user'
|
||||
|
||||
@Entity({ name: 'user_device_tokens' })
|
||||
export class UserDeviceToken extends BaseEntity {
|
||||
export class UserDeviceToken {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id!: string
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { EntityManager } from 'typeorm'
|
||||
import { EntityManager, EntityTarget, Repository } from 'typeorm'
|
||||
import { AppDataSource } from '../server'
|
||||
|
||||
export const setClaims = async (
|
||||
t: EntityManager,
|
||||
@ -9,3 +10,7 @@ export const setClaims = async (
|
||||
.query('SELECT * from omnivore.set_claims($1, $2)', [uid, dbRole])
|
||||
.then()
|
||||
}
|
||||
|
||||
export const getRepository = <T>(entity: EntityTarget<T>): Repository<T> => {
|
||||
return AppDataSource.getRepository(entity)
|
||||
}
|
||||
|
||||
@ -32,8 +32,7 @@ export class FollowOmnivoreUser implements EntitySubscriberInterface<Profile> {
|
||||
|
||||
await event.manager
|
||||
.getRepository(Follower)
|
||||
.create({ user: event.entity.user, followee: omnivoreProfile.user })
|
||||
.save()
|
||||
.save({ user: event.entity.user, followee: omnivoreProfile.user })
|
||||
|
||||
await event.manager.query(
|
||||
`insert into omnivore.links (user_id, article_id, article_url, article_hash, slug)
|
||||
|
||||
@ -20,10 +20,11 @@ import { analytics } from '../../utils/analytics'
|
||||
import { env } from '../../env'
|
||||
import { User } from '../../entity/user'
|
||||
import { Label } from '../../entity/label'
|
||||
import { getManager, getRepository, ILike } from 'typeorm'
|
||||
import { setClaims } from '../../entity/utils'
|
||||
import { ILike, In } from 'typeorm'
|
||||
import { getRepository, setClaims } from '../../entity/utils'
|
||||
import { deleteLabelInPages, getPageById, updatePage } from '../../elastic'
|
||||
import { createPubSubClient } from '../../datalayer/pubsub'
|
||||
import { AppDataSource } from '../../server'
|
||||
|
||||
export const labelsResolver = authorized<LabelsSuccess, LabelsError>(
|
||||
async (_obj, _params, { claims: { uid }, log }) => {
|
||||
@ -38,7 +39,8 @@ export const labelsResolver = authorized<LabelsSuccess, LabelsError>(
|
||||
})
|
||||
|
||||
try {
|
||||
const user = await User.findOne(uid, {
|
||||
const user = await getRepository(User).findOne({
|
||||
where: { id: uid },
|
||||
relations: ['labels'],
|
||||
})
|
||||
if (!user) {
|
||||
@ -69,7 +71,7 @@ export const createLabelResolver = authorized<
|
||||
const { name, color, description } = input
|
||||
|
||||
try {
|
||||
const user = await getRepository(User).findOne(uid)
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [CreateLabelErrorCode.Unauthorized],
|
||||
@ -77,11 +79,9 @@ export const createLabelResolver = authorized<
|
||||
}
|
||||
|
||||
// Check if label already exists ignoring case of name
|
||||
const existingLabel = await getRepository(Label).findOne({
|
||||
where: {
|
||||
user,
|
||||
name: ILike(name),
|
||||
},
|
||||
const existingLabel = await getRepository(Label).findOneBy({
|
||||
user: { id: user.id },
|
||||
name: ILike(name),
|
||||
})
|
||||
if (existingLabel) {
|
||||
return {
|
||||
@ -89,14 +89,12 @@ export const createLabelResolver = authorized<
|
||||
}
|
||||
}
|
||||
|
||||
const label = await getRepository(Label)
|
||||
.create({
|
||||
user,
|
||||
name,
|
||||
color,
|
||||
description: description || '',
|
||||
})
|
||||
.save()
|
||||
const label = await getRepository(Label).save({
|
||||
user,
|
||||
name,
|
||||
color,
|
||||
description: description || '',
|
||||
})
|
||||
|
||||
analytics.track({
|
||||
userId: uid,
|
||||
@ -128,14 +126,15 @@ export const deleteLabelResolver = authorized<
|
||||
log.info('deleteLabelResolver')
|
||||
|
||||
try {
|
||||
const user = await getRepository(User).findOne(uid)
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [DeleteLabelErrorCode.Unauthorized],
|
||||
}
|
||||
}
|
||||
|
||||
const label = await getRepository(Label).findOne(labelId, {
|
||||
const label = await getRepository(Label).findOne({
|
||||
where: { id: labelId },
|
||||
relations: ['user'],
|
||||
})
|
||||
if (!label) {
|
||||
@ -150,7 +149,7 @@ export const deleteLabelResolver = authorized<
|
||||
}
|
||||
}
|
||||
|
||||
const result = await getManager().transaction(async (t) => {
|
||||
const result = await AppDataSource.transaction(async (t) => {
|
||||
await setClaims(t, uid)
|
||||
return t.getRepository(Label).delete(labelId)
|
||||
})
|
||||
@ -197,7 +196,7 @@ export const setLabelsResolver = authorized<
|
||||
const { linkId: pageId, labelIds } = input
|
||||
|
||||
try {
|
||||
const user = await getRepository(User).findOne(uid)
|
||||
const user = await getRepository(User).findOneBy({ id: uid })
|
||||
if (!user) {
|
||||
return {
|
||||
errorCodes: [SetLabelsErrorCode.Unauthorized],
|
||||
@ -211,10 +210,8 @@ export const setLabelsResolver = authorized<
|
||||
}
|
||||
}
|
||||
|
||||
const labels = await getRepository(Label).findByIds(labelIds, {
|
||||
where: {
|
||||
user,
|
||||
},
|
||||
const labels = await getRepository(Label).find({
|
||||
where: { id: In(labelIds), user: { id: user.id } },
|
||||
relations: ['user'],
|
||||
})
|
||||
if (labels.length !== labelIds.length) {
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { authorized } from '../../utils/helpers'
|
||||
import {
|
||||
CreateNewsletterEmailSuccess,
|
||||
CreateNewsletterEmailError,
|
||||
CreateNewsletterEmailErrorCode,
|
||||
NewsletterEmailsSuccess,
|
||||
NewsletterEmailsError,
|
||||
NewsletterEmailsErrorCode,
|
||||
CreateNewsletterEmailSuccess,
|
||||
DeleteNewsletterEmailError,
|
||||
DeleteNewsletterEmailErrorCode,
|
||||
DeleteNewsletterEmailSuccess,
|
||||
DeleteNewsletterEmailError,
|
||||
MutationDeleteNewsletterEmailArgs,
|
||||
NewsletterEmailsError,
|
||||
NewsletterEmailsErrorCode,
|
||||
NewsletterEmailsSuccess,
|
||||
} from '../../generated/graphql'
|
||||
import {
|
||||
createNewsletterEmail,
|
||||
@ -19,6 +19,8 @@ import {
|
||||
import { NewsletterEmail } from '../../entity/newsletter_email'
|
||||
import { analytics } from '../../utils/analytics'
|
||||
import { env } from '../../env'
|
||||
import { AppDataSource } from '../../server'
|
||||
import { User } from '../../entity/user'
|
||||
|
||||
export const createNewsletterEmailResolver = authorized<
|
||||
CreateNewsletterEmailSuccess,
|
||||
@ -55,7 +57,16 @@ export const newsletterEmailsResolver = authorized<
|
||||
console.log('newsletterEmailsResolver')
|
||||
|
||||
try {
|
||||
const newsletterEmails = await getNewsletterEmails(claims.uid)
|
||||
const user = await AppDataSource.getRepository(User).findOneBy({
|
||||
id: claims.uid,
|
||||
})
|
||||
if (!user) {
|
||||
return Promise.reject({
|
||||
errorCode: NewsletterEmailsErrorCode.Unauthorized,
|
||||
})
|
||||
}
|
||||
|
||||
const newsletterEmails = await getNewsletterEmails(user.id)
|
||||
|
||||
return {
|
||||
newsletterEmails: newsletterEmails,
|
||||
@ -84,10 +95,14 @@ export const deleteNewsletterEmailResolver = authorized<
|
||||
})
|
||||
|
||||
try {
|
||||
const newsletterEmail = await NewsletterEmail.findOne(
|
||||
args.newsletterEmailId,
|
||||
{ relations: ['user'] }
|
||||
)
|
||||
const newsletterEmail = await AppDataSource.getRepository(
|
||||
NewsletterEmail
|
||||
).findOne({
|
||||
where: {
|
||||
id: args.newsletterEmailId,
|
||||
},
|
||||
relations: ['user'],
|
||||
})
|
||||
|
||||
if (!newsletterEmail) {
|
||||
return {
|
||||
|
||||
@ -19,7 +19,7 @@ import { articleRouter } from './routers/article_router'
|
||||
import { mobileAuthRouter } from './routers/auth/mobile/mobile_auth_router'
|
||||
import { contentServiceRouter } from './routers/svc/content'
|
||||
import { localDebugRouter } from './routers/local_debug_router'
|
||||
import { Connection, createConnection } from 'typeorm'
|
||||
import { DataSource } from 'typeorm'
|
||||
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
|
||||
import { linkServiceRouter } from './routers/svc/links'
|
||||
import UserModel from './datalayer/user'
|
||||
@ -57,21 +57,19 @@ export const initModels = (kx: Knex, cache = true): DataModels => ({
|
||||
reminder: new ReminderModel(kx, cache),
|
||||
})
|
||||
|
||||
const initEntities = async (): Promise<Connection> => {
|
||||
return createConnection({
|
||||
type: 'postgres',
|
||||
host: env.pg.host,
|
||||
port: env.pg.port,
|
||||
schema: 'omnivore',
|
||||
username: env.pg.userName,
|
||||
password: env.pg.password,
|
||||
database: env.pg.dbName,
|
||||
logging: ['query', 'info'],
|
||||
entities: [__dirname + '/entity/**/*{.js,.ts}'],
|
||||
subscribers: [__dirname + '/events/**/*{.js,.ts}'],
|
||||
namingStrategy: new SnakeNamingStrategy(),
|
||||
})
|
||||
}
|
||||
export const AppDataSource = new DataSource({
|
||||
type: 'postgres',
|
||||
host: env.pg.host,
|
||||
port: env.pg.port,
|
||||
schema: 'omnivore',
|
||||
username: env.pg.userName,
|
||||
password: env.pg.password,
|
||||
database: env.pg.dbName,
|
||||
logging: ['query', 'info'],
|
||||
entities: [__dirname + '/entity/**/*{.js,.ts}'],
|
||||
subscribers: [__dirname + '/events/**/*{.js,.ts}'],
|
||||
namingStrategy: new SnakeNamingStrategy(),
|
||||
})
|
||||
|
||||
export const createApp = (): {
|
||||
app: Express
|
||||
@ -126,7 +124,7 @@ const main = async (): Promise<void> => {
|
||||
// If creating the DB entities fails, we want this to throw
|
||||
// so the container will be restarted and not come online
|
||||
// as healthy.
|
||||
await initEntities()
|
||||
await AppDataSource.initialize()
|
||||
|
||||
await initElasticsearch()
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { getManager } from 'typeorm'
|
||||
import { Link } from '../entity/link'
|
||||
import { setClaims } from '../entity/utils'
|
||||
import { AppDataSource } from '../server'
|
||||
|
||||
export const setLinkArchived = async (
|
||||
userId: string,
|
||||
linkId: string,
|
||||
archived: boolean
|
||||
): Promise<void> => {
|
||||
await getManager().transaction(async (t) => {
|
||||
await AppDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
await t.getRepository(Link).update(
|
||||
{
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { getManager } from 'typeorm'
|
||||
import { User } from '../entity/user'
|
||||
import { Group } from '../entity/groups/group'
|
||||
import { Invite } from '../entity/groups/invite'
|
||||
import { GroupMembership } from '../entity/groups/group_membership'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { AppDataSource } from '../server'
|
||||
|
||||
export const createGroup = async (input: {
|
||||
admin: User
|
||||
@ -11,15 +11,12 @@ export const createGroup = async (input: {
|
||||
maxMembers?: number
|
||||
expiresInDays?: number
|
||||
}): Promise<[Group, Invite]> => {
|
||||
const [group, invite] = await getManager().transaction<[Group, Invite]>(
|
||||
const [group, invite] = await AppDataSource.transaction<[Group, Invite]>(
|
||||
async (t) => {
|
||||
const group = await t
|
||||
.getRepository(Group)
|
||||
.create({
|
||||
name: input.name,
|
||||
createdBy: input.admin,
|
||||
})
|
||||
.save()
|
||||
const group = await t.getRepository(Group).save({
|
||||
name: input.name,
|
||||
createdBy: input.admin,
|
||||
})
|
||||
|
||||
const code = nanoid(8)
|
||||
const expirationTime = (() => {
|
||||
@ -27,25 +24,19 @@ export const createGroup = async (input: {
|
||||
r.setDate(r.getDate() + (input.expiresInDays || 7))
|
||||
return r
|
||||
})()
|
||||
const invite = await t
|
||||
.getRepository(Invite)
|
||||
.create({
|
||||
group,
|
||||
code,
|
||||
createdBy: input.admin,
|
||||
maxMembers: input.maxMembers || 50,
|
||||
expirationTime: expirationTime,
|
||||
})
|
||||
.save()
|
||||
const invite = await t.getRepository(Invite).save({
|
||||
group,
|
||||
code,
|
||||
createdBy: input.admin,
|
||||
maxMembers: input.maxMembers || 50,
|
||||
expirationTime: expirationTime,
|
||||
})
|
||||
// Add the admin to the group as its first user
|
||||
await t
|
||||
.getRepository(GroupMembership)
|
||||
.create({
|
||||
user: input.admin,
|
||||
group,
|
||||
invite,
|
||||
})
|
||||
.save()
|
||||
await t.getRepository(GroupMembership).save({
|
||||
user: input.admin,
|
||||
group,
|
||||
invite,
|
||||
})
|
||||
return [group, invite]
|
||||
}
|
||||
)
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
import { AuthProvider } from '../routers/auth/auth_types'
|
||||
import { MembershipTier } from '../datalayer/user/model'
|
||||
import { EntityManager, getManager, getRepository } from 'typeorm'
|
||||
import { EntityManager } from 'typeorm'
|
||||
import { User } from '../entity/user'
|
||||
import { Profile } from '../entity/profile'
|
||||
import { SignupErrorCode } from '../generated/graphql'
|
||||
import { validateUsername } from '../utils/usernamePolicy'
|
||||
import { Invite } from '../entity/groups/invite'
|
||||
import { GroupMembership } from '../entity/groups/group_membership'
|
||||
import { AppDataSource } from '../server'
|
||||
import { getRepository } from '../entity/utils'
|
||||
|
||||
export const createUser = async (input: {
|
||||
provider: AuthProvider
|
||||
@ -28,15 +30,12 @@ export const createUser = async (input: {
|
||||
}
|
||||
|
||||
// create profile if user exists but profile does not exist
|
||||
const profile = await getManager()
|
||||
.getRepository(Profile)
|
||||
.create({
|
||||
username: input.username,
|
||||
pictureUrl: input.pictureUrl,
|
||||
bio: input.bio,
|
||||
user: existingUser,
|
||||
})
|
||||
.save()
|
||||
const profile = await getRepository(Profile).save({
|
||||
username: input.username,
|
||||
pictureUrl: input.pictureUrl,
|
||||
bio: input.bio,
|
||||
user: existingUser,
|
||||
})
|
||||
|
||||
return [existingUser, profile]
|
||||
}
|
||||
@ -45,10 +44,10 @@ export const createUser = async (input: {
|
||||
return Promise.reject({ errorCode: SignupErrorCode.InvalidUsername })
|
||||
}
|
||||
|
||||
const [user, profile] = await getManager().transaction<[User, Profile]>(
|
||||
const [user, profile] = await AppDataSource.transaction<[User, Profile]>(
|
||||
async (t) => {
|
||||
let hasInvite = false
|
||||
let invite: Invite | undefined = undefined
|
||||
let invite: Invite | null = null
|
||||
|
||||
if (input.inviteCode) {
|
||||
const inviteCodeRepo = t.getRepository(Invite)
|
||||
@ -60,37 +59,28 @@ export const createUser = async (input: {
|
||||
hasInvite = true
|
||||
}
|
||||
}
|
||||
const user = await t
|
||||
.getRepository(User)
|
||||
.create({
|
||||
source: input.provider,
|
||||
membership:
|
||||
input.membershipTier ||
|
||||
(hasInvite ? MembershipTier.Beta : MembershipTier.WaitList),
|
||||
name: input.name,
|
||||
email: input.email,
|
||||
sourceUserId: input.sourceUserId,
|
||||
password: input.password,
|
||||
})
|
||||
.save()
|
||||
const profile = await t
|
||||
.getRepository(Profile)
|
||||
.create({
|
||||
username: input.username,
|
||||
pictureUrl: input.pictureUrl,
|
||||
bio: input.bio,
|
||||
user,
|
||||
})
|
||||
.save()
|
||||
const user = await t.getRepository(User).save({
|
||||
source: input.provider,
|
||||
membership:
|
||||
input.membershipTier ||
|
||||
(hasInvite ? MembershipTier.Beta : MembershipTier.WaitList),
|
||||
name: input.name,
|
||||
email: input.email,
|
||||
sourceUserId: input.sourceUserId,
|
||||
password: input.password,
|
||||
})
|
||||
const profile = await t.getRepository(Profile).save({
|
||||
username: input.username,
|
||||
pictureUrl: input.pictureUrl,
|
||||
bio: input.bio,
|
||||
user,
|
||||
})
|
||||
if (hasInvite && invite) {
|
||||
await t
|
||||
.getRepository(GroupMembership)
|
||||
.create({
|
||||
user: user,
|
||||
invite: invite,
|
||||
group: invite.group,
|
||||
})
|
||||
.save()
|
||||
await t.getRepository(GroupMembership).save({
|
||||
user: user,
|
||||
invite: invite,
|
||||
group: invite.group,
|
||||
})
|
||||
}
|
||||
return [user, profile]
|
||||
}
|
||||
@ -119,7 +109,7 @@ const validateInvite = async (
|
||||
return true
|
||||
}
|
||||
|
||||
const getUser = async (email: string): Promise<User | undefined> => {
|
||||
const getUser = async (email: string): Promise<User | null> => {
|
||||
const userRepo = getRepository(User)
|
||||
|
||||
return userRepo.findOne({
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getRepository } from 'typeorm'
|
||||
import { User } from '../entity/user'
|
||||
import { Follower } from '../entity/follower'
|
||||
import { getRepository } from '../entity/utils'
|
||||
|
||||
export const getUserFollowers = async (
|
||||
user: User,
|
||||
@ -9,7 +9,7 @@ export const getUserFollowers = async (
|
||||
): Promise<User[]> => {
|
||||
return (
|
||||
await getRepository(Follower).find({
|
||||
where: { user: user },
|
||||
where: { user: { id: user.id } },
|
||||
relations: ['user', 'followee'],
|
||||
skip: offset,
|
||||
take: count,
|
||||
@ -24,7 +24,7 @@ export const getUserFollowing = async (
|
||||
): Promise<User[]> => {
|
||||
return (
|
||||
await getRepository(Follower).find({
|
||||
where: { followee: user },
|
||||
where: { followee: { id: user.id } },
|
||||
relations: ['user', 'followee'],
|
||||
skip: offset,
|
||||
take: count,
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import DataLoader from 'dataloader'
|
||||
import { Label } from '../entity/label'
|
||||
import { getRepository, ILike, In } from 'typeorm'
|
||||
import { Link } from '../entity/link'
|
||||
import { ILike, In } from 'typeorm'
|
||||
import { PageContext } from '../elastic/types'
|
||||
import { User } from '../entity/user'
|
||||
import { addLabelInPage } from '../elastic'
|
||||
import { getRepository } from '../entity/utils'
|
||||
import { Link } from '../entity/link'
|
||||
import DataLoader from 'dataloader'
|
||||
|
||||
const batchGetLabelsFromLinkIds = async (
|
||||
linkIds: readonly string[]
|
||||
@ -30,13 +31,16 @@ export const addLabelToPage = async (
|
||||
description?: string
|
||||
}
|
||||
): Promise<boolean> => {
|
||||
const user = await getRepository(User).findOne(ctx.uid)
|
||||
const user = await getRepository(User).findOneBy({
|
||||
id: ctx.uid,
|
||||
})
|
||||
if (!user) {
|
||||
return false
|
||||
}
|
||||
|
||||
let labelEntity = await getRepository(Label).findOne({
|
||||
where: {
|
||||
user: user,
|
||||
name: ILike(label.name),
|
||||
},
|
||||
let labelEntity = await getRepository(Label).findOneBy({
|
||||
user: { id: user.id },
|
||||
name: ILike(label.name),
|
||||
})
|
||||
|
||||
if (!labelEntity) {
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { getRepository } from 'typeorm'
|
||||
import { NewsletterEmail } from '../entity/newsletter_email'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { User } from '../entity/user'
|
||||
import { CreateNewsletterEmailErrorCode } from '../generated/graphql'
|
||||
import { env } from '../env'
|
||||
import { AppDataSource } from '../server'
|
||||
import { getRepository } from '../entity/utils'
|
||||
|
||||
import addressparser = require('nodemailer/lib/addressparser')
|
||||
|
||||
const parsedAddress = (emailAddress: string): string | undefined => {
|
||||
@ -17,7 +19,8 @@ const parsedAddress = (emailAddress: string): string | undefined => {
|
||||
export const createNewsletterEmail = async (
|
||||
userId: string
|
||||
): Promise<NewsletterEmail> => {
|
||||
const user = await getRepository(User).findOne(userId, {
|
||||
const user = await getRepository(User).findOne({
|
||||
where: { id: userId },
|
||||
relations: ['profile'],
|
||||
})
|
||||
if (!user) {
|
||||
@ -28,19 +31,17 @@ export const createNewsletterEmail = async (
|
||||
// generate a random email address with username prefix
|
||||
const emailAddress = createRandomEmailAddress(user.profile.username, 8)
|
||||
|
||||
return getRepository(NewsletterEmail)
|
||||
.create({
|
||||
address: emailAddress,
|
||||
user: user,
|
||||
})
|
||||
.save()
|
||||
return getRepository(NewsletterEmail).save({
|
||||
address: emailAddress,
|
||||
user: user,
|
||||
})
|
||||
}
|
||||
|
||||
export const getNewsletterEmails = async (
|
||||
userId: string
|
||||
): Promise<NewsletterEmail[]> => {
|
||||
return getRepository(NewsletterEmail).find({
|
||||
where: { user: userId },
|
||||
where: { user: { id: userId } },
|
||||
order: { createdAt: 'DESC' },
|
||||
})
|
||||
}
|
||||
@ -69,7 +70,7 @@ export const updateConfirmationCode = async (
|
||||
|
||||
export const getNewsletterEmail = async (
|
||||
emailAddress: string
|
||||
): Promise<NewsletterEmail | undefined> => {
|
||||
): Promise<NewsletterEmail | null> => {
|
||||
const address = parsedAddress(emailAddress)
|
||||
return getRepository(NewsletterEmail)
|
||||
.createQueryBuilder('newsletter_email')
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { getRepository } from 'typeorm'
|
||||
import { ReportItemInput, ReportType } from '../generated/graphql'
|
||||
import { ContentDisplayReport } from '../entity/reports/content_display_report'
|
||||
import { AbuseReport } from '../entity/reports/abuse_report'
|
||||
import { getPageById } from '../elastic'
|
||||
import { getRepository } from '../entity/utils'
|
||||
|
||||
export const saveContentDisplayReport = async (
|
||||
uid: string,
|
||||
@ -20,16 +20,14 @@ export const saveContentDisplayReport = async (
|
||||
// We capture the article content and original html now, in case it
|
||||
// reparsed or updated later, this gives us a view of exactly
|
||||
// what the user saw.
|
||||
const result = await repo
|
||||
.create({
|
||||
userId: uid,
|
||||
elasticPageId: input.pageId,
|
||||
content: page.content,
|
||||
originalHtml: page.originalHtml || undefined,
|
||||
originalUrl: page.url,
|
||||
reportComment: input.reportComment,
|
||||
})
|
||||
.save()
|
||||
const result = await repo.save({
|
||||
userId: uid,
|
||||
elasticPageId: input.pageId,
|
||||
content: page.content,
|
||||
originalHtml: page.originalHtml || undefined,
|
||||
originalUrl: page.url,
|
||||
reportComment: input.reportComment,
|
||||
})
|
||||
|
||||
return !!result
|
||||
}
|
||||
@ -55,16 +53,14 @@ export const saveAbuseReport = async (
|
||||
// We capture the article content and original html now, in case it
|
||||
// reparsed or updated later, this gives us a view of exactly
|
||||
// what the user saw.
|
||||
const result = await repo
|
||||
.create({
|
||||
reportedBy: uid,
|
||||
sharedBy: input.sharedBy,
|
||||
elasticPageId: input.pageId,
|
||||
itemUrl: input.itemUrl,
|
||||
reportTypes: [ReportType.Abusive],
|
||||
reportComment: input.reportComment,
|
||||
})
|
||||
.save()
|
||||
const result = await repo.save({
|
||||
reportedBy: uid,
|
||||
sharedBy: input.sharedBy,
|
||||
elasticPageId: input.pageId,
|
||||
itemUrl: input.itemUrl,
|
||||
reportTypes: [ReportType.Abusive],
|
||||
reportComment: input.reportComment,
|
||||
})
|
||||
|
||||
return !!result
|
||||
}
|
||||
|
||||
@ -1,34 +1,36 @@
|
||||
import { getManager, getRepository } from 'typeorm'
|
||||
import { UserDeviceToken } from '../entity/user_device_tokens'
|
||||
import { User } from '../entity/user'
|
||||
import { SetDeviceTokenErrorCode } from '../generated/graphql'
|
||||
import { setClaims } from '../entity/utils'
|
||||
import { getRepository, setClaims } from '../entity/utils'
|
||||
import { analytics } from '../utils/analytics'
|
||||
import { env } from '../env'
|
||||
import { AppDataSource } from '../server'
|
||||
|
||||
export const getDeviceToken = async (
|
||||
id: string
|
||||
): Promise<UserDeviceToken | undefined> => {
|
||||
return getRepository(UserDeviceToken).findOne(id)
|
||||
): Promise<UserDeviceToken | null> => {
|
||||
return getRepository(UserDeviceToken).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const getDeviceTokenByToken = async (
|
||||
token: string
|
||||
): Promise<UserDeviceToken | undefined> => {
|
||||
return getRepository(UserDeviceToken).findOne({ token })
|
||||
): Promise<UserDeviceToken | null> => {
|
||||
return getRepository(UserDeviceToken).findOneBy({ token })
|
||||
}
|
||||
|
||||
export const getDeviceTokensByUserId = async (
|
||||
userId: string
|
||||
): Promise<UserDeviceToken[] | undefined> => {
|
||||
return getRepository(UserDeviceToken).find({ where: { user: userId } })
|
||||
return getRepository(UserDeviceToken).find({
|
||||
where: { user: { id: userId } },
|
||||
})
|
||||
}
|
||||
|
||||
export const createDeviceToken = async (
|
||||
userId: string,
|
||||
token: string
|
||||
): Promise<UserDeviceToken> => {
|
||||
const user = await getRepository(User).findOne(userId)
|
||||
const user = await getRepository(User).findOneBy({ id: userId })
|
||||
if (!user) {
|
||||
return Promise.reject({
|
||||
errorCode: SetDeviceTokenErrorCode.Unauthorized,
|
||||
@ -43,19 +45,17 @@ export const createDeviceToken = async (
|
||||
},
|
||||
})
|
||||
|
||||
return getRepository(UserDeviceToken)
|
||||
.create({
|
||||
token: token,
|
||||
user: user,
|
||||
})
|
||||
.save()
|
||||
return getRepository(UserDeviceToken).save({
|
||||
token: token,
|
||||
user: user,
|
||||
})
|
||||
}
|
||||
|
||||
export const deleteDeviceToken = async (
|
||||
id: string,
|
||||
userId: string
|
||||
): Promise<boolean> => {
|
||||
const user = await getRepository(User).findOne(userId)
|
||||
const user = await getRepository(User).findOneBy({ id: userId })
|
||||
if (!user) {
|
||||
return Promise.reject({
|
||||
errorCode: SetDeviceTokenErrorCode.Unauthorized,
|
||||
@ -70,7 +70,7 @@ export const deleteDeviceToken = async (
|
||||
},
|
||||
})
|
||||
|
||||
return getManager().transaction(async (t) => {
|
||||
return AppDataSource.transaction(async (t) => {
|
||||
await setClaims(t, userId)
|
||||
const result = await t.getRepository(UserDeviceToken).delete(id)
|
||||
|
||||
|
||||
@ -1,13 +1,5 @@
|
||||
import {
|
||||
createConnection,
|
||||
getConnection,
|
||||
getManager,
|
||||
getRepository,
|
||||
} from 'typeorm'
|
||||
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
|
||||
import Postgrator from 'postgrator'
|
||||
import { User } from '../src/entity/user'
|
||||
import { createUser } from '../src/services/create_user'
|
||||
import { Profile } from '../src/entity/profile'
|
||||
import { Page } from '../src/entity/page'
|
||||
import { Link } from '../src/entity/link'
|
||||
@ -15,6 +7,10 @@ import { Reminder } from '../src/entity/reminder'
|
||||
import { NewsletterEmail } from '../src/entity/newsletter_email'
|
||||
import { UserDeviceToken } from '../src/entity/user_device_tokens'
|
||||
import { Label } from '../src/entity/label'
|
||||
import { AppDataSource } from '../src/server'
|
||||
import { getRepository } from '../src/entity/utils'
|
||||
import { createUser } from '../src/services/create_user'
|
||||
import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
|
||||
|
||||
const runMigrations = async () => {
|
||||
const migrationDirectory = __dirname + '/../../db/migrations'
|
||||
@ -43,8 +39,10 @@ const runMigrations = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const createEntityConnection = async (): Promise<void> => {
|
||||
await createConnection({
|
||||
export const createTestConnection = async (): Promise<void> => {
|
||||
await runMigrations()
|
||||
|
||||
AppDataSource.setOptions({
|
||||
type: 'postgres',
|
||||
host: process.env.PG_HOST,
|
||||
port: Number(process.env.PG_PORT),
|
||||
@ -57,21 +55,11 @@ const createEntityConnection = async (): Promise<void> => {
|
||||
subscribers: [__dirname + '/../src/events/**/*{.js,.ts}'],
|
||||
namingStrategy: new SnakeNamingStrategy(),
|
||||
})
|
||||
}
|
||||
|
||||
export const createTestConnection = async (): Promise<void> => {
|
||||
try {
|
||||
getConnection()
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (error) {}
|
||||
|
||||
await runMigrations()
|
||||
await createEntityConnection()
|
||||
await AppDataSource.initialize()
|
||||
}
|
||||
|
||||
export const deleteTestUser = async (name: string) => {
|
||||
await getConnection()
|
||||
.createQueryBuilder()
|
||||
await AppDataSource.createQueryBuilder()
|
||||
.delete()
|
||||
.from(User)
|
||||
.where({ email: `${name}@fake.com` })
|
||||
@ -93,68 +81,58 @@ export const createTestUser = async (
|
||||
inviteCode: invite,
|
||||
password: password,
|
||||
})
|
||||
|
||||
return newUser
|
||||
}
|
||||
|
||||
export const createUserWithoutProfile = async (name: string): Promise<User> => {
|
||||
return getManager()
|
||||
.getRepository(User)
|
||||
.create({
|
||||
source: 'GOOGLE',
|
||||
sourceUserId: 'fake-user-id-' + name,
|
||||
email: `${name}@fake.com`,
|
||||
name: name,
|
||||
})
|
||||
.save()
|
||||
return getRepository(User).save({
|
||||
source: 'GOOGLE',
|
||||
sourceUserId: 'fake-user-id-' + name,
|
||||
email: `${name}@fake.com`,
|
||||
name: name,
|
||||
})
|
||||
}
|
||||
|
||||
export const getProfile = async (user: User): Promise<Profile | undefined> => {
|
||||
return Profile.findOne({ where: { user: user } })
|
||||
export const getProfile = async (user: User): Promise<Profile | null> => {
|
||||
return getRepository(Profile).findOneBy({ user: { id: user.id } })
|
||||
}
|
||||
|
||||
export const createTestPage = async (): Promise<Page> => {
|
||||
return getRepository(Page)
|
||||
.create({
|
||||
originalHtml: 'html',
|
||||
content: 'Test content',
|
||||
description: 'Test description',
|
||||
title: 'Test title',
|
||||
author: 'Test author',
|
||||
url: 'Test url',
|
||||
hash: 'Test hash',
|
||||
})
|
||||
.save()
|
||||
return getRepository(Page).save({
|
||||
originalHtml: 'html',
|
||||
content: 'Test content',
|
||||
description: 'Test description',
|
||||
title: 'Test title',
|
||||
author: 'Test author',
|
||||
url: 'Test url',
|
||||
hash: 'Test hash',
|
||||
})
|
||||
}
|
||||
|
||||
export const createTestLink = async (user: User, page: Page): Promise<Link> => {
|
||||
return getRepository(Link)
|
||||
.create({
|
||||
user: user,
|
||||
page: page,
|
||||
slug: 'Test slug',
|
||||
articleUrl: 'Test url',
|
||||
articleHash: 'Test hash',
|
||||
})
|
||||
.save()
|
||||
return getRepository(Link).save({
|
||||
user: user,
|
||||
page: page,
|
||||
slug: 'Test slug',
|
||||
articleUrl: 'Test url',
|
||||
articleHash: 'Test hash',
|
||||
})
|
||||
}
|
||||
|
||||
export const createTestReminder = async (
|
||||
user: User,
|
||||
link?: string
|
||||
): Promise<Reminder> => {
|
||||
return getRepository(Reminder)
|
||||
.create({
|
||||
user: user,
|
||||
link: link,
|
||||
remindAt: new Date(),
|
||||
})
|
||||
.save()
|
||||
return getRepository(Reminder).save({
|
||||
user: user,
|
||||
link: link,
|
||||
remindAt: new Date(),
|
||||
})
|
||||
}
|
||||
|
||||
export const getReminder = async (
|
||||
id: string
|
||||
): Promise<Reminder | undefined> => {
|
||||
return getRepository(Reminder).findOne(id)
|
||||
export const getReminder = async (id: string): Promise<Reminder | null> => {
|
||||
return getRepository(Reminder).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const createTestNewsletterEmail = async (
|
||||
@ -162,44 +140,40 @@ export const createTestNewsletterEmail = async (
|
||||
emailAddress?: string,
|
||||
confirmationCode?: string
|
||||
): Promise<NewsletterEmail> => {
|
||||
return getRepository(NewsletterEmail)
|
||||
.create({
|
||||
user: user,
|
||||
address: emailAddress,
|
||||
confirmationCode: confirmationCode,
|
||||
})
|
||||
.save()
|
||||
return getRepository(NewsletterEmail).save({
|
||||
user: user,
|
||||
address: emailAddress,
|
||||
confirmationCode: confirmationCode,
|
||||
})
|
||||
}
|
||||
|
||||
export const getNewsletterEmail = async (
|
||||
id: string
|
||||
): Promise<NewsletterEmail | undefined> => {
|
||||
return getRepository(NewsletterEmail).findOne(id)
|
||||
): Promise<NewsletterEmail | null> => {
|
||||
return getRepository(NewsletterEmail).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const createTestDeviceToken = async (
|
||||
user: User
|
||||
): Promise<UserDeviceToken> => {
|
||||
return getRepository(UserDeviceToken)
|
||||
.create({
|
||||
user: user,
|
||||
token: 'Test token',
|
||||
})
|
||||
.save()
|
||||
return getRepository(UserDeviceToken).save({
|
||||
user: user,
|
||||
token: 'Test token',
|
||||
})
|
||||
}
|
||||
|
||||
export const getDeviceToken = async (
|
||||
id: string
|
||||
): Promise<UserDeviceToken | undefined> => {
|
||||
return getRepository(UserDeviceToken).findOne(id)
|
||||
): Promise<UserDeviceToken | null> => {
|
||||
return getRepository(UserDeviceToken).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const getUser = async (id: string): Promise<User | undefined> => {
|
||||
return getRepository(User).findOne(id)
|
||||
export const getUser = async (id: string): Promise<User | null> => {
|
||||
return getRepository(User).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const getLink = async (id: string): Promise<Link | undefined> => {
|
||||
return getRepository(Link).findOne(id)
|
||||
export const getLink = async (id: string): Promise<Link | null> => {
|
||||
return getRepository(Link).findOneBy({ id })
|
||||
}
|
||||
|
||||
export const createTestLabel = async (
|
||||
@ -207,11 +181,9 @@ export const createTestLabel = async (
|
||||
name: string,
|
||||
color: string
|
||||
): Promise<Label> => {
|
||||
return getRepository(Label)
|
||||
.create({
|
||||
user: user,
|
||||
name: name,
|
||||
color: color,
|
||||
})
|
||||
.save()
|
||||
return getRepository(Label).save({
|
||||
user: user,
|
||||
name: name,
|
||||
color: color,
|
||||
})
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getConnection } from 'typeorm'
|
||||
import { AppDataSource } from '../src/server'
|
||||
|
||||
export const mochaGlobalTeardown = async () => {
|
||||
await getConnection().close()
|
||||
await AppDataSource.destroy()
|
||||
console.log('db connection closed')
|
||||
}
|
||||
|
||||
@ -1,12 +1,5 @@
|
||||
import { createTestUser, deleteTestUser, getProfile, getUser } from '../db'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { graphqlRequest, request } from '../util'
|
||||
import { expect } from 'chai'
|
||||
import {
|
||||
LoginErrorCode,
|
||||
SignupErrorCode,
|
||||
UpdateUserErrorCode,
|
||||
UpdateUserProfileErrorCode,
|
||||
} from '../../src/generated/graphql'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { hashPassword } from '../../src/utils/auth'
|
||||
import 'mocha'
|
||||
@ -33,7 +26,7 @@ describe('Sanitize Directive', () => {
|
||||
})
|
||||
|
||||
describe('Update user with a bio that is too long', () => {
|
||||
let bio = "".padStart(500, '*');
|
||||
let bio = ''.padStart(500, '*')
|
||||
let query: string
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@ -19,9 +19,9 @@ import {
|
||||
} from '../../src/elastic'
|
||||
import { PageType, UploadFileStatus } from '../../src/generated/graphql'
|
||||
import { Page, PageContext } from '../../src/elastic/types'
|
||||
import { getRepository } from 'typeorm'
|
||||
import { UploadFile } from '../../src/entity/upload_file'
|
||||
import { createPubSubClient } from '../../src/datalayer/pubsub'
|
||||
import { getRepository } from '../../src/entity/utils'
|
||||
|
||||
chai.use(chaiString)
|
||||
|
||||
|
||||
@ -7,11 +7,11 @@ import {
|
||||
} from '../util'
|
||||
import { Label } from '../../src/entity/label'
|
||||
import { expect } from 'chai'
|
||||
import { getRepository } from 'typeorm'
|
||||
import 'mocha'
|
||||
import { User } from '../../src/entity/user'
|
||||
import { Page } from '../../src/elastic/types'
|
||||
import { getPageById } from '../../src/elastic'
|
||||
import { getRepository } from '../../src/entity/utils'
|
||||
|
||||
describe('Labels API', () => {
|
||||
const username = 'fakeUser'
|
||||
@ -76,7 +76,9 @@ describe('Labels API', () => {
|
||||
it('should return labels', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
|
||||
const labels = await getRepository(Label).find({ where: { user } })
|
||||
const labels = await getRepository(Label).findBy({
|
||||
user: { id: user.id },
|
||||
})
|
||||
expect(res.body.data.labels.labels).to.eql(
|
||||
labels.map((label) => ({
|
||||
id: label.id,
|
||||
@ -137,9 +139,9 @@ describe('Labels API', () => {
|
||||
|
||||
it('should create label', async () => {
|
||||
const res = await graphqlRequest(query, authToken).expect(200)
|
||||
const label = await getRepository(Label).findOne(
|
||||
res.body.data.createLabel.label.id
|
||||
)
|
||||
const label = await getRepository(Label).findOneBy({
|
||||
id: res.body.data.createLabel.label.id,
|
||||
})
|
||||
expect(label).to.exist
|
||||
})
|
||||
})
|
||||
@ -203,7 +205,7 @@ describe('Labels API', () => {
|
||||
|
||||
it('should delete label', async () => {
|
||||
await graphqlRequest(query, authToken).expect(200)
|
||||
const label = await getRepository(Label).findOne(labelId)
|
||||
const label = await getRepository(Label).findOneBy({ id: labelId })
|
||||
expect(label).to.not.exist
|
||||
})
|
||||
})
|
||||
|
||||
@ -164,7 +164,7 @@ describe('Newsletters API', () => {
|
||||
const newsletterEmail = await getNewsletterEmail(
|
||||
response.body.data.deleteNewsletterEmail.newsletterEmail.id
|
||||
)
|
||||
expect(newsletterEmail).to.be.undefined
|
||||
expect(newsletterEmail).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -3,9 +3,9 @@ import { Page } from '../../src/elastic/types'
|
||||
import { createTestUser, deleteTestUser } from '../db'
|
||||
import { createTestElasticPage, graphqlRequest, request } from '../util'
|
||||
import { ReportType } from '../../src/generated/graphql'
|
||||
import { getRepository } from 'typeorm'
|
||||
import { ContentDisplayReport } from '../../src/entity/reports/content_display_report'
|
||||
import { expect } from 'chai'
|
||||
import { getRepository } from '../../src/entity/utils'
|
||||
|
||||
describe('Report API', () => {
|
||||
const username = 'fakeUser'
|
||||
@ -70,7 +70,7 @@ describe('Report API', () => {
|
||||
await graphqlRequest(query, authToken).expect(200)
|
||||
|
||||
expect(
|
||||
await getRepository(ContentDisplayReport).find({
|
||||
await getRepository(ContentDisplayReport).findBy({
|
||||
elasticPageId: pageId,
|
||||
})
|
||||
).to.exist
|
||||
|
||||
@ -75,7 +75,7 @@ describe('Device tokens API', () => {
|
||||
const deviceToken = await getDeviceToken(
|
||||
response.body.data.setDeviceToken.deviceToken.id
|
||||
)
|
||||
expect(deviceToken).to.be.undefined
|
||||
expect(deviceToken).to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
@ -105,7 +105,7 @@ describe('Device tokens API', () => {
|
||||
const deviceToken = await getDeviceToken(
|
||||
response.body.data.setDeviceToken.deviceToken.id
|
||||
)
|
||||
expect(deviceToken).not.to.be.undefined
|
||||
expect(deviceToken).not.to.be.null
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@ import { SharedArticleErrorCode } from '../../src/generated/graphql'
|
||||
import { Page } from '../../src/entity/page'
|
||||
import { Link } from '../../src/entity/link'
|
||||
import { Highlight } from '../../src/entity/highlight'
|
||||
import { getRepository } from 'typeorm'
|
||||
import 'mocha'
|
||||
import { getRepository } from '../../src/entity/utils'
|
||||
|
||||
describe('User feed article API', () => {
|
||||
const existingUsername = 'fakeUser'
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import 'mocha'
|
||||
import { expect } from 'chai'
|
||||
import 'chai/register-should'
|
||||
import { labelsLoader } from '../../src/services/labels'
|
||||
import {
|
||||
createTestLabel,
|
||||
createTestLink,
|
||||
@ -9,10 +8,11 @@ import {
|
||||
createTestUser,
|
||||
deleteTestUser,
|
||||
} from '../db'
|
||||
import { getRepository } from 'typeorm'
|
||||
import { LinkLabel } from '../../src/entity/link_label'
|
||||
import { Label } from '../../src/entity/label'
|
||||
import { Link } from '../../src/entity/link'
|
||||
import { labelsLoader } from '../../src/services/labels'
|
||||
import { getRepository } from '../../src/entity/utils'
|
||||
|
||||
describe('batch get labels from linkIds', () => {
|
||||
let username = 'testUser'
|
||||
|
||||
87
yarn.lock
87
yarn.lock
@ -6663,11 +6663,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.11.tgz#d654a112973f5e004bf8438122bd7e56a8e5cd7e"
|
||||
integrity sha512-9cwk3c87qQKZrT251EDoibiYRILjCmxBvvcb4meofCmx1vdnNcR9gyildy5vOHASpOKMsn42CugxUvcwK5eu1g==
|
||||
|
||||
"@types/zen-observable@0.8.3":
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3"
|
||||
integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^5.9.0":
|
||||
version "5.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.0.tgz#382182d5cb062f52aac54434cfc47c28898c8006"
|
||||
@ -9167,6 +9162,11 @@ date-fns@^2.16.1:
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9"
|
||||
integrity sha512-5ycpauovVyAk0kXNZz6ZoB9AYMZB4DObse7P3BPWmyEjXNORTI8EJ6X0uaSAq4sCHzM1uajzrkr6HnsLQpxGXA==
|
||||
|
||||
date-fns@^2.28.0:
|
||||
version "2.28.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2"
|
||||
integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==
|
||||
|
||||
dateformat@^3.0.0:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
|
||||
@ -9649,6 +9649,11 @@ dotenv@^10.0.0:
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
|
||||
integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
|
||||
|
||||
dotenv@^16.0.0:
|
||||
version "16.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.0.tgz#c619001253be89ebb638d027b609c75c26e47411"
|
||||
integrity sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==
|
||||
|
||||
dotenv@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
|
||||
@ -11120,6 +11125,18 @@ glob@7.1.7, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
|
||||
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
global-dirs@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686"
|
||||
@ -18646,7 +18663,7 @@ tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@^2, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@~2.3.0:
|
||||
tslib@^2, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1, tslib@~2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
|
||||
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
|
||||
@ -18754,33 +18771,33 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typeorm-naming-strategies@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/typeorm-naming-strategies/-/typeorm-naming-strategies-2.0.0.tgz#c7c10bc768ddce2592ef9ad4d2dca55fd5fa6ad6"
|
||||
integrity sha512-nsJ5jDjhBBEG6olFmxojkO4yrW7hEv38sH7ZXWWx9wnDoo9uaoH/mo2mBYAh/VKgwoFHBLu+CYxGmzXz2GUMcA==
|
||||
typeorm-naming-strategies@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/typeorm-naming-strategies/-/typeorm-naming-strategies-4.1.0.tgz#1ec6eb296c8d7b69bb06764d5b9083ff80e814a9"
|
||||
integrity sha512-vPekJXzZOTZrdDvTl1YoM+w+sUIfQHG4kZTpbFYoTsufyv9NIBRe4Q+PdzhEAFA2std3D9LZHEb1EjE9zhRpiQ==
|
||||
|
||||
typeorm@^0.2.37:
|
||||
version "0.2.45"
|
||||
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.45.tgz#e5bbb3af822dc4646bad96cfa48cd22fa4687cea"
|
||||
integrity sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==
|
||||
typeorm@^0.3.4:
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.4.tgz#6608f7efb15c40f3fa2863cefb45ff78a208c40c"
|
||||
integrity sha512-6v3HH12viDhIQwQDod/B0Plt1o7IYIVDxP7zwatD6fzN+IDdqTTinW/sWNw84Edpbhh2t7XILTaQEqj0NXFP/Q==
|
||||
dependencies:
|
||||
"@sqltools/formatter" "^1.2.2"
|
||||
app-root-path "^3.0.0"
|
||||
buffer "^6.0.3"
|
||||
chalk "^4.1.0"
|
||||
cli-highlight "^2.1.11"
|
||||
debug "^4.3.1"
|
||||
dotenv "^8.2.0"
|
||||
glob "^7.1.6"
|
||||
js-yaml "^4.0.0"
|
||||
date-fns "^2.28.0"
|
||||
debug "^4.3.3"
|
||||
dotenv "^16.0.0"
|
||||
glob "^7.2.0"
|
||||
js-yaml "^4.1.0"
|
||||
mkdirp "^1.0.4"
|
||||
reflect-metadata "^0.1.13"
|
||||
sha.js "^2.4.11"
|
||||
tslib "^2.1.0"
|
||||
tslib "^2.3.1"
|
||||
uuid "^8.3.2"
|
||||
xml2js "^0.4.23"
|
||||
yargs "^17.0.1"
|
||||
zen-observable-ts "^1.0.0"
|
||||
yargs "^17.3.1"
|
||||
|
||||
typescript@^2.9.2:
|
||||
version "2.9.2"
|
||||
@ -19812,7 +19829,7 @@ yargs@^15.0.2, yargs@^15.3.1:
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.2"
|
||||
|
||||
yargs@^17.0.0, yargs@^17.0.1:
|
||||
yargs@^17.0.0:
|
||||
version "17.3.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9"
|
||||
integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==
|
||||
@ -19825,6 +19842,19 @@ yargs@^17.0.0, yargs@^17.0.1:
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^21.0.0"
|
||||
|
||||
yargs@^17.3.1:
|
||||
version "17.4.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.4.0.tgz#9fc9efc96bd3aa2c1240446af28499f0e7593d00"
|
||||
integrity sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA==
|
||||
dependencies:
|
||||
cliui "^7.0.2"
|
||||
escalade "^3.1.1"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.3"
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^21.0.0"
|
||||
|
||||
yauzl@^2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
|
||||
@ -19853,16 +19883,3 @@ yup@^0.31.0:
|
||||
lodash-es "^4.17.11"
|
||||
property-expr "^2.0.4"
|
||||
toposort "^2.0.2"
|
||||
|
||||
zen-observable-ts@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz#2d1aa9d79b87058e9b75698b92791c1838551f83"
|
||||
integrity sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==
|
||||
dependencies:
|
||||
"@types/zen-observable" "0.8.3"
|
||||
zen-observable "0.8.15"
|
||||
|
||||
zen-observable@0.8.15:
|
||||
version "0.8.15"
|
||||
resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
|
||||
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
|
||||
|
||||
Reference in New Issue
Block a user